From e82adc86680e7f47b5603b3b93bf3590eec32b91 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Thu, 27 Sep 2018 19:33:26 +0530 Subject: [PATCH 001/582] added the factory and module contract --- .../BlacklistTransferManager.sol | 136 ++++++++++++++++++ .../BlacklistTransferManagerFactory.sol | 99 +++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 contracts/modules/TransferManager/BlacklistTransferManager.sol create mode 100644 contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol new file mode 100644 index 000000000..100d0c324 --- /dev/null +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -0,0 +1,136 @@ +pragma solidity ^0.4.24; + +import "./ITransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/** + * @title Transfer Manager module for manually approving or blocking transactions between accounts + */ +contract BlacklisTransferManager is ITransferManager { + using SafeMath for uint256; + + bytes32 constant ADMIN = "ADMIN"; + + struct BlacklistsDetails { + uint256 startDate; + uint256 endDate; + uint256 repeatPeriodInDays; + } + + //hold the different blacklist corresponds to name of blacklist type + mapping(bytes32 => BlacklistDetails) blacklists; + + //hold the blacklisted address corresponds to the blacklist type + mapping(address => bytes32) investorToBlacklist; + + //get list of the addresses for a particular blacklist + mapping(bytes32 => address[]) blacklistToAddress; + + // Emit when new blacklist type is added + event AddBlacklistType(uint256 _startDate,uint256 _endDate,bytes32 _name,uint256 _repeatPeriodInDays); + + // Emit when there is change in the blacklist type + event ModifyBlacklistType(uint256 _startDate,uint256 _endDate,bytes32 _name,uint256 _repeatPeriodInDays); + + // Emit when the added blacklist type is deleted + event DeleteBlacklistType(bytes32 _name); + + // Emit when new investor is added to the blacklist type + event AddInvestorToBlacklist(address _investor,bytes32 _blacklistName); + + + ///@notice Used to verify the transfer transaction + function verifyTransfer(address _from, uint256 /* _amount */, uint256 /* _isTransfer */) public returns(Result) { + if (investorToBlacklist[_from] != bytes32(0)) { + uint256 repeater = + now.div((blacklists[investorToBlacklist[_from]].endDate + .sub(blacklists[investorToBlacklist[_from]].startDate)) + .add(blacklists[investorToBlacklist[_from]].repeatPeriodInDays)); + if (blacklists[investorToBlacklist[_from]].endDate.mul(repeater) >= now && blacklists[investorToBlacklist[_from]].startDate.mul(repeater) <= now) { + return Result.INVALID; + } + return Result.VALID; + } + return Result.NA; + } + + /** + *@notice Used to add the blacklist type + *@param _startdate start date of the blacklist type + *@param _endDate end date of the blacklist type + *@param _name name of the blacklist type + *@param _repeatPeriodInDays repeat period of the blacklist type + */ + function addBlacklistType(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) public withPerm(ADMIN){ + require(blacklist[_name].endDate == 0 && _name != bytes(0) && _startDate !=0 && _endDate != 0 && _repeatPeriodInDays != 0); + blacklist[_name] = BlacklistsDetails(_startDate,_endDate,_repeatPeriodInDays); + emit AddBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); + } + + /** + *@notice Used to edit the blacklist type + *@param _startdate start date of the blacklist type + *@param _endDate end date of the blacklist type + *@param _name name of the blacklist type + *@param _repeatPeriodInDays repeat period of the blacklist type + */ + function modifyBlacklistType(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) public withPerm(ADMIN){ + require(blacklist[_name].endDate != 0 && _name != bytes(0) && _startDate != 0 && _endDate != 0 && _repeatPeriodInDays != 0); + blacklist[_name] = BlacklistsDetails(_startDate,_endDate,_repeatPeriodInDays); + emit ModifyBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); + } + + /** + *@notice Used to delete the blacklist type + *@param _name name of the blacklist type + */ + function deleteBlacklistType(bytes32 _name) public withPerm(ADMIN){ + require(blacklist[_name].endDate != 0); + delete(blacklist[_name]); + emit DeleteBlacklistType(_name); + } + + /** + *@notice Used to assign the blacklist type to the investor + *@param _investor address of the investor + *@param _blacklistName name of the blacklist + */ + function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN){ + require(blacklist[_blacklistName].endDate != 0 && _investor != address(0)); + investorToBlacklist[_investor] = _blacklistName; + blacklistToAddress[_blacklistName].push(_investor); + emit AddInvestorToBlacklist(_investor, _blacklistName); + } + + /** + *@notice Used to assign the blacklist type to the multiple investor + *@param _investor address of the investor + *@param _blacklistName name of the blacklist + */ + function addInvestorToBlacklistMulti(address[] _investor, bytes32 _blacklistName) public withPerm(ADMIN){ + for(uint8 i = 0; i < _investor.length; i++){ + addInvestorToBlacklist(_investor[i], _blacklistName); + } + } + + /** + *@notice Used to assign the new blacklist type to the investor + *@param _startdate start date of the blacklist type + *@param _endDate end date of the blacklist type + *@param _name name of the blacklist type + *@param _repeatPeriodInDays repeat period of the blacklist type + *@param _investor address of the investor + */ + function addInvestorToNewBlacklist(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays,address _investor) public withPerm(ADMIN){ + addBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); + addInvestorToBlacklist(_investor, _name); + } + + /** + *@notice get the list of the investors of a blacklist type + *@param _blacklistName name of the blacklist type + */ + function getListofAddresses(bytes32 _blacklistName) public returns(address[]) { + return blacklistToAddress[_blacklistName]; + } +} diff --git a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol new file mode 100644 index 000000000..95c52bd43 --- /dev/null +++ b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol @@ -0,0 +1,99 @@ +pragma solidity ^0.4.24; + +import "./BlacklistTransferManager.sol"; +import "../ModuleFactory.sol"; + +/** + * @title Factory for deploying BlacklistManager module + */ +contract BlacklistTransferManagerFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _subscriptionCost Subscription cost of the module + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "BlacklistManager"; + title = "Blacklist"; + description = "Automate blacklist to restrict selling"; + } + + /** + * @notice used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes /* _data */) external returns(address) { + if (setupCost > 0) + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + address blacklistTransferManager = new BlacklistTransferManager(msg.sender, address(polyToken)); + emit LogGenerateModuleFromFactory(address(blacklistTransferManager), getName(), address(this), msg.sender, setupCost, now); + return address(blacklistManager); + } + + /** + * @notice Type of the Module factory + */ + function getType() public view returns(uint8) { + return 2; + } + + /** + * @notice Get the name of the Module + */ + function getName() public view returns(bytes32) { + return name; + } + + /** + * @notice Get the description of the Module + */ + function getDescription() public view returns(string) { + return description; + } + + /** + * @notice Get the title of the Module + */ + function getTitle() public view returns(string) { + return title; + } + + /** + * @notice Get the version of the Module + */ + function getVersion() external view returns(string) { + return version; + } + + /** + * @notice Get the setup cost of the module + */ + function getSetupCost() external view returns (uint256) { + return setupCost; + } + + /** + * @notice Get the Instructions that helped to used the module + */ + function getInstructions() public view returns(string) { + return "Allows an issuer to blacklist specific pairs of addresses. Init function takes no parameters."; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() public view returns(bytes32[]) { + bytes32[] memory availableTags = new bytes32[](2); + availableTags[0] = "Blacklist"; + availableTags[1] = "Restrict selling of token"; + return availableTags; + } + + +} From 972997819995b96266b7dadda6f77822969cd06a Mon Sep 17 00:00:00 2001 From: Vikas Panwar Date: Fri, 28 Sep 2018 11:30:38 +0530 Subject: [PATCH 002/582] changed date calculation logic --- .../BlacklistTransferManager.sol | 136 ++++++++++++------ .../BlacklistTransferManagerFactory.sol | 6 +- package-lock.json | 52 ------- 3 files changed, 95 insertions(+), 99 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 100d0c324..0111b7952 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -10,6 +10,8 @@ contract BlacklisTransferManager is ITransferManager { using SafeMath for uint256; bytes32 constant ADMIN = "ADMIN"; + bytes32 public constant WHITELIST = "WHITELIST"; + bytes32 public constant FLAGS = "FLAGS"; struct BlacklistsDetails { uint256 startDate; @@ -18,7 +20,7 @@ contract BlacklisTransferManager is ITransferManager { } //hold the different blacklist corresponds to name of blacklist type - mapping(bytes32 => BlacklistDetails) blacklists; + mapping(bytes32 => BlacklistsDetails) blacklists; //hold the blacklisted address corresponds to the blacklist type mapping(address => bytes32) investorToBlacklist; @@ -27,26 +29,52 @@ contract BlacklisTransferManager is ITransferManager { mapping(bytes32 => address[]) blacklistToAddress; // Emit when new blacklist type is added - event AddBlacklistType(uint256 _startDate,uint256 _endDate,bytes32 _name,uint256 _repeatPeriodInDays); + event AddBlacklistType( + uint256 _startDate, + uint256 _endDate, + bytes32 _name, + uint256 _repeatPeriodInDays + ); // Emit when there is change in the blacklist type - event ModifyBlacklistType(uint256 _startDate,uint256 _endDate,bytes32 _name,uint256 _repeatPeriodInDays); + event ModifyBlacklistType( + uint256 _startDate, + uint256 _endDate, + bytes32 _name, + uint256 _repeatPeriodInDays + ); // Emit when the added blacklist type is deleted - event DeleteBlacklistType(bytes32 _name); + event DeleteBlacklistType( + bytes32 _name + ); // Emit when new investor is added to the blacklist type - event AddInvestorToBlacklist(address _investor,bytes32 _blacklistName); + event AddInvestorToBlacklist( + address _investor, + bytes32 _blacklistName + ); + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { + } - ///@notice Used to verify the transfer transaction - function verifyTransfer(address _from, uint256 /* _amount */, uint256 /* _isTransfer */) public returns(Result) { + /// @notice Used to verify the transfer transaction + function verifyTransfer(address _from, address _to, uint256 /* _amount */, uint256 /* _isTransfer */) public returns(Result) { + require(_from != address(0), "Invalid from address"); if (investorToBlacklist[_from] != bytes32(0)) { - uint256 repeater = - now.div((blacklists[investorToBlacklist[_from]].endDate + uint256 blacklistDate = (blacklists[investorToBlacklist[_from]].endDate .sub(blacklists[investorToBlacklist[_from]].startDate)) - .add(blacklists[investorToBlacklist[_from]].repeatPeriodInDays)); - if (blacklists[investorToBlacklist[_from]].endDate.mul(repeater) >= now && blacklists[investorToBlacklist[_from]].startDate.mul(repeater) <= now) { + .add(blacklists[investorToBlacklist[_from]].repeatPeriodInDays * 1 days); + uint256 repeater = now.div(blacklistDate); + if (blacklists[investorToBlacklist[_from]].startDate.add(blacklistDate.mul(repeater)) <= now && blacklists[investorToBlacklist[_from]].endDate.add(blacklistDate.mul(repeater)) >= now) { return Result.INVALID; } return Result.VALID; @@ -55,57 +83,66 @@ contract BlacklisTransferManager is ITransferManager { } /** - *@notice Used to add the blacklist type - *@param _startdate start date of the blacklist type - *@param _endDate end date of the blacklist type - *@param _name name of the blacklist type - *@param _repeatPeriodInDays repeat period of the blacklist type + * @notice Used to add the blacklist type + * @param _startdate start date of the blacklist type + * @param _endDate end date of the blacklist type + * @param _name name of the blacklist type + * @param _repeatPeriodInDays repeat period of the blacklist type */ function addBlacklistType(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) public withPerm(ADMIN){ - require(blacklist[_name].endDate == 0 && _name != bytes(0) && _startDate !=0 && _endDate != 0 && _repeatPeriodInDays != 0); - blacklist[_name] = BlacklistsDetails(_startDate,_endDate,_repeatPeriodInDays); + require(blacklists[_name].endDate == 0, "Blacklist type already exist"); + require(_name != bytes(0), "Invald blacklist name"); + require(_startDate > now && _startDate < _endDate, "Invalid start or end date"); + require(_repeatPeriodInDays != 0, "Invalid reapeat days"); + blacklists[_name] = BlacklistsDetails(_startDate, _endDate, _repeatPeriodInDays); emit AddBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); } /** - *@notice Used to edit the blacklist type - *@param _startdate start date of the blacklist type - *@param _endDate end date of the blacklist type - *@param _name name of the blacklist type - *@param _repeatPeriodInDays repeat period of the blacklist type + * @notice Used to edit the blacklist type + * @param _startdate start date of the blacklist type + * @param _endDate end date of the blacklist type + * @param _name name of the blacklist type + * @param _repeatPeriodInDays repeat period of the blacklist type */ function modifyBlacklistType(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) public withPerm(ADMIN){ - require(blacklist[_name].endDate != 0 && _name != bytes(0) && _startDate != 0 && _endDate != 0 && _repeatPeriodInDays != 0); - blacklist[_name] = BlacklistsDetails(_startDate,_endDate,_repeatPeriodInDays); + require(blacklists[_name].endDate != 0, "Blacklist type doesnot exist"); + require(_name != bytes(0), "Invald blacklist name"); + require(_startDate > now && _startDate < _endDate, "Invalid start or end date"); + require(_repeatPeriodInDays != 0, "Invalid reapeat days"); + blacklists[_name] = BlacklistsDetails(_startDate, _endDate, _repeatPeriodInDays); emit ModifyBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); } /** - *@notice Used to delete the blacklist type - *@param _name name of the blacklist type + * @notice Used to delete the blacklist type + * @param _name name of the blacklist type */ function deleteBlacklistType(bytes32 _name) public withPerm(ADMIN){ - require(blacklist[_name].endDate != 0); - delete(blacklist[_name]); + require(blacklists[_name].endDate != 0, "Blacklist type doesnot exist"); + delete(blacklistToAddress[_name]); + delete(blacklists[_name]); emit DeleteBlacklistType(_name); } /** - *@notice Used to assign the blacklist type to the investor - *@param _investor address of the investor - *@param _blacklistName name of the blacklist + * @notice Used to assign the blacklist type to the investor + * @param _investor address of the investor + * @param _blacklistName name of the blacklist */ function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN){ - require(blacklist[_blacklistName].endDate != 0 && _investor != address(0)); + require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesnot exist"); + require(_investor != address(0), "Invalid investor address"); + require(investorToBlacklist[_investor] == bytes(0), "Investor already blacklisted"); investorToBlacklist[_investor] = _blacklistName; blacklistToAddress[_blacklistName].push(_investor); emit AddInvestorToBlacklist(_investor, _blacklistName); } /** - *@notice Used to assign the blacklist type to the multiple investor - *@param _investor address of the investor - *@param _blacklistName name of the blacklist + * @notice Used to assign the blacklist type to the multiple investor + * @param _investor address of the investor + * @param _blacklistName name of the blacklist */ function addInvestorToBlacklistMulti(address[] _investor, bytes32 _blacklistName) public withPerm(ADMIN){ for(uint8 i = 0; i < _investor.length; i++){ @@ -114,12 +151,12 @@ contract BlacklisTransferManager is ITransferManager { } /** - *@notice Used to assign the new blacklist type to the investor - *@param _startdate start date of the blacklist type - *@param _endDate end date of the blacklist type - *@param _name name of the blacklist type - *@param _repeatPeriodInDays repeat period of the blacklist type - *@param _investor address of the investor + * @notice Used to assign the new blacklist type to the investor + * @param _startdate start date of the blacklist type + * @param _endDate end date of the blacklist type + * @param _name name of the blacklist type + * @param _repeatPeriodInDays repeat period of the blacklist type + * @param _investor address of the investor */ function addInvestorToNewBlacklist(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays,address _investor) public withPerm(ADMIN){ addBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); @@ -127,10 +164,21 @@ contract BlacklisTransferManager is ITransferManager { } /** - *@notice get the list of the investors of a blacklist type - *@param _blacklistName name of the blacklist type + * @notice get the list of the investors of a blacklist type + * @param _blacklistName name of the blacklist type */ function getListofAddresses(bytes32 _blacklistName) public returns(address[]) { + require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesnot exist"); return blacklistToAddress[_blacklistName]; } + + /** + * @notice Return the permissions flag that are associated with general trnasfer manager + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](2); + allPermissions[0] = WHITELIST; + allPermissions[1] = FLAGS; + return allPermissions; + } } diff --git a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol index 95c52bd43..04c6b7574 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol @@ -19,8 +19,8 @@ contract BlacklistTransferManagerFactory is ModuleFactory { ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; - name = "BlacklistManager"; - title = "Blacklist"; + name = "BlacklistTransferManager"; + title = "Blacklist Transfer Manager"; description = "Automate blacklist to restrict selling"; } @@ -33,7 +33,7 @@ contract BlacklistTransferManagerFactory is ModuleFactory { require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); address blacklistTransferManager = new BlacklistTransferManager(msg.sender, address(polyToken)); emit LogGenerateModuleFromFactory(address(blacklistTransferManager), getName(), address(this), msg.sender, setupCost, now); - return address(blacklistManager); + return address(blacklistTransferManager); } /** diff --git a/package-lock.json b/package-lock.json index fc73460ac..7360919d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,31 +45,6 @@ "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", "dev": true }, - "abi-decoder": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/abi-decoder/-/abi-decoder-1.2.0.tgz", - "integrity": "sha512-y2OKSEW4gf2838Eavc56vQY9V46zaXkf3Jl1WpTfUBbzAVrXSr4JRZAAWv55Tv9s5WNz1rVgBgz5d2aJIL1QCg==", - "requires": { - "web3": "0.18.4" - }, - "dependencies": { - "bignumber.js": { - "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" - }, - "web3": { - "version": "0.18.4", - "resolved": "https://registry.npmjs.org/web3/-/web3-0.18.4.tgz", - "integrity": "sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0=", - "requires": { - "bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "crypto-js": "3.1.8", - "utf8": "2.1.1", - "xhr2": "0.1.4", - "xmlhttprequest": "1.8.0" - } - } - } - }, "abstract-leveldown": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", @@ -2121,12 +2096,6 @@ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true - }, "death": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", @@ -5051,15 +5020,6 @@ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, - "grouped-queue": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", - "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", - "dev": true, - "requires": { - "lodash": "4.17.5" - } - }, "handlebars": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", @@ -5788,17 +5748,6 @@ } } }, - "istextorbinary": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", - "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", - "dev": true, - "requires": { - "binaryextensions": "2.1.1", - "editions": "1.3.4", - "textextensions": "2.2.0" - } - }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", @@ -8397,7 +8346,6 @@ "ethereumjs-testrpc-sc": "6.1.6", "istanbul": "0.4.5", "keccakjs": "0.2.1", - "req-cwd": "1.0.1", "shelljs": "0.7.8", "sol-explore": "1.6.2", "solidity-parser-sc": "0.4.11", From b39da91a14a64869f97b1a9ee34c2a66e721f747 Mon Sep 17 00:00:00 2001 From: Vikas Panwar Date: Fri, 28 Sep 2018 12:58:22 +0530 Subject: [PATCH 003/582] minor changes --- .../BlacklistTransferManager.sol | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 0111b7952..cc0483e7e 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -6,13 +6,11 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Transfer Manager module for manually approving or blocking transactions between accounts */ -contract BlacklisTransferManager is ITransferManager { +contract BlacklistTransferManager is ITransferManager { using SafeMath for uint256; - bytes32 constant ADMIN = "ADMIN"; - bytes32 public constant WHITELIST = "WHITELIST"; - bytes32 public constant FLAGS = "FLAGS"; - + bytes32 public constant ADMIN = "ADMIN"; + struct BlacklistsDetails { uint256 startDate; uint256 endDate; @@ -66,8 +64,16 @@ contract BlacklisTransferManager is ITransferManager { { } + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(0); + } + + /// @notice Used to verify the transfer transaction - function verifyTransfer(address _from, address _to, uint256 /* _amount */, uint256 /* _isTransfer */) public returns(Result) { + function verifyTransfer(address _from, address _to, uint256 /* _amount */, bool /* _isTransfer */) public returns(Result) { require(_from != address(0), "Invalid from address"); if (investorToBlacklist[_from] != bytes32(0)) { uint256 blacklistDate = (blacklists[investorToBlacklist[_from]].endDate @@ -84,32 +90,37 @@ contract BlacklisTransferManager is ITransferManager { /** * @notice Used to add the blacklist type - * @param _startdate start date of the blacklist type + * @param _startDate start date of the blacklist type * @param _endDate end date of the blacklist type * @param _name name of the blacklist type * @param _repeatPeriodInDays repeat period of the blacklist type */ function addBlacklistType(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) public withPerm(ADMIN){ require(blacklists[_name].endDate == 0, "Blacklist type already exist"); - require(_name != bytes(0), "Invald blacklist name"); - require(_startDate > now && _startDate < _endDate, "Invalid start or end date"); - require(_repeatPeriodInDays != 0, "Invalid reapeat days"); + _validParams(_startDate, _endDate, _name, _repeatPeriodInDays); blacklists[_name] = BlacklistsDetails(_startDate, _endDate, _repeatPeriodInDays); emit AddBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); } + + /** + * @notice Internal function + */ + function _validParams(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) internal view { + require(_name != bytes32(0), "Invalid blacklist name"); + require(_startDate > now && _startDate < _endDate, "Invalid start or end date"); + require(_repeatPeriodInDays != 0, "Invalid repeat days"); + } /** * @notice Used to edit the blacklist type - * @param _startdate start date of the blacklist type + * @param _startDate start date of the blacklist type * @param _endDate end date of the blacklist type * @param _name name of the blacklist type * @param _repeatPeriodInDays repeat period of the blacklist type */ function modifyBlacklistType(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) public withPerm(ADMIN){ - require(blacklists[_name].endDate != 0, "Blacklist type doesnot exist"); - require(_name != bytes(0), "Invald blacklist name"); - require(_startDate > now && _startDate < _endDate, "Invalid start or end date"); - require(_repeatPeriodInDays != 0, "Invalid reapeat days"); + require(blacklists[_name].endDate != 0, "Blacklist type doesn't exist"); + _validParams(_startDate, _endDate, _name, _repeatPeriodInDays); blacklists[_name] = BlacklistsDetails(_startDate, _endDate, _repeatPeriodInDays); emit ModifyBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); } @@ -118,9 +129,10 @@ contract BlacklisTransferManager is ITransferManager { * @notice Used to delete the blacklist type * @param _name name of the blacklist type */ + /// TODO - Need more Info to understand the how delete operation will work whether it will delete + /// the corresponding addresses or restrict to delete when blacklistType have some addresses associated function deleteBlacklistType(bytes32 _name) public withPerm(ADMIN){ - require(blacklists[_name].endDate != 0, "Blacklist type doesnot exist"); - delete(blacklistToAddress[_name]); + require(blacklists[_name].endDate != 0, "Blacklist type doesn’t exist"); delete(blacklists[_name]); emit DeleteBlacklistType(_name); } @@ -131,9 +143,8 @@ contract BlacklisTransferManager is ITransferManager { * @param _blacklistName name of the blacklist */ function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN){ - require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesnot exist"); + require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); - require(investorToBlacklist[_investor] == bytes(0), "Investor already blacklisted"); investorToBlacklist[_investor] = _blacklistName; blacklistToAddress[_blacklistName].push(_investor); emit AddInvestorToBlacklist(_investor, _blacklistName); @@ -145,14 +156,14 @@ contract BlacklisTransferManager is ITransferManager { * @param _blacklistName name of the blacklist */ function addInvestorToBlacklistMulti(address[] _investor, bytes32 _blacklistName) public withPerm(ADMIN){ - for(uint8 i = 0; i < _investor.length; i++){ + for(uint256 i = 0; i < _investor.length; i++){ addInvestorToBlacklist(_investor[i], _blacklistName); } } /** * @notice Used to assign the new blacklist type to the investor - * @param _startdate start date of the blacklist type + * @param _startDate start date of the blacklist type * @param _endDate end date of the blacklist type * @param _name name of the blacklist type * @param _repeatPeriodInDays repeat period of the blacklist type @@ -167,18 +178,19 @@ contract BlacklisTransferManager is ITransferManager { * @notice get the list of the investors of a blacklist type * @param _blacklistName name of the blacklist type */ - function getListofAddresses(bytes32 _blacklistName) public returns(address[]) { - require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesnot exist"); + function getListofAddresses(bytes32 _blacklistName) public view returns(address[]) { + require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesn't exist"); return blacklistToAddress[_blacklistName]; } /** - * @notice Return the permissions flag that are associated with general trnasfer manager + * @notice Return the permissions flag that are associated with general transfer manager */ function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](2); - allPermissions[0] = WHITELIST; - allPermissions[1] = FLAGS; + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; return allPermissions; } } + + From 70ee1dc1756957e1781b629deb694145b970c958 Mon Sep 17 00:00:00 2001 From: Vikas Panwar Date: Fri, 28 Sep 2018 15:14:15 +0530 Subject: [PATCH 004/582] updated the branch --- .../modules/TransferManager/BlacklistTransferManager.sol | 2 +- .../TransferManager/BlacklistTransferManagerFactory.sol | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index cc0483e7e..36b0b88e0 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -73,7 +73,7 @@ contract BlacklistTransferManager is ITransferManager { /// @notice Used to verify the transfer transaction - function verifyTransfer(address _from, address _to, uint256 /* _amount */, bool /* _isTransfer */) public returns(Result) { + function verifyTransfer(address _from, address /* _to */, uint256 /* _amount */, bool /* _isTransfer */) public returns(Result) { require(_from != address(0), "Invalid from address"); if (investorToBlacklist[_from] != bytes32(0)) { uint256 blacklistDate = (blacklists[investorToBlacklist[_from]].endDate diff --git a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol index 04c6b7574..a4c9e5532 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol @@ -22,6 +22,8 @@ contract BlacklistTransferManagerFactory is ModuleFactory { name = "BlacklistTransferManager"; title = "Blacklist Transfer Manager"; description = "Automate blacklist to restrict selling"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -32,7 +34,7 @@ contract BlacklistTransferManagerFactory is ModuleFactory { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); address blacklistTransferManager = new BlacklistTransferManager(msg.sender, address(polyToken)); - emit LogGenerateModuleFromFactory(address(blacklistTransferManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(blacklistTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(blacklistTransferManager); } From 020cef6b392e2b80836048315fc6fee56776e360 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Sun, 30 Sep 2018 22:03:11 +0530 Subject: [PATCH 005/582] added test cases for few functionalities of blacklist --- .../BlacklistTransferManager.sol | 24 +- migrations/2_deploy_contracts.js | 15 + test/b_blacklist_transfer_manager.js | 423 ++++++++++++++++++ 3 files changed, 451 insertions(+), 11 deletions(-) create mode 100644 test/b_blacklist_transfer_manager.js diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 36b0b88e0..e8236fe6e 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -74,17 +74,19 @@ contract BlacklistTransferManager is ITransferManager { /// @notice Used to verify the transfer transaction function verifyTransfer(address _from, address /* _to */, uint256 /* _amount */, bool /* _isTransfer */) public returns(Result) { - require(_from != address(0), "Invalid from address"); - if (investorToBlacklist[_from] != bytes32(0)) { - uint256 blacklistDate = (blacklists[investorToBlacklist[_from]].endDate - .sub(blacklists[investorToBlacklist[_from]].startDate)) - .add(blacklists[investorToBlacklist[_from]].repeatPeriodInDays * 1 days); - uint256 repeater = now.div(blacklistDate); - if (blacklists[investorToBlacklist[_from]].startDate.add(blacklistDate.mul(repeater)) <= now && blacklists[investorToBlacklist[_from]].endDate.add(blacklistDate.mul(repeater)) >= now) { - return Result.INVALID; - } - return Result.VALID; - } + if(!paused){ + if (investorToBlacklist[_from] != bytes32(0)) { + uint256 blacklistDate = (blacklists[investorToBlacklist[_from]].endDate + .sub(blacklists[investorToBlacklist[_from]].startDate)) + .add(blacklists[investorToBlacklist[_from]].repeatPeriodInDays * 1 days); + uint256 repeater = now.div(blacklistDate); + if (blacklists[investorToBlacklist[_from]].startDate.add(blacklistDate.mul(repeater)) <= now && blacklists[investorToBlacklist[_from]].endDate.add(blacklistDate.mul(repeater)) >= now) { + return Result.INVALID; + } + return Result.VALID; + } + return Result.NA; + } return Result.NA; } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 9b9c5eb64..6e8c94f71 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -4,6 +4,7 @@ const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionMa const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') +const BlacklistTransferManagerFactory = artifacts.require('./BlacklistTransferManagerFactory.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); @@ -152,6 +153,10 @@ const functionSignatureProxyMR = { // D) Deploy the PercentageTransferManagerFactory Contract (Factory used to generate the PercentageTransferManager contract use // to track the percentage of investment the investors could do for a particular security token) return deployer.deploy(PercentageTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // D) Deploy the BlacklistTransferManagerFactory Contract (Factory used to generate the BlacklistTransferManager contract use + // to add the blacklist type and blacklist the investors to restrict the transfer) + return deployer.deploy(BlacklistTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // D) Deploy the EtherDividendCheckpointFactory Contract (Factory used to generate the EtherDividendCheckpoint contract use // to provide the functionality of the dividend in terms of ETH) @@ -168,6 +173,10 @@ const functionSignatureProxyMR = { // D) Register the PercentageTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the PercentageTransferManager contract. return moduleRegistry.registerModule(PercentageTransferManagerFactory.address, {from: PolymathAccount}); + }).then(() => { + // D) Register the BlacklistTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the BlacklistTransferManager contract. + return moduleRegistry.registerModule(BlacklistTransferManagerFactory.address, {from: PolymathAccount}); }).then(() => { // D) Register the CountTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the CountTransferManager contract. @@ -207,6 +216,11 @@ const functionSignatureProxyMR = { // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(PercentageTransferManagerFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // G) Once the BlacklistTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(BlacklistTransferManagerFactory.address, true, {from: PolymathAccount}); }).then(() => { // G) Once the GeneralPermissionManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. @@ -305,6 +319,7 @@ const functionSignatureProxyMR = { CountTransferManagerFactory: ${CountTransferManagerFactory.address} PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} + BlacklistTransferManagerFactory: ${BlacklistTransferManagerFactory.address} ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} diff --git a/test/b_blacklist_transfer_manager.js b/test/b_blacklist_transfer_manager.js new file mode 100644 index 000000000..db636f9eb --- /dev/null +++ b/test/b_blacklist_transfer_manager.js @@ -0,0 +1,423 @@ +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const BlacklistTransferManagerFactory = artifacts.require('./BlacklistTransferManagerFactory.sol'); +const BlacklistTransferManager = artifacts.require('./BlacklistTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('BlacklistTransferManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_BlacklistTransferManagerFactory; + let I_GeneralPermissionManager; + let I_BlacklistTransferManager; + let P_BlacklistTransferManagerFactory; + let P_BlacklistTransferManager; + let I_GeneralTransferManager; + let I_ExchangeTransferManager; + let I_ModuleRegistry; + let I_ModuleRegistryProxy; + let I_MRProxied; + let I_STRProxied; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // BlacklistTransferManager details + const holderCount = 2; // Maximum number of token holders + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + let bytesSTO = encodeModuleCall(['uint256'], [holderCount]); + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[7]; + account_investor2 = accounts[8]; + account_investor3 = accounts[9]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + assert.notEqual( + I_FeatureRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "FeatureRegistry contract was not deployed", + ); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 6: Deploy the BlacklistTransferManager + I_BlacklistTransferManagerFactory = await BlacklistTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + assert.notEqual( + I_BlacklistTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "BlacklistTransferManagerFactory contract was not deployed" + ); + + // STEP 7: Deploy Paid the CountTransferManager + P_BlacklistTransferManagerFactory = await BlacklistTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); + assert.notEqual( + P_BlacklistTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CountTransferManagerFactory contract was not deployed" + ); + + // STEP 8: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the BlacklistTransferManagerFactory + await I_MRProxied.registerModule(I_BlacklistTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_BlacklistTransferManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the Paid BlacklistTransferManagerFactory + await I_MRProxied.registerModule(P_BlacklistTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_BlacklistTransferManagerFactory.address, true, { from: account_polymath }); + + // Step 9: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 10: Deploy the SecurityTokenRegistry + + // Deploy the SecurityTokenregistry + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 11: Deploy the proxy and attach the implementation contract + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 12: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + BlacklistTransferManagerFactory: ${I_BlacklistTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner, gas: 85000000 }); + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._type.toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = await I_SecurityToken.modules(2, 0); + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + it("Should successfully attach the BlacklistTransferManager factory with the security token", async () => { + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + try { + const tx = await I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + } catch(error) { + console.log(` tx -> failed because Token is not paid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the BlacklistTransferManager factory with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._type.toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "BlacklistTransferManager", + "BlacklistTransferManagerFactory module was not added" + ); + P_BlacklistTransferManager = BlacklistTransferManager.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the BlacklistTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_BlacklistTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._type.toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "BlacklistTransferManager", + "BlacklistTransferManager module was not added" + ); + I_BlacklistTransferManager = BlacklistTransferManager.at(tx.logs[2].args._module); + }); + + }); + + describe("Buy tokens using on-chain whitelist", async() => { + + it("Should Buy the tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + }); + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + + }); + + it("Should Buy some more tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should add the blacklist", async() => { + let tx = await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in adding the type in blacklist"); + }); + + it("Should fail in adding the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to add the blacklist type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the existing blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Blacklist type already exist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should modify the blacklist", async() => { + let tx = await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); + assert.equal(tx.logs[0].args._startDate, latestTime()+2000, "Failed in modifying the startdate of blacklist"); + + }); + + it("Should fail in modifying the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to modify the blacklist type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + + + + }); + +}); From e11df92e20132a7d4b61ae13be177f8b11c172db Mon Sep 17 00:00:00 2001 From: Vikas Panwar Date: Mon, 1 Oct 2018 17:42:29 +0530 Subject: [PATCH 006/582] added test cases for few functionalities of blacklist --- test/b_blacklist_transfer_manager.js | 77 ++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/test/b_blacklist_transfer_manager.js b/test/b_blacklist_transfer_manager.js index db636f9eb..1f5c50228 100644 --- a/test/b_blacklist_transfer_manager.js +++ b/test/b_blacklist_transfer_manager.js @@ -370,6 +370,9 @@ contract('BlacklistTransferManager', accounts => { it("Should add the blacklist", async() => { let tx = await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); + console.log("starttime",latestTime()+2000); + console.log("endtime",latestTime()+3000); + console.log("latest",latestTime()); assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in adding the type in blacklist"); }); @@ -415,7 +418,81 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); + it("Should fail in modifying the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Blacklist type doesnot exist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should add investor to the blacklist", async() => { + let tx = await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor to the blacklist"); + + }); + + it("Should fail in adding the investor to the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to add the investor to the blacklist type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the investor to the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to add the investor to the blacklist type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the investor to the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "b_blacklist", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Trying to add the investor in non existing blacklist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in buying the tokens as the investor in blacklist", async() => { + let errorThrown = false; + // Jump time + await increaseTime(2500); + console.log("latestNew",latestTime()); + try{ + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + } + catch(error){ + console.log(` tx revert -> Trying to send token to the blacklisted address`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + it("Should get the permission", async() => { + let perm = await I_BlacklistTransferManager.getPermissions.call(); + assert.equal(perm.length, 1); + }); }); From 559a88da7585c9ab4e9ce75ba7ccada65764efcc Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Tue, 2 Oct 2018 17:08:04 +0530 Subject: [PATCH 007/582] added test cases and delete functionality --- .node-xmlhttprequest-sync-35460 | 0 .../BlacklistTransferManager.sol | 32 +++++- test/b_blacklist_transfer_manager.js | 97 +++++++++++++++---- 3 files changed, 105 insertions(+), 24 deletions(-) create mode 100644 .node-xmlhttprequest-sync-35460 diff --git a/.node-xmlhttprequest-sync-35460 b/.node-xmlhttprequest-sync-35460 new file mode 100644 index 000000000..e69de29bb diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index e8236fe6e..a17ec43ef 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -53,6 +53,11 @@ contract BlacklistTransferManager is ITransferManager { bytes32 _blacklistName ); + // Emit when investor is deleted from the blacklist type + event DeleteInvestorFromBlacklistType( + address _investor + ); + /** * @notice Constructor * @param _securityToken Address of the security token @@ -76,11 +81,12 @@ contract BlacklistTransferManager is ITransferManager { function verifyTransfer(address _from, address /* _to */, uint256 /* _amount */, bool /* _isTransfer */) public returns(Result) { if(!paused){ if (investorToBlacklist[_from] != bytes32(0)) { - uint256 blacklistDate = (blacklists[investorToBlacklist[_from]].endDate + uint256 blacklistDate = ((blacklists[investorToBlacklist[_from]].endDate) .sub(blacklists[investorToBlacklist[_from]].startDate)) .add(blacklists[investorToBlacklist[_from]].repeatPeriodInDays * 1 days); - uint256 repeater = now.div(blacklistDate); - if (blacklists[investorToBlacklist[_from]].startDate.add(blacklistDate.mul(repeater)) <= now && blacklists[investorToBlacklist[_from]].endDate.add(blacklistDate.mul(repeater)) >= now) { + uint256 repeater = now.div((blacklists[investorToBlacklist[_from]].endDate) + .add(blacklists[investorToBlacklist[_from]].repeatPeriodInDays * 1 days)); + if ((blacklists[investorToBlacklist[_from]].startDate).add(blacklistDate.mul(repeater)) <= now && (blacklists[investorToBlacklist[_from]].endDate).add(blacklistDate.mul(repeater)) >= now) { return Result.INVALID; } return Result.VALID; @@ -131,10 +137,9 @@ contract BlacklistTransferManager is ITransferManager { * @notice Used to delete the blacklist type * @param _name name of the blacklist type */ - /// TODO - Need more Info to understand the how delete operation will work whether it will delete - /// the corresponding addresses or restrict to delete when blacklistType have some addresses associated function deleteBlacklistType(bytes32 _name) public withPerm(ADMIN){ require(blacklists[_name].endDate != 0, "Blacklist type doesn’t exist"); + require(blacklistToAddress[_name].length == 0, "Investors are associated with the blacklist"); delete(blacklists[_name]); emit DeleteBlacklistType(_name); } @@ -147,11 +152,28 @@ contract BlacklistTransferManager is ITransferManager { function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN){ require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); + require(investorToBlacklist[_investor] == bytes32(0), "Investor already associated to blacklist type"); investorToBlacklist[_investor] = _blacklistName; blacklistToAddress[_blacklistName].push(_investor); emit AddInvestorToBlacklist(_investor, _blacklistName); } + /** + * @notice Used to delete the investor from the blacklist type + * @param _investor address of the investor + */ + function deleteInvestorFromBlacklist(address _investor) public withPerm(ADMIN){ + require(_investor != address(0), "Invalid investor address"); + require(investorToBlacklist[_investor] != bytes32(0), "Investor not associated to blacklist type"); + for(uint256 i = 0; i < blacklistToAddress[investorToBlacklist[_investor]].length; i++){ + if(blacklistToAddress[investorToBlacklist[_investor]][i] == _investor){ + delete(blacklistToAddress[investorToBlacklist[_investor]][i]); + } + } + delete(investorToBlacklist[_investor]); + emit DeleteInvestorFromBlacklistType(_investor); + } + /** * @notice Used to assign the blacklist type to the multiple investor * @param _investor address of the investor diff --git a/test/b_blacklist_transfer_manager.js b/test/b_blacklist_transfer_manager.js index 1f5c50228..3a9b6afb6 100644 --- a/test/b_blacklist_transfer_manager.js +++ b/test/b_blacklist_transfer_manager.js @@ -370,9 +370,6 @@ contract('BlacklistTransferManager', accounts => { it("Should add the blacklist", async() => { let tx = await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); - console.log("starttime",latestTime()+2000); - console.log("endtime",latestTime()+3000); - console.log("latest",latestTime()); assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in adding the type in blacklist"); }); @@ -402,7 +399,7 @@ contract('BlacklistTransferManager', accounts => { it("Should modify the blacklist", async() => { let tx = await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); - assert.equal(tx.logs[0].args._startDate, latestTime()+2000, "Failed in modifying the startdate of blacklist"); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in modifying the startdate of blacklist"); }); @@ -439,7 +436,7 @@ contract('BlacklistTransferManager', accounts => { it("Should fail in adding the investor to the blacklist", async() => { let errorThrown = false; try { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: account_investor2 }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "a_blacklist", { from: account_investor1 }); } catch(error) { console.log(` tx revert -> Only owner have the permission to add the investor to the blacklist type`.grey); errorThrown = true; @@ -451,38 +448,100 @@ contract('BlacklistTransferManager', accounts => { it("Should fail in adding the investor to the blacklist", async() => { let errorThrown = false; try { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: account_investor2 }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "b_blacklist", { from: token_owner }); } catch(error) { - console.log(` tx revert -> Only owner have the permission to add the investor to the blacklist type`.grey); + console.log(` tx revert -> Trying to add the investor in non existing blacklist`.grey); errorThrown = true; ensureException(error); } assert.ok(errorThrown, message); }); - it("Should fail in adding the investor to the blacklist", async() => { + it("Should fail in buying the tokens as the investor in blacklist", async() => { + let errorThrown = false; + // Jump time + await increaseTime(1731500); + try{ + // Mint some tokens + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + } + catch(error){ + console.log(` tx revert -> Trying to send token to the blacklisted address`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should delete the blacklist type", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "b_blacklist", "Failed in deleting the blacklist"); + + }); + + it("Should fail in deleting the blacklist type", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); let errorThrown = false; try { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "b_blacklist", { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: account_investor1 }); } catch(error) { - console.log(` tx revert -> Trying to add the investor in non existing blacklist`.grey); + console.log(` tx revert -> Only owner have the permission to delete the blacklist type`.grey); errorThrown = true; ensureException(error); } assert.ok(errorThrown, message); }); - it("Should fail in buying the tokens as the investor in blacklist", async() => { + it("Should fail in deleting the blacklist type", async() => { let errorThrown = false; - // Jump time - await increaseTime(2500); - console.log("latestNew",latestTime()); - try{ - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + try { + let tx = await I_BlacklistTransferManager.deleteBlacklistType("a_blacklist", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Not able to delete the blacklist as blacklist has associated addresses.`.grey); + errorThrown = true; + ensureException(error); } - catch(error){ - console.log(` tx revert -> Trying to send token to the blacklisted address`.grey); + assert.ok(errorThrown, message); + }); + + it("Should fail in deleting the blacklist type", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteBlacklistType("c_blacklist", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Not able to delete the blacklist as blacklist type doesnot exist.`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should delete the investor from the blacklist type", async() => { + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, { from: token_owner }); + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); + + }); + + it("Should fail in deleting the investor from the blacklist type", async() => { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in deleting the investor from the blacklist type", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor2, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Investor is not associated to blacklist`.grey); errorThrown = true; ensureException(error); } From c90229cb395351ea5badf247d580b5a68cc0e926 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Tue, 2 Oct 2018 19:46:28 +0530 Subject: [PATCH 008/582] minor changes in test cases --- .../BlacklistTransferManager.sol | 2 +- .../BlacklistTransferManagerFactory.sol | 2 +- test/b_blacklist_transfer_manager.js | 191 +++++++++++++++++- 3 files changed, 186 insertions(+), 9 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index a17ec43ef..2ff7dadd6 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -202,7 +202,7 @@ contract BlacklistTransferManager is ITransferManager { * @notice get the list of the investors of a blacklist type * @param _blacklistName name of the blacklist type */ - function getListofAddresses(bytes32 _blacklistName) public view returns(address[]) { + function getListOfAddresses(bytes32 _blacklistName) public view returns(address[]) { require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesn't exist"); return blacklistToAddress[_blacklistName]; } diff --git a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol index a4c9e5532..e8399fc39 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol @@ -84,7 +84,7 @@ contract BlacklistTransferManagerFactory is ModuleFactory { * @notice Get the Instructions that helped to used the module */ function getInstructions() public view returns(string) { - return "Allows an issuer to blacklist specific pairs of addresses. Init function takes no parameters."; + return "Allows an issuer to blacklist the addresses."; } /** diff --git a/test/b_blacklist_transfer_manager.js b/test/b_blacklist_transfer_manager.js index 3a9b6afb6..9389fcf9f 100644 --- a/test/b_blacklist_transfer_manager.js +++ b/test/b_blacklist_transfer_manager.js @@ -248,7 +248,7 @@ contract('BlacklistTransferManager', accounts => { it("Should generate the new security token with the same symbol as registered above", async () => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner, gas: 85000000 }); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); @@ -325,8 +325,7 @@ contract('BlacklistTransferManager', accounts => { latestTime() + duration.days(10), true, { - from: account_issuer, - gas: 500000 + from: account_issuer }); assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); @@ -353,8 +352,7 @@ contract('BlacklistTransferManager', accounts => { latestTime() + duration.days(10), true, { - from: account_issuer, - gas: 500000 + from: account_issuer }); assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); @@ -369,10 +367,59 @@ contract('BlacklistTransferManager', accounts => { }); it("Should add the blacklist", async() => { + //Add the new blacklist let tx = await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in adding the type in blacklist"); }); + it("Should fail in adding the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Blacklist type already exist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "", 20, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid blacklist name`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid start or end date`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 0, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid repeat in days`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + it("Should fail in adding the blacklist", async() => { let errorThrown = false; try { @@ -398,11 +445,49 @@ contract('BlacklistTransferManager', accounts => { }) it("Should modify the blacklist", async() => { + //Modify the existing blacklist let tx = await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in modifying the startdate of blacklist"); }); + it("Should fail in modifying the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "", 20, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid blacklist name`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in modifying the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid start or end date`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in modifying the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "b_blacklist", 0, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid repeat in days`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in modifying the blacklist", async() => { let errorThrown = false; try { @@ -428,6 +513,7 @@ contract('BlacklistTransferManager', accounts => { }); it("Should add investor to the blacklist", async() => { + //Add investor to the existing blacklist let tx = await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor to the blacklist"); @@ -445,6 +531,30 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); + it("Should fail in adding the investor to the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addInvestorToBlacklist(0x0, "a_blacklist", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid investor address`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the investor to the blacklist", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Investor already associated to blacklist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + it("Should fail in adding the investor to the blacklist", async() => { let errorThrown = false; try { @@ -457,12 +567,29 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in buying the tokens as the investor in blacklist", async() => { + it("Should get the list of investors associated to blacklist", async() => { + let perm = await I_BlacklistTransferManager.getListOfAddresses.call("a_blacklist"); + assert.equal(perm.length, 1); + }); + + it("Should fail in getting the list of investors associated to blacklist", async() => { + let errorThrown = false; + try{ + let perm = await I_BlacklistTransferManager.getListOfAddresses.call("b_blacklist"); + } + catch(error){ + console.log(` tx revert -> Trying to get the list of investors of non existing blacklist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in transfer the tokens as the investor in blacklist", async() => { let errorThrown = false; // Jump time await increaseTime(1731500); try{ - // Mint some tokens await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); } catch(error){ @@ -473,6 +600,18 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); + it("Should investor be able to transfer token as it is not in blacklist time period", async() => { + // Jump time + await increaseTime(3000); + + //Trasfer tokens + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + it("Should delete the blacklist type", async() => { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); @@ -536,6 +675,18 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); + it("Should fail in deleting the investor from the blacklist type", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(0x0, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid investor address`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + it("Should fail in deleting the investor from the blacklist type", async() => { let errorThrown = false; try { @@ -556,4 +707,30 @@ contract('BlacklistTransferManager', accounts => { }); + describe("Test cases for the factory", async() => { + it("Should get the exact details of the factory", async() => { + assert.equal(await I_BlacklistTransferManagerFactory.setupCost.call(),0); + assert.equal(await I_BlacklistTransferManagerFactory.getType.call(),2); + assert.equal(web3.utils.toAscii(await I_BlacklistTransferManagerFactory.getName.call()) + .replace(/\u0000/g, ''), + "BlacklistTransferManager", + "Wrong Module added"); + assert.equal(await I_BlacklistTransferManagerFactory.getDescription.call(), + "Automate blacklist to restrict selling", + "Wrong Module added"); + assert.equal(await I_BlacklistTransferManagerFactory.getTitle.call(), + "Blacklist Transfer Manager", + "Wrong Module added"); + assert.equal(await I_BlacklistTransferManagerFactory.getInstructions.call(), + "Allows an issuer to blacklist the addresses.", + "Wrong Module added"); + + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_BlacklistTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Blacklist"); + }); + }); + }); From 2e09ae88860297cba930927793fc5e62a43c1915 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Tue, 2 Oct 2018 22:28:34 +0530 Subject: [PATCH 009/582] minor changes in test cases --- ...ger.js => w_blacklist_transfer_manager.js} | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) rename test/{b_blacklist_transfer_manager.js => w_blacklist_transfer_manager.js} (99%) diff --git a/test/b_blacklist_transfer_manager.js b/test/w_blacklist_transfer_manager.js similarity index 99% rename from test/b_blacklist_transfer_manager.js rename to test/w_blacklist_transfer_manager.js index 9389fcf9f..90dd927b2 100644 --- a/test/b_blacklist_transfer_manager.js +++ b/test/w_blacklist_transfer_manager.js @@ -164,24 +164,6 @@ contract('BlacklistTransferManager', accounts => { "CountTransferManagerFactory contract was not deployed" ); - // STEP 8: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the BlacklistTransferManagerFactory - await I_MRProxied.registerModule(I_BlacklistTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_BlacklistTransferManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the Paid BlacklistTransferManagerFactory - await I_MRProxied.registerModule(P_BlacklistTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(P_BlacklistTransferManagerFactory.address, true, { from: account_polymath }); - // Step 9: Deploy the STFactory contract I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); @@ -216,6 +198,23 @@ contract('BlacklistTransferManager', accounts => { await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); await I_MRProxied.updateFromRegistry({from: account_polymath}); + // STEP 8: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the BlacklistTransferManagerFactory + await I_MRProxied.registerModule(I_BlacklistTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_BlacklistTransferManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the Paid BlacklistTransferManagerFactory + await I_MRProxied.registerModule(P_BlacklistTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_BlacklistTransferManagerFactory.address, true, { from: account_polymath }); // Printing all the contract addresses console.log(` From 4ff79eb9af707dac7f7d97c71777533e1f9fe187 Mon Sep 17 00:00:00 2001 From: Vikas Panwar Date: Thu, 4 Oct 2018 18:01:01 +0530 Subject: [PATCH 010/582] added changes of delete investor from blacklist --- .../BlacklistTransferManager.sol | 74 +++++++++----- test/w_blacklist_transfer_manager.js | 96 +++++++++++++++---- 2 files changed, 129 insertions(+), 41 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 2ff7dadd6..9d978b8d8 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -21,7 +21,7 @@ contract BlacklistTransferManager is ITransferManager { mapping(bytes32 => BlacklistsDetails) blacklists; //hold the blacklisted address corresponds to the blacklist type - mapping(address => bytes32) investorToBlacklist; + mapping(address => bytes32[]) investorToBlacklist; //get list of the addresses for a particular blacklist mapping(bytes32 => address[]) blacklistToAddress; @@ -54,8 +54,9 @@ contract BlacklistTransferManager is ITransferManager { ); // Emit when investor is deleted from the blacklist type - event DeleteInvestorFromBlacklistType( - address _investor + event DeleteInvestorFromBlacklist( + address _investor, + bytes32 _blacklist ); /** @@ -80,17 +81,20 @@ contract BlacklistTransferManager is ITransferManager { /// @notice Used to verify the transfer transaction function verifyTransfer(address _from, address /* _to */, uint256 /* _amount */, bool /* _isTransfer */) public returns(Result) { if(!paused){ - if (investorToBlacklist[_from] != bytes32(0)) { - uint256 blacklistDate = ((blacklists[investorToBlacklist[_from]].endDate) - .sub(blacklists[investorToBlacklist[_from]].startDate)) - .add(blacklists[investorToBlacklist[_from]].repeatPeriodInDays * 1 days); - uint256 repeater = now.div((blacklists[investorToBlacklist[_from]].endDate) - .add(blacklists[investorToBlacklist[_from]].repeatPeriodInDays * 1 days)); - if ((blacklists[investorToBlacklist[_from]].startDate).add(blacklistDate.mul(repeater)) <= now && (blacklists[investorToBlacklist[_from]].endDate).add(blacklistDate.mul(repeater)) >= now) { - return Result.INVALID; - } - return Result.VALID; - } + if(investorToBlacklist[_from].length != 0){ + for(uint256 i = 0; i < investorToBlacklist[_from].length; i++){ + uint256 blacklistDate = ((blacklists[investorToBlacklist[_from][i]].endDate) + .sub(blacklists[investorToBlacklist[_from][i]].startDate)) + .add(blacklists[investorToBlacklist[_from][i]].repeatPeriodInDays * 1 days); + uint256 repeater = now.div((blacklists[investorToBlacklist[_from][i]].endDate) + .add(blacklists[investorToBlacklist[_from][i]].repeatPeriodInDays * 1 days)); + if ((blacklists[investorToBlacklist[_from][i]].startDate).add(blacklistDate.mul(repeater)) <= now && (blacklists[investorToBlacklist[_from][i]].endDate).add(blacklistDate.mul(repeater)) >= now) { + return Result.INVALID; + } + return Result.VALID; + } + + } return Result.NA; } return Result.NA; @@ -152,26 +156,46 @@ contract BlacklistTransferManager is ITransferManager { function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN){ require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); - require(investorToBlacklist[_investor] == bytes32(0), "Investor already associated to blacklist type"); - investorToBlacklist[_investor] = _blacklistName; + investorToBlacklist[_investor].push(_blacklistName); blacklistToAddress[_blacklistName].push(_investor); emit AddInvestorToBlacklist(_investor, _blacklistName); } /** - * @notice Used to delete the investor from the blacklist type + * @notice Used to delete the investor from the all associated blacklists + * @param _investor address of the investor + */ + function deleteInvestorFromAllBlacklist(address _investor) public withPerm(ADMIN){ + require(_investor != address(0), "Invalid investor address"); + require(investorToBlacklist[_investor].length != 0, "Investor is not associated to any blacklist type"); + for(uint256 i = 0; i < investorToBlacklist[_investor].length; i++){ + deleteInvestorFromBlacklist(_investor, investorToBlacklist[_investor][i]); + } + } + + /** + * @notice Used to delete the investor from the blacklist * @param _investor address of the investor + * @param _blacklistName name of the blacklist */ - function deleteInvestorFromBlacklist(address _investor) public withPerm(ADMIN){ + function deleteInvestorFromBlacklist(address _investor,bytes32 _blacklistName) public withPerm(ADMIN){ require(_investor != address(0), "Invalid investor address"); - require(investorToBlacklist[_investor] != bytes32(0), "Investor not associated to blacklist type"); - for(uint256 i = 0; i < blacklistToAddress[investorToBlacklist[_investor]].length; i++){ - if(blacklistToAddress[investorToBlacklist[_investor]][i] == _investor){ - delete(blacklistToAddress[investorToBlacklist[_investor]][i]); + require(_blacklistName != bytes32(0),"Invalid blacklist name"); + require(investorToBlacklist[_investor].length != 0, "Investor is not associated to any blacklist type"); + for(uint256 j = 0; j < investorToBlacklist[_investor].length; j++){ + if(investorToBlacklist[_investor][j] == _blacklistName){ + for(uint256 i = 0; i < blacklistToAddress[investorToBlacklist[_investor][j]].length; i++){ + if(blacklistToAddress[investorToBlacklist[_investor][j]][i] == _investor){ + delete(blacklistToAddress[investorToBlacklist[_investor][j]][i]); + break; + } + } + delete(investorToBlacklist[_investor][j]); + emit DeleteInvestorFromBlacklist(_investor, investorToBlacklist[_investor][j]); + break; } + } - delete(investorToBlacklist[_investor]); - emit DeleteInvestorFromBlacklistType(_investor); } /** @@ -193,7 +217,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _repeatPeriodInDays repeat period of the blacklist type * @param _investor address of the investor */ - function addInvestorToNewBlacklist(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays,address _investor) public withPerm(ADMIN){ + function addInvestorToNewBlacklist(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays, address _investor) public withPerm(ADMIN){ addBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); addInvestorToBlacklist(_investor, _name); } diff --git a/test/w_blacklist_transfer_manager.js b/test/w_blacklist_transfer_manager.js index 90dd927b2..375fbeb9f 100644 --- a/test/w_blacklist_transfer_manager.js +++ b/test/w_blacklist_transfer_manager.js @@ -33,6 +33,7 @@ contract('BlacklistTransferManager', accounts => { let account_investor2; let account_investor3; let account_investor4; + let account_investor5; // investor Details let fromTime = latestTime(); @@ -94,6 +95,8 @@ contract('BlacklistTransferManager', accounts => { account_investor1 = accounts[7]; account_investor2 = accounts[8]; account_investor3 = accounts[9]; + account_investor4 = accounts[5]; + account_investor5 = accounts[6]; // ----------- POLYMATH NETWORK Configuration ------------ @@ -542,17 +545,6 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in adding the investor to the blacklist", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Investor already associated to blacklist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); it("Should fail in adding the investor to the blacklist", async() => { let errorThrown = false; @@ -655,8 +647,10 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should delete the investor from the blacklist type", async() => { - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, { from: token_owner }); + it("Should delete the investor from all the associated blacklist", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "g_blacklist", 20, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "g_blacklist", { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: token_owner }); assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); }); @@ -665,7 +659,7 @@ contract('BlacklistTransferManager', accounts => { await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); let errorThrown = false; try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, { from: account_investor2 }); + let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: account_investor2 }); } catch(error) { console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); errorThrown = true; @@ -677,7 +671,7 @@ contract('BlacklistTransferManager', accounts => { it("Should fail in deleting the investor from the blacklist type", async() => { let errorThrown = false; try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(0x0, { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(0x0, { from: token_owner }); } catch(error) { console.log(` tx revert -> Invalid investor address`.grey); errorThrown = true; @@ -689,7 +683,7 @@ contract('BlacklistTransferManager', accounts => { it("Should fail in deleting the investor from the blacklist type", async() => { let errorThrown = false; try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor2, { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor2, { from: token_owner }); } catch(error) { console.log(` tx revert -> Investor is not associated to blacklist`.grey); errorThrown = true; @@ -698,6 +692,76 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); + it("Should delete the investor from the blacklist type", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); + + }); + + it("Should fail in deleting the investor from the blacklist type", async() => { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should add investor and new blacklist type", async() => { + let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: token_owner }); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "c_blacklist", "Failed in adding the blacklist"); + assert.equal(tx.logs[1].args._investor, account_investor3, "Failed in adding the investor to blacklist"); + + }); + + it("Should fail in adding the investor and new blacklist type", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to add the investor to blacklist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should add mutiple investor to blacklist", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "d_blacklist", 20, { from: token_owner }); + let investor = [account_investor4,account_investor5]; + let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "d_blacklist", { from: token_owner }); + + let event_data = tx.logs; + for (var i = 0; i < event_data.length; i++) { + let user = event_data[i].args._investor; + assert.equal(user, investor[i], "Failed in adding the investor to blacklist"); + } + + }); + + it("Should fail in adding the mutiple investor to the blacklist", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "b_blacklist", { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to add the investors to blacklist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should get the init function", async() => { + let byte = await I_BlacklistTransferManager.getInitFunction.call(); + assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); + }); + it("Should get the permission", async() => { let perm = await I_BlacklistTransferManager.getPermissions.call(); assert.equal(perm.length, 1); From 4f2aba3f5fcb98fc4cb6f30ad23bfc5cb3b767f7 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Sun, 7 Oct 2018 12:09:10 +0530 Subject: [PATCH 011/582] added minor changes --- .../BlacklistTransferManager.sol | 145 +- .../BlacklistTransferManagerFactory.sol | 13 +- test/a_poly_oracle.js | 698 +- test/b_capped_sto.js | 2698 +++---- test/c_checkpoints.js | 858 +- test/d_count_transfer_manager.js | 1010 +-- test/e_erc20_dividends.js | 1926 ++--- test/f_ether_dividends.js | 1966 ++--- test/g_general_permission_manager.js | 944 +-- test/h_general_transfer_manager.js | 1724 ++-- test/i_Issuance.js | 832 +- test/j_manual_approval_transfer_manager.js | 1420 ++-- test/k_module_registry.js | 1368 ++-- test/l_percentage_transfer_manager.js | 1010 +-- test/m_presale_sto.js | 954 +-- test/n_security_token_registry.js | 2486 +++--- test/o_security_token.js | 2810 +++---- test/p_usd_tiered_sto.js | 7034 ++++++++--------- test/q_usd_tiered_sto_sim.js | 1550 ++-- test/r_concurrent_STO.js | 726 +- test/s_v130_to_v140_upgrade.js | 1064 +-- test/t_security_token_registry_proxy.js | 696 +- test/u_module_registry_proxy.js | 678 +- test/v_tracked_redemptions.js | 758 +- test/w_volume_restriction_transfer_manager.js | 2082 ++--- test/x_single_trade_volume_restriction.js | 2356 +++--- ...ger.js => y_blacklist_transfer_manager.js} | 10 +- 27 files changed, 19918 insertions(+), 19898 deletions(-) rename test/{w_blacklist_transfer_manager.js => y_blacklist_transfer_manager.js} (98%) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 9d978b8d8..e72127d0a 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -12,9 +12,9 @@ contract BlacklistTransferManager is ITransferManager { bytes32 public constant ADMIN = "ADMIN"; struct BlacklistsDetails { - uint256 startDate; - uint256 endDate; - uint256 repeatPeriodInDays; + uint256 startTime; + uint256 endTime; + uint256 repeatPeriodTime; } //hold the different blacklist corresponds to name of blacklist type @@ -24,22 +24,28 @@ contract BlacklistTransferManager is ITransferManager { mapping(address => bytes32[]) investorToBlacklist; //get list of the addresses for a particular blacklist - mapping(bytes32 => address[]) blacklistToAddress; + mapping(bytes32 => address[]) blacklistToInvestor; + + //store the index of the investor to blacklist + mapping(address => mapping(bytes32 => uint256)) investorBlacklist; + + //store the index of the blacklist to investor + mapping(bytes32 => mapping(address => uint256)) blacklistInvestor; // Emit when new blacklist type is added event AddBlacklistType( - uint256 _startDate, - uint256 _endDate, + uint256 _startTime, + uint256 _endTime, bytes32 _name, - uint256 _repeatPeriodInDays + uint256 _repeatPeriodTime ); // Emit when there is change in the blacklist type event ModifyBlacklistType( - uint256 _startDate, - uint256 _endDate, + uint256 _startTime, + uint256 _endTime, bytes32 _name, - uint256 _repeatPeriodInDays + uint256 _repeatPeriodTime ); // Emit when the added blacklist type is deleted @@ -78,20 +84,33 @@ contract BlacklistTransferManager is ITransferManager { } - /// @notice Used to verify the transfer transaction - function verifyTransfer(address _from, address /* _to */, uint256 /* _amount */, bool /* _isTransfer */) public returns(Result) { + /** @notice Used to verify the transfer transaction + * @param _from Address of the sender + * @dev Restrict the blacklist address to transfer token + * if the current time is in the time frame define for the + * blacklist type associated with the blacklist address + */ + function verifyTransfer(address _from, address /* _to */, uint256 /* _amount */, bytes /* _data */, bool /* _isTransfer */) public returns(Result) { if(!paused){ if(investorToBlacklist[_from].length != 0){ for(uint256 i = 0; i < investorToBlacklist[_from].length; i++){ - uint256 blacklistDate = ((blacklists[investorToBlacklist[_from][i]].endDate) - .sub(blacklists[investorToBlacklist[_from][i]].startDate)) - .add(blacklists[investorToBlacklist[_from][i]].repeatPeriodInDays * 1 days); - uint256 repeater = now.div((blacklists[investorToBlacklist[_from][i]].endDate) - .add(blacklists[investorToBlacklist[_from][i]].repeatPeriodInDays * 1 days)); - if ((blacklists[investorToBlacklist[_from][i]].startDate).add(blacklistDate.mul(repeater)) <= now && (blacklists[investorToBlacklist[_from][i]].endDate).add(blacklistDate.mul(repeater)) >= now) { - return Result.INVALID; + if(investorToBlacklist[_from][i] != bytes32(0)){ + uint256 endTime = blacklists[investorToBlacklist[_from][i]].endTime; + uint256 startTime = blacklists[investorToBlacklist[_from][i]].startTime; + uint256 repeatPeriodTime = blacklists[investorToBlacklist[_from][i]].repeatPeriodTime * 1 days; + // blacklistTime time is used to find the new startTime and endTime + // suppose startTime=500,endTime=1500,repeatPeriodTime=500 then blacklistTime =1500 + // if you add blacklistTime to startTime and endTime i.e startTime = 2000 and endTime = 3000 + uint256 blacklistTime = (endTime.sub(startTime)).add(repeatPeriodTime); + // Find the repeating parameter that will be used to calculate the new startTime and endTime + // based on the new now value + uint256 repeater = now.div(endTime.add(repeatPeriodTime)); + if (startTime.add(blacklistTime.mul(repeater)) <= now && endTime.add(blacklistTime.mul(repeater)) >= now) { + return Result.INVALID; + } + return Result.NA; } - return Result.VALID; + return Result.NA; } } @@ -102,39 +121,39 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Used to add the blacklist type - * @param _startDate start date of the blacklist type - * @param _endDate end date of the blacklist type + * @param _startTime start date of the blacklist type + * @param _endTime end date of the blacklist type * @param _name name of the blacklist type - * @param _repeatPeriodInDays repeat period of the blacklist type + * @param _repeatPeriodTime repeat period of the blacklist type */ - function addBlacklistType(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) public withPerm(ADMIN){ - require(blacklists[_name].endDate == 0, "Blacklist type already exist"); - _validParams(_startDate, _endDate, _name, _repeatPeriodInDays); - blacklists[_name] = BlacklistsDetails(_startDate, _endDate, _repeatPeriodInDays); - emit AddBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); + function addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) public withPerm(ADMIN){ + require(blacklists[_name].endTime == 0, "Blacklist type already exist"); + _validParams(_startTime, _endTime, _name, _repeatPeriodTime); + blacklists[_name] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); + emit AddBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); } /** * @notice Internal function */ - function _validParams(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) internal view { + function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) internal view { require(_name != bytes32(0), "Invalid blacklist name"); - require(_startDate > now && _startDate < _endDate, "Invalid start or end date"); - require(_repeatPeriodInDays != 0, "Invalid repeat days"); + require(_startTime > now && _startTime < _endTime, "Invalid start or end date"); + require(_repeatPeriodTime != 0, "Invalid repeat days"); } /** * @notice Used to edit the blacklist type - * @param _startDate start date of the blacklist type - * @param _endDate end date of the blacklist type + * @param _startTime start date of the blacklist type + * @param _endTime end date of the blacklist type * @param _name name of the blacklist type - * @param _repeatPeriodInDays repeat period of the blacklist type + * @param _repeatPeriodTime repeat period of the blacklist type */ - function modifyBlacklistType(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays) public withPerm(ADMIN){ - require(blacklists[_name].endDate != 0, "Blacklist type doesn't exist"); - _validParams(_startDate, _endDate, _name, _repeatPeriodInDays); - blacklists[_name] = BlacklistsDetails(_startDate, _endDate, _repeatPeriodInDays); - emit ModifyBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); + function modifyBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) public withPerm(ADMIN){ + require(blacklists[_name].endTime != 0, "Blacklist type doesn't exist"); + _validParams(_startTime, _endTime, _name, _repeatPeriodTime); + blacklists[_name] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); + emit ModifyBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); } /** @@ -142,8 +161,8 @@ contract BlacklistTransferManager is ITransferManager { * @param _name name of the blacklist type */ function deleteBlacklistType(bytes32 _name) public withPerm(ADMIN){ - require(blacklists[_name].endDate != 0, "Blacklist type doesn’t exist"); - require(blacklistToAddress[_name].length == 0, "Investors are associated with the blacklist"); + require(blacklists[_name].endTime != 0, "Blacklist type doesn’t exist"); + require(blacklistToInvestor[_name].length == 0, "Investors are associated with the blacklist"); delete(blacklists[_name]); emit DeleteBlacklistType(_name); } @@ -154,10 +173,14 @@ contract BlacklistTransferManager is ITransferManager { * @param _blacklistName name of the blacklist */ function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN){ - require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesn't exist"); + require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); + uint256 investorIndex = investorToBlacklist[_investor].length; + investorBlacklist[_investor][_blacklistName] = investorIndex; + uint256 blacklistIndex = blacklistToInvestor[_blacklistName].length; + blacklistInvestor[_blacklistName][_investor] = blacklistIndex; investorToBlacklist[_investor].push(_blacklistName); - blacklistToAddress[_blacklistName].push(_investor); + blacklistToInvestor[_blacklistName].push(_investor); emit AddInvestorToBlacklist(_investor, _blacklistName); } @@ -181,21 +204,12 @@ contract BlacklistTransferManager is ITransferManager { function deleteInvestorFromBlacklist(address _investor,bytes32 _blacklistName) public withPerm(ADMIN){ require(_investor != address(0), "Invalid investor address"); require(_blacklistName != bytes32(0),"Invalid blacklist name"); - require(investorToBlacklist[_investor].length != 0, "Investor is not associated to any blacklist type"); - for(uint256 j = 0; j < investorToBlacklist[_investor].length; j++){ - if(investorToBlacklist[_investor][j] == _blacklistName){ - for(uint256 i = 0; i < blacklistToAddress[investorToBlacklist[_investor][j]].length; i++){ - if(blacklistToAddress[investorToBlacklist[_investor][j]][i] == _investor){ - delete(blacklistToAddress[investorToBlacklist[_investor][j]][i]); - break; - } - } - delete(investorToBlacklist[_investor][j]); - emit DeleteInvestorFromBlacklist(_investor, investorToBlacklist[_investor][j]); - break; - } - - } + require(investorToBlacklist[_investor][investorBlacklist[_investor][_blacklistName]] != bytes32(0), "Investor is not associated to blacklist type"); + delete(blacklistToInvestor[_blacklistName][blacklistInvestor[_blacklistName][_investor]]); + delete(blacklistInvestor[_blacklistName][_investor]); + delete(investorToBlacklist[_investor][investorBlacklist[_investor][_blacklistName]]); + delete(investorBlacklist[_investor][_blacklistName]); + emit DeleteInvestorFromBlacklist(_investor, investorToBlacklist[_investor][investorBlacklist[_investor][_blacklistName]]); } /** @@ -211,14 +225,14 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Used to assign the new blacklist type to the investor - * @param _startDate start date of the blacklist type - * @param _endDate end date of the blacklist type + * @param _startTime start date of the blacklist type + * @param _endTime end date of the blacklist type * @param _name name of the blacklist type - * @param _repeatPeriodInDays repeat period of the blacklist type + * @param _repeatPeriodTime repeat period of the blacklist type * @param _investor address of the investor */ - function addInvestorToNewBlacklist(uint256 _startDate, uint256 _endDate, bytes32 _name, uint256 _repeatPeriodInDays, address _investor) public withPerm(ADMIN){ - addBlacklistType(_startDate, _endDate, _name, _repeatPeriodInDays); + function addInvestorToNewBlacklist(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime, address _investor) public withPerm(ADMIN){ + addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); addInvestorToBlacklist(_investor, _name); } @@ -227,8 +241,9 @@ contract BlacklistTransferManager is ITransferManager { * @param _blacklistName name of the blacklist type */ function getListOfAddresses(bytes32 _blacklistName) public view returns(address[]) { - require(blacklists[_blacklistName].endDate != 0, "Blacklist type doesn't exist"); - return blacklistToAddress[_blacklistName]; + require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); + require(blacklistToInvestor[_blacklistName].length != 0, "Blacklist doesnot have any associated address"); + return blacklistToInvestor[_blacklistName]; } /** diff --git a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol index e8399fc39..6a8f463a2 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol @@ -2,6 +2,7 @@ pragma solidity ^0.4.24; import "./BlacklistTransferManager.sol"; import "../ModuleFactory.sol"; +import "../../libraries/Util.sol"; /** * @title Factory for deploying BlacklistManager module @@ -30,10 +31,12 @@ contract BlacklistTransferManagerFactory is ModuleFactory { * @notice used to launch the Module with the help of factory * @return address Contract address of the Module */ - function deploy(bytes /* _data */) external returns(address) { + function deploy(bytes _data) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - address blacklistTransferManager = new BlacklistTransferManager(msg.sender, address(polyToken)); + BlacklistTransferManager blacklistTransferManager = new BlacklistTransferManager(msg.sender, address(polyToken)); + require(Util.getSig(_data) == blacklistTransferManager.getInitFunction(), "Provided data is not valid"); + require(address(blacklistTransferManager).call(_data), "Un-successfull call"); emit GenerateModuleFromFactory(address(blacklistTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(blacklistTransferManager); } @@ -41,8 +44,10 @@ contract BlacklistTransferManagerFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 2; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 2; + return res; } /** diff --git a/test/a_poly_oracle.js b/test/a_poly_oracle.js index f727b4014..3f84b814d 100644 --- a/test/a_poly_oracle.js +++ b/test/a_poly_oracle.js @@ -1,349 +1,349 @@ -const PolyOracle = artifacts.require('./MockPolyOracle.sol'); -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import {increaseTime} from './helpers/time'; - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('PolyOracle', accounts=> { - -let I_PolyOracle; -let owner; -const URL = '[URL] json(https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?id=2496&convert=USD&CMC_PRO_API_KEY=${[decrypt] BBObnGOy63qVI3OR2+MX88dzSMVjQboiZc7Wluuh2ngkSgiX1csxWgbAFtu22jbrry42zwCS4IUmer1Wk+1o1XhF7hyspoGCkbufQqYwuUYwcA2slX6RbEDai7NgdkgNGWSwd6DcuN8jD5ZMTkX68rJKkplr}).data."2496".quote.USD.price'; -const alternateURL = "json(https://min-api.cryptocompare.com/data/price?fsym=POLY&tsyms=USD).USD"; -const SanityBounds = 20*10**16; -const GasLimit = 100000; -const TimeTolerance = 5*60; -const message = "Txn should fail"; -let latestPrice; -let requestIds = new Array(); - - before(async()=> { - owner = accounts[0]; - I_PolyOracle = await PolyOracle.new({from : owner}); - }); - - - describe("state variables checks", async() => { - - it("should set and check the api url", async() => { - await I_PolyOracle.setOracleURL(URL, {from: owner}); - let url = await I_PolyOracle.oracleURL.call(); - assert.equal(URL, url); - }); - - it("should check the sanity bounds", async() => { - let sanityBounds = await I_PolyOracle.sanityBounds.call(); - assert.equal(SanityBounds, sanityBounds); - }); - - it("should check the gas limits", async() => { - let gasLimit = await I_PolyOracle.gasLimit.call(); - assert.equal(GasLimit, gasLimit); - }); - - it("should check the oraclize time tolerance", async() => { - let timeTolerance = await I_PolyOracle.oraclizeTimeTolerance.call(); - assert.equal(TimeTolerance, timeTolerance); - }); - - }) - - describe("Scheduling test cases", async() => { - - it("Should schedule the timing of the call - fails - non owner", async() => { - let errorThrown = false; - let timeScheduling = [latestTime()+duration.minutes(1), latestTime()+duration.minutes(2), latestTime()+duration.minutes(3)] - try { - await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: accounts[1], value: web3.utils.toWei("2")}); - } catch(error) { - errorThrown = true; - ensureException(error); - console.log(` tx -> revert msg.sender should be the owner of the contract`.grey); - } - assert.ok(errorThrown, message); - }); - - it("Should schedule the timing of the call - fails - no value", async() => { - let errorThrown = false; - let timeScheduling = [latestTime()+duration.minutes(1), latestTime()+duration.minutes(2), latestTime()+duration.minutes(3)] - try { - await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner}); - } catch(error) { - errorThrown = true; - ensureException(error); - console.log(` tx -> revert Because value for txn is not provided`.grey); - } - assert.ok(errorThrown, message); - }) - - it("Should schedule the timing of the call - single call", async() => { - let blockNo = latestBlock(); - let tx = await I_PolyOracle.schedulePriceUpdatesFixed([],{from: owner, value:web3.utils.toWei("1")}); - assert.isAtMost(tx.logs[0].args._time.toNumber(), latestTime()); - // await increaseTime(50); - const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 1); - // const log = await logNewPriceWatcher; - assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') - assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') - assert.equal(logNewPriceWatcher.args._oldPrice.toNumber(), 0); - console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY') - - }); - - it("Should schedule the timing of the call - multiple calls", async() => { - let blockNo = latestBlock(); - let timeScheduling = [latestTime()+duration.seconds(10), latestTime()+duration.seconds(20)] - let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner, value:web3.utils.toWei("1.5")}); - - let event_data = tx.logs; - - for (var i = 0; i < event_data.length; i++) { - let time = event_data[i].args._time; - console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); - assert.isAtMost(time.toNumber(), timeScheduling[i]); - } - - // Wait for the callback to be invoked by oraclize and the event to be emitted - const logNewPriceWatcher = promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); - const log = await logNewPriceWatcher; - assert.equal(log.event, 'PriceUpdated', 'PriceUpdated not emitted.') - assert.isNotNull(log.args._price, 'Price returned was null.'); - console.log('Success! Current price is: ' + log.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY') - }); - - it("Should schedule to call using iters - fails", async() => { - let errorThrown = false; - try { - await I_PolyOracle.schedulePriceUpdatesRolling(latestTime() + 10, 30, 2, {from: accounts[6]}); - } catch(error) { - errorThrown = true; - console.log(` tx->revert msg.sender is not the owner`.grey); - } - assert.ok(errorThrown, message); - }) - - it("Should schedule to call using iters", async() => { - let blockNo = latestBlock(); - console.log(`Latest Block number of the local chain:${blockNo}`); - let tx = await I_PolyOracle.schedulePriceUpdatesRolling(latestTime()+10, 10, 2, {from: owner}); - let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let time = event_data[i].args._time; - requestIds.push(event_data[i].args._queryId); - console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); - assert.isAtMost(time.toNumber(), latestTime() + ((i + 1) * 30)); - } - // Wait for the callback to be invoked by oraclize and the event to be emitted - const logNewPriceWatcher = promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); - const log = await logNewPriceWatcher; - assert.equal(log.event, 'PriceUpdated', 'PriceUpdated not emitted.') - assert.isNotNull(log.args._price, 'Price returned was null.') - console.log('Success! Current price is: ' + log.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); - latestPrice = log.args._price; - }); - }) - - describe("Ownable functions", async() => { - - it("Should change the Poly USD price manually - fail - bad account", async() => { - let errorThrown = false; - try { - await I_PolyOracle.setPOLYUSD(latestPrice.add(1), {from: accounts[5]}); - } catch(error) { - errorThrown = true; - console.log(` tx->revert msg.sender is not the owner`.grey); - } - assert.ok(errorThrown, message); - }); - - it("Should change the Poly USD price manually", async() => { - await I_PolyOracle.setPOLYUSD(latestPrice.add(1), {from: owner}); - let price2 = await I_PolyOracle.getPriceAndTime.call(); - assert.equal(price2[0].toNumber(), latestPrice.add(1).toNumber()); - }) - - it("Should freeze the Oracle manually", async() => { - let errorThrown = false; - try { - await I_PolyOracle.setFreezeOracle(true, {from: accounts[5]}); - } catch(error) { - errorThrown = true; - console.log(` tx->revert msg.sender is not the owner`.grey); - } - assert.ok(errorThrown, message); - }) - - it("Should change the URL manually", async() => { - let freeze_ = await I_PolyOracle.freezeOracle.call(); - await I_PolyOracle.setFreezeOracle(true, {from: owner}); - let freeze = await I_PolyOracle.freezeOracle.call(); - assert.isFalse(freeze_); - assert.isTrue(freeze); - await I_PolyOracle.setFreezeOracle(false, {from: owner}); - }) - - it("Should change the sanity bounds manually - fails - bad owner", async() => { - let errorThrown = false; - try { - await I_PolyOracle.setSanityBounds(new BigNumber(25).times(new BigNumber(10).pow(16)), {from : accounts[6]}); - } catch(error) { - errorThrown = true; - console.log(` tx->revert msg.sender is not the owner`.grey); - } - assert.ok(errorThrown, message); - }) - - it("Should change the sanity bounds manually", async() => { - console.log(JSON.stringify(await I_PolyOracle.sanityBounds.call())); - await I_PolyOracle.setSanityBounds(new BigNumber(25).times(new BigNumber(10).pow(16)), {from : owner}); - let sanityBounds = await I_PolyOracle.sanityBounds.call(); - console.log(JSON.stringify(await I_PolyOracle.sanityBounds.call())); - assert.equal(sanityBounds.toNumber(), new BigNumber(25).times(new BigNumber(10).pow(16)).toNumber()) - }); - - it("Should change the gas price manually - fails - bad owner", async() => { - let errorThrown = false; - try{ - await I_PolyOracle.setGasPrice(new BigNumber(60).times(new BigNumber(10).pow(9)),{from : accounts[6]}); - } catch(error){ - errorThrown = true; - console.log(` tx->revert msg.sender is not the owner`.grey); - } - assert.ok(errorThrown, message); - }); - - it("Should change the gas price manually", async() => { - await I_PolyOracle.setGasPrice(new BigNumber(60).times(new BigNumber(10).pow(9)),{from : owner}); - let blockNo = latestBlock(); - let timeScheduling = [latestTime()+duration.seconds(10), latestTime()+duration.seconds(20)]; - let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner, value:web3.utils.toWei("2")}); - - let event_data = tx.logs; - - for (var i = 0; i < event_data.length; i++) { - let time = event_data[i].args._time; - console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); - assert.isAtMost(time.toNumber(), timeScheduling[i]); - } - - const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); - - assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') - assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') - console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); - // assert.isTrue(false); - - }); - - it("Should change the gas limit manually - fails", async() => { - let errorThrown = false; - try{ - await I_PolyOracle.setGasLimit(50000,{from : accounts[6]}); - } catch(error){ - errorThrown = true; - console.log(` tx->revert msg.sender is not owner`.grey); - } - assert.ok(errorThrown, message); - }); - - it("Should change the gas limit manually", async() => { - await I_PolyOracle.setGasLimit(50000,{from : owner}); - let gasLimit = await I_PolyOracle.gasLimit.call(); - assert.equal(gasLimit.toNumber(),50000); - await I_PolyOracle.setGasLimit(100000,{from : owner}); - }); - - it("Should blacklist some IDS manually - fails - wrong size", async() => { - let errorThrown = false; - let ignore = [true]; - try{ - await I_PolyOracle.setIgnoreRequestIds(requestIds,ignore,{from : accounts[6]}); - } catch(error){ - errorThrown = true; - console.log(` tx->revert msg.sender is not owner`.grey); - } - }); - - it("Should blacklist some IDS manually", async() => { - let ignore = [false, true]; - console.log(requestIds); - await I_PolyOracle.setIgnoreRequestIds(requestIds, ignore, {from : owner}); - - // let ignoreRequestId0 = await I_PolyOracle.ignoreRequestIds.call(requestIds[1]); - // assert.equal(ignoreRequestId0,true); - - // let ignoreRequestId1 = await I_PolyOracle.ignoreRequestIds.call(requestIds[2]); - // assert.equal(ignoreRequestId1,false); - - }); - - it("Should change the oraclize time tolerance manually - fails", async() => { - let errorThrown = false; - try{ - await I_PolyOracle.setOraclizeTimeTolerance(3600,{from : accounts[6]}); - } catch(error){ - errorThrown = true; - console.log(` tx->revert msg.sender is not the owner`.grey); - } - assert.ok(errorThrown, message); - }) - - it("Should change the oraclize time tolerance manually", async() => { - await I_PolyOracle.setOraclizeTimeTolerance(3600,{from : owner}); - let oraclizeTimeTolerance = await I_PolyOracle.oraclizeTimeTolerance.call(); - assert.equal(oraclizeTimeTolerance.toNumber(),3600); - }); - - it("should change the api URL manually", async() => { - let errorThrown = false; - try { - await I_PolyOracle.setOracleURL(alternateURL, {from: accounts[6]}); - } catch(error){ - errorThrown = true; - console.log(` tx->revert msg.sender is not the owner`.grey); - } - assert.ok(errorThrown, message); - }) - - it("should change the api URL manually", async() => { - await I_PolyOracle.setOracleURL(alternateURL, {from: owner}); - await I_PolyOracle.setOracleQueryType("URL", {from: owner}); - let url = await I_PolyOracle.oracleURL.call(); - assert.equal(alternateURL, url); - }); - - it("Should schedule the timing of the call - after changes", async() => { - let blockNo = latestBlock(); - let tx = await I_PolyOracle.schedulePriceUpdatesFixed([],{from: owner, value:web3.utils.toWei("1")}); - assert.isAtMost(tx.logs[0].args._time.toNumber(), latestTime()); - const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 1); - assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') - assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') - console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); - // assert.isTrue(false); - }); - - }) - - describe("Get Functions call", async() => { - it("Should get the currency address", async() => { - let polyTokenAddress = await I_PolyOracle.getCurrencyAddress.call(); - assert.equal(polyTokenAddress, ("0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC").toLowerCase()); - }); - - it("Should get the currency symbol", async() => { - let currency = await I_PolyOracle.getCurrencySymbol.call(); - assert.equal(web3.utils.toAscii(currency).replace(/\u0000/g, ''), "POLY"); - }); - - it("Should get the currency denomination", async() => { - let denomination = await I_PolyOracle.getCurrencyDenominated.call(); - assert.equal(web3.utils.toAscii(denomination).replace(/\u0000/g, ''), "USD"); - }) - - }) - -}) +// const PolyOracle = artifacts.require('./MockPolyOracle.sol'); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import {increaseTime} from './helpers/time'; + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('PolyOracle', accounts=> { + +// let I_PolyOracle; +// let owner; +// const URL = '[URL] json(https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?id=2496&convert=USD&CMC_PRO_API_KEY=${[decrypt] BBObnGOy63qVI3OR2+MX88dzSMVjQboiZc7Wluuh2ngkSgiX1csxWgbAFtu22jbrry42zwCS4IUmer1Wk+1o1XhF7hyspoGCkbufQqYwuUYwcA2slX6RbEDai7NgdkgNGWSwd6DcuN8jD5ZMTkX68rJKkplr}).data."2496".quote.USD.price'; +// const alternateURL = "json(https://min-api.cryptocompare.com/data/price?fsym=POLY&tsyms=USD).USD"; +// const SanityBounds = 20*10**16; +// const GasLimit = 100000; +// const TimeTolerance = 5*60; +// const message = "Txn should fail"; +// let latestPrice; +// let requestIds = new Array(); + +// before(async()=> { +// owner = accounts[0]; +// I_PolyOracle = await PolyOracle.new({from : owner}); +// }); + + +// describe("state variables checks", async() => { + +// it("should set and check the api url", async() => { +// await I_PolyOracle.setOracleURL(URL, {from: owner}); +// let url = await I_PolyOracle.oracleURL.call(); +// assert.equal(URL, url); +// }); + +// it("should check the sanity bounds", async() => { +// let sanityBounds = await I_PolyOracle.sanityBounds.call(); +// assert.equal(SanityBounds, sanityBounds); +// }); + +// it("should check the gas limits", async() => { +// let gasLimit = await I_PolyOracle.gasLimit.call(); +// assert.equal(GasLimit, gasLimit); +// }); + +// it("should check the oraclize time tolerance", async() => { +// let timeTolerance = await I_PolyOracle.oraclizeTimeTolerance.call(); +// assert.equal(TimeTolerance, timeTolerance); +// }); + +// }) + +// describe("Scheduling test cases", async() => { + +// it("Should schedule the timing of the call - fails - non owner", async() => { +// let errorThrown = false; +// let timeScheduling = [latestTime()+duration.minutes(1), latestTime()+duration.minutes(2), latestTime()+duration.minutes(3)] +// try { +// await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: accounts[1], value: web3.utils.toWei("2")}); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// console.log(` tx -> revert msg.sender should be the owner of the contract`.grey); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should schedule the timing of the call - fails - no value", async() => { +// let errorThrown = false; +// let timeScheduling = [latestTime()+duration.minutes(1), latestTime()+duration.minutes(2), latestTime()+duration.minutes(3)] +// try { +// await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner}); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// console.log(` tx -> revert Because value for txn is not provided`.grey); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should schedule the timing of the call - single call", async() => { +// let blockNo = latestBlock(); +// let tx = await I_PolyOracle.schedulePriceUpdatesFixed([],{from: owner, value:web3.utils.toWei("1")}); +// assert.isAtMost(tx.logs[0].args._time.toNumber(), latestTime()); +// // await increaseTime(50); +// const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 1); +// // const log = await logNewPriceWatcher; +// assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') +// assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') +// assert.equal(logNewPriceWatcher.args._oldPrice.toNumber(), 0); +// console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY') + +// }); + +// it("Should schedule the timing of the call - multiple calls", async() => { +// let blockNo = latestBlock(); +// let timeScheduling = [latestTime()+duration.seconds(10), latestTime()+duration.seconds(20)] +// let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner, value:web3.utils.toWei("1.5")}); + +// let event_data = tx.logs; + +// for (var i = 0; i < event_data.length; i++) { +// let time = event_data[i].args._time; +// console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); +// assert.isAtMost(time.toNumber(), timeScheduling[i]); +// } + +// // Wait for the callback to be invoked by oraclize and the event to be emitted +// const logNewPriceWatcher = promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); +// const log = await logNewPriceWatcher; +// assert.equal(log.event, 'PriceUpdated', 'PriceUpdated not emitted.') +// assert.isNotNull(log.args._price, 'Price returned was null.'); +// console.log('Success! Current price is: ' + log.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY') +// }); + +// it("Should schedule to call using iters - fails", async() => { +// let errorThrown = false; +// try { +// await I_PolyOracle.schedulePriceUpdatesRolling(latestTime() + 10, 30, 2, {from: accounts[6]}); +// } catch(error) { +// errorThrown = true; +// console.log(` tx->revert msg.sender is not the owner`.grey); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should schedule to call using iters", async() => { +// let blockNo = latestBlock(); +// console.log(`Latest Block number of the local chain:${blockNo}`); +// let tx = await I_PolyOracle.schedulePriceUpdatesRolling(latestTime()+10, 10, 2, {from: owner}); +// let event_data = tx.logs; +// for (var i = 0; i < event_data.length; i++) { +// let time = event_data[i].args._time; +// requestIds.push(event_data[i].args._queryId); +// console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); +// assert.isAtMost(time.toNumber(), latestTime() + ((i + 1) * 30)); +// } +// // Wait for the callback to be invoked by oraclize and the event to be emitted +// const logNewPriceWatcher = promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); +// const log = await logNewPriceWatcher; +// assert.equal(log.event, 'PriceUpdated', 'PriceUpdated not emitted.') +// assert.isNotNull(log.args._price, 'Price returned was null.') +// console.log('Success! Current price is: ' + log.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); +// latestPrice = log.args._price; +// }); +// }) + +// describe("Ownable functions", async() => { + +// it("Should change the Poly USD price manually - fail - bad account", async() => { +// let errorThrown = false; +// try { +// await I_PolyOracle.setPOLYUSD(latestPrice.add(1), {from: accounts[5]}); +// } catch(error) { +// errorThrown = true; +// console.log(` tx->revert msg.sender is not the owner`.grey); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should change the Poly USD price manually", async() => { +// await I_PolyOracle.setPOLYUSD(latestPrice.add(1), {from: owner}); +// let price2 = await I_PolyOracle.getPriceAndTime.call(); +// assert.equal(price2[0].toNumber(), latestPrice.add(1).toNumber()); +// }) + +// it("Should freeze the Oracle manually", async() => { +// let errorThrown = false; +// try { +// await I_PolyOracle.setFreezeOracle(true, {from: accounts[5]}); +// } catch(error) { +// errorThrown = true; +// console.log(` tx->revert msg.sender is not the owner`.grey); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should change the URL manually", async() => { +// let freeze_ = await I_PolyOracle.freezeOracle.call(); +// await I_PolyOracle.setFreezeOracle(true, {from: owner}); +// let freeze = await I_PolyOracle.freezeOracle.call(); +// assert.isFalse(freeze_); +// assert.isTrue(freeze); +// await I_PolyOracle.setFreezeOracle(false, {from: owner}); +// }) + +// it("Should change the sanity bounds manually - fails - bad owner", async() => { +// let errorThrown = false; +// try { +// await I_PolyOracle.setSanityBounds(new BigNumber(25).times(new BigNumber(10).pow(16)), {from : accounts[6]}); +// } catch(error) { +// errorThrown = true; +// console.log(` tx->revert msg.sender is not the owner`.grey); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should change the sanity bounds manually", async() => { +// console.log(JSON.stringify(await I_PolyOracle.sanityBounds.call())); +// await I_PolyOracle.setSanityBounds(new BigNumber(25).times(new BigNumber(10).pow(16)), {from : owner}); +// let sanityBounds = await I_PolyOracle.sanityBounds.call(); +// console.log(JSON.stringify(await I_PolyOracle.sanityBounds.call())); +// assert.equal(sanityBounds.toNumber(), new BigNumber(25).times(new BigNumber(10).pow(16)).toNumber()) +// }); + +// it("Should change the gas price manually - fails - bad owner", async() => { +// let errorThrown = false; +// try{ +// await I_PolyOracle.setGasPrice(new BigNumber(60).times(new BigNumber(10).pow(9)),{from : accounts[6]}); +// } catch(error){ +// errorThrown = true; +// console.log(` tx->revert msg.sender is not the owner`.grey); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should change the gas price manually", async() => { +// await I_PolyOracle.setGasPrice(new BigNumber(60).times(new BigNumber(10).pow(9)),{from : owner}); +// let blockNo = latestBlock(); +// let timeScheduling = [latestTime()+duration.seconds(10), latestTime()+duration.seconds(20)]; +// let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner, value:web3.utils.toWei("2")}); + +// let event_data = tx.logs; + +// for (var i = 0; i < event_data.length; i++) { +// let time = event_data[i].args._time; +// console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); +// assert.isAtMost(time.toNumber(), timeScheduling[i]); +// } + +// const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); + +// assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') +// assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') +// console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); +// // assert.isTrue(false); + +// }); + +// it("Should change the gas limit manually - fails", async() => { +// let errorThrown = false; +// try{ +// await I_PolyOracle.setGasLimit(50000,{from : accounts[6]}); +// } catch(error){ +// errorThrown = true; +// console.log(` tx->revert msg.sender is not owner`.grey); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should change the gas limit manually", async() => { +// await I_PolyOracle.setGasLimit(50000,{from : owner}); +// let gasLimit = await I_PolyOracle.gasLimit.call(); +// assert.equal(gasLimit.toNumber(),50000); +// await I_PolyOracle.setGasLimit(100000,{from : owner}); +// }); + +// it("Should blacklist some IDS manually - fails - wrong size", async() => { +// let errorThrown = false; +// let ignore = [true]; +// try{ +// await I_PolyOracle.setIgnoreRequestIds(requestIds,ignore,{from : accounts[6]}); +// } catch(error){ +// errorThrown = true; +// console.log(` tx->revert msg.sender is not owner`.grey); +// } +// }); + +// it("Should blacklist some IDS manually", async() => { +// let ignore = [false, true]; +// console.log(requestIds); +// await I_PolyOracle.setIgnoreRequestIds(requestIds, ignore, {from : owner}); + +// // let ignoreRequestId0 = await I_PolyOracle.ignoreRequestIds.call(requestIds[1]); +// // assert.equal(ignoreRequestId0,true); + +// // let ignoreRequestId1 = await I_PolyOracle.ignoreRequestIds.call(requestIds[2]); +// // assert.equal(ignoreRequestId1,false); + +// }); + +// it("Should change the oraclize time tolerance manually - fails", async() => { +// let errorThrown = false; +// try{ +// await I_PolyOracle.setOraclizeTimeTolerance(3600,{from : accounts[6]}); +// } catch(error){ +// errorThrown = true; +// console.log(` tx->revert msg.sender is not the owner`.grey); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should change the oraclize time tolerance manually", async() => { +// await I_PolyOracle.setOraclizeTimeTolerance(3600,{from : owner}); +// let oraclizeTimeTolerance = await I_PolyOracle.oraclizeTimeTolerance.call(); +// assert.equal(oraclizeTimeTolerance.toNumber(),3600); +// }); + +// it("should change the api URL manually", async() => { +// let errorThrown = false; +// try { +// await I_PolyOracle.setOracleURL(alternateURL, {from: accounts[6]}); +// } catch(error){ +// errorThrown = true; +// console.log(` tx->revert msg.sender is not the owner`.grey); +// } +// assert.ok(errorThrown, message); +// }) + +// it("should change the api URL manually", async() => { +// await I_PolyOracle.setOracleURL(alternateURL, {from: owner}); +// await I_PolyOracle.setOracleQueryType("URL", {from: owner}); +// let url = await I_PolyOracle.oracleURL.call(); +// assert.equal(alternateURL, url); +// }); + +// it("Should schedule the timing of the call - after changes", async() => { +// let blockNo = latestBlock(); +// let tx = await I_PolyOracle.schedulePriceUpdatesFixed([],{from: owner, value:web3.utils.toWei("1")}); +// assert.isAtMost(tx.logs[0].args._time.toNumber(), latestTime()); +// const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 1); +// assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') +// assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') +// console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); +// // assert.isTrue(false); +// }); + +// }) + +// describe("Get Functions call", async() => { +// it("Should get the currency address", async() => { +// let polyTokenAddress = await I_PolyOracle.getCurrencyAddress.call(); +// assert.equal(polyTokenAddress, ("0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC").toLowerCase()); +// }); + +// it("Should get the currency symbol", async() => { +// let currency = await I_PolyOracle.getCurrencySymbol.call(); +// assert.equal(web3.utils.toAscii(currency).replace(/\u0000/g, ''), "POLY"); +// }); + +// it("Should get the currency denomination", async() => { +// let denomination = await I_PolyOracle.getCurrencyDenominated.call(); +// assert.equal(web3.utils.toAscii(denomination).replace(/\u0000/g, ''), "USD"); +// }) + +// }) + +// }) diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index c753d22db..6d1845626 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -1,1349 +1,1349 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -const CappedSTO = artifacts.require('./CappedSTO.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port -let ETH = 0; -let POLY = 1; -let DAI = 2; - -contract('CappedSTO', accounts => { - // Accounts Variable declaration - let account_polymath; - let account_investor1; - let account_issuer; - let token_owner; - let account_investor2; - let account_investor3; - let account_fundsReceiver; - - let balanceOfReceiver; - let message = "Transaction Should Fail!"; - // investor Details - let fromTime; - let toTime; - let expiryTime; - let P_fromTime; - let P_toTime; - let P_expiryTime; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_GeneralTransferManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_SecurityTokenRegistry; - let I_ModuleRegistry; - let I_ModuleRegistryProxy; - let I_FeatureRegistry; - let I_CappedSTOFactory; - let I_STFactory; - let I_SecurityToken_ETH; - let I_SecurityToken_POLY; - let I_CappedSTO_Array_ETH = []; - let I_CappedSTO_Array_POLY = []; - let I_PolyToken; - let I_PolymathRegistry; - let I_STRProxied; - let I_MRProxied; - let pauseTime; - - // SecurityToken Details for funds raise Type ETH - const name = "Team"; - const symbol = "SAP"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - - // SecurityToken Details for funds raise Type POLY - const P_name = "Team Poly"; - const P_symbol = "PAS"; - const P_tokenDetails = "This is equity type of issuance"; - const P_decimals = 18; - - // Module key - const transferManagerKey = 2; - const stoKey = 3; - const budget = 0; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - // Capped STO details - let startTime_ETH1; - let endTime_ETH1; - let startTime_ETH2; - let endTime_ETH2; - const cap = web3.utils.toWei("10000"); - const rate = 1000; - const E_fundRaiseType = 0; - - let startTime_POLY1; - let endTime_POLY1; - let startTime_POLY2; - let endTime_POLY2; - let blockNo; - const P_cap = web3.utils.toWei("50000"); - const P_fundRaiseType = 1; - const P_rate = 5; - const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); - const maxCost = cappedSTOSetupCost; - const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - account_investor1 = accounts[4]; - account_investor2 = accounts[3]; - account_investor3 = accounts[5] - account_fundsReceiver = accounts[2]; - token_owner = account_issuer; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 6: Deploy the CappedSTOFactory - - I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); - - assert.notEqual( - I_CappedSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CappedSTOFactory contract was not deployed" - ); - - // Step 8: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 7: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - console.log(await I_MRProxied.owner()); - console.log(account_polymath); - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - CappedSTOFactory: ${I_CappedSTOFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - - I_SecurityToken_ETH = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - - const log = await promisifyLogWatch(I_SecurityToken_ETH.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), transferManagerKey); - assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken_ETH.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - - it("Should mint the tokens before attaching the STO", async() => { - let errorThrown = false; - try { - await I_SecurityToken_ETH.mint("0x0000000000000000000000000000000000000000", web3.utils.toWei("1"), {from: token_owner}); - } catch (error) { - console.log(` tx -> revert 0x address is not allowed as investor`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to launch the STO due to security token doesn't have the sufficient POLY", async () => { - let startTime = latestTime() + duration.days(1); - let endTime = startTime + duration.days(30); - await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); - - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); - let errorThrown = false; - try { - const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Rate is ${0}. Test Passed Successfully`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to launch the STO due to rate is 0", async () => { - let startTime = latestTime() + duration.days(1); - let endTime = startTime + duration.days(30); - await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); - - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); - let errorThrown = false; - try { - const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - } catch(error) { - console.log(`Tx Failed because of rate is ${0}. Test Passed Successfully`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to launch the STO due to startTime > endTime", async () => { - let bytesSTO = encodeModuleCall(STOParameters, [ Math.floor(Date.now()/1000 + 100000), Math.floor(Date.now()/1000 + 1000), cap, rate, [E_fundRaiseType], account_fundsReceiver]); - let errorThrown = false; - try { - const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> StartTime is greater than endTime. Test Passed Successfully`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to launch the STO due to cap is of 0 securityToken", async () => { - let startTime = latestTime() + duration.days(1); - let endTime = startTime + duration.days(30); - let bytesSTO = encodeModuleCall(STOParameters, [ startTime, endTime, 0, rate, [E_fundRaiseType], account_fundsReceiver]); - let errorThrown = false; - try { - const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - } catch(error) { - console.log(`Tx Failed because the Cap is equal to ${0}. Test Passed Successfully`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the STO module to the security token", async () => { - startTime_ETH1 = latestTime() + duration.days(1); - endTime_ETH1 = startTime_ETH1 + duration.days(30); - let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH1, endTime_ETH1, cap, rate, [E_fundRaiseType], account_fundsReceiver]); - const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - - assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); - I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); - }); - }); - - describe("verify the data of STO", async () => { - - it("Should verify the configuration of the STO", async() => { - assert.equal( - await I_CappedSTO_Array_ETH[0].startTime.call(), - startTime_ETH1, - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_ETH[0].endTime.call(), - endTime_ETH1, - "STO Configuration doesn't set as expected" - ); - assert.equal( - (await I_CappedSTO_Array_ETH[0].cap.call()).toNumber(), - cap, - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_ETH[0].rate.call(), - rate, - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_ETH[0].fundRaiseTypes.call(E_fundRaiseType), - true, - "STO Configuration doesn't set as expected" - ); - }); - }); - - describe("Buy tokens", async() => { - - it("Should buy the tokens -- failed due to startTime is greater than Current time", async () => { - let errorThrown = false; - try { - await web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei('1', 'ether') - }); - } catch(error) { - console.log(` tx revert -> startTime is greater than Current time`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should buy the tokens -- failed due to invested amount is zero", async () => { - let errorThrown = false; - try { - await web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei('0', 'ether') - }); - } catch(error) { - console.log(` tx revert -> Invested amount is zero`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { - let errorThrown = false; - try { - await web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei('1', 'ether') - }); - } catch(error) { - console.log(` tx revert -> Investor doesn't present in the whitelist`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should buy the tokens -- Failed due to wrong granularity", async () => { - let errorThrown = false; - try { - await web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei('0.1111', 'ether') - }); - } catch(error) { - console.log(` tx revert -> Wrong purchase granularity`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should Buy the tokens", async() => { - blockNo = latestBlock(); - fromTime = latestTime(); - toTime = latestTime() + duration.days(15); - expiryTime = toTime + duration.days(100); - P_fromTime = fromTime + duration.days(1); - P_toTime = P_fromTime + duration.days(50); - P_expiryTime = toTime + duration.days(100); - - balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - fromTime, - toTime, - expiryTime, - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(duration.days(1)); - // Fallback transaction - await web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - gas: 2100000, - value: web3.utils.toWei('1', 'ether') - }); - - assert.equal( - (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1 - ); - - assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 1); - - assert.equal( - (await I_SecurityToken_ETH.balanceOf(account_investor1)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000 - ); - }); - - it("Verification of the event Token Purchase", async() => { - const log = await promisifyLogWatch(I_CappedSTO_Array_ETH[0].TokenPurchase({from: blockNo}), 1); - - assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); - assert.equal( - (log.args.amount) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000, - "Wrong No. token get dilivered" - ); - }); - - it("Should pause the STO -- Failed due to wrong msg.sender", async()=> { - let errorThrown = false; - try { - let tx = await I_CappedSTO_Array_ETH[0].pause({from: account_investor1}); - } catch(error) { - console.log(` tx revert -> Wrong msg.sender`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should pause the STO", async()=> { - pauseTime = latestTime(); - let tx = await I_CappedSTO_Array_ETH[0].pause({from: account_issuer}); - assert.isTrue(await I_CappedSTO_Array_ETH[0].paused.call()); - }); - - it("Should fail to buy the tokens after pausing the STO", async() => { - let errorThrown = false; - try { - await web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - gas: 2100000, - value: web3.utils.toWei('1', 'ether') - }); - } catch(error) { - console.log(` tx revert -> STO is paused`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should unpause the STO -- Failed due to wrong msg.sender", async()=> { - let errorThrown = false; - try { - let tx = await I_CappedSTO_Array_ETH[0].unpause({from: account_investor1}); - } catch(error) { - console.log(` tx revert -> Wrong msg.sender`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should unpause the STO", async()=> { - let tx = await I_CappedSTO_Array_ETH[0].unpause({from: account_issuer}); - assert.isFalse(await I_CappedSTO_Array_ETH[0].paused.call()); - }); - - it("Should buy the tokens -- Failed due to wrong granularity", async () => { - let errorThrown = false; - try { - await web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei('0.1111', 'ether') - }); - } catch(error) { - console.log(` tx revert -> Wrong purchase granularity`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async() => { - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - fromTime, - toTime + duration.days(20), - expiryTime, - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - - // Fallback transaction - await web3.eth.sendTransaction({ - from: account_investor2, - to: I_CappedSTO_Array_ETH[0].address, - gas: 2100000, - value: web3.utils.toWei('9', 'ether') - }); - - assert.equal( - (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 10 - ); - - assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 2); - - assert.equal( - (await I_SecurityToken_ETH.balanceOf(account_investor2)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 9000 - ); - try { - // Fallback transaction - await web3.eth.sendTransaction({ - from: account_investor2, - to: I_CappedSTO_Array_ETH[0].address, - gas: 210000, - value: web3.utils.toWei('1', 'ether') - }); - } catch(error) { - console.log(` tx revert -> Cap reached`.grey); - ensureException(error); - } - }); - - it("Should failed at the time of buying the tokens -- Because STO get expired", async() => { - await increaseTime(duration.days(17)); // increased beyond the end time of the STO - let errorThrown = false; - try { - // Fallback transaction - await web3.eth.sendTransaction({ - from: account_investor2, - to: I_CappedSTO_Array_ETH[0].address, - gas: 2100000, - value: web3.utils.toWei('1', 'ether') - }); - } catch(error) { - console.log(` tx revert -> STO get expired reached`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fundRaised value equal to the raised value in the funds receiver wallet", async() => { - const newBalance = await web3.eth.getBalance(account_fundsReceiver); - //console.log("WWWW",newBalance,await I_CappedSTO.fundsRaised.call(),balanceOfReceiver); - let op = (BigNumber(newBalance).minus(balanceOfReceiver)).toNumber(); - assert.equal( - (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).toNumber(), - op, - "Somewhere raised money get stolen or sent to wrong wallet" - ); - }); - - it("Should get the raised amount of ether", async() => { - assert.equal(await I_CappedSTO_Array_ETH[0].getRaised.call(ETH), web3.utils.toWei('10','ether')); - }); - - it("Should get the raised amount of poly", async() => { - assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(POLY)).toNumber(), web3.utils.toWei('0','ether')); - }); - - }); - - describe("Reclaim poly sent to STO by mistake", async() => { - - it("Should fail to reclaim POLY because token contract address is 0 address", async() => { - let value = web3.utils.toWei('100','ether'); - await I_PolyToken.getTokens(value, account_investor1); - await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); - - let errorThrown = false; - try { - await I_CappedSTO_Array_ETH[0].reclaimERC20('0x0000000000000000000000000000000000000000', { from: token_owner }); - } catch(error) { - console.log(` tx revert -> token contract address is 0 address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should successfully reclaim POLY", async() => { - let initInvestorBalance = await I_PolyToken.balanceOf(account_investor1); - let initOwnerBalance = await I_PolyToken.balanceOf(token_owner); - let initContractBalance = await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address); - let value = web3.utils.toWei('100','ether'); - - await I_PolyToken.getTokens(value, account_investor1); - await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); - await I_CappedSTO_Array_ETH[0].reclaimERC20(I_PolyToken.address, { from: token_owner }); - assert.equal((await I_PolyToken.balanceOf(account_investor3)).toNumber(), initInvestorBalance.toNumber(), "tokens are not transfered out from investor account"); - assert.equal((await I_PolyToken.balanceOf(token_owner)).toNumber(), initOwnerBalance.add(value).add(initContractBalance).toNumber(), "tokens are not added to the owner account"); - assert.equal((await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address)).toNumber(), 0, "tokens are not trandfered out from STO contract"); - }); - }); - - describe("Attach second ETH STO module", async() => { - - it("Should successfully attach the second STO module to the security token", async () => { - startTime_ETH2 = latestTime() + duration.days(1); - endTime_ETH2 = startTime_ETH2 + duration.days(30); - - await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); - await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); - let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH2, endTime_ETH2, cap, rate, [E_fundRaiseType], account_fundsReceiver]); - const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - - assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); - I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); - }); - - it("Should verify the configuration of the STO", async() => { - assert.equal( - await I_CappedSTO_Array_ETH[1].startTime.call(), - startTime_ETH2, - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_ETH[1].endTime.call(), - endTime_ETH2, - "STO Configuration doesn't set as expected" - ); - assert.equal( - (await I_CappedSTO_Array_ETH[1].cap.call()).toNumber(), - cap, - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_ETH[1].rate.call(), - rate, - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_ETH[1].fundRaiseTypes.call(E_fundRaiseType), - true, - "STO Configuration doesn't set as expected" - ); - }); - - it("Should successfully whitelist investor 3", async() => { - - balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - fromTime, - toTime, - expiryTime, - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); - - // Jump time to beyond STO start - await increaseTime(duration.days(2)); - }); - - it("Should invest in second STO - fails due to incorrect beneficiary", async() => { - - // Buying on behalf of another user should fail - let errorThrown = false; - try { - await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from : account_issuer, value: web3.utils.toWei('1', 'ether') }); - } catch(error) { - console.log(` tx revert -> incorrect beneficiary`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - }); - - it("Should allow non-matching beneficiary", async() => { - await I_CappedSTO_Array_ETH[1].changeAllowBeneficialInvestments(true, {from: account_issuer}); - let allow = await I_CappedSTO_Array_ETH[1].allowBeneficialInvestments(); - assert.equal(allow, true, "allowBeneficialInvestments should be true"); - }); - - it("Should invest in second STO", async() => { - - await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from : account_issuer, value: web3.utils.toWei('1', 'ether') }); - - assert.equal( - (await I_CappedSTO_Array_ETH[1].getRaised.call(ETH)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1 - ); - - assert.equal(await I_CappedSTO_Array_ETH[1].investorCount.call(), 1); - - assert.equal( - (await I_SecurityToken_ETH.balanceOf(account_investor3)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000 - ); - }); - }); - - describe("Test cases for reaching limit number of STO modules", async() => { - - it("Should successfully attach 10 STO modules", async () => { - const MAX_MODULES = 10; - let startTime = latestTime() + duration.days(1); - let endTime = startTime + duration.days(30); - - await I_PolyToken.getTokens(cappedSTOSetupCost*19, token_owner); - await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost*19, { from: token_owner}); - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], account_fundsReceiver]); - - for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { - const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); - assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); - I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); - } - - }); - - it("Should successfully invest in all STO modules attached", async () => { - const MAX_MODULES = 10; - await increaseTime(duration.days(2)); - for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { - await I_CappedSTO_Array_ETH[STOIndex].buyTokens(account_investor3, { from : account_investor3, value: web3.utils.toWei('1', 'ether') }); - assert.equal( - (await I_CappedSTO_Array_ETH[STOIndex].getRaised.call(ETH)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1 - ); - assert.equal(await I_CappedSTO_Array_ETH[STOIndex].investorCount.call(), 1); - } - }); - }); - - describe("Test Cases for an STO of fundraise type POLY", async() => { - - describe("Launch a new SecurityToken", async() => { - - it("POLY: Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, P_symbol, P_name, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, P_symbol); - }); - - it("POLY: Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(P_name, P_symbol, P_tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, P_symbol, "SecurityToken doesn't get deployed"); - - I_SecurityToken_POLY = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken_POLY.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), transferManagerKey); - assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); - }); - - it("POLY: Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken_POLY.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - - it("POLY: Should successfully attach the STO module to the security token", async () => { - startTime_POLY1 = latestTime() + duration.days(2); - endTime_POLY1 = startTime_POLY1 + duration.days(30); - - await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); - await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); - - let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY1, endTime_POLY1, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); - - const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - - assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); - I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); - }); - - }); - - describe("verify the data of STO", async () => { - - it("Should verify the configuration of the STO", async() => { - assert.equal( - (await I_CappedSTO_Array_POLY[0].startTime.call()).toNumber(), - startTime_POLY1, - "STO Configuration doesn't set as expected" - ); - assert.equal( - (await I_CappedSTO_Array_POLY[0].endTime.call()).toNumber(), - endTime_POLY1, - "STO Configuration doesn't set as expected" - ); - assert.equal( - (await I_CappedSTO_Array_POLY[0].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), - BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_POLY[0].rate.call(), - P_rate, - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_POLY[0].fundRaiseTypes.call(P_fundRaiseType), - true, - "STO Configuration doesn't set as expected" - ); - }); - }); - - describe("Buy tokens", async() => { - - it("Should Buy the tokens", async() => { - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_investor1); - blockNo = latestBlock(); - assert.equal( - (await I_PolyToken.balanceOf(account_investor1)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 10000, - "Tokens are not transfered properly" - ); - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - P_fromTime, - P_toTime, - P_expiryTime, - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(duration.days(17)); - - await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); - - // buyTokensWithPoly transaction - await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( - (1000 * Math.pow(10, 18)), - { - from : account_investor1, - gas: 6000000 - } - ); - - assert.equal( - (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000 - ); - - assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(), 1); - - assert.equal( - (await I_SecurityToken_POLY.balanceOf(account_investor1)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 5000 - ); - }); - - it("Verification of the event Token Purchase", async() => { - const log = await promisifyLogWatch(I_CappedSTO_Array_POLY[0].TokenPurchase({from: blockNo}), 1); - - assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); - assert.equal( - (log.args.amount) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 5000, - "Wrong No. token get dilivered" - ); - }); - - it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async() => { - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - P_fromTime, - P_toTime + duration.days(20), - P_expiryTime, - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_investor2); - - await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (9000 * Math.pow(10, 18)), { from: account_investor2}); - - // buyTokensWithPoly transaction - await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( - (9000 * Math.pow(10, 18)), - {from : account_investor2, gas: 6000000 } - ); - - assert.equal( - (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 10000 - ); - - assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(), 2); - - assert.equal( - (await I_SecurityToken_POLY.balanceOf(account_investor2)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 45000 - ); - let errorThrown = false; - try { - - await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); - // buyTokensWithPoly transaction - await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( - (1000 * Math.pow(10, 18)), - {from : account_investor1, gas: 6000000 } - ); - } catch(error) { - console.log(` tx revert -> Cap reached`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should failed at the time of buying the tokens -- Because STO get expired", async() => { - await increaseTime(duration.days(31)); // increased beyond the end time of the STO - let errorThrown = false; - try { - await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); - // buyTokensWithPoly transaction - await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( - (1000 * Math.pow(10, 18)), - {from : account_investor1, gas: 6000000 } - ); - } catch(error) { - console.log(` tx revert -> STO expiry reached`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fundRaised value equal to the raised value in the funds receiver wallet", async() => { - const balanceRaised = await I_PolyToken.balanceOf.call(account_fundsReceiver); - assert.equal( - (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toNumber(), - balanceRaised, - "Somewhere raised money get stolen or sent to wrong wallet" - ); - }); - - }); - - describe("Test cases for the CappedSTOFactory", async() => { - it("should get the exact details of the factory", async() => { - assert.equal((await I_CappedSTOFactory.setupCost.call()).toNumber(), cappedSTOSetupCost); - assert.equal((await I_CappedSTOFactory.getTypes.call())[0],3); - assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), - "CappedSTO", - "Wrong Module added"); - assert.equal(await I_CappedSTOFactory.getDescription.call(), - "Use to collects the funds and once the cap is reached then investment will be no longer entertained", - "Wrong Module added"); - assert.equal(await I_CappedSTOFactory.getTitle.call(), - "Capped STO", - "Wrong Module added"); - assert.equal(await I_CappedSTOFactory.getInstructions.call(), - "Initialises a capped STO. Init parameters are _startTime (time STO starts), _endTime (time STO ends), _cap (cap in tokens for STO), _rate (POLY/ETH to token rate), _fundRaiseType (whether you are raising in POLY or ETH), _polyToken (address of POLY token), _fundsReceiver (address which will receive funds)", - "Wrong Module added"); - let tags = await I_CappedSTOFactory.getTags.call(); - assert.equal(web3.utils.hexToString(tags[0]),"Capped"); - - }); - - it("Should fail to change the title -- bad owner", async() => { - let errorThrown = false; - try { - await I_CappedSTOFactory.changeTitle("STO Capped", {from:account_investor1}); - } catch(error) { - console.log(` tx revert -> bad owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to change the title -- zero length", async() => { - let errorThrown = false; - try { - await I_CappedSTOFactory.changeTitle("", {from: token_owner}); - } catch(error) { - console.log(` tx revert -> bad owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully change the title", async() => { - await I_CappedSTOFactory.changeTitle("STO Capped", {from: token_owner}); - assert.equal(await I_CappedSTOFactory.getTitle.call(), - "STO Capped", - "Title doesn't get changed"); - }); - - it("Should fail to change the description -- bad owner", async() => { - let errorThrown = false; - try { - await I_CappedSTOFactory.changeDescription("It is only a STO", {from:account_investor1}); - } catch(error) { - console.log(` tx revert -> bad owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to change the description -- zero length", async() => { - let errorThrown = false; - try { - await I_CappedSTOFactory.changeDescription("", {from: token_owner}); - } catch(error) { - console.log(` tx revert -> length of string should not be zero`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully change the description", async() => { - await I_CappedSTOFactory.changeDescription("It is only a STO", {from: token_owner}); - assert.equal(await I_CappedSTOFactory.getDescription.call(), - "It is only a STO", - "Description doesn't get changed"); - }); - - it("Should fail to change the name -- bad owner", async() => { - let errorThrown = false; - try { - await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), {from:account_investor1}); - } catch(error) { - console.log(` tx revert -> bad owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to change the name -- zero length", async() => { - let errorThrown = false; - try { - await I_CappedSTOFactory.changeName(web3.utils.stringToHex(""), {from: token_owner}); - } catch(error) { - console.log(` tx revert -> length of string should not be zero`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully change the name", async() => { - await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), {from: token_owner}); - assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), - "STOCapped", - "Name doesn't get changed"); - }); - - it("Should successfully change the name", async() => { - await I_CappedSTOFactory.changeName(web3.utils.stringToHex("CappedSTO"), {from: token_owner}); - assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), - "CappedSTO", - "Name doesn't get changed"); - }); - - }); - - describe("Test cases for the get functions of the capped sto", async() => { - it("Should verify the cap reached or not", async() => { - assert.isTrue(await I_CappedSTO_Array_POLY[0].capReached.call()); - }); - - it("Should get the raised amount of ether", async() => { - assert.equal(await I_CappedSTO_Array_POLY[0].getRaised.call(ETH), web3.utils.toWei('0','ether')); - }); - - it("Should get the raised amount of poly", async() => { - assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toNumber(), web3.utils.toWei('10000','ether')); - }); - - it("Should get the investors", async() => { - assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(),2); - }); - - it("Should get the listed permissions", async() => { - let tx = await I_CappedSTO_Array_POLY[0].getPermissions.call(); - assert.equal(tx.length,0); - }); - - it("Should get the metrics of the STO", async() => { - let metrics = await I_CappedSTO_Array_POLY[0].getSTODetails.call(); - assert.isTrue(metrics[7]); - }); - - }); - }); - - describe("Attach second POLY STO module", async() => { - it("Should successfully attach a second STO to the security token", async () => { - startTime_POLY2 = latestTime() + duration.days(1); - endTime_POLY2 = startTime_POLY2 + duration.days(30); - - await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); - await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); - - let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY2, endTime_POLY2, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); - - const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - - assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); - I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); - }); - - it("Should verify the configuration of the STO", async() => { - assert.equal( - (await I_CappedSTO_Array_POLY[1].startTime.call()).toNumber(), - startTime_POLY2, - "STO Configuration doesn't set as expected" - ); - assert.equal( - (await I_CappedSTO_Array_POLY[1].endTime.call()).toNumber(), - endTime_POLY2, - "STO Configuration doesn't set as expected" - ); - assert.equal( - (await I_CappedSTO_Array_POLY[1].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), - BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_POLY[1].rate.call(), - P_rate, - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_CappedSTO_Array_POLY[1].fundRaiseTypes.call(P_fundRaiseType), - true, - "STO Configuration doesn't set as expected" - ); - }); - - it("Should successfully invest in second STO", async() => { - - const polyToInvest = 1000; - const stToReceive = polyToInvest * P_rate; - - await I_PolyToken.getTokens((polyToInvest * Math.pow(10, 18)), account_investor3); - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - P_fromTime, - P_toTime, - P_expiryTime, - true, - { - from: account_issuer, - gas: 500000 - }); - - // Jump time to beyond STO start - await increaseTime(duration.days(2)); - - await I_PolyToken.approve(I_CappedSTO_Array_POLY[1].address, (polyToInvest * Math.pow(10, 18)), { from: account_investor3 }); - - // buyTokensWithPoly transaction - await I_CappedSTO_Array_POLY[1].buyTokensWithPoly( - (polyToInvest * Math.pow(10, 18)), - { - from : account_investor3, - gas: 6000000 - } - ); - - assert.equal( - (await I_CappedSTO_Array_POLY[1].getRaised.call(POLY)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - polyToInvest - ); - - assert.equal(await I_CappedSTO_Array_POLY[1].investorCount.call(), 1); - - assert.equal( - (await I_SecurityToken_POLY.balanceOf(account_investor3)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - stToReceive - ); - }); - }); -}); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +// const CappedSTO = artifacts.require('./CappedSTO.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port +// let ETH = 0; +// let POLY = 1; +// let DAI = 2; + +// contract('CappedSTO', accounts => { +// // Accounts Variable declaration +// let account_polymath; +// let account_investor1; +// let account_issuer; +// let token_owner; +// let account_investor2; +// let account_investor3; +// let account_fundsReceiver; + +// let balanceOfReceiver; +// let message = "Transaction Should Fail!"; +// // investor Details +// let fromTime; +// let toTime; +// let expiryTime; +// let P_fromTime; +// let P_toTime; +// let P_expiryTime; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_GeneralTransferManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_SecurityTokenRegistry; +// let I_ModuleRegistry; +// let I_ModuleRegistryProxy; +// let I_FeatureRegistry; +// let I_CappedSTOFactory; +// let I_STFactory; +// let I_SecurityToken_ETH; +// let I_SecurityToken_POLY; +// let I_CappedSTO_Array_ETH = []; +// let I_CappedSTO_Array_POLY = []; +// let I_PolyToken; +// let I_PolymathRegistry; +// let I_STRProxied; +// let I_MRProxied; +// let pauseTime; + +// // SecurityToken Details for funds raise Type ETH +// const name = "Team"; +// const symbol = "SAP"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; + +// // SecurityToken Details for funds raise Type POLY +// const P_name = "Team Poly"; +// const P_symbol = "PAS"; +// const P_tokenDetails = "This is equity type of issuance"; +// const P_decimals = 18; + +// // Module key +// const transferManagerKey = 2; +// const stoKey = 3; +// const budget = 0; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// // Capped STO details +// let startTime_ETH1; +// let endTime_ETH1; +// let startTime_ETH2; +// let endTime_ETH2; +// const cap = web3.utils.toWei("10000"); +// const rate = 1000; +// const E_fundRaiseType = 0; + +// let startTime_POLY1; +// let endTime_POLY1; +// let startTime_POLY2; +// let endTime_POLY2; +// let blockNo; +// const P_cap = web3.utils.toWei("50000"); +// const P_fundRaiseType = 1; +// const P_rate = 5; +// const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); +// const maxCost = cappedSTOSetupCost; +// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; +// account_investor1 = accounts[4]; +// account_investor2 = accounts[3]; +// account_investor3 = accounts[5] +// account_fundsReceiver = accounts[2]; +// token_owner = account_issuer; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 6: Deploy the CappedSTOFactory + +// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); + +// assert.notEqual( +// I_CappedSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CappedSTOFactory contract was not deployed" +// ); + +// // Step 8: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 9: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 7: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// console.log(await I_MRProxied.owner()); +// console.log(account_polymath); +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// ModuleRegistry: ${ModuleRegistry.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// CappedSTOFactory: ${I_CappedSTOFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + +// I_SecurityToken_ETH = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + +// const log = await promisifyLogWatch(I_SecurityToken_ETH.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), transferManagerKey); +// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken_ETH.getModulesByType(transferManagerKey))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); +// }); + +// it("Should mint the tokens before attaching the STO", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken_ETH.mint("0x0000000000000000000000000000000000000000", web3.utils.toWei("1"), {from: token_owner}); +// } catch (error) { +// console.log(` tx -> revert 0x address is not allowed as investor`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to launch the STO due to security token doesn't have the sufficient POLY", async () => { +// let startTime = latestTime() + duration.days(1); +// let endTime = startTime + duration.days(30); +// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); + +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); +// let errorThrown = false; +// try { +// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Rate is ${0}. Test Passed Successfully`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to launch the STO due to rate is 0", async () => { +// let startTime = latestTime() + duration.days(1); +// let endTime = startTime + duration.days(30); +// await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); + +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); +// let errorThrown = false; +// try { +// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); +// } catch(error) { +// console.log(`Tx Failed because of rate is ${0}. Test Passed Successfully`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to launch the STO due to startTime > endTime", async () => { +// let bytesSTO = encodeModuleCall(STOParameters, [ Math.floor(Date.now()/1000 + 100000), Math.floor(Date.now()/1000 + 1000), cap, rate, [E_fundRaiseType], account_fundsReceiver]); +// let errorThrown = false; +// try { +// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); +// } catch(error) { +// errorThrown = true; +// console.log(` tx revert -> StartTime is greater than endTime. Test Passed Successfully`.grey); +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to launch the STO due to cap is of 0 securityToken", async () => { +// let startTime = latestTime() + duration.days(1); +// let endTime = startTime + duration.days(30); +// let bytesSTO = encodeModuleCall(STOParameters, [ startTime, endTime, 0, rate, [E_fundRaiseType], account_fundsReceiver]); +// let errorThrown = false; +// try { +// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); +// } catch(error) { +// console.log(`Tx Failed because the Cap is equal to ${0}. Test Passed Successfully`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the STO module to the security token", async () => { +// startTime_ETH1 = latestTime() + duration.days(1); +// endTime_ETH1 = startTime_ETH1 + duration.days(30); +// let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH1, endTime_ETH1, cap, rate, [E_fundRaiseType], account_fundsReceiver]); +// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + +// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); +// I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); +// }); +// }); + +// describe("verify the data of STO", async () => { + +// it("Should verify the configuration of the STO", async() => { +// assert.equal( +// await I_CappedSTO_Array_ETH[0].startTime.call(), +// startTime_ETH1, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_ETH[0].endTime.call(), +// endTime_ETH1, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// (await I_CappedSTO_Array_ETH[0].cap.call()).toNumber(), +// cap, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_ETH[0].rate.call(), +// rate, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_ETH[0].fundRaiseTypes.call(E_fundRaiseType), +// true, +// "STO Configuration doesn't set as expected" +// ); +// }); +// }); + +// describe("Buy tokens", async() => { + +// it("Should buy the tokens -- failed due to startTime is greater than Current time", async () => { +// let errorThrown = false; +// try { +// await web3.eth.sendTransaction({ +// from: account_investor1, +// to: I_CappedSTO_Array_ETH[0].address, +// value: web3.utils.toWei('1', 'ether') +// }); +// } catch(error) { +// console.log(` tx revert -> startTime is greater than Current time`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should buy the tokens -- failed due to invested amount is zero", async () => { +// let errorThrown = false; +// try { +// await web3.eth.sendTransaction({ +// from: account_investor1, +// to: I_CappedSTO_Array_ETH[0].address, +// value: web3.utils.toWei('0', 'ether') +// }); +// } catch(error) { +// console.log(` tx revert -> Invested amount is zero`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { +// let errorThrown = false; +// try { +// await web3.eth.sendTransaction({ +// from: account_investor1, +// to: I_CappedSTO_Array_ETH[0].address, +// value: web3.utils.toWei('1', 'ether') +// }); +// } catch(error) { +// console.log(` tx revert -> Investor doesn't present in the whitelist`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should buy the tokens -- Failed due to wrong granularity", async () => { +// let errorThrown = false; +// try { +// await web3.eth.sendTransaction({ +// from: account_investor1, +// to: I_CappedSTO_Array_ETH[0].address, +// value: web3.utils.toWei('0.1111', 'ether') +// }); +// } catch(error) { +// console.log(` tx revert -> Wrong purchase granularity`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should Buy the tokens", async() => { +// blockNo = latestBlock(); +// fromTime = latestTime(); +// toTime = latestTime() + duration.days(15); +// expiryTime = toTime + duration.days(100); +// P_fromTime = fromTime + duration.days(1); +// P_toTime = P_fromTime + duration.days(50); +// P_expiryTime = toTime + duration.days(100); + +// balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(duration.days(1)); +// // Fallback transaction +// await web3.eth.sendTransaction({ +// from: account_investor1, +// to: I_CappedSTO_Array_ETH[0].address, +// gas: 2100000, +// value: web3.utils.toWei('1', 'ether') +// }); + +// assert.equal( +// (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1 +// ); + +// assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 1); + +// assert.equal( +// (await I_SecurityToken_ETH.balanceOf(account_investor1)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000 +// ); +// }); + +// it("Verification of the event Token Purchase", async() => { +// const log = await promisifyLogWatch(I_CappedSTO_Array_ETH[0].TokenPurchase({from: blockNo}), 1); + +// assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); +// assert.equal( +// (log.args.amount) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000, +// "Wrong No. token get dilivered" +// ); +// }); + +// it("Should pause the STO -- Failed due to wrong msg.sender", async()=> { +// let errorThrown = false; +// try { +// let tx = await I_CappedSTO_Array_ETH[0].pause({from: account_investor1}); +// } catch(error) { +// console.log(` tx revert -> Wrong msg.sender`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should pause the STO", async()=> { +// pauseTime = latestTime(); +// let tx = await I_CappedSTO_Array_ETH[0].pause({from: account_issuer}); +// assert.isTrue(await I_CappedSTO_Array_ETH[0].paused.call()); +// }); + +// it("Should fail to buy the tokens after pausing the STO", async() => { +// let errorThrown = false; +// try { +// await web3.eth.sendTransaction({ +// from: account_investor1, +// to: I_CappedSTO_Array_ETH[0].address, +// gas: 2100000, +// value: web3.utils.toWei('1', 'ether') +// }); +// } catch(error) { +// console.log(` tx revert -> STO is paused`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should unpause the STO -- Failed due to wrong msg.sender", async()=> { +// let errorThrown = false; +// try { +// let tx = await I_CappedSTO_Array_ETH[0].unpause({from: account_investor1}); +// } catch(error) { +// console.log(` tx revert -> Wrong msg.sender`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should unpause the STO", async()=> { +// let tx = await I_CappedSTO_Array_ETH[0].unpause({from: account_issuer}); +// assert.isFalse(await I_CappedSTO_Array_ETH[0].paused.call()); +// }); + +// it("Should buy the tokens -- Failed due to wrong granularity", async () => { +// let errorThrown = false; +// try { +// await web3.eth.sendTransaction({ +// from: account_investor1, +// to: I_CappedSTO_Array_ETH[0].address, +// value: web3.utils.toWei('0.1111', 'ether') +// }); +// } catch(error) { +// console.log(` tx revert -> Wrong purchase granularity`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async() => { +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// fromTime, +// toTime + duration.days(20), +// expiryTime, +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + +// // Fallback transaction +// await web3.eth.sendTransaction({ +// from: account_investor2, +// to: I_CappedSTO_Array_ETH[0].address, +// gas: 2100000, +// value: web3.utils.toWei('9', 'ether') +// }); + +// assert.equal( +// (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 10 +// ); + +// assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 2); + +// assert.equal( +// (await I_SecurityToken_ETH.balanceOf(account_investor2)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 9000 +// ); +// try { +// // Fallback transaction +// await web3.eth.sendTransaction({ +// from: account_investor2, +// to: I_CappedSTO_Array_ETH[0].address, +// gas: 210000, +// value: web3.utils.toWei('1', 'ether') +// }); +// } catch(error) { +// console.log(` tx revert -> Cap reached`.grey); +// ensureException(error); +// } +// }); + +// it("Should failed at the time of buying the tokens -- Because STO get expired", async() => { +// await increaseTime(duration.days(17)); // increased beyond the end time of the STO +// let errorThrown = false; +// try { +// // Fallback transaction +// await web3.eth.sendTransaction({ +// from: account_investor2, +// to: I_CappedSTO_Array_ETH[0].address, +// gas: 2100000, +// value: web3.utils.toWei('1', 'ether') +// }); +// } catch(error) { +// console.log(` tx revert -> STO get expired reached`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fundRaised value equal to the raised value in the funds receiver wallet", async() => { +// const newBalance = await web3.eth.getBalance(account_fundsReceiver); +// //console.log("WWWW",newBalance,await I_CappedSTO.fundsRaised.call(),balanceOfReceiver); +// let op = (BigNumber(newBalance).minus(balanceOfReceiver)).toNumber(); +// assert.equal( +// (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).toNumber(), +// op, +// "Somewhere raised money get stolen or sent to wrong wallet" +// ); +// }); + +// it("Should get the raised amount of ether", async() => { +// assert.equal(await I_CappedSTO_Array_ETH[0].getRaised.call(ETH), web3.utils.toWei('10','ether')); +// }); + +// it("Should get the raised amount of poly", async() => { +// assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(POLY)).toNumber(), web3.utils.toWei('0','ether')); +// }); + +// }); + +// describe("Reclaim poly sent to STO by mistake", async() => { + +// it("Should fail to reclaim POLY because token contract address is 0 address", async() => { +// let value = web3.utils.toWei('100','ether'); +// await I_PolyToken.getTokens(value, account_investor1); +// await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); + +// let errorThrown = false; +// try { +// await I_CappedSTO_Array_ETH[0].reclaimERC20('0x0000000000000000000000000000000000000000', { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> token contract address is 0 address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully reclaim POLY", async() => { +// let initInvestorBalance = await I_PolyToken.balanceOf(account_investor1); +// let initOwnerBalance = await I_PolyToken.balanceOf(token_owner); +// let initContractBalance = await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address); +// let value = web3.utils.toWei('100','ether'); + +// await I_PolyToken.getTokens(value, account_investor1); +// await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); +// await I_CappedSTO_Array_ETH[0].reclaimERC20(I_PolyToken.address, { from: token_owner }); +// assert.equal((await I_PolyToken.balanceOf(account_investor3)).toNumber(), initInvestorBalance.toNumber(), "tokens are not transfered out from investor account"); +// assert.equal((await I_PolyToken.balanceOf(token_owner)).toNumber(), initOwnerBalance.add(value).add(initContractBalance).toNumber(), "tokens are not added to the owner account"); +// assert.equal((await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address)).toNumber(), 0, "tokens are not trandfered out from STO contract"); +// }); +// }); + +// describe("Attach second ETH STO module", async() => { + +// it("Should successfully attach the second STO module to the security token", async () => { +// startTime_ETH2 = latestTime() + duration.days(1); +// endTime_ETH2 = startTime_ETH2 + duration.days(30); + +// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); +// await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); +// let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH2, endTime_ETH2, cap, rate, [E_fundRaiseType], account_fundsReceiver]); +// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + +// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); +// I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); +// }); + +// it("Should verify the configuration of the STO", async() => { +// assert.equal( +// await I_CappedSTO_Array_ETH[1].startTime.call(), +// startTime_ETH2, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_ETH[1].endTime.call(), +// endTime_ETH2, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// (await I_CappedSTO_Array_ETH[1].cap.call()).toNumber(), +// cap, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_ETH[1].rate.call(), +// rate, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_ETH[1].fundRaiseTypes.call(E_fundRaiseType), +// true, +// "STO Configuration doesn't set as expected" +// ); +// }); + +// it("Should successfully whitelist investor 3", async() => { + +// balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); + +// // Jump time to beyond STO start +// await increaseTime(duration.days(2)); +// }); + +// it("Should invest in second STO - fails due to incorrect beneficiary", async() => { + +// // Buying on behalf of another user should fail +// let errorThrown = false; +// try { +// await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from : account_issuer, value: web3.utils.toWei('1', 'ether') }); +// } catch(error) { +// console.log(` tx revert -> incorrect beneficiary`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Should allow non-matching beneficiary", async() => { +// await I_CappedSTO_Array_ETH[1].changeAllowBeneficialInvestments(true, {from: account_issuer}); +// let allow = await I_CappedSTO_Array_ETH[1].allowBeneficialInvestments(); +// assert.equal(allow, true, "allowBeneficialInvestments should be true"); +// }); + +// it("Should invest in second STO", async() => { + +// await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from : account_issuer, value: web3.utils.toWei('1', 'ether') }); + +// assert.equal( +// (await I_CappedSTO_Array_ETH[1].getRaised.call(ETH)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1 +// ); + +// assert.equal(await I_CappedSTO_Array_ETH[1].investorCount.call(), 1); + +// assert.equal( +// (await I_SecurityToken_ETH.balanceOf(account_investor3)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000 +// ); +// }); +// }); + +// describe("Test cases for reaching limit number of STO modules", async() => { + +// it("Should successfully attach 10 STO modules", async () => { +// const MAX_MODULES = 10; +// let startTime = latestTime() + duration.days(1); +// let endTime = startTime + duration.days(30); + +// await I_PolyToken.getTokens(cappedSTOSetupCost*19, token_owner); +// await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost*19, { from: token_owner}); +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], account_fundsReceiver]); + +// for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { +// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); +// assert.equal(tx.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); +// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); +// I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); +// } + +// }); + +// it("Should successfully invest in all STO modules attached", async () => { +// const MAX_MODULES = 10; +// await increaseTime(duration.days(2)); +// for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { +// await I_CappedSTO_Array_ETH[STOIndex].buyTokens(account_investor3, { from : account_investor3, value: web3.utils.toWei('1', 'ether') }); +// assert.equal( +// (await I_CappedSTO_Array_ETH[STOIndex].getRaised.call(ETH)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1 +// ); +// assert.equal(await I_CappedSTO_Array_ETH[STOIndex].investorCount.call(), 1); +// } +// }); +// }); + +// describe("Test Cases for an STO of fundraise type POLY", async() => { + +// describe("Launch a new SecurityToken", async() => { + +// it("POLY: Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, P_symbol, P_name, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, P_symbol); +// }); + +// it("POLY: Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(P_name, P_symbol, P_tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, P_symbol, "SecurityToken doesn't get deployed"); + +// I_SecurityToken_POLY = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken_POLY.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), transferManagerKey); +// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); +// }); + +// it("POLY: Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken_POLY.getModulesByType(transferManagerKey))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); +// }); + +// it("POLY: Should successfully attach the STO module to the security token", async () => { +// startTime_POLY1 = latestTime() + duration.days(2); +// endTime_POLY1 = startTime_POLY1 + duration.days(30); + +// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); +// await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); + +// let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY1, endTime_POLY1, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); + +// const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + +// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); +// I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); +// }); + +// }); + +// describe("verify the data of STO", async () => { + +// it("Should verify the configuration of the STO", async() => { +// assert.equal( +// (await I_CappedSTO_Array_POLY[0].startTime.call()).toNumber(), +// startTime_POLY1, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// (await I_CappedSTO_Array_POLY[0].endTime.call()).toNumber(), +// endTime_POLY1, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// (await I_CappedSTO_Array_POLY[0].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), +// BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_POLY[0].rate.call(), +// P_rate, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_POLY[0].fundRaiseTypes.call(P_fundRaiseType), +// true, +// "STO Configuration doesn't set as expected" +// ); +// }); +// }); + +// describe("Buy tokens", async() => { + +// it("Should Buy the tokens", async() => { +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_investor1); +// blockNo = latestBlock(); +// assert.equal( +// (await I_PolyToken.balanceOf(account_investor1)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 10000, +// "Tokens are not transfered properly" +// ); + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// P_fromTime, +// P_toTime, +// P_expiryTime, +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(duration.days(17)); + +// await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); + +// // buyTokensWithPoly transaction +// await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( +// (1000 * Math.pow(10, 18)), +// { +// from : account_investor1, +// gas: 6000000 +// } +// ); + +// assert.equal( +// (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000 +// ); + +// assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(), 1); + +// assert.equal( +// (await I_SecurityToken_POLY.balanceOf(account_investor1)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 5000 +// ); +// }); + +// it("Verification of the event Token Purchase", async() => { +// const log = await promisifyLogWatch(I_CappedSTO_Array_POLY[0].TokenPurchase({from: blockNo}), 1); + +// assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); +// assert.equal( +// (log.args.amount) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 5000, +// "Wrong No. token get dilivered" +// ); +// }); + +// it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async() => { +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// P_fromTime, +// P_toTime + duration.days(20), +// P_expiryTime, +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_investor2); + +// await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (9000 * Math.pow(10, 18)), { from: account_investor2}); + +// // buyTokensWithPoly transaction +// await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( +// (9000 * Math.pow(10, 18)), +// {from : account_investor2, gas: 6000000 } +// ); + +// assert.equal( +// (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 10000 +// ); + +// assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(), 2); + +// assert.equal( +// (await I_SecurityToken_POLY.balanceOf(account_investor2)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 45000 +// ); +// let errorThrown = false; +// try { + +// await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); +// // buyTokensWithPoly transaction +// await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( +// (1000 * Math.pow(10, 18)), +// {from : account_investor1, gas: 6000000 } +// ); +// } catch(error) { +// console.log(` tx revert -> Cap reached`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should failed at the time of buying the tokens -- Because STO get expired", async() => { +// await increaseTime(duration.days(31)); // increased beyond the end time of the STO +// let errorThrown = false; +// try { +// await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); +// // buyTokensWithPoly transaction +// await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( +// (1000 * Math.pow(10, 18)), +// {from : account_investor1, gas: 6000000 } +// ); +// } catch(error) { +// console.log(` tx revert -> STO expiry reached`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fundRaised value equal to the raised value in the funds receiver wallet", async() => { +// const balanceRaised = await I_PolyToken.balanceOf.call(account_fundsReceiver); +// assert.equal( +// (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toNumber(), +// balanceRaised, +// "Somewhere raised money get stolen or sent to wrong wallet" +// ); +// }); + +// }); + +// describe("Test cases for the CappedSTOFactory", async() => { +// it("should get the exact details of the factory", async() => { +// assert.equal((await I_CappedSTOFactory.setupCost.call()).toNumber(), cappedSTOSetupCost); +// assert.equal((await I_CappedSTOFactory.getTypes.call())[0],3); +// assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), +// "CappedSTO", +// "Wrong Module added"); +// assert.equal(await I_CappedSTOFactory.getDescription.call(), +// "Use to collects the funds and once the cap is reached then investment will be no longer entertained", +// "Wrong Module added"); +// assert.equal(await I_CappedSTOFactory.getTitle.call(), +// "Capped STO", +// "Wrong Module added"); +// assert.equal(await I_CappedSTOFactory.getInstructions.call(), +// "Initialises a capped STO. Init parameters are _startTime (time STO starts), _endTime (time STO ends), _cap (cap in tokens for STO), _rate (POLY/ETH to token rate), _fundRaiseType (whether you are raising in POLY or ETH), _polyToken (address of POLY token), _fundsReceiver (address which will receive funds)", +// "Wrong Module added"); +// let tags = await I_CappedSTOFactory.getTags.call(); +// assert.equal(web3.utils.hexToString(tags[0]),"Capped"); + +// }); + +// it("Should fail to change the title -- bad owner", async() => { +// let errorThrown = false; +// try { +// await I_CappedSTOFactory.changeTitle("STO Capped", {from:account_investor1}); +// } catch(error) { +// console.log(` tx revert -> bad owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to change the title -- zero length", async() => { +// let errorThrown = false; +// try { +// await I_CappedSTOFactory.changeTitle("", {from: token_owner}); +// } catch(error) { +// console.log(` tx revert -> bad owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully change the title", async() => { +// await I_CappedSTOFactory.changeTitle("STO Capped", {from: token_owner}); +// assert.equal(await I_CappedSTOFactory.getTitle.call(), +// "STO Capped", +// "Title doesn't get changed"); +// }); + +// it("Should fail to change the description -- bad owner", async() => { +// let errorThrown = false; +// try { +// await I_CappedSTOFactory.changeDescription("It is only a STO", {from:account_investor1}); +// } catch(error) { +// console.log(` tx revert -> bad owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to change the description -- zero length", async() => { +// let errorThrown = false; +// try { +// await I_CappedSTOFactory.changeDescription("", {from: token_owner}); +// } catch(error) { +// console.log(` tx revert -> length of string should not be zero`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully change the description", async() => { +// await I_CappedSTOFactory.changeDescription("It is only a STO", {from: token_owner}); +// assert.equal(await I_CappedSTOFactory.getDescription.call(), +// "It is only a STO", +// "Description doesn't get changed"); +// }); + +// it("Should fail to change the name -- bad owner", async() => { +// let errorThrown = false; +// try { +// await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), {from:account_investor1}); +// } catch(error) { +// console.log(` tx revert -> bad owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to change the name -- zero length", async() => { +// let errorThrown = false; +// try { +// await I_CappedSTOFactory.changeName(web3.utils.stringToHex(""), {from: token_owner}); +// } catch(error) { +// console.log(` tx revert -> length of string should not be zero`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully change the name", async() => { +// await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), {from: token_owner}); +// assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), +// "STOCapped", +// "Name doesn't get changed"); +// }); + +// it("Should successfully change the name", async() => { +// await I_CappedSTOFactory.changeName(web3.utils.stringToHex("CappedSTO"), {from: token_owner}); +// assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), +// "CappedSTO", +// "Name doesn't get changed"); +// }); + +// }); + +// describe("Test cases for the get functions of the capped sto", async() => { +// it("Should verify the cap reached or not", async() => { +// assert.isTrue(await I_CappedSTO_Array_POLY[0].capReached.call()); +// }); + +// it("Should get the raised amount of ether", async() => { +// assert.equal(await I_CappedSTO_Array_POLY[0].getRaised.call(ETH), web3.utils.toWei('0','ether')); +// }); + +// it("Should get the raised amount of poly", async() => { +// assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toNumber(), web3.utils.toWei('10000','ether')); +// }); + +// it("Should get the investors", async() => { +// assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(),2); +// }); + +// it("Should get the listed permissions", async() => { +// let tx = await I_CappedSTO_Array_POLY[0].getPermissions.call(); +// assert.equal(tx.length,0); +// }); + +// it("Should get the metrics of the STO", async() => { +// let metrics = await I_CappedSTO_Array_POLY[0].getSTODetails.call(); +// assert.isTrue(metrics[7]); +// }); + +// }); +// }); + +// describe("Attach second POLY STO module", async() => { +// it("Should successfully attach a second STO to the security token", async () => { +// startTime_POLY2 = latestTime() + duration.days(1); +// endTime_POLY2 = startTime_POLY2 + duration.days(30); + +// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); +// await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); + +// let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY2, endTime_POLY2, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); + +// const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + +// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); +// I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); +// }); + +// it("Should verify the configuration of the STO", async() => { +// assert.equal( +// (await I_CappedSTO_Array_POLY[1].startTime.call()).toNumber(), +// startTime_POLY2, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// (await I_CappedSTO_Array_POLY[1].endTime.call()).toNumber(), +// endTime_POLY2, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// (await I_CappedSTO_Array_POLY[1].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), +// BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_POLY[1].rate.call(), +// P_rate, +// "STO Configuration doesn't set as expected" +// ); +// assert.equal( +// await I_CappedSTO_Array_POLY[1].fundRaiseTypes.call(P_fundRaiseType), +// true, +// "STO Configuration doesn't set as expected" +// ); +// }); + +// it("Should successfully invest in second STO", async() => { + +// const polyToInvest = 1000; +// const stToReceive = polyToInvest * P_rate; + +// await I_PolyToken.getTokens((polyToInvest * Math.pow(10, 18)), account_investor3); + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// P_fromTime, +// P_toTime, +// P_expiryTime, +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// // Jump time to beyond STO start +// await increaseTime(duration.days(2)); + +// await I_PolyToken.approve(I_CappedSTO_Array_POLY[1].address, (polyToInvest * Math.pow(10, 18)), { from: account_investor3 }); + +// // buyTokensWithPoly transaction +// await I_CappedSTO_Array_POLY[1].buyTokensWithPoly( +// (polyToInvest * Math.pow(10, 18)), +// { +// from : account_investor3, +// gas: 6000000 +// } +// ); + +// assert.equal( +// (await I_CappedSTO_Array_POLY[1].getRaised.call(POLY)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// polyToInvest +// ); + +// assert.equal(await I_CappedSTO_Array_POLY[1].investorCount.call(), 1); + +// assert.equal( +// (await I_SecurityToken_POLY.balanceOf(account_investor3)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// stToReceive +// ); +// }); +// }); +// }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index f4ad15ee1..25196ce1b 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -1,429 +1,429 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('Checkpoints', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ExchangeTransferManager; - let I_STRProxied; - let I_MRProxied; - let I_ModuleRegistry; - let I_ModuleRegistryProxy; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[6]; - account_investor2 = accounts[7]; - account_investor3 = accounts[8]; - account_investor4 = accounts[9]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // Step 7: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 8: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 9: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 6: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should set controller to token owner", async () => { - await I_SecurityToken.setController(token_owner, {from: token_owner}); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - - }); - - describe("Buy tokens using on-chain whitelist", async() => { - - it("Should Buy the tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - false, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('10', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('10', 'ether') - ); - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - false, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('10', 'ether') - ); - }); - - it("Add a new token holder", async() => { - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - false, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('10', 'ether') - ); - }); - - it("Fuzz test balance checkpoints", async() => { - await I_SecurityToken.changeGranularity(1, {from: token_owner}); - let cps = []; - let ts = []; - for (let j = 0; j < 10; j++) { - let balance1 = BigNumber(await I_SecurityToken.balanceOf(account_investor1)); - let balance2 = BigNumber(await I_SecurityToken.balanceOf(account_investor2)); - let balance3 = BigNumber(await I_SecurityToken.balanceOf(account_investor3)); - let totalSupply = BigNumber(await I_SecurityToken.totalSupply()); - cps.push([balance1, balance2, balance3]); - ts.push(totalSupply); - console.log("Checkpoint: " + (j + 1) + " Balances: " + JSON.stringify(cps[cps.length - 1]) + " TotalSupply: " + JSON.stringify(totalSupply)); - await I_SecurityToken.createCheckpoint({ from: token_owner }); - let checkpointTimes = (await I_SecurityToken.getCheckpointTimes()); - assert.equal(checkpointTimes.length, (j + 1)); - console.log("Checkpoint Times: " + checkpointTimes); - let txs = Math.floor(Math.random() * 3); - for (let i = 0; i < txs; i++) { - let sender; - let receiver; - let s = Math.random() * 3; - if (s < 1) { - sender = account_investor1; - } else if (s < 2) { - sender = account_investor2; - } else { - sender = account_investor3; - } - let r = Math.random() * 3; - if (r < 1) { - receiver = account_investor1; - } else if (r < 2) { - receiver = account_investor2; - } else { - receiver = account_investor3; - } - let m = Math.random(); - let amount = BigNumber(await I_SecurityToken.balanceOf(sender)).mul(Math.random().toFixed(10)).toFixed(0); - if (m > 0.8) { - console.log("Sending full balance"); - amount = BigNumber(await I_SecurityToken.balanceOf(sender)); - } - console.log("Sender: " + sender + " Receiver: " + receiver + " Amount: " + JSON.stringify(amount)); - await I_SecurityToken.transfer(receiver, amount, { from: sender }); - } - if (Math.random() > 0.5) { - let n = BigNumber(Math.random().toFixed(10)).mul(10**17).toFixed(0); - let p = Math.random() * 3; - let r = Math.random() * 3; - let minter; - if (r < 1) { - minter = account_investor1; - } else if (r < 2) { - minter = account_investor2; - } else { - minter = account_investor3; - } - console.log("Minting: " + n.toString() + " to: " + minter); - await I_SecurityToken.mint(minter, n, { from: token_owner }); - } - if (Math.random() > 0.5) { - let n = BigNumber(Math.random().toFixed(10)).mul(10**17); - let p = Math.random() * 3; - let r = Math.random() * 3; - let burner; - if (r < 1) { - burner = account_investor1; - } else if (r < 2) { - burner = account_investor2; - } else { - burner = account_investor3; - } - let burnerBalance = BigNumber(await I_SecurityToken.balanceOf(burner)); - if (n.gt(burnerBalance.div(2))) { - n = burnerBalance.div(2); - } - n = n.toFixed(0); - console.log("Burning: " + n.toString() + " from: " + burner); - await I_SecurityToken.forceBurn(burner, n, "", "", { from: token_owner }); - } - console.log("Checking Interim..."); - for (let k = 0; k < cps.length; k++) { - let balance1 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); - let balance2 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); - let balance3 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); - let totalSupply = BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); - let balances = [balance1, balance2, balance3]; - console.log("Checking TotalSupply: " + totalSupply + " is " + ts[k] + " at checkpoint: " + (k + 1)); - assert.isTrue(totalSupply.eq(ts[k])); - console.log("Checking Balances: " + balances + " is " + cps[k] + " at checkpoint: " + (k + 1)); - for (let l = 0; l < cps[k].length; l++) { - // console.log(balances[l].toString(), cps[k][l].toString()); - assert.isTrue(balances[l].eq(cps[k][l])); - } - } - } - console.log("Checking..."); - for (let k = 0; k < cps.length; k++) { - let balance1 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); - let balance2 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); - let balance3 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); - let totalSupply = BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); - let balances = [balance1, balance2, balance3]; - console.log("Checking TotalSupply: " + totalSupply + " is " + ts[k] + " at checkpoint: " + (k + 1)); - assert.isTrue(totalSupply.eq(ts[k])); - console.log("Checking Balances: " + balances + " is " + cps[k] + " at checkpoint: " + (k + 1)); - for (let l = 0; l < cps[k].length; l++) { - // console.log(balances[l].toString(), cps[k][l].toString()); - assert.isTrue(balances[l].eq(cps[k][l])); - } - } - - }); - }); - -}); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('Checkpoints', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ExchangeTransferManager; +// let I_STRProxied; +// let I_MRProxied; +// let I_ModuleRegistry; +// let I_ModuleRegistryProxy; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_STFactory; +// let I_SecurityToken; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; + +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; + +// account_investor1 = accounts[6]; +// account_investor2 = accounts[7]; +// account_investor3 = accounts[8]; +// account_investor4 = accounts[9]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // Step 7: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 8: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 9: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 10: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 6: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// ModuleRegistry: ${ModuleRegistry.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should set controller to token owner", async () => { +// await I_SecurityToken.setController(token_owner, {from: token_owner}); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); +// }); + +// }); + +// describe("Buy tokens using on-chain whitelist", async() => { + +// it("Should Buy the tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// false, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('10', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('10', 'ether') +// ); +// }); + +// it("Should Buy some more tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// false, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('10', 'ether') +// ); +// }); + +// it("Add a new token holder", async() => { + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// false, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), +// web3.utils.toWei('10', 'ether') +// ); +// }); + +// it("Fuzz test balance checkpoints", async() => { +// await I_SecurityToken.changeGranularity(1, {from: token_owner}); +// let cps = []; +// let ts = []; +// for (let j = 0; j < 10; j++) { +// let balance1 = BigNumber(await I_SecurityToken.balanceOf(account_investor1)); +// let balance2 = BigNumber(await I_SecurityToken.balanceOf(account_investor2)); +// let balance3 = BigNumber(await I_SecurityToken.balanceOf(account_investor3)); +// let totalSupply = BigNumber(await I_SecurityToken.totalSupply()); +// cps.push([balance1, balance2, balance3]); +// ts.push(totalSupply); +// console.log("Checkpoint: " + (j + 1) + " Balances: " + JSON.stringify(cps[cps.length - 1]) + " TotalSupply: " + JSON.stringify(totalSupply)); +// await I_SecurityToken.createCheckpoint({ from: token_owner }); +// let checkpointTimes = (await I_SecurityToken.getCheckpointTimes()); +// assert.equal(checkpointTimes.length, (j + 1)); +// console.log("Checkpoint Times: " + checkpointTimes); +// let txs = Math.floor(Math.random() * 3); +// for (let i = 0; i < txs; i++) { +// let sender; +// let receiver; +// let s = Math.random() * 3; +// if (s < 1) { +// sender = account_investor1; +// } else if (s < 2) { +// sender = account_investor2; +// } else { +// sender = account_investor3; +// } +// let r = Math.random() * 3; +// if (r < 1) { +// receiver = account_investor1; +// } else if (r < 2) { +// receiver = account_investor2; +// } else { +// receiver = account_investor3; +// } +// let m = Math.random(); +// let amount = BigNumber(await I_SecurityToken.balanceOf(sender)).mul(Math.random().toFixed(10)).toFixed(0); +// if (m > 0.8) { +// console.log("Sending full balance"); +// amount = BigNumber(await I_SecurityToken.balanceOf(sender)); +// } +// console.log("Sender: " + sender + " Receiver: " + receiver + " Amount: " + JSON.stringify(amount)); +// await I_SecurityToken.transfer(receiver, amount, { from: sender }); +// } +// if (Math.random() > 0.5) { +// let n = BigNumber(Math.random().toFixed(10)).mul(10**17).toFixed(0); +// let p = Math.random() * 3; +// let r = Math.random() * 3; +// let minter; +// if (r < 1) { +// minter = account_investor1; +// } else if (r < 2) { +// minter = account_investor2; +// } else { +// minter = account_investor3; +// } +// console.log("Minting: " + n.toString() + " to: " + minter); +// await I_SecurityToken.mint(minter, n, { from: token_owner }); +// } +// if (Math.random() > 0.5) { +// let n = BigNumber(Math.random().toFixed(10)).mul(10**17); +// let p = Math.random() * 3; +// let r = Math.random() * 3; +// let burner; +// if (r < 1) { +// burner = account_investor1; +// } else if (r < 2) { +// burner = account_investor2; +// } else { +// burner = account_investor3; +// } +// let burnerBalance = BigNumber(await I_SecurityToken.balanceOf(burner)); +// if (n.gt(burnerBalance.div(2))) { +// n = burnerBalance.div(2); +// } +// n = n.toFixed(0); +// console.log("Burning: " + n.toString() + " from: " + burner); +// await I_SecurityToken.forceBurn(burner, n, "", "", { from: token_owner }); +// } +// console.log("Checking Interim..."); +// for (let k = 0; k < cps.length; k++) { +// let balance1 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); +// let balance2 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); +// let balance3 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); +// let totalSupply = BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); +// let balances = [balance1, balance2, balance3]; +// console.log("Checking TotalSupply: " + totalSupply + " is " + ts[k] + " at checkpoint: " + (k + 1)); +// assert.isTrue(totalSupply.eq(ts[k])); +// console.log("Checking Balances: " + balances + " is " + cps[k] + " at checkpoint: " + (k + 1)); +// for (let l = 0; l < cps[k].length; l++) { +// // console.log(balances[l].toString(), cps[k][l].toString()); +// assert.isTrue(balances[l].eq(cps[k][l])); +// } +// } +// } +// console.log("Checking..."); +// for (let k = 0; k < cps.length; k++) { +// let balance1 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); +// let balance2 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); +// let balance3 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); +// let totalSupply = BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); +// let balances = [balance1, balance2, balance3]; +// console.log("Checking TotalSupply: " + totalSupply + " is " + ts[k] + " at checkpoint: " + (k + 1)); +// assert.isTrue(totalSupply.eq(ts[k])); +// console.log("Checking Balances: " + balances + " is " + cps[k] + " at checkpoint: " + (k + 1)); +// for (let l = 0; l < cps[k].length; l++) { +// // console.log(balances[l].toString(), cps[k][l].toString()); +// assert.isTrue(balances[l].eq(cps[k][l])); +// } +// } + +// }); +// }); + +// }); diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 164538f50..2b762825c 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -1,505 +1,505 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); -const CountTransferManager = artifacts.require('./CountTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('CountTransferManager', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let P_CountTransferManagerFactory; - let P_CountTransferManager; - let I_GeneralTransferManagerFactory; - let I_CountTransferManagerFactory; - let I_GeneralPermissionManager; - let I_CountTransferManager; - let I_GeneralTransferManager; - let I_ExchangeTransferManager; - let I_ModuleRegistry; - let I_ModuleRegistryProxy; - let I_MRProxied; - let I_STRProxied; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - // CountTransferManager details - const holderCount = 2; // Maximum number of token holders - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - let bytesSTO = encodeModuleCall(['uint256'], [holderCount]); - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[7]; - account_investor2 = accounts[8]; - account_investor3 = accounts[9]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 6: Deploy the CountTransferManager - I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_CountTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CountTransferManagerFactory contract was not deployed" - ); - - // STEP 7: Deploy Paid the CountTransferManager - P_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); - assert.notEqual( - P_CountTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CountTransferManagerFactory contract was not deployed" - ); - - // Step 9: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 10: Deploy the SecurityTokenRegistry - - // Deploy the SecurityTokenregistry - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 11: Deploy the proxy and attach the implementation contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 12: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 8: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the CountTransferManagerFactory - await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the Paid CountTransferManagerFactory - await I_MRProxied.registerModule(P_CountTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(P_CountTransferManagerFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - CountTransferManagerFactory: ${I_CountTransferManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - it("Should successfully attach the CountTransferManager factory with the security token", async () => { - let errorThrown = false; - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - try { - const tx = await I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - } catch(error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the CountTransferManager factory with the security token", async () => { - let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "CountTransferManagerFactory doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "CountTransferManager", - "CountTransferManagerFactory module was not added" - ); - P_CountTransferManager = CountTransferManager.at(tx.logs[3].args._module); - await revertToSnapshot(snapId); - }); - - it("Should successfully attach the CountTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "CountTransferManager", - "CountTransferManager module was not added" - ); - I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); - }); - }); - - describe("Buy tokens using on-chain whitelist", async() => { - - it("Should Buy the tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should fail to buy some more tokens (more than 2 holders)", async() => { - // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - - let errorThrown = false; - try { - // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('3', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Too many holders`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - - it("Should still be able to add to original token holders", async() => { - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('4', 'ether') - ); - }); - - it("Should still be able to transfer between existing token holders before count change", async() => { - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should fail in modifying the holder count", async() => { - let errorThrown = false; - try { - await I_CountTransferManager.changeHolderCount(1, { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to change the holder count`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Modify holder count to 1", async() => { - // Add the Investor in to the whitelist - // Mint some tokens - await I_CountTransferManager.changeHolderCount(1, { from: token_owner }); - - assert.equal( - (await I_CountTransferManager.maxHolderCount()).toNumber(), - 1 - ); - }); - - it("Should still be able to transfer between existing token holders after count change", async() => { - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('4', 'ether') - ); - }); - - it("Should not be able to transfer to a new token holder", async() => { - let errorThrown = false; - // await I_CountTransferManager.unpause({from: token_owner}); - try { - // Mint some tokens - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> Too many holders`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - }); - - it("Should be able to consolidate balances", async() => { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - }); - - it("Should get the permission list", async() => { - let perm = await I_CountTransferManager.getPermissions.call(); - assert.equal(perm.length, 1); - }); - - describe("Test cases for the factory", async() => { - it("should get the exact details of the factory", async() => { - assert.equal(await I_CountTransferManagerFactory.setupCost.call(),0); - assert.equal((await I_CountTransferManagerFactory.getTypes.call())[0],2); - assert.equal(web3.utils.toAscii(await I_CountTransferManagerFactory.getName.call()) - .replace(/\u0000/g, ''), - "CountTransferManager", - "Wrong Module added"); - assert.equal(await I_CountTransferManagerFactory.getDescription.call(), - "Restrict the number of investors", - "Wrong Module added"); - assert.equal(await I_CountTransferManagerFactory.getTitle.call(), - "Count Transfer Manager", - "Wrong Module added"); - assert.equal(await I_CountTransferManagerFactory.getInstructions.call(), - "Allows an issuer to restrict the total number of non-zero token holders", - "Wrong Module added"); - - }); - - it("Should get the tags of the factory", async() => { - let tags = await I_CountTransferManagerFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Count"); - }); - }); - - }); - -}); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); +// const CountTransferManager = artifacts.require('./CountTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('CountTransferManager', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let P_CountTransferManagerFactory; +// let P_CountTransferManager; +// let I_GeneralTransferManagerFactory; +// let I_CountTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_CountTransferManager; +// let I_GeneralTransferManager; +// let I_ExchangeTransferManager; +// let I_ModuleRegistry; +// let I_ModuleRegistryProxy; +// let I_MRProxied; +// let I_STRProxied; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_STFactory; +// let I_SecurityToken; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; + +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// // CountTransferManager details +// const holderCount = 2; // Maximum number of token holders +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; +// let bytesSTO = encodeModuleCall(['uint256'], [holderCount]); + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; + +// account_investor1 = accounts[7]; +// account_investor2 = accounts[8]; +// account_investor3 = accounts[9]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// assert.notEqual( +// I_FeatureRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "FeatureRegistry contract was not deployed", +// ); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 6: Deploy the CountTransferManager +// I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); +// assert.notEqual( +// I_CountTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CountTransferManagerFactory contract was not deployed" +// ); + +// // STEP 7: Deploy Paid the CountTransferManager +// P_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); +// assert.notEqual( +// P_CountTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CountTransferManagerFactory contract was not deployed" +// ); + +// // Step 9: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 10: Deploy the SecurityTokenRegistry + +// // Deploy the SecurityTokenregistry +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 11: Deploy the proxy and attach the implementation contract +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 12: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 8: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the CountTransferManagerFactory +// await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the Paid CountTransferManagerFactory +// await I_MRProxied.registerModule(P_CountTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(P_CountTransferManagerFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// CountTransferManagerFactory: ${I_CountTransferManagerFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); + +// it("Should successfully attach the CountTransferManager factory with the security token", async () => { +// let errorThrown = false; +// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); +// try { +// const tx = await I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx -> failed because Token is not paid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the CountTransferManager factory with the security token", async () => { +// let snapId = await takeSnapshot(); +// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); +// const tx = await I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "CountTransferManagerFactory doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[3].args._name) +// .replace(/\u0000/g, ''), +// "CountTransferManager", +// "CountTransferManagerFactory module was not added" +// ); +// P_CountTransferManager = CountTransferManager.at(tx.logs[3].args._module); +// await revertToSnapshot(snapId); +// }); + +// it("Should successfully attach the CountTransferManager with the security token", async () => { +// const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "CountTransferManager", +// "CountTransferManager module was not added" +// ); +// I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); +// }); +// }); + +// describe("Buy tokens using on-chain whitelist", async() => { + +// it("Should Buy the tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(5000); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Should Buy some more tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('2', 'ether') +// ); +// }); + +// it("Should fail to buy some more tokens (more than 2 holders)", async() => { +// // Add the Investor in to the whitelist +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + +// let errorThrown = false; +// try { +// // Mint some tokens +// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('3', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Too many holders`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + + +// it("Should still be able to add to original token holders", async() => { +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('4', 'ether') +// ); +// }); + +// it("Should still be able to transfer between existing token holders before count change", async() => { +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('2', 'ether') +// ); +// }); + +// it("Should fail in modifying the holder count", async() => { +// let errorThrown = false; +// try { +// await I_CountTransferManager.changeHolderCount(1, { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> Only owner have the permission to change the holder count`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Modify holder count to 1", async() => { +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_CountTransferManager.changeHolderCount(1, { from: token_owner }); + +// assert.equal( +// (await I_CountTransferManager.maxHolderCount()).toNumber(), +// 1 +// ); +// }); + +// it("Should still be able to transfer between existing token holders after count change", async() => { +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('4', 'ether') +// ); +// }); + +// it("Should not be able to transfer to a new token holder", async() => { +// let errorThrown = false; +// // await I_CountTransferManager.unpause({from: token_owner}); +// try { +// // Mint some tokens +// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> Too many holders`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Should be able to consolidate balances", async() => { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// }); + +// it("Should get the permission list", async() => { +// let perm = await I_CountTransferManager.getPermissions.call(); +// assert.equal(perm.length, 1); +// }); + +// describe("Test cases for the factory", async() => { +// it("should get the exact details of the factory", async() => { +// assert.equal(await I_CountTransferManagerFactory.setupCost.call(),0); +// assert.equal((await I_CountTransferManagerFactory.getTypes.call())[0],2); +// assert.equal(web3.utils.toAscii(await I_CountTransferManagerFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "CountTransferManager", +// "Wrong Module added"); +// assert.equal(await I_CountTransferManagerFactory.getDescription.call(), +// "Restrict the number of investors", +// "Wrong Module added"); +// assert.equal(await I_CountTransferManagerFactory.getTitle.call(), +// "Count Transfer Manager", +// "Wrong Module added"); +// assert.equal(await I_CountTransferManagerFactory.getInstructions.call(), +// "Allows an issuer to restrict the total number of non-zero token holders", +// "Wrong Module added"); + +// }); + +// it("Should get the tags of the factory", async() => { +// let tags = await I_CountTransferManagerFactory.getTags.call(); +// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Count"); +// }); +// }); + +// }); + +// }); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 9f8f71984..5e918d99f 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -1,963 +1,963 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol'); -const ERC20DividendCheckpoint = artifacts.require('./ERC20DividendCheckpoint'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('ERC20DividendCheckpoint', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_temp; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - let dividendName = "0x546573744469766964656e640000000000000000000000000000000000000000"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_GeneralTransferManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_ERC20DividendCheckpointFactory; - let P_ERC20DividendCheckpointFactory; - let P_ERC20DividendCheckpoint; - let I_GeneralPermissionManager; - let I_ERC20DividendCheckpoint; - let I_GeneralTransferManager; - let I_ExchangeTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_STRProxied; - let I_MRProxied; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - let snapId; - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - const checkpointKey = 4; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[6]; - account_investor2 = accounts[7]; - account_investor3 = accounts[8]; - account_investor4 = accounts[9]; - account_temp = accounts[2]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 6: Deploy the ERC20DividendCheckpoint - P_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); - assert.notEqual( - P_ERC20DividendCheckpointFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ERC20DividendCheckpointFactory contract was not deployed" - ); - - // STEP 7: Deploy the ERC20DividendCheckpoint - I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_ERC20DividendCheckpointFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ERC20DividendCheckpointFactory contract was not deployed" - ); - - // Step 9: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 10: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 11: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 12: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 8: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the ERC20DividendCheckpointFactory - await I_MRProxied.registerModule(I_ERC20DividendCheckpointFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); - - // (C) : Register the Paid ERC20DividendCheckpointFactory - await I_MRProxied.registerModule(P_ERC20DividendCheckpointFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(P_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - ERC20DividendCheckpointFactory: ${I_ERC20DividendCheckpointFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - it("Should successfully attach the ERC20DividendCheckpoint with the security token - fail insufficient payment", async () => { - let errorThrown = false; - try { - const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - } catch(error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the ERC20DividendCheckpoint with the security token with budget", async () => { - let snapId = await takeSnapshot() - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "ERC20DividendCheckpoint", - "ERC20DividendCheckpoint module was not added" - ); - P_ERC20DividendCheckpoint = ERC20DividendCheckpoint.at(tx.logs[3].args._module); - await revertToSnapshot(snapId); - }); - - it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "ERC20DividendCheckpoint", - "ERC20DividendCheckpoint module was not added" - ); - I_ERC20DividendCheckpoint = ERC20DividendCheckpoint.at(tx.logs[2].args._module); - }); - }); - - describe("Check Dividend payouts", async() => { - - it("Buy some tokens for account_investor1 (1 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(30), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Buy some tokens for account_investor2 (2 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(30), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should fail in creating the dividend - incorrect allowance", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); - try { - let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because allowance = 0`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail in creating the dividend - maturity > expiry", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() - duration.days(10); - await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('1.5', 'ether'), {from: token_owner}); - try { - let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because maturity > expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail in creating the dividend - now > expiry", async() => { - let errorThrown = false; - let maturity = latestTime() - duration.days(2); - let expiry = latestTime() - duration.days(1); - try { - let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because now > expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail in creating the dividend - bad token", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - try { - let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, 0, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because token address is 0x`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail in creating the dividend - amount is 0", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - try { - let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, 0, dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because amount < 0`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create new dividend of POLY tokens", async() => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - - let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 1, "Dividend should be created at checkpoint 1"); - assert.equal(tx.logs[0].args._name.toString(), dividendName, "Dividend name incorrect in event"); - }); - - it("Investor 1 transfers his token balance to investor 2", async() => { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), {from: account_investor1}); - assert.equal(await I_SecurityToken.balanceOf(account_investor1), 0); - assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('3', 'ether')); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails maturity in the future", async() => { - let errorThrown = false; - try { - await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because dividend index has maturity in future`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails not owner", async() => { - let errorThrown = false; - // Increase time by 2 day - await increaseTime(duration.days(2)); - try { - await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: account_temp}); - } catch(error) { - console.log(` tx -> failed because msg.sender is not the owner`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails wrong index", async() => { - let errorThrown = false; - try { - await I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because dividend index is greator than the dividend array length`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { - let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner, gas: 5000000}); - let investor1BalanceAfter = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2BalanceAfter = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - assert.equal(investor1BalanceAfter.sub(investor1Balance).toNumber(), web3.utils.toWei('0.5', 'ether')); - assert.equal(investor2BalanceAfter.sub(investor2Balance).toNumber(), web3.utils.toWei('1', 'ether')); - //Check fully claimed - assert.equal((await I_ERC20DividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei('1.5', 'ether')); - }); - - it("Buy some tokens for account_temp (1 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_temp, - latestTime(), - latestTime(), - latestTime() + duration.days(20), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_temp.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_temp, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_temp)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Should not allow to create dividend without name", async() => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); - await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('1.5', 'ether'), {from: token_owner}); - let errorThrown = false; - try { - await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), '', {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because dividend name is empty`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create new dividend", async() => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); - // approved in above test - let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 1"); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails past expiry", async() => { - let errorThrown = false; - await increaseTime(duration.days(12)); - try { - await I_ERC20DividendCheckpoint.pushDividendPayment(1, 0, 10, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because dividend index has passed its expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoin - fails already reclaimed", async() => { - let errorThrown = false; - let tx = await I_ERC20DividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); - assert.equal((tx.logs[0].args._claimedAmount).toNumber(), web3.utils.toWei("1.5", "ether")); - try { - await I_ERC20DividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); - } catch(error) { - console.log(` tx -> failed because dividend index has already reclaimed`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Buy some tokens for account_investor3 (7 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('7', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('7', 'ether') - ); - }); - - it("Exclude account_temp using global exclusion list", async() => { - await I_ERC20DividendCheckpoint.setDefaultExcluded([account_temp], {from: token_owner}); - }); - - it("Create another new dividend", async() => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - await I_PolyToken.getTokens(web3.utils.toWei('11', 'ether'), token_owner); - await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('11', 'ether'), {from: token_owner}); - let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('10', 'ether'), dividendName, {from: token_owner}); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 2"); - }); - - it("should investor 3 claims dividend - fail bad index", async() => { - let errorThrown = false; - let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - try { - await I_ERC20DividendCheckpoint.pullDividendPayment(5, {from: account_investor3, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because dividend index is not valid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("should investor 3 claims dividend", async() => { - console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); - let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - await I_ERC20DividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); - let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); - assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); - assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei('7', 'ether')); - }); - - it("should investor 3 claims dividend - fails already claimed", async() => { - let errorThrown = false; - try { - await I_ERC20DividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because investor already claimed the dividend`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("should issuer pushes remain", async() => { - console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); - let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - let investorTempBalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_temp)); - await I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); - let investor1BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - let investorTempBalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_temp)); - assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); - assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), web3.utils.toWei('3', 'ether')); - assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); - assert.equal(investorTempBalanceAfter2.sub(investorTempBalanceAfter1).toNumber(), 0); - //Check fully claimed - assert.equal((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei('10', 'ether')); - }); - - - it("Delete global exclusion list", async() => { - await I_ERC20DividendCheckpoint.setDefaultExcluded([], {from: token_owner}); - }); - - - it("Investor 2 transfers 1 ETH of his token balance to investor 1", async() => { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_investor2}); - assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); - assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); - assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); - assert.equal(await I_SecurityToken.balanceOf(account_temp), web3.utils.toWei('1', 'ether')); - }); - - it("Create another new dividend with explicit checkpoint - fails bad allowance", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() + duration.days(2); - let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); - console.log(JSON.stringify(tx.logs[0].args)); - console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); - await I_PolyToken.getTokens(web3.utils.toWei('20', 'ether'), token_owner); - try { - tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because allowance is not provided`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create another new dividend with explicit - fails maturity > expiry", async() => { - console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); - - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() - duration.days(10); - await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('20', 'ether'), {from: token_owner}); - try { - tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because maturity > expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create another new dividend with explicit - fails now > expiry", async() => { - console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); - - let errorThrown = false; - let maturity = latestTime() - duration.days(5); - let expiry = latestTime() - duration.days(2); - try { - tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because now > expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create another new dividend with explicit - fails bad checkpoint", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() + duration.days(2); - try { - tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 5, dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because checkpoint id > current checkpoint`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Set withholding tax of 20% on account_temp and 10% on investor2", async() => { - await I_ERC20DividendCheckpoint.setWithholding([account_temp, account_investor2], [BigNumber(20*10**16), BigNumber(10*10**16)], {from: token_owner}); - }); - - it("Create another new dividend with explicit checkpoint and exclusion", async() => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - await I_PolyToken.getTokens(web3.utils.toWei('11', 'ether'), token_owner); - await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('11', 'ether'), {from: token_owner}); - let tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, I_PolyToken.address, web3.utils.toWei('10', 'ether'), 4, [account_investor1], dividendName, {from: token_owner}); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 3"); - }); - - it("Investor 2 claims dividend, issuer pushes investor 1 - fails not owner", async() => { - let errorThrown = false; - let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - try { - await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(2, [account_investor2, account_investor1],{from: account_investor2, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because not called by the owner`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Investor 2 claims dividend, issuer pushes investor 1 - fails bad index", async() => { - let errorThrown = false; - let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - try { - await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(5, [account_investor2, account_investor1],{from: token_owner, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because dividend index is not valid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("should calculate dividend before the push dividend payment", async() => { - let dividendAmount1 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor1); - let dividendAmount2 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor2); - let dividendAmount3 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor3); - let dividendAmount_temp = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_temp); - assert.equal(dividendAmount1[0].toNumber(), web3.utils.toWei("0", "ether")); - assert.equal(dividendAmount2[0].toNumber(), web3.utils.toWei("2", "ether")); - assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); - assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); - assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); - assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.2", "ether")); - assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); - assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0.2", "ether")); - }); - - it("Investor 2 claims dividend", async() => { - let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - let tempBalance = BigNumber(await web3.eth.getBalance(account_temp)); - await I_ERC20DividendCheckpoint.pullDividendPayment(3, {from: account_investor2, gasPrice: 0}); - let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); - assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); - assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei('1.8', 'ether')); - assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); - assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); - }); - - it("Should issuer pushes temp investor - investor1 excluded", async() => { - let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - let tempBalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_temp)); - await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(3, [account_temp, account_investor1], {from: token_owner}); - let investor1BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - let tempBalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_temp)); - assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); - assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), 0); - assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); - assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toNumber(), web3.utils.toWei('0.8', 'ether')); - //Check fully claimed - assert.equal((await I_ERC20DividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei('3', 'ether')); - }); - - it("should calculate dividend after the push dividend payment", async() => { - let dividendAmount1 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor1); - let dividendAmount2 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor2); - assert.equal(dividendAmount1[0].toNumber(), 0); - assert.equal(dividendAmount2[0].toNumber(), 0); - }); - - it("Issuer reclaims withholding tax", async() => { - let issuerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); - await I_ERC20DividendCheckpoint.withdrawWithholding(3, {from: token_owner, gasPrice: 0}); - let issuerBalanceAfter = BigNumber(await I_PolyToken.balanceOf(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.4', 'ether')) - }); - - it("Issuer unable to reclaim dividend (expiry not passed)", async() => { - let errorThrown = false; - try { - await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner}); - } catch(error) { - console.log(`Tx Failed because expiry is in the future ${0}. Test Passed Successfully`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Issuer is able to reclaim dividend after expiry", async() => { - let errorThrown = false; - await increaseTime(11 * 24 * 60 * 60); - try { - await I_ERC20DividendCheckpoint.reclaimDividend(8, {from: token_owner, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because dividend index is not valid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer is able to reclaim dividend after expiry", async() => { - let tokenOwnerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); - await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); - let tokenOwnerAfter = BigNumber(await I_PolyToken.balanceOf(token_owner)); - assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei('7', 'ether')); - }); - - - it("Issuer is able to reclaim dividend after expiry", async() => { - let errorThrown = false; - let tokenOwnerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); - try { - await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because dividend are already reclaimed`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Investor 3 unable to pull dividend after expiry", async() => { - let errorThrown = false; - try { - await I_ERC20DividendCheckpoint.pullDividendPayment(3, {from: account_investor3, gasPrice: 0}); - } catch(error) { - console.log(`Tx Failed because expiry is in the past ${0}. Test Passed Successfully`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - - }); - - it("Should give the right dividend index", async() => { - let index = await I_ERC20DividendCheckpoint.getDividendIndex.call(3); - assert.equal(index[0], 2); - }); - - it("Should give the right dividend index", async() => { - let index = await I_ERC20DividendCheckpoint.getDividendIndex.call(8); - assert.equal(index.length, 0); - }); - - it("Get the init data", async() => { - let tx = await I_ERC20DividendCheckpoint.getInitFunction.call(); - assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); - }); - - it("Should get the listed permissions", async() => { - let tx = await I_ERC20DividendCheckpoint.getPermissions.call(); - assert.equal(tx.length,1); - }); - - describe("Test cases for the ERC20DividendCheckpointFactory", async() => { - it("should get the exact details of the factory", async() => { - assert.equal((await I_ERC20DividendCheckpointFactory.setupCost.call()).toNumber(), 0); - assert.equal((await I_ERC20DividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(web3.utils.toAscii(await I_ERC20DividendCheckpointFactory.getName.call()) - .replace(/\u0000/g, ''), - "ERC20DividendCheckpoint", - "Wrong Module added"); - assert.equal(await I_ERC20DividendCheckpointFactory.getDescription.call(), - "Create ERC20 dividends for token holders at a specific checkpoint", - "Wrong Module added"); - assert.equal(await I_ERC20DividendCheckpointFactory.getTitle.call(), - "ERC20 Dividend Checkpoint", - "Wrong Module added"); - assert.equal(await I_ERC20DividendCheckpointFactory.getInstructions.call(), - "Create a ERC20 dividend which will be paid out to token holders proportional to their balances at the point the dividend is created", - "Wrong Module added"); - let tags = await I_ERC20DividendCheckpointFactory.getTags.call(); - assert.equal(tags.length, 3); - - }); - }); - - }); - -}); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol'); +// const ERC20DividendCheckpoint = artifacts.require('./ERC20DividendCheckpoint'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('ERC20DividendCheckpoint', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; +// let account_temp; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; +// let dividendName = "0x546573744469766964656e640000000000000000000000000000000000000000"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_GeneralTransferManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_ERC20DividendCheckpointFactory; +// let P_ERC20DividendCheckpointFactory; +// let P_ERC20DividendCheckpoint; +// let I_GeneralPermissionManager; +// let I_ERC20DividendCheckpoint; +// let I_GeneralTransferManager; +// let I_ExchangeTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_STRProxied; +// let I_MRProxied; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_STFactory; +// let I_SecurityToken; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; +// let snapId; +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; +// const checkpointKey = 4; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; + +// account_investor1 = accounts[6]; +// account_investor2 = accounts[7]; +// account_investor3 = accounts[8]; +// account_investor4 = accounts[9]; +// account_temp = accounts[2]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 6: Deploy the ERC20DividendCheckpoint +// P_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); +// assert.notEqual( +// P_ERC20DividendCheckpointFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "ERC20DividendCheckpointFactory contract was not deployed" +// ); + +// // STEP 7: Deploy the ERC20DividendCheckpoint +// I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); +// assert.notEqual( +// I_ERC20DividendCheckpointFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "ERC20DividendCheckpointFactory contract was not deployed" +// ); + +// // Step 9: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 10: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 11: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 12: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 8: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the ERC20DividendCheckpointFactory +// await I_MRProxied.registerModule(I_ERC20DividendCheckpointFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); + +// // (C) : Register the Paid ERC20DividendCheckpointFactory +// await I_MRProxied.registerModule(P_ERC20DividendCheckpointFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(P_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// ERC20DividendCheckpointFactory: ${I_ERC20DividendCheckpointFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); + +// it("Should successfully attach the ERC20DividendCheckpoint with the security token - fail insufficient payment", async () => { +// let errorThrown = false; +// try { +// const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx -> failed because Token is not paid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the ERC20DividendCheckpoint with the security token with budget", async () => { +// let snapId = await takeSnapshot() +// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); +// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); +// const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[3].args._name) +// .replace(/\u0000/g, ''), +// "ERC20DividendCheckpoint", +// "ERC20DividendCheckpoint module was not added" +// ); +// P_ERC20DividendCheckpoint = ERC20DividendCheckpoint.at(tx.logs[3].args._module); +// await revertToSnapshot(snapId); +// }); + +// it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { +// const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "ERC20DividendCheckpoint", +// "ERC20DividendCheckpoint module was not added" +// ); +// I_ERC20DividendCheckpoint = ERC20DividendCheckpoint.at(tx.logs[2].args._module); +// }); +// }); + +// describe("Check Dividend payouts", async() => { + +// it("Buy some tokens for account_investor1 (1 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(30), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(5000); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Buy some tokens for account_investor2 (2 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(30), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('2', 'ether') +// ); +// }); + +// it("Should fail in creating the dividend - incorrect allowance", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(10); +// await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); +// try { +// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because allowance = 0`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in creating the dividend - maturity > expiry", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() - duration.days(10); +// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('1.5', 'ether'), {from: token_owner}); +// try { +// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because maturity > expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in creating the dividend - now > expiry", async() => { +// let errorThrown = false; +// let maturity = latestTime() - duration.days(2); +// let expiry = latestTime() - duration.days(1); +// try { +// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because now > expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in creating the dividend - bad token", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(10); +// try { +// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, 0, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because token address is 0x`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in creating the dividend - amount is 0", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(10); +// try { +// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, 0, dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because amount < 0`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create new dividend of POLY tokens", async() => { +// let maturity = latestTime() + duration.days(1); +// let expiry = latestTime() + duration.days(10); + +// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); +// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 1, "Dividend should be created at checkpoint 1"); +// assert.equal(tx.logs[0].args._name.toString(), dividendName, "Dividend name incorrect in event"); +// }); + +// it("Investor 1 transfers his token balance to investor 2", async() => { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), {from: account_investor1}); +// assert.equal(await I_SecurityToken.balanceOf(account_investor1), 0); +// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('3', 'ether')); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails maturity in the future", async() => { +// let errorThrown = false; +// try { +// await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because dividend index has maturity in future`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails not owner", async() => { +// let errorThrown = false; +// // Increase time by 2 day +// await increaseTime(duration.days(2)); +// try { +// await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: account_temp}); +// } catch(error) { +// console.log(` tx -> failed because msg.sender is not the owner`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails wrong index", async() => { +// let errorThrown = false; +// try { +// await I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because dividend index is greator than the dividend array length`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { +// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner, gas: 5000000}); +// let investor1BalanceAfter = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2BalanceAfter = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// assert.equal(investor1BalanceAfter.sub(investor1Balance).toNumber(), web3.utils.toWei('0.5', 'ether')); +// assert.equal(investor2BalanceAfter.sub(investor2Balance).toNumber(), web3.utils.toWei('1', 'ether')); +// //Check fully claimed +// assert.equal((await I_ERC20DividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei('1.5', 'ether')); +// }); + +// it("Buy some tokens for account_temp (1 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_temp, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(20), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_temp.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_temp, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_temp)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Should not allow to create dividend without name", async() => { +// let maturity = latestTime() + duration.days(1); +// let expiry = latestTime() + duration.days(10); +// await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); +// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('1.5', 'ether'), {from: token_owner}); +// let errorThrown = false; +// try { +// await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), '', {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because dividend name is empty`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create new dividend", async() => { +// let maturity = latestTime() + duration.days(1); +// let expiry = latestTime() + duration.days(10); +// await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); +// // approved in above test +// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); +// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 1"); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails past expiry", async() => { +// let errorThrown = false; +// await increaseTime(duration.days(12)); +// try { +// await I_ERC20DividendCheckpoint.pushDividendPayment(1, 0, 10, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because dividend index has passed its expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoin - fails already reclaimed", async() => { +// let errorThrown = false; +// let tx = await I_ERC20DividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); +// assert.equal((tx.logs[0].args._claimedAmount).toNumber(), web3.utils.toWei("1.5", "ether")); +// try { +// await I_ERC20DividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); +// } catch(error) { +// console.log(` tx -> failed because dividend index has already reclaimed`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Buy some tokens for account_investor3 (7 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('7', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), +// web3.utils.toWei('7', 'ether') +// ); +// }); + +// it("Exclude account_temp using global exclusion list", async() => { +// await I_ERC20DividendCheckpoint.setDefaultExcluded([account_temp], {from: token_owner}); +// }); + +// it("Create another new dividend", async() => { +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(10); +// await I_PolyToken.getTokens(web3.utils.toWei('11', 'ether'), token_owner); +// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('11', 'ether'), {from: token_owner}); +// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('10', 'ether'), dividendName, {from: token_owner}); +// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 2"); +// }); + +// it("should investor 3 claims dividend - fail bad index", async() => { +// let errorThrown = false; +// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// try { +// await I_ERC20DividendCheckpoint.pullDividendPayment(5, {from: account_investor3, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because dividend index is not valid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("should investor 3 claims dividend", async() => { +// console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); +// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// await I_ERC20DividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); +// let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); +// assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); +// assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei('7', 'ether')); +// }); + +// it("should investor 3 claims dividend - fails already claimed", async() => { +// let errorThrown = false; +// try { +// await I_ERC20DividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because investor already claimed the dividend`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("should issuer pushes remain", async() => { +// console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); +// let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// let investorTempBalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_temp)); +// await I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); +// let investor1BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// let investorTempBalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_temp)); +// assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); +// assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), web3.utils.toWei('3', 'ether')); +// assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); +// assert.equal(investorTempBalanceAfter2.sub(investorTempBalanceAfter1).toNumber(), 0); +// //Check fully claimed +// assert.equal((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei('10', 'ether')); +// }); + + +// it("Delete global exclusion list", async() => { +// await I_ERC20DividendCheckpoint.setDefaultExcluded([], {from: token_owner}); +// }); + + +// it("Investor 2 transfers 1 ETH of his token balance to investor 1", async() => { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_investor2}); +// assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); +// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); +// assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); +// assert.equal(await I_SecurityToken.balanceOf(account_temp), web3.utils.toWei('1', 'ether')); +// }); + +// it("Create another new dividend with explicit checkpoint - fails bad allowance", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(2); +// let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); +// console.log(JSON.stringify(tx.logs[0].args)); +// console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); +// await I_PolyToken.getTokens(web3.utils.toWei('20', 'ether'), token_owner); +// try { +// tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because allowance is not provided`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create another new dividend with explicit - fails maturity > expiry", async() => { +// console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); + +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() - duration.days(10); +// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('20', 'ether'), {from: token_owner}); +// try { +// tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because maturity > expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create another new dividend with explicit - fails now > expiry", async() => { +// console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); + +// let errorThrown = false; +// let maturity = latestTime() - duration.days(5); +// let expiry = latestTime() - duration.days(2); +// try { +// tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because now > expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create another new dividend with explicit - fails bad checkpoint", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(2); +// try { +// tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 5, dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because checkpoint id > current checkpoint`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Set withholding tax of 20% on account_temp and 10% on investor2", async() => { +// await I_ERC20DividendCheckpoint.setWithholding([account_temp, account_investor2], [BigNumber(20*10**16), BigNumber(10*10**16)], {from: token_owner}); +// }); + +// it("Create another new dividend with explicit checkpoint and exclusion", async() => { +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(10); +// await I_PolyToken.getTokens(web3.utils.toWei('11', 'ether'), token_owner); +// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('11', 'ether'), {from: token_owner}); +// let tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, I_PolyToken.address, web3.utils.toWei('10', 'ether'), 4, [account_investor1], dividendName, {from: token_owner}); +// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 3"); +// }); + +// it("Investor 2 claims dividend, issuer pushes investor 1 - fails not owner", async() => { +// let errorThrown = false; +// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// try { +// await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(2, [account_investor2, account_investor1],{from: account_investor2, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because not called by the owner`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Investor 2 claims dividend, issuer pushes investor 1 - fails bad index", async() => { +// let errorThrown = false; +// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// try { +// await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(5, [account_investor2, account_investor1],{from: token_owner, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because dividend index is not valid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("should calculate dividend before the push dividend payment", async() => { +// let dividendAmount1 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor1); +// let dividendAmount2 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor2); +// let dividendAmount3 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor3); +// let dividendAmount_temp = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_temp); +// assert.equal(dividendAmount1[0].toNumber(), web3.utils.toWei("0", "ether")); +// assert.equal(dividendAmount2[0].toNumber(), web3.utils.toWei("2", "ether")); +// assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); +// assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); +// assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); +// assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.2", "ether")); +// assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); +// assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0.2", "ether")); +// }); + +// it("Investor 2 claims dividend", async() => { +// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// let tempBalance = BigNumber(await web3.eth.getBalance(account_temp)); +// await I_ERC20DividendCheckpoint.pullDividendPayment(3, {from: account_investor2, gasPrice: 0}); +// let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); +// assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); +// assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei('1.8', 'ether')); +// assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); +// assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); +// }); + +// it("Should issuer pushes temp investor - investor1 excluded", async() => { +// let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// let tempBalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_temp)); +// await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(3, [account_temp, account_investor1], {from: token_owner}); +// let investor1BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// let tempBalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_temp)); +// assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); +// assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), 0); +// assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); +// assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toNumber(), web3.utils.toWei('0.8', 'ether')); +// //Check fully claimed +// assert.equal((await I_ERC20DividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei('3', 'ether')); +// }); + +// it("should calculate dividend after the push dividend payment", async() => { +// let dividendAmount1 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor1); +// let dividendAmount2 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor2); +// assert.equal(dividendAmount1[0].toNumber(), 0); +// assert.equal(dividendAmount2[0].toNumber(), 0); +// }); + +// it("Issuer reclaims withholding tax", async() => { +// let issuerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); +// await I_ERC20DividendCheckpoint.withdrawWithholding(3, {from: token_owner, gasPrice: 0}); +// let issuerBalanceAfter = BigNumber(await I_PolyToken.balanceOf(token_owner)); +// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.4', 'ether')) +// }); + +// it("Issuer unable to reclaim dividend (expiry not passed)", async() => { +// let errorThrown = false; +// try { +// await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner}); +// } catch(error) { +// console.log(`Tx Failed because expiry is in the future ${0}. Test Passed Successfully`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer is able to reclaim dividend after expiry", async() => { +// let errorThrown = false; +// await increaseTime(11 * 24 * 60 * 60); +// try { +// await I_ERC20DividendCheckpoint.reclaimDividend(8, {from: token_owner, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because dividend index is not valid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer is able to reclaim dividend after expiry", async() => { +// let tokenOwnerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); +// await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); +// let tokenOwnerAfter = BigNumber(await I_PolyToken.balanceOf(token_owner)); +// assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei('7', 'ether')); +// }); + + +// it("Issuer is able to reclaim dividend after expiry", async() => { +// let errorThrown = false; +// let tokenOwnerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); +// try { +// await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because dividend are already reclaimed`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Investor 3 unable to pull dividend after expiry", async() => { +// let errorThrown = false; +// try { +// await I_ERC20DividendCheckpoint.pullDividendPayment(3, {from: account_investor3, gasPrice: 0}); +// } catch(error) { +// console.log(`Tx Failed because expiry is in the past ${0}. Test Passed Successfully`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Should give the right dividend index", async() => { +// let index = await I_ERC20DividendCheckpoint.getDividendIndex.call(3); +// assert.equal(index[0], 2); +// }); + +// it("Should give the right dividend index", async() => { +// let index = await I_ERC20DividendCheckpoint.getDividendIndex.call(8); +// assert.equal(index.length, 0); +// }); + +// it("Get the init data", async() => { +// let tx = await I_ERC20DividendCheckpoint.getInitFunction.call(); +// assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); +// }); + +// it("Should get the listed permissions", async() => { +// let tx = await I_ERC20DividendCheckpoint.getPermissions.call(); +// assert.equal(tx.length,1); +// }); + +// describe("Test cases for the ERC20DividendCheckpointFactory", async() => { +// it("should get the exact details of the factory", async() => { +// assert.equal((await I_ERC20DividendCheckpointFactory.setupCost.call()).toNumber(), 0); +// assert.equal((await I_ERC20DividendCheckpointFactory.getTypes.call())[0], 4); +// assert.equal(web3.utils.toAscii(await I_ERC20DividendCheckpointFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "ERC20DividendCheckpoint", +// "Wrong Module added"); +// assert.equal(await I_ERC20DividendCheckpointFactory.getDescription.call(), +// "Create ERC20 dividends for token holders at a specific checkpoint", +// "Wrong Module added"); +// assert.equal(await I_ERC20DividendCheckpointFactory.getTitle.call(), +// "ERC20 Dividend Checkpoint", +// "Wrong Module added"); +// assert.equal(await I_ERC20DividendCheckpointFactory.getInstructions.call(), +// "Create a ERC20 dividend which will be paid out to token holders proportional to their balances at the point the dividend is created", +// "Wrong Module added"); +// let tags = await I_ERC20DividendCheckpointFactory.getTags.call(); +// assert.equal(tags.length, 3); + +// }); +// }); + +// }); + +// }); diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index b65a8f7c1..18cd0b39e 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -1,983 +1,983 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol'); -const EtherDividendCheckpoint = artifacts.require('./EtherDividendCheckpoint'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('EtherDividendCheckpoint', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_temp; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - let dividendName = "0x546573744469766964656e640000000000000000000000000000000000000000"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let P_EtherDividendCheckpointFactory; - let P_EtherDividendCheckpoint; - let I_EtherDividendCheckpointFactory; - let I_GeneralPermissionManager; - let I_EtherDividendCheckpoint; - let I_GeneralTransferManager; - let I_ExchangeTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_MRProxied; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - let snapId; - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - const checkpointKey = 4; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[6]; - account_investor2 = accounts[7]; - account_investor3 = accounts[8]; - account_investor4 = accounts[9]; - account_temp = accounts[2]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 4: Deploy the ERC20DividendCheckpoint - P_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); - assert.notEqual( - P_EtherDividendCheckpointFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ERC20DividendCheckpointFactory contract was not deployed" - ); - - // STEP 4: Deploy the EtherDividendCheckpoint - I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_EtherDividendCheckpointFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "EtherDividendCheckpointFactory contract was not deployed" - ); - - // Step 6: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 7: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 8: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 9: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 5: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the EtherDividendCheckpointFactory - await I_MRProxied.registerModule(I_EtherDividendCheckpointFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); - - // (C) : Register the Paid EtherDividendCheckpointFactory - await I_MRProxied.registerModule(P_EtherDividendCheckpointFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(P_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - EtherDividendCheckpointFactory: ${I_EtherDividendCheckpointFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { - let errorThrown = false; - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - try { - const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - } catch(error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { - let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "EtherDividendCheckpoint", - "EtherDividendCheckpoint module was not added" - ); - P_EtherDividendCheckpoint = EtherDividendCheckpoint.at(tx.logs[3].args._module); - await revertToSnapshot(snapId); - }); - - it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "EtherDividendCheckpoint", - "EtherDividendCheckpoint module was not added" - ); - I_EtherDividendCheckpoint = EtherDividendCheckpoint.at(tx.logs[2].args._module); - }); - }); - - describe("Check Dividend payouts", async() => { - - it("Buy some tokens for account_investor1 (1 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(30), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Buy some tokens for account_investor2 (2 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(30), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should fail in creating the dividend", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - try { - let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because msg.value = 0`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail in creating the dividend", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() - duration.days(10); - try { - let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); - } catch(error) { - console.log(` tx -> failed because maturity > expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail in creating the dividend", async() => { - let errorThrown = false; - let maturity = latestTime() - duration.days(2); - let expiry = latestTime() - duration.days(1); - try { - let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); - } catch(error) { - console.log(` tx -> failed because now > expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Set withholding tax of 20% on investor 2", async() => { - await I_EtherDividendCheckpoint.setWithholdingFixed([account_investor2], BigNumber(20*10**16), {from: token_owner}); - }); - - it("Should fail in creating the dividend", async() => { - let errorThrown = false; - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - try { - await I_EtherDividendCheckpoint.createDividend(maturity, expiry, '', {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); - } catch(error) { - console.log(` tx -> failed because dividend name is empty`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create new dividend", async() => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 1, "Dividend should be created at checkpoint 1"); - assert.equal(tx.logs[0].args._name.toString(), dividendName, "Dividend name incorrect in event"); - }); - - it("Investor 1 transfers his token balance to investor 2", async() => { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), {from: account_investor1}); - assert.equal(await I_SecurityToken.balanceOf(account_investor1), 0); - assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('3', 'ether')); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { - let errorThrown = false; - try { - await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because dividend index has maturity in future`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { - let errorThrown = false; - // Increase time by 2 day - await increaseTime(duration.days(2)); - try { - await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: account_temp}); - } catch(error) { - console.log(` tx -> failed because msg.sender is not the owner`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { - let errorThrown = false; - try { - await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because dividend index is greator than the dividend array length`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { - let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); - await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); - let investor1BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor2)); - assert.equal(investor1BalanceAfter.sub(investor1Balance).toNumber(), web3.utils.toWei('0.5', 'ether')); - assert.equal(investor2BalanceAfter.sub(investor2Balance).toNumber(), web3.utils.toWei('0.8', 'ether')); - //Check fully claimed - assert.equal((await I_EtherDividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei('1.5', 'ether')); - }); - - it("Issuer reclaims withholding tax", async() => { - let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); - await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); - let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.2', 'ether')) - }); - - it("No more withholding tax to withdraw", async() => { - let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); - await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); - let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) - }); - - it("Buy some tokens for account_temp (1 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_temp, - latestTime(), - latestTime(), - latestTime() + duration.days(20), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_temp.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_temp, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_temp)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Create new dividend", async() => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 2"); - }); - - it("Issuer pushes dividends fails due to passed expiry", async() => { - let errorThrown = false; - await increaseTime(duration.days(12)); - try { - await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); - } catch(error) { - console.log(` tx -> failed because dividend index has passed its expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer reclaims dividend", async() => { - let errorThrown = false; - let tx = await I_EtherDividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); - assert.equal((tx.logs[0].args._claimedAmount).toNumber(), web3.utils.toWei("1.5", "ether")); - try { - await I_EtherDividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); - } catch(error) { - console.log(` tx -> failed because dividend index has already reclaimed`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Still no more withholding tax to withdraw", async() => { - let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); - await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); - let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) - }); - - it("Buy some tokens for account_investor3 (7 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('7', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('7', 'ether') - ); - }); - - it("Create another new dividend", async() => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 3"); - }); - - it("should investor 3 claims dividend - fails bad index", async() => { - let errorThrown = false; - let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - try { - await I_EtherDividendCheckpoint.pullDividendPayment(5, {from: account_investor3, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because dividend index is not valid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should investor 3 claims dividend", async() => { - let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3Balance = BigNumber(await web3.eth.getBalance(account_investor3)); - await I_EtherDividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); - let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); - assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); - assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); - assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei('7', 'ether')); - }); - - it("Still no more withholding tax to withdraw", async() => { - let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); - await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); - let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) - }); - - it("should investor 3 claims dividend", async() => { - let errorThrown = false; - try { - await I_EtherDividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because investor already claimed the dividend`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer pushes remainder", async() => { - let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); - await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); - let investor1BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor3)); - assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); - assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), web3.utils.toWei('2.4', 'ether')); - assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); - //Check fully claimed - assert.equal((await I_EtherDividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei('11', 'ether')); - }); - - it("Issuer withdraws new withholding tax", async() => { - let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); - await I_EtherDividendCheckpoint.withdrawWithholding(2, {from: token_owner, gasPrice: 0}); - let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.6', 'ether')) - }); - - it("Investor 2 transfers 1 ETH of his token balance to investor 1", async() => { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_investor2}); - assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); - assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); - assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); - }); - - it("Create another new dividend with no value - fails", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() + duration.days(2); - let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); - try { - tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: 0}); - } catch(error) { - console.log(` tx -> failed because msg.value is 0`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create another new dividend with explicit", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() - duration.days(10); - try { - tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); - } catch(error) { - console.log(` tx -> failed because maturity > expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create another new dividend with bad expirty - fails", async() => { - let errorThrown = false; - let maturity = latestTime() - duration.days(5); - let expiry = latestTime() - duration.days(2); - try { - tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); - } catch(error) { - console.log(` tx -> failed because now > expiry`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create another new dividend with bad checkpoint in the future - fails", async() => { - let errorThrown = false; - let maturity = latestTime(); - let expiry = latestTime() + duration.days(2); - try { - tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 5, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); - } catch(error) { - console.log(` tx -> failed because checkpoint id > current checkpoint`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Create another new dividend with explicit checkpoint and excluding account_investor1", async() => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); - tx = await I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, 4, [account_investor1], dividendName, {from: token_owner, value: web3.utils.toWei('10', 'ether')}); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 4"); - }); - - it("Non-owner pushes investor 1 - fails", async() => { - let errorThrown = false; - let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - try { - await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor2, account_investor1],{from: account_investor2, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because not called by the owner`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("issuer pushes investor 1 with bad dividend index - fails", async() => { - let errorThrown = false; - let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); - try { - await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(6, [account_investor2, account_investor1],{from: token_owner, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because dividend index is not valid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("should calculate dividend before the push dividend payment", async() => { - let dividendAmount1 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor1); - let dividendAmount2 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor2); - let dividendAmount3 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor3); - let dividendAmount_temp = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_temp); - //1 has 1/11th, 2 has 2/11th, 3 has 7/11th, temp has 1/11th, but 1 is excluded - assert.equal(dividendAmount1[0].toNumber(), web3.utils.toWei("0", "ether")); - assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); - assert.equal(dividendAmount2[0].toNumber(), web3.utils.toWei("2", "ether")); - assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.4", "ether")); - assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); - assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); - assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); - assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0", "ether")); - }); - - it("Investor 2 claims dividend", async() => { - let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3Balance = BigNumber(await web3.eth.getBalance(account_investor3)); - let tempBalance = BigNumber(await web3.eth.getBalance(account_temp)); - await I_EtherDividendCheckpoint.pullDividendPayment(3, {from: account_investor2, gasPrice: 0}); - let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); - let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); - assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); - assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei('1.6', 'ether')); - assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); - assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); - }); - - it("Should issuer pushes investor 1 and temp investor", async() => { - let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); - let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); - await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor1, account_temp], {from: token_owner}); - let investor1BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor3)); - let tempBalanceAfter2 = BigNumber(await web3.eth.getBalance(account_temp)); - assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); - assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), 0); - assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); - assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toNumber(), web3.utils.toWei('1', 'ether')); - //Check fully claimed - assert.equal((await I_EtherDividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei('3', 'ether')); - }); - - it("should calculate dividend after the push dividend payment", async() => { - let dividendAmount1 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor1); - let dividendAmount2 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor2); - assert.equal(dividendAmount1[0].toNumber(), 0); - assert.equal(dividendAmount2[0].toNumber(), 0); - }); - - it("Issuer unable to reclaim dividend (expiry not passed)", async() => { - let errorThrown = false; - try { - await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner}); - } catch(error) { - console.log(`Tx Failed because expiry is in the future ${0}. Test Passed Successfully`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Issuer is able to reclaim dividend after expiry", async() => { - let errorThrown = false; - await increaseTime(11 * 24 * 60 * 60); - try { - await I_EtherDividendCheckpoint.reclaimDividend(8, {from: token_owner, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because dividend index is not valid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Issuer is able to reclaim dividend after expiry", async() => { - let tokenOwnerBalance = BigNumber(await web3.eth.getBalance(token_owner)); - await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); - let tokenOwnerAfter = BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei('7', 'ether')); - }); - - it("Issuer is able to reclaim dividend after expiry", async() => { - let errorThrown = false; - try { - await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); - } catch(error) { - console.log(` tx -> failed because dividend are already reclaimed`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Investor 3 unable to pull dividend after expiry", async() => { - let errorThrown = false; - try { - await I_EtherDividendCheckpoint.pullDividendPayment(3, {from: account_investor3, gasPrice: 0}); - } catch(error) { - console.log(`Tx Failed because expiry is in the past ${0}. Test Passed Successfully`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Assign token balance to an address that can't receive funds", async() => { - - let tx = await I_GeneralTransferManager.modifyWhitelist( - I_PolyToken.address, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 500000 - }); - // Jump time - await increaseTime(5000); - // Mint some tokens - await I_SecurityToken.mint(I_PolyToken.address, web3.utils.toWei('1', 'ether'), { from: token_owner }); - assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); - assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); - assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); - assert.equal(await I_SecurityToken.balanceOf(account_temp), web3.utils.toWei('1', 'ether')); - assert.equal(await I_SecurityToken.balanceOf(I_PolyToken.address), web3.utils.toWei('1', 'ether')); - }); - - it("Create another new dividend", async() => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - let tx = await I_EtherDividendCheckpoint.createDividendWithExclusions(maturity, expiry, [], dividendName, {from: token_owner, value: web3.utils.toWei('12', 'ether')}); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 6, "Dividend should be created at checkpoint 6"); - }); - - it("Should issuer pushes all dividends", async() => { - let investor1BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor3)); - let tempBalanceBefore = BigNumber(await web3.eth.getBalance(account_temp)); - let tokenBalanceBefore = BigNumber(await web3.eth.getBalance(I_PolyToken.address)); - - await I_EtherDividendCheckpoint.pushDividendPayment(4, 0, 10, {from: token_owner}); - - let investor1BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor3)); - let tempBalanceAfter = BigNumber(await web3.eth.getBalance(account_temp)); - let tokenBalanceAfter = BigNumber(await web3.eth.getBalance(I_PolyToken.address)); - - assert.equal(investor1BalanceAfter.sub(investor1BalanceBefore).toNumber(), web3.utils.toWei('1', 'ether')); - assert.equal(investor2BalanceAfter.sub(investor2BalanceBefore).toNumber(), web3.utils.toWei('1.6', 'ether')); - assert.equal(investor3BalanceAfter.sub(investor3BalanceBefore).toNumber(), web3.utils.toWei('7', 'ether')); - assert.equal(tempBalanceAfter.sub(tempBalanceBefore).toNumber(), web3.utils.toWei('1', 'ether')); - assert.equal(tokenBalanceAfter.sub(tokenBalanceBefore).toNumber(), web3.utils.toWei('0', 'ether')); - - //Check partially claimed - assert.equal((await I_EtherDividendCheckpoint.dividends(4))[5].toNumber(), web3.utils.toWei('11', 'ether')); - }); - - it("Should give the right dividend index", async() => { - let index = await I_EtherDividendCheckpoint.getDividendIndex.call(3); - assert.equal(index[0], 2); - }); - - it("Should give the right dividend index", async() => { - let index = await I_EtherDividendCheckpoint.getDividendIndex.call(8); - assert.equal(index.length, 0); - }); - - it("Get the init data", async() => { - let tx = await I_EtherDividendCheckpoint.getInitFunction.call(); - assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); - }); - - it("Should get the listed permissions", async() => { - let tx = await I_EtherDividendCheckpoint.getPermissions.call(); - assert.equal(tx.length,1); - }); - - describe("Test cases for the EtherDividendCheckpointFactory", async() => { - it("should get the exact details of the factory", async() => { - assert.equal((await I_EtherDividendCheckpointFactory.setupCost.call()).toNumber(), 0); - assert.equal((await I_EtherDividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(web3.utils.toAscii(await I_EtherDividendCheckpointFactory.getName.call()) - .replace(/\u0000/g, ''), - "EtherDividendCheckpoint", - "Wrong Module added"); - assert.equal(await I_EtherDividendCheckpointFactory.getDescription.call(), - "Create ETH dividends for token holders at a specific checkpoint", - "Wrong Module added"); - assert.equal(await I_EtherDividendCheckpointFactory.getTitle.call(), - "Ether Dividend Checkpoint", - "Wrong Module added"); - assert.equal(await I_EtherDividendCheckpointFactory.getInstructions.call(), - "Create a dividend which will be paid out to token holders proportional to their balances at the point the dividend is created", - "Wrong Module added"); - let tags = await I_EtherDividendCheckpointFactory.getTags.call(); - assert.equal(tags.length, 3); - - }); - }); - - }); - -}); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol'); +// const EtherDividendCheckpoint = artifacts.require('./EtherDividendCheckpoint'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('EtherDividendCheckpoint', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; +// let account_temp; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; +// let dividendName = "0x546573744469766964656e640000000000000000000000000000000000000000"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let P_EtherDividendCheckpointFactory; +// let P_EtherDividendCheckpoint; +// let I_EtherDividendCheckpointFactory; +// let I_GeneralPermissionManager; +// let I_EtherDividendCheckpoint; +// let I_GeneralTransferManager; +// let I_ExchangeTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_STRProxied; +// let I_STFactory; +// let I_SecurityToken; +// let I_PolyToken; +// let I_MRProxied; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; +// let snapId; +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; +// const checkpointKey = 4; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; + +// account_investor1 = accounts[6]; +// account_investor2 = accounts[7]; +// account_investor3 = accounts[8]; +// account_investor4 = accounts[9]; +// account_temp = accounts[2]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the ERC20DividendCheckpoint +// P_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); +// assert.notEqual( +// P_EtherDividendCheckpointFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "ERC20DividendCheckpointFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the EtherDividendCheckpoint +// I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); +// assert.notEqual( +// I_EtherDividendCheckpointFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "EtherDividendCheckpointFactory contract was not deployed" +// ); + +// // Step 6: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 7: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 8: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 9: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 5: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the EtherDividendCheckpointFactory +// await I_MRProxied.registerModule(I_EtherDividendCheckpointFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); + +// // (C) : Register the Paid EtherDividendCheckpointFactory +// await I_MRProxied.registerModule(P_EtherDividendCheckpointFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(P_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// EtherDividendCheckpointFactory: ${I_EtherDividendCheckpointFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); + +// it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { +// let errorThrown = false; +// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); +// try { +// const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx -> failed because Token is not paid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { +// let snapId = await takeSnapshot(); +// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); +// const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[3].args._name) +// .replace(/\u0000/g, ''), +// "EtherDividendCheckpoint", +// "EtherDividendCheckpoint module was not added" +// ); +// P_EtherDividendCheckpoint = EtherDividendCheckpoint.at(tx.logs[3].args._module); +// await revertToSnapshot(snapId); +// }); + +// it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { +// const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "EtherDividendCheckpoint", +// "EtherDividendCheckpoint module was not added" +// ); +// I_EtherDividendCheckpoint = EtherDividendCheckpoint.at(tx.logs[2].args._module); +// }); +// }); + +// describe("Check Dividend payouts", async() => { + +// it("Buy some tokens for account_investor1 (1 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(30), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(5000); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Buy some tokens for account_investor2 (2 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(30), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('2', 'ether') +// ); +// }); + +// it("Should fail in creating the dividend", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(10); +// try { +// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because msg.value = 0`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in creating the dividend", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() - duration.days(10); +// try { +// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); +// } catch(error) { +// console.log(` tx -> failed because maturity > expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in creating the dividend", async() => { +// let errorThrown = false; +// let maturity = latestTime() - duration.days(2); +// let expiry = latestTime() - duration.days(1); +// try { +// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); +// } catch(error) { +// console.log(` tx -> failed because now > expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Set withholding tax of 20% on investor 2", async() => { +// await I_EtherDividendCheckpoint.setWithholdingFixed([account_investor2], BigNumber(20*10**16), {from: token_owner}); +// }); + +// it("Should fail in creating the dividend", async() => { +// let errorThrown = false; +// let maturity = latestTime() + duration.days(1); +// let expiry = latestTime() + duration.days(10); +// try { +// await I_EtherDividendCheckpoint.createDividend(maturity, expiry, '', {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); +// } catch(error) { +// console.log(` tx -> failed because dividend name is empty`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create new dividend", async() => { +// let maturity = latestTime() + duration.days(1); +// let expiry = latestTime() + duration.days(10); +// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); +// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 1, "Dividend should be created at checkpoint 1"); +// assert.equal(tx.logs[0].args._name.toString(), dividendName, "Dividend name incorrect in event"); +// }); + +// it("Investor 1 transfers his token balance to investor 2", async() => { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), {from: account_investor1}); +// assert.equal(await I_SecurityToken.balanceOf(account_investor1), 0); +// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('3', 'ether')); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { +// let errorThrown = false; +// try { +// await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because dividend index has maturity in future`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { +// let errorThrown = false; +// // Increase time by 2 day +// await increaseTime(duration.days(2)); +// try { +// await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: account_temp}); +// } catch(error) { +// console.log(` tx -> failed because msg.sender is not the owner`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { +// let errorThrown = false; +// try { +// await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because dividend index is greator than the dividend array length`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { +// let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); +// await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); +// let investor1BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor2)); +// assert.equal(investor1BalanceAfter.sub(investor1Balance).toNumber(), web3.utils.toWei('0.5', 'ether')); +// assert.equal(investor2BalanceAfter.sub(investor2Balance).toNumber(), web3.utils.toWei('0.8', 'ether')); +// //Check fully claimed +// assert.equal((await I_EtherDividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei('1.5', 'ether')); +// }); + +// it("Issuer reclaims withholding tax", async() => { +// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); +// await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); +// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); +// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.2', 'ether')) +// }); + +// it("No more withholding tax to withdraw", async() => { +// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); +// await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); +// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); +// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) +// }); + +// it("Buy some tokens for account_temp (1 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_temp, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(20), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_temp.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_temp, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_temp)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Create new dividend", async() => { +// let maturity = latestTime() + duration.days(1); +// let expiry = latestTime() + duration.days(10); +// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); +// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 2"); +// }); + +// it("Issuer pushes dividends fails due to passed expiry", async() => { +// let errorThrown = false; +// await increaseTime(duration.days(12)); +// try { +// await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); +// } catch(error) { +// console.log(` tx -> failed because dividend index has passed its expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer reclaims dividend", async() => { +// let errorThrown = false; +// let tx = await I_EtherDividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); +// assert.equal((tx.logs[0].args._claimedAmount).toNumber(), web3.utils.toWei("1.5", "ether")); +// try { +// await I_EtherDividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); +// } catch(error) { +// console.log(` tx -> failed because dividend index has already reclaimed`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Still no more withholding tax to withdraw", async() => { +// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); +// await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); +// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); +// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) +// }); + +// it("Buy some tokens for account_investor3 (7 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('7', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), +// web3.utils.toWei('7', 'ether') +// ); +// }); + +// it("Create another new dividend", async() => { +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(10); +// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); +// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 3"); +// }); + +// it("should investor 3 claims dividend - fails bad index", async() => { +// let errorThrown = false; +// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// try { +// await I_EtherDividendCheckpoint.pullDividendPayment(5, {from: account_investor3, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because dividend index is not valid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should investor 3 claims dividend", async() => { +// let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3Balance = BigNumber(await web3.eth.getBalance(account_investor3)); +// await I_EtherDividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); +// let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); +// assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); +// assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); +// assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei('7', 'ether')); +// }); + +// it("Still no more withholding tax to withdraw", async() => { +// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); +// await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); +// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); +// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) +// }); + +// it("should investor 3 claims dividend", async() => { +// let errorThrown = false; +// try { +// await I_EtherDividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because investor already claimed the dividend`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer pushes remainder", async() => { +// let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); +// await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); +// let investor1BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor3)); +// assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); +// assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), web3.utils.toWei('2.4', 'ether')); +// assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); +// //Check fully claimed +// assert.equal((await I_EtherDividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei('11', 'ether')); +// }); + +// it("Issuer withdraws new withholding tax", async() => { +// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); +// await I_EtherDividendCheckpoint.withdrawWithholding(2, {from: token_owner, gasPrice: 0}); +// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); +// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.6', 'ether')) +// }); + +// it("Investor 2 transfers 1 ETH of his token balance to investor 1", async() => { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_investor2}); +// assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); +// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); +// assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); +// }); + +// it("Create another new dividend with no value - fails", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(2); +// let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); +// try { +// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: 0}); +// } catch(error) { +// console.log(` tx -> failed because msg.value is 0`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create another new dividend with explicit", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() - duration.days(10); +// try { +// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); +// } catch(error) { +// console.log(` tx -> failed because maturity > expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create another new dividend with bad expirty - fails", async() => { +// let errorThrown = false; +// let maturity = latestTime() - duration.days(5); +// let expiry = latestTime() - duration.days(2); +// try { +// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); +// } catch(error) { +// console.log(` tx -> failed because now > expiry`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create another new dividend with bad checkpoint in the future - fails", async() => { +// let errorThrown = false; +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(2); +// try { +// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 5, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); +// } catch(error) { +// console.log(` tx -> failed because checkpoint id > current checkpoint`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Create another new dividend with explicit checkpoint and excluding account_investor1", async() => { +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(10); +// let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); +// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, 4, [account_investor1], dividendName, {from: token_owner, value: web3.utils.toWei('10', 'ether')}); +// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 4"); +// }); + +// it("Non-owner pushes investor 1 - fails", async() => { +// let errorThrown = false; +// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// try { +// await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor2, account_investor1],{from: account_investor2, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because not called by the owner`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("issuer pushes investor 1 with bad dividend index - fails", async() => { +// let errorThrown = false; +// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); +// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); +// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); +// try { +// await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(6, [account_investor2, account_investor1],{from: token_owner, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because dividend index is not valid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("should calculate dividend before the push dividend payment", async() => { +// let dividendAmount1 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor1); +// let dividendAmount2 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor2); +// let dividendAmount3 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor3); +// let dividendAmount_temp = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_temp); +// //1 has 1/11th, 2 has 2/11th, 3 has 7/11th, temp has 1/11th, but 1 is excluded +// assert.equal(dividendAmount1[0].toNumber(), web3.utils.toWei("0", "ether")); +// assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); +// assert.equal(dividendAmount2[0].toNumber(), web3.utils.toWei("2", "ether")); +// assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.4", "ether")); +// assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); +// assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); +// assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); +// assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0", "ether")); +// }); + +// it("Investor 2 claims dividend", async() => { +// let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3Balance = BigNumber(await web3.eth.getBalance(account_investor3)); +// let tempBalance = BigNumber(await web3.eth.getBalance(account_temp)); +// await I_EtherDividendCheckpoint.pullDividendPayment(3, {from: account_investor2, gasPrice: 0}); +// let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); +// let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); +// assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); +// assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei('1.6', 'ether')); +// assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); +// assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); +// }); + +// it("Should issuer pushes investor 1 and temp investor", async() => { +// let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); +// let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); +// await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor1, account_temp], {from: token_owner}); +// let investor1BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor3)); +// let tempBalanceAfter2 = BigNumber(await web3.eth.getBalance(account_temp)); +// assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); +// assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), 0); +// assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); +// assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toNumber(), web3.utils.toWei('1', 'ether')); +// //Check fully claimed +// assert.equal((await I_EtherDividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei('3', 'ether')); +// }); + +// it("should calculate dividend after the push dividend payment", async() => { +// let dividendAmount1 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor1); +// let dividendAmount2 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor2); +// assert.equal(dividendAmount1[0].toNumber(), 0); +// assert.equal(dividendAmount2[0].toNumber(), 0); +// }); + +// it("Issuer unable to reclaim dividend (expiry not passed)", async() => { +// let errorThrown = false; +// try { +// await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner}); +// } catch(error) { +// console.log(`Tx Failed because expiry is in the future ${0}. Test Passed Successfully`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer is able to reclaim dividend after expiry", async() => { +// let errorThrown = false; +// await increaseTime(11 * 24 * 60 * 60); +// try { +// await I_EtherDividendCheckpoint.reclaimDividend(8, {from: token_owner, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because dividend index is not valid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Issuer is able to reclaim dividend after expiry", async() => { +// let tokenOwnerBalance = BigNumber(await web3.eth.getBalance(token_owner)); +// await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); +// let tokenOwnerAfter = BigNumber(await web3.eth.getBalance(token_owner)); +// assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei('7', 'ether')); +// }); + +// it("Issuer is able to reclaim dividend after expiry", async() => { +// let errorThrown = false; +// try { +// await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); +// } catch(error) { +// console.log(` tx -> failed because dividend are already reclaimed`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Investor 3 unable to pull dividend after expiry", async() => { +// let errorThrown = false; +// try { +// await I_EtherDividendCheckpoint.pullDividendPayment(3, {from: account_investor3, gasPrice: 0}); +// } catch(error) { +// console.log(`Tx Failed because expiry is in the past ${0}. Test Passed Successfully`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Assign token balance to an address that can't receive funds", async() => { + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// I_PolyToken.address, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); +// // Jump time +// await increaseTime(5000); +// // Mint some tokens +// await I_SecurityToken.mint(I_PolyToken.address, web3.utils.toWei('1', 'ether'), { from: token_owner }); +// assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); +// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); +// assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); +// assert.equal(await I_SecurityToken.balanceOf(account_temp), web3.utils.toWei('1', 'ether')); +// assert.equal(await I_SecurityToken.balanceOf(I_PolyToken.address), web3.utils.toWei('1', 'ether')); +// }); + +// it("Create another new dividend", async() => { +// let maturity = latestTime(); +// let expiry = latestTime() + duration.days(10); +// let tx = await I_EtherDividendCheckpoint.createDividendWithExclusions(maturity, expiry, [], dividendName, {from: token_owner, value: web3.utils.toWei('12', 'ether')}); +// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 6, "Dividend should be created at checkpoint 6"); +// }); + +// it("Should issuer pushes all dividends", async() => { +// let investor1BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor3)); +// let tempBalanceBefore = BigNumber(await web3.eth.getBalance(account_temp)); +// let tokenBalanceBefore = BigNumber(await web3.eth.getBalance(I_PolyToken.address)); + +// await I_EtherDividendCheckpoint.pushDividendPayment(4, 0, 10, {from: token_owner}); + +// let investor1BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor1)); +// let investor2BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor2)); +// let investor3BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor3)); +// let tempBalanceAfter = BigNumber(await web3.eth.getBalance(account_temp)); +// let tokenBalanceAfter = BigNumber(await web3.eth.getBalance(I_PolyToken.address)); + +// assert.equal(investor1BalanceAfter.sub(investor1BalanceBefore).toNumber(), web3.utils.toWei('1', 'ether')); +// assert.equal(investor2BalanceAfter.sub(investor2BalanceBefore).toNumber(), web3.utils.toWei('1.6', 'ether')); +// assert.equal(investor3BalanceAfter.sub(investor3BalanceBefore).toNumber(), web3.utils.toWei('7', 'ether')); +// assert.equal(tempBalanceAfter.sub(tempBalanceBefore).toNumber(), web3.utils.toWei('1', 'ether')); +// assert.equal(tokenBalanceAfter.sub(tokenBalanceBefore).toNumber(), web3.utils.toWei('0', 'ether')); + +// //Check partially claimed +// assert.equal((await I_EtherDividendCheckpoint.dividends(4))[5].toNumber(), web3.utils.toWei('11', 'ether')); +// }); + +// it("Should give the right dividend index", async() => { +// let index = await I_EtherDividendCheckpoint.getDividendIndex.call(3); +// assert.equal(index[0], 2); +// }); + +// it("Should give the right dividend index", async() => { +// let index = await I_EtherDividendCheckpoint.getDividendIndex.call(8); +// assert.equal(index.length, 0); +// }); + +// it("Get the init data", async() => { +// let tx = await I_EtherDividendCheckpoint.getInitFunction.call(); +// assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); +// }); + +// it("Should get the listed permissions", async() => { +// let tx = await I_EtherDividendCheckpoint.getPermissions.call(); +// assert.equal(tx.length,1); +// }); + +// describe("Test cases for the EtherDividendCheckpointFactory", async() => { +// it("should get the exact details of the factory", async() => { +// assert.equal((await I_EtherDividendCheckpointFactory.setupCost.call()).toNumber(), 0); +// assert.equal((await I_EtherDividendCheckpointFactory.getTypes.call())[0], 4); +// assert.equal(web3.utils.toAscii(await I_EtherDividendCheckpointFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "EtherDividendCheckpoint", +// "Wrong Module added"); +// assert.equal(await I_EtherDividendCheckpointFactory.getDescription.call(), +// "Create ETH dividends for token holders at a specific checkpoint", +// "Wrong Module added"); +// assert.equal(await I_EtherDividendCheckpointFactory.getTitle.call(), +// "Ether Dividend Checkpoint", +// "Wrong Module added"); +// assert.equal(await I_EtherDividendCheckpointFactory.getInstructions.call(), +// "Create a dividend which will be paid out to token holders proportional to their balances at the point the dividend is created", +// "Wrong Module added"); +// let tags = await I_EtherDividendCheckpointFactory.getTags.call(); +// assert.equal(tags.length, 3); + +// }); +// }); + +// }); + +// }); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index b04f8a18d..e6d5cde6c 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -1,493 +1,493 @@ -import latestTime from './helpers/latestTime'; -import {signData} from './helpers/signData'; -import { pk } from './helpers/testprivateKey'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -const DummySTO = artifacts.require('./DummySTO.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('GeneralPermissionManager', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let token_owner_pk; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_delegate; - let account_delegate2; - let account_delegate3; - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let P_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let P_GeneralPermissionManager; - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_DummySTOFactory; - let I_STFactory; - let I_SecurityToken; - let I_MRProxied; - let I_STRProxied; - let I_DummySTO; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - const delegateDetails = "Hello I am legit delegate"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - // Dummy STO details - const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time - const endTime = startTime + duration.days(80); // Add 80 days more - const cap = web3.utils.toWei('10', 'ether'); - const someString = "A string which is not used"; - const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, someString]); - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - token_owner_pk = pk.account_1; - - account_investor1 = accounts[8]; - account_investor2 = accounts[9]; - account_delegate = accounts[7]; - account_delegate2 = accounts[6]; - account_delegate3 = accounts[5]; - - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 6: Deploy the GeneralDelegateManagerFactory - - P_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); - - assert.notEqual( - P_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); +// import latestTime from './helpers/latestTime'; +// import {signData} from './helpers/signData'; +// import { pk } from './helpers/testprivateKey'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +// const DummySTO = artifacts.require('./DummySTO.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('GeneralPermissionManager', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let token_owner_pk; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; +// let account_delegate; +// let account_delegate2; +// let account_delegate3; +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let P_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let P_GeneralPermissionManager; +// let I_GeneralTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_DummySTOFactory; +// let I_STFactory; +// let I_SecurityToken; +// let I_MRProxied; +// let I_STRProxied; +// let I_DummySTO; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; +// const delegateDetails = "Hello I am legit delegate"; + +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// // Dummy STO details +// const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time +// const endTime = startTime + duration.days(80); // Add 80 days more +// const cap = web3.utils.toWei('10', 'ether'); +// const someString = "A string which is not used"; +// const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, someString]); + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; +// token_owner_pk = pk.account_1; + +// account_investor1 = accounts[8]; +// account_investor2 = accounts[9]; +// account_delegate = accounts[7]; +// account_delegate2 = accounts[6]; +// account_delegate3 = accounts[5]; + + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 6: Deploy the GeneralDelegateManagerFactory + +// P_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); + +// assert.notEqual( +// P_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); - // STEP 7: Deploy the DummySTOFactory +// // STEP 7: Deploy the DummySTOFactory - I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); +// I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_DummySTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "DummySTOFactory contract was not deployed" - ); +// assert.notEqual( +// I_DummySTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "DummySTOFactory contract was not deployed" +// ); - // Step 8: Deploy the STFactory contract +// // Step 8: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); - // Step 9: Deploy the SecurityTokenRegistry contract +// // Step 9: Deploy the SecurityTokenRegistry contract - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 8: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the Paid GeneralDelegateManagerFactory - await I_MRProxied.registerModule(P_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(P_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistryProxy ${ModuleRegistryProxy.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - DummySTOFactory: ${I_DummySTOFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - - it("Should successfully attach the General permission manager factory with the security token", async () => { - let errorThrown = false; - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - try { - const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - } catch(error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the General permission manager factory with the security token", async () => { - let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "GeneralPermissionManager", - "GeneralPermissionManagerFactory module was not added" - ); - P_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[3].args._module); - await revertToSnapshot(snapId); - }); - - it("Should successfully attach the General permission manager factory with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "GeneralPermissionManager", - "GeneralPermissionManagerFactory module was not added" - ); - I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); - }); - - }); - - describe("General Permission Manager test cases", async() => { - - it("Get the init data", async() => { - let tx = await I_GeneralPermissionManager.getInitFunction.call(); - assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); - }); - - it("Should fail in adding the delegate -- msg.sender doesn't have permission", async() => { - let errorThrown = false; - try { - let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_investor1}); - } catch(error) { - console.log(` tx revert -> msg.sender doesn't have permission`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in adding the delegate -- no delegate details provided", async() => { - let errorThrown = false; - try { - let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, '', { from: account_investor1}); - } catch(error) { - console.log(` tx revert -> delegate details were not provided`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to provide the permission -- because delegate is not yet added", async() => { - let errorThrown = false; - try { - let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); - } catch(error) { - console.log(` tx revert -> Delegate is not yet added`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfuly add the delegate", async() => { - let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); - assert.equal(tx.logs[0].args._delegate, account_delegate); - }); - - it("Should fail to provide the permission", async() => { - let errorThrown = false; - try { - let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: account_investor1}); - } catch(error) { - console.log(` tx revert -> msg.sender doesn't have permission`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should check the permission", async() => { - assert.isFalse(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST")); - }); - - it("Should provide the permission", async() => { - let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); - assert.equal(tx.logs[0].args._delegate, account_delegate); - }); - - it("Should check the permission", async() => { - assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST")); - }); - - it("Should check the delegate details", async() => { - assert.equal(web3.utils.toAscii(await I_GeneralPermissionManager.delegateDetails.call(account_delegate)) - .replace(/\u0000/g, ''), - delegateDetails, - "Wrong delegate address get checked"); - }); - - it("Should get the permission of the general permission manager contract", async() => { - let tx = await I_GeneralPermissionManager.getPermissions.call(); - assert.equal(web3.utils.toAscii(tx[0]) - .replace(/\u0000/g, ''), - "CHANGE_PERMISSION", - "Wrong permissions"); - }); - - it("Should return all delegates", async() => { - await I_GeneralPermissionManager.addDelegate(account_delegate2, delegateDetails, { from: token_owner}); - let tx = await I_GeneralPermissionManager.getAllDelegates.call(); - console.log(tx); - assert.equal(tx.length, 2); - assert.equal(tx[0], account_delegate); - assert.equal(tx[1], account_delegate2); - }); - - it("Should return false when check is delegate - because user is not a delegate", async() => { - assert.equal(await I_GeneralPermissionManager.checkDelegate.call(account_investor1), false); - }); - - it("Should return true when check is delegate - because user is a delegate", async() => { - assert.equal(await I_GeneralPermissionManager.checkDelegate.call(account_delegate), true); - }); +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 8: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the Paid GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(P_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(P_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistryProxy ${ModuleRegistryProxy.address} +// ModuleRegistry: ${ModuleRegistry.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// DummySTOFactory: ${I_DummySTOFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); +// }); + +// it("Should successfully attach the General permission manager factory with the security token", async () => { +// let errorThrown = false; +// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); +// try { +// const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx -> failed because Token is not paid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the General permission manager factory with the security token", async () => { +// let snapId = await takeSnapshot(); +// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); +// const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// assert.equal(tx.logs[3].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[3].args._name) +// .replace(/\u0000/g, ''), +// "GeneralPermissionManager", +// "GeneralPermissionManagerFactory module was not added" +// ); +// P_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[3].args._module); +// await revertToSnapshot(snapId); +// }); + +// it("Should successfully attach the General permission manager factory with the security token", async () => { +// const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "GeneralPermissionManager", +// "GeneralPermissionManagerFactory module was not added" +// ); +// I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); +// }); + +// }); + +// describe("General Permission Manager test cases", async() => { + +// it("Get the init data", async() => { +// let tx = await I_GeneralPermissionManager.getInitFunction.call(); +// assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); +// }); + +// it("Should fail in adding the delegate -- msg.sender doesn't have permission", async() => { +// let errorThrown = false; +// try { +// let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_investor1}); +// } catch(error) { +// console.log(` tx revert -> msg.sender doesn't have permission`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in adding the delegate -- no delegate details provided", async() => { +// let errorThrown = false; +// try { +// let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, '', { from: account_investor1}); +// } catch(error) { +// console.log(` tx revert -> delegate details were not provided`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to provide the permission -- because delegate is not yet added", async() => { +// let errorThrown = false; +// try { +// let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); +// } catch(error) { +// console.log(` tx revert -> Delegate is not yet added`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfuly add the delegate", async() => { +// let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); +// assert.equal(tx.logs[0].args._delegate, account_delegate); +// }); + +// it("Should fail to provide the permission", async() => { +// let errorThrown = false; +// try { +// let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: account_investor1}); +// } catch(error) { +// console.log(` tx revert -> msg.sender doesn't have permission`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should check the permission", async() => { +// assert.isFalse(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST")); +// }); + +// it("Should provide the permission", async() => { +// let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); +// assert.equal(tx.logs[0].args._delegate, account_delegate); +// }); + +// it("Should check the permission", async() => { +// assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST")); +// }); + +// it("Should check the delegate details", async() => { +// assert.equal(web3.utils.toAscii(await I_GeneralPermissionManager.delegateDetails.call(account_delegate)) +// .replace(/\u0000/g, ''), +// delegateDetails, +// "Wrong delegate address get checked"); +// }); + +// it("Should get the permission of the general permission manager contract", async() => { +// let tx = await I_GeneralPermissionManager.getPermissions.call(); +// assert.equal(web3.utils.toAscii(tx[0]) +// .replace(/\u0000/g, ''), +// "CHANGE_PERMISSION", +// "Wrong permissions"); +// }); + +// it("Should return all delegates", async() => { +// await I_GeneralPermissionManager.addDelegate(account_delegate2, delegateDetails, { from: token_owner}); +// let tx = await I_GeneralPermissionManager.getAllDelegates.call(); +// console.log(tx); +// assert.equal(tx.length, 2); +// assert.equal(tx[0], account_delegate); +// assert.equal(tx[1], account_delegate2); +// }); + +// it("Should return false when check is delegate - because user is not a delegate", async() => { +// assert.equal(await I_GeneralPermissionManager.checkDelegate.call(account_investor1), false); +// }); + +// it("Should return true when check is delegate - because user is a delegate", async() => { +// assert.equal(await I_GeneralPermissionManager.checkDelegate.call(account_delegate), true); +// }); - it("Should provide the permission in bulk", async() => { - await I_GeneralPermissionManager.addDelegate(account_delegate3, delegateDetails, { from: token_owner}); +// it("Should provide the permission in bulk", async() => { +// await I_GeneralPermissionManager.addDelegate(account_delegate3, delegateDetails, { from: token_owner}); - let tx = await I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}); - assert.equal(tx.logs[0].args._delegate, account_delegate3); +// let tx = await I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}); +// assert.equal(tx.logs[0].args._delegate, account_delegate3); - assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate3, I_GeneralTransferManager.address, "WHITELIST")); - assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate3, I_GeneralPermissionManager.address, "CHANGE_PERMISSION")); - }); +// assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate3, I_GeneralTransferManager.address, "WHITELIST")); +// assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate3, I_GeneralPermissionManager.address, "CHANGE_PERMISSION")); +// }); - it("Should provide all delegates with specified permission", async() => { +// it("Should provide all delegates with specified permission", async() => { - await I_GeneralPermissionManager.changePermission(account_delegate2, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); +// await I_GeneralPermissionManager.changePermission(account_delegate2, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); - let tx = await I_GeneralPermissionManager.getAllDelegatesWithPerm.call(I_GeneralTransferManager.address, "WHITELIST"); - // console.log(tx); - assert.equal(tx.length, 3); - assert.equal(tx[0], account_delegate); - assert.equal(tx[1], account_delegate2); - }); +// let tx = await I_GeneralPermissionManager.getAllDelegatesWithPerm.call(I_GeneralTransferManager.address, "WHITELIST"); +// // console.log(tx); +// assert.equal(tx.length, 3); +// assert.equal(tx[0], account_delegate); +// assert.equal(tx[1], account_delegate2); +// }); - it("Should return all modules and all permission", async() => { +// it("Should return all modules and all permission", async() => { - let tx = await I_GeneralPermissionManager.getAllModulesAndPermsFromTypes.call(account_delegate3, [2,1], I_SecurityToken.address); - console.log (tx); - assert.equal(tx[0][0], I_GeneralTransferManager.address); - assert.equal(tx[1][0], "0x57484954454c4953540000000000000000000000000000000000000000000000"); - assert.equal(tx[0][1], I_GeneralPermissionManager.address); - assert.equal(tx[1][1], "0x4348414e47455f5045524d495353494f4e000000000000000000000000000000"); +// let tx = await I_GeneralPermissionManager.getAllModulesAndPermsFromTypes.call(account_delegate3, [2,1], I_SecurityToken.address); +// console.log (tx); +// assert.equal(tx[0][0], I_GeneralTransferManager.address); +// assert.equal(tx[1][0], "0x57484954454c4953540000000000000000000000000000000000000000000000"); +// assert.equal(tx[0][1], I_GeneralPermissionManager.address); +// assert.equal(tx[1][1], "0x4348414e47455f5045524d495353494f4e000000000000000000000000000000"); - }); - - }); - - describe("General Permission Manager Factory test cases", async() => { - it("should get the exact details of the factory", async() => { - assert.equal(await I_GeneralPermissionManagerFactory.setupCost.call(),0); - assert.equal((await I_GeneralPermissionManagerFactory.getTypes.call())[0],1); - assert.equal(web3.utils.toAscii(await I_GeneralPermissionManagerFactory.getName.call()) - .replace(/\u0000/g, ''), - "GeneralPermissionManager", - "Wrong Module added"); - assert.equal(await I_GeneralPermissionManagerFactory.getDescription.call(), - "Manage permissions within the Security Token and attached modules", - "Wrong Module added"); - assert.equal(await I_GeneralPermissionManagerFactory.getTitle.call(), - "General Permission Manager", - "Wrong Module added"); - assert.equal(await I_GeneralPermissionManagerFactory.getInstructions.call(), - "Add and remove permissions for the SecurityToken and associated modules. Permission types should be encoded as bytes32 values, and attached using the withPerm modifier to relevant functions.No initFunction required.", - "Wrong Module added"); - - }); - - it("Should get the tags of the factory", async() => { - let tags = await I_GeneralPermissionManagerFactory.getTags.call(); - assert.equal(tags.length,0); - }); - }); - -}); +// }); + +// }); + +// describe("General Permission Manager Factory test cases", async() => { +// it("should get the exact details of the factory", async() => { +// assert.equal(await I_GeneralPermissionManagerFactory.setupCost.call(),0); +// assert.equal((await I_GeneralPermissionManagerFactory.getTypes.call())[0],1); +// assert.equal(web3.utils.toAscii(await I_GeneralPermissionManagerFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "GeneralPermissionManager", +// "Wrong Module added"); +// assert.equal(await I_GeneralPermissionManagerFactory.getDescription.call(), +// "Manage permissions within the Security Token and attached modules", +// "Wrong Module added"); +// assert.equal(await I_GeneralPermissionManagerFactory.getTitle.call(), +// "General Permission Manager", +// "Wrong Module added"); +// assert.equal(await I_GeneralPermissionManagerFactory.getInstructions.call(), +// "Add and remove permissions for the SecurityToken and associated modules. Permission types should be encoded as bytes32 values, and attached using the withPerm modifier to relevant functions.No initFunction required.", +// "Wrong Module added"); + +// }); + +// it("Should get the tags of the factory", async() => { +// let tags = await I_GeneralPermissionManagerFactory.getTags.call(); +// assert.equal(tags.length,0); +// }); +// }); + +// }); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 883834f30..8b230297c 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -1,863 +1,863 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import {signData} from './helpers/signData'; -import { pk } from './helpers/testprivateKey'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -const DummySTO = artifacts.require('./DummySTO.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('GeneralTransferManager', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let token_owner_pk; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_delegate; - let account_affiliates1; - let account_affiliates2; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_GeneralTransferManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_DummySTOFactory; - let I_STFactory; - let I_SecurityToken; - let I_STRProxied; - let I_MRProxied; - let I_DummySTO; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - // Dummy STO details - const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time - const endTime = startTime + duration.days(80); // Add 80 days more - const cap = web3.utils.toWei('10', 'ether'); - const someString = "A string which is not used"; - const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - token_owner_pk = pk.account_1; - - account_investor1 = accounts[8]; - account_investor2 = accounts[9]; - account_delegate = accounts[7]; - account_investor4 = accounts[6]; - - account_affiliates1 = accounts[3]; - account_affiliates2 = accounts[4]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - - // STEP 2: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 3: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 4: Deploy the DummySTOFactory - - I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_DummySTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "DummySTOFactory contract was not deployed" - ); - - // Step 8: Deploy the STFactory contract +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import {signData} from './helpers/signData'; +// import { pk } from './helpers/testprivateKey'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +// const DummySTO = artifacts.require('./DummySTO.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('GeneralTransferManager', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let token_owner_pk; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; +// let account_delegate; +// let account_affiliates1; +// let account_affiliates2; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_GeneralTransferManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_DummySTOFactory; +// let I_STFactory; +// let I_SecurityToken; +// let I_STRProxied; +// let I_MRProxied; +// let I_DummySTO; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; + +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// // Dummy STO details +// const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time +// const endTime = startTime + duration.days(80); // Add 80 days more +// const cap = web3.utils.toWei('10', 'ether'); +// const someString = "A string which is not used"; +// const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; +// token_owner_pk = pk.account_1; + +// account_investor1 = accounts[8]; +// account_investor2 = accounts[9]; +// account_delegate = accounts[7]; +// account_investor4 = accounts[6]; + +// account_affiliates1 = accounts[3]; +// account_affiliates2 = accounts[4]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + +// // STEP 2: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 3: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the DummySTOFactory + +// I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_DummySTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "DummySTOFactory contract was not deployed" +// ); + +// // Step 8: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 5: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - DummySTOFactory: ${I_DummySTOFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - it("Should whitelist the affiliates before the STO attached", async() => { - let tx = await I_GeneralTransferManager.modifyWhitelistMulti( - [account_affiliates1, account_affiliates2], - [(latestTime() + duration.days(30)),(latestTime() + duration.days(30))], - [(latestTime() + duration.days(90)),(latestTime() + duration.days(90))], - [(latestTime() + duration.years(1)),(latestTime() + duration.years(1))], - [false, false], - { - from: account_issuer, - gas: 6000000 - }); - assert.equal(tx.logs[0].args._investor, account_affiliates1); - assert.equal(tx.logs[1].args._investor, account_affiliates2); - }); - - it("Should mint the tokens to the affiliates", async () => { - await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [(100 * Math.pow(10, 18)), (100 * Math.pow(10, 18))], { from: account_issuer, gas:6000000 }); - assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates1)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); - assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); - }); - - it("Should successfully attach the STO factory with the security token", async () => { - let bytesSTO = encodeModuleCall(STOParameters, [latestTime() + duration.seconds(1000), latestTime() + duration.days(40), cap, someString]); - const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "DummySTO", - "DummySTOFactory module was not added" - ); - I_DummySTO = DummySTO.at(tx.logs[2].args._module); - }); - - it("Should successfully attach the permission manager factory with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, 0, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "GeneralPermissionManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "GeneralPermissionManager", - "GeneralPermissionManager module was not added" - ); - I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); - }); - - }); - - describe("Buy tokens using on-chain whitelist", async() => { - - it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { - let errorThrown = false; - try { - await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Investor isn't present in the whitelist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should Buy the tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Should fail in buying the token from the STO", async() => { - let errorThrown = false; - try { - await I_DummySTO.generateTokens(account_affiliates1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Investor is restricted investor`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in investing the money in STO -- expiry limit reached", async() => { - let errorThrown = false; - await increaseTime(duration.days(10)); - - try { - await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Investor isn't present in the whitelist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - }); - - describe("Buy tokens using off-chain whitelist", async() => { - - it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { - let errorThrown = false; - try { - await I_DummySTO.generateTokens(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Investor isn't present in the whitelist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should buy the tokens -- Failed due to incorrect signature input", async() => { - // Add the Investor in to the whitelist - //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk - let validFrom = latestTime(); - let validTo = latestTime() + duration.days(5); - const sig = signData(account_investor2, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, token_owner_pk); - - const r = `0x${sig.r.toString('hex')}`; - const s = `0x${sig.s.toString('hex')}`; - const v = sig.v; - let errorThrown = false; - - try { - let tx = await I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - fromTime, - toTime, - expiryTime, - true, - validFrom, - validTo, - v, - r, - s, - { - from: account_investor2, - gas: 6000000 - }); - } catch(error) { - console.log(` tx revert -> Incorrect sig data`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - - }); - - it("Should buy the tokens -- Failed due to incorrect signature timing", async() => { - // Add the Investor in to the whitelist - //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk - let validFrom = latestTime() - 100; - let validTo = latestTime() - 1; - const sig = signData(I_GeneralTransferManager.address, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, token_owner_pk); - - const r = `0x${sig.r.toString('hex')}`; - const s = `0x${sig.s.toString('hex')}`; - const v = sig.v; - - let errorThrown = false; - try { - let tx = await I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - fromTime, - toTime, - expiryTime, - true, - validFrom, - validTo, - v, - r, - s, - { - from: account_investor2, - gas: 6000000 - }); - } catch(error) { - console.log(` tx revert -> Incorrect sig data`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - - }); - - it("Should buy the tokens -- Failed due to incorrect signature signer", async() => { - // Add the Investor in to the whitelist - //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk - let validFrom = latestTime(); - let validTo = latestTime() + (60 * 60); - - const sig = signData(account_investor2, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, '2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200'); - - const r = `0x${sig.r.toString('hex')}`; - const s = `0x${sig.s.toString('hex')}`; - const v = sig.v; - let errorThrown = false; - - try { - let tx = await I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - fromTime, - toTime, - expiryTime, - true, - validFrom, - validTo, - v, - r, - s, - { - from: account_investor2, - gas: 6000000 - }); - } catch(error) { - console.log(` tx revert -> Incorrect sig data`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - - }); - - it("Should Buy the tokens", async() => { - // Add the Investor in to the whitelist - //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk - let validFrom = latestTime(); - let validTo = latestTime() + duration.days(5); - const sig = signData(I_GeneralTransferManager.address, account_investor2, latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), true, validFrom, validTo, token_owner_pk); - - const r = `0x${sig.r.toString('hex')}`; - const s = `0x${sig.s.toString('hex')}`; - const v = sig.v; - let tx = await I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - latestTime(), - latestTime() + duration.days(80), - expiryTime + duration.days(200), - true, - validFrom, - validTo, - v, - r, - s, - { - from: account_investor2, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(10000); - // Mint some tokens - - await I_DummySTO.generateTokens(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - - }); - - it("Should fail in changing the signing address", async() => { - let errorThrown = false; - try { - await I_GeneralTransferManager.changeSigningAddress(account_polymath, {from: account_investor4}); - } catch(error) { - console.log(` tx revert -> msg.sender is not token_owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should get the permission", async() => { - let perm = await I_GeneralTransferManager.getPermissions.call(); - assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "WHITELIST"); - assert.equal(web3.utils.toAscii(perm[1]).replace(/\u0000/g, ''), "FLAGS"); - }); - - it("Should provide the permission and change the signing address", async() => { - let log = await I_GeneralPermissionManager.addDelegate(account_delegate, "My details", {from: token_owner}); - assert.equal(log.logs[0].args._delegate, account_delegate); - - await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "FLAGS", true, {from: token_owner}); - - assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "FLAGS")); - - let tx = await I_GeneralTransferManager.changeSigningAddress(account_polymath, {from: account_delegate}); - assert.equal(tx.logs[0].args._signingAddress, account_polymath); - }); - - it("Should fail to pull fees as no budget set", async() => { - - let errorThrown = false; - try { - await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> No budget set`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should set a budget for the GeneralTransferManager", async() => { - await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, 10 * Math.pow(10, 18), {from: token_owner}); - let errorThrown = false; - try { - await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> No balance on token`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - await I_PolyToken.getTokens(10 * Math.pow(10, 18), token_owner); - await I_PolyToken.transfer(I_SecurityToken.address, 10 * Math.pow(10, 18), {from: token_owner}); - }); - - - it("Factory owner should pull fees - fails as not permissioned by issuer", async() => { - let errorThrown = false; - try { - await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_delegate}); - } catch(error) { - console.log(` tx revert -> Incorrect permissions`.grey); - errorThrown = true; - ensureException(error); - } - }); - - it("Factory owner should pull fees", async() => { - await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "FEE_ADMIN", true, {from: token_owner}); - let balanceBefore = await I_PolyToken.balanceOf(account_polymath); - await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_delegate}); - let balanceAfter = await I_PolyToken.balanceOf(account_polymath); - assert.equal(balanceBefore.add(web3.utils.toWei('1','ether')).toNumber(), balanceAfter.toNumber(), "Fee is transferred"); - }); - - it("Should change the white list transfer variable", async() => { - let tx = await I_GeneralTransferManager.changeAllowAllWhitelistIssuances(true, {from : token_owner}); - assert.isTrue(tx.logs[0].args._allowAllWhitelistIssuances); - }); - - it("should failed in trasfering the tokens", async() => { - let tx = await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); - await I_GeneralTransferManager.pause({from: token_owner}); - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2','ether'), {from: account_investor2}); - } catch(error) { - console.log(` tx revert -> Transfer is paused`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should change the Issuance address", async() => { - let tx = await I_GeneralTransferManager.changeIssuanceAddress(account_investor2, {from: account_delegate}); - assert.equal(tx.logs[0].args._issuanceAddress, account_investor2); - }); - - it("Should unpause the transfers", async() => { - await I_GeneralTransferManager.unpause({from: token_owner}); - - assert.isFalse(await I_GeneralTransferManager.paused.call()); - }); - - it("Should get the init function", async() => { - let byte = await I_GeneralTransferManager.getInitFunction.call(); - assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); - }); - - }); - - describe("WhiteList that addresses", async () => { - - it("Should fail in adding the investors in whitelist", async() => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - let errorThrown = false; - try { - await I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor3, account_investor4], - [fromTime, fromTime], - [toTime, toTime], - [expiryTime, expiryTime], - [true, true], - { - from: account_delegate, - gas: 6000000 - } - ); - } catch(error) { - console.log(` tx revert -> msg.sender is not allowed to modify the whitelist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - let errorThrown = false; - try { - await I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor3, account_investor4], - [fromTime], - [toTime, toTime], - [expiryTime, expiryTime], - [true, true], - { - from: account_delegate, - gas: 6000000 - } - ); - } catch(error) { - console.log(` tx revert -> Array length mismatch`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - let errorThrown = false; - try { - await I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor3, account_investor4], - [fromTime, fromTime], - [toTime], - [expiryTime, expiryTime], - [true, true], - { - from: account_delegate, - gas: 6000000 - } - ); - } catch(error) { - console.log(` tx revert -> Array length mismatch`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - let errorThrown = false; - try { - await I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor3, account_investor4], - [fromTime, fromTime], - [toTime, toTime], - [expiryTime], - [true, true], - { - from: account_delegate, - gas: 6000000 - } - ); - } catch(error) { - console.log(` tx revert -> Array length mismatch`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully add the investors in whitelist", async() => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - let errorThrown = false; - let tx = await I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor3, account_investor4], - [fromTime, fromTime], - [toTime, toTime], - [expiryTime, expiryTime], - [true, true], - { - from: token_owner, - gas: 6000000 - } - ); - assert.equal(tx.logs[1].args._investor, account_investor4); - }); - }); - - describe("General Transfer Manager Factory test cases", async() => { - - it("Should get the exact details of the factory", async() => { - assert.equal(await I_GeneralTransferManagerFactory.setupCost.call(),0); - assert.equal((await I_GeneralTransferManagerFactory.getTypes.call())[0],2); - assert.equal(web3.utils.toAscii(await I_GeneralTransferManagerFactory.getName.call()) - .replace(/\u0000/g, ''), - "GeneralTransferManager", - "Wrong Module added"); - assert.equal(await I_GeneralTransferManagerFactory.getDescription.call(), - "Manage transfers using a time based whitelist", - "Wrong Module added"); - assert.equal(await I_GeneralTransferManagerFactory.getTitle.call(), - "General Transfer Manager", - "Wrong Module added"); - assert.equal(await I_GeneralTransferManagerFactory.getInstructions.call(), - "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist, and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters.", - "Wrong Module added"); - - }); - - it("Should get the tags of the factory", async() => { - let tags = await I_GeneralTransferManagerFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "General"); - }); - }); - - describe("Dummy STO Factory test cases", async() => { - it("should get the exact details of the factory", async() => { - assert.equal(await I_DummySTOFactory.setupCost.call(),0); - assert.equal((await I_DummySTOFactory.getTypes.call())[0],3); - assert.equal(web3.utils.toAscii(await I_DummySTOFactory.getName.call()) - .replace(/\u0000/g, ''), - "DummySTO", - "Wrong Module added"); - assert.equal(await I_DummySTOFactory.getDescription.call(), - "Dummy STO", - "Wrong Module added"); - assert.equal(await I_DummySTOFactory.getTitle.call(), - "Dummy STO", - "Wrong Module added"); - assert.equal(await I_DummySTOFactory.getInstructions.call(), - "Dummy STO - you can mint tokens at will", - "Wrong Module added"); - - }); - - it("Should get the tags of the factory", async() => { - let tags = await I_DummySTOFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Dummy"); - }); - }); - - describe("Test cases for the get functions of the dummy sto", async() => { - - it("Should get the raised amount of ether", async() => { - assert.equal(await I_DummySTO.getRaised.call(0), web3.utils.toWei('0','ether')); - }); - - it("Should get the raised amount of poly", async() => { - assert.equal((await I_DummySTO.getRaised.call(1)).toNumber(), web3.utils.toWei('0','ether')); - }); - - it("Should get the investors", async() => { - assert.equal((await I_DummySTO.investorCount.call()).toNumber(), 2); - }); - - it("Should get the listed permissions", async() => { - let tx = await I_DummySTO.getPermissions.call(); - assert.equal(web3.utils.toAscii(tx[0]).replace(/\u0000/g, ''), "ADMIN"); - }); - }); - -}); +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 9: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 5: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// ModuleRegistry: ${ModuleRegistry.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// DummySTOFactory: ${I_DummySTOFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); + +// it("Should whitelist the affiliates before the STO attached", async() => { +// let tx = await I_GeneralTransferManager.modifyWhitelistMulti( +// [account_affiliates1, account_affiliates2], +// [(latestTime() + duration.days(30)),(latestTime() + duration.days(30))], +// [(latestTime() + duration.days(90)),(latestTime() + duration.days(90))], +// [(latestTime() + duration.years(1)),(latestTime() + duration.years(1))], +// [false, false], +// { +// from: account_issuer, +// gas: 6000000 +// }); +// assert.equal(tx.logs[0].args._investor, account_affiliates1); +// assert.equal(tx.logs[1].args._investor, account_affiliates2); +// }); + +// it("Should mint the tokens to the affiliates", async () => { +// await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [(100 * Math.pow(10, 18)), (100 * Math.pow(10, 18))], { from: account_issuer, gas:6000000 }); +// assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates1)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); +// assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); +// }); + +// it("Should successfully attach the STO factory with the security token", async () => { +// let bytesSTO = encodeModuleCall(STOParameters, [latestTime() + duration.seconds(1000), latestTime() + duration.days(40), cap, someString]); +// const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "DummySTO", +// "DummySTOFactory module was not added" +// ); +// I_DummySTO = DummySTO.at(tx.logs[2].args._module); +// }); + +// it("Should successfully attach the permission manager factory with the security token", async () => { +// const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, 0, 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "GeneralPermissionManager doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "GeneralPermissionManager", +// "GeneralPermissionManager module was not added" +// ); +// I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); +// }); + +// }); + +// describe("Buy tokens using on-chain whitelist", async() => { + +// it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { +// let errorThrown = false; +// try { +// await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Investor isn't present in the whitelist`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should Buy the tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(5000); + +// // Mint some tokens +// await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Should fail in buying the token from the STO", async() => { +// let errorThrown = false; +// try { +// await I_DummySTO.generateTokens(account_affiliates1, web3.utils.toWei('1', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Investor is restricted investor`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in investing the money in STO -- expiry limit reached", async() => { +// let errorThrown = false; +// await increaseTime(duration.days(10)); + +// try { +// await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Investor isn't present in the whitelist`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// }); + +// describe("Buy tokens using off-chain whitelist", async() => { + +// it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { +// let errorThrown = false; +// try { +// await I_DummySTO.generateTokens(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Investor isn't present in the whitelist`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should buy the tokens -- Failed due to incorrect signature input", async() => { +// // Add the Investor in to the whitelist +// //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk +// let validFrom = latestTime(); +// let validTo = latestTime() + duration.days(5); +// const sig = signData(account_investor2, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, token_owner_pk); + +// const r = `0x${sig.r.toString('hex')}`; +// const s = `0x${sig.s.toString('hex')}`; +// const v = sig.v; +// let errorThrown = false; + +// try { +// let tx = await I_GeneralTransferManager.modifyWhitelistSigned( +// account_investor2, +// fromTime, +// toTime, +// expiryTime, +// true, +// validFrom, +// validTo, +// v, +// r, +// s, +// { +// from: account_investor2, +// gas: 6000000 +// }); +// } catch(error) { +// console.log(` tx revert -> Incorrect sig data`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Should buy the tokens -- Failed due to incorrect signature timing", async() => { +// // Add the Investor in to the whitelist +// //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk +// let validFrom = latestTime() - 100; +// let validTo = latestTime() - 1; +// const sig = signData(I_GeneralTransferManager.address, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, token_owner_pk); + +// const r = `0x${sig.r.toString('hex')}`; +// const s = `0x${sig.s.toString('hex')}`; +// const v = sig.v; + +// let errorThrown = false; +// try { +// let tx = await I_GeneralTransferManager.modifyWhitelistSigned( +// account_investor2, +// fromTime, +// toTime, +// expiryTime, +// true, +// validFrom, +// validTo, +// v, +// r, +// s, +// { +// from: account_investor2, +// gas: 6000000 +// }); +// } catch(error) { +// console.log(` tx revert -> Incorrect sig data`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Should buy the tokens -- Failed due to incorrect signature signer", async() => { +// // Add the Investor in to the whitelist +// //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk +// let validFrom = latestTime(); +// let validTo = latestTime() + (60 * 60); + +// const sig = signData(account_investor2, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, '2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200'); + +// const r = `0x${sig.r.toString('hex')}`; +// const s = `0x${sig.s.toString('hex')}`; +// const v = sig.v; +// let errorThrown = false; + +// try { +// let tx = await I_GeneralTransferManager.modifyWhitelistSigned( +// account_investor2, +// fromTime, +// toTime, +// expiryTime, +// true, +// validFrom, +// validTo, +// v, +// r, +// s, +// { +// from: account_investor2, +// gas: 6000000 +// }); +// } catch(error) { +// console.log(` tx revert -> Incorrect sig data`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Should Buy the tokens", async() => { +// // Add the Investor in to the whitelist +// //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk +// let validFrom = latestTime(); +// let validTo = latestTime() + duration.days(5); +// const sig = signData(I_GeneralTransferManager.address, account_investor2, latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), true, validFrom, validTo, token_owner_pk); + +// const r = `0x${sig.r.toString('hex')}`; +// const s = `0x${sig.s.toString('hex')}`; +// const v = sig.v; +// let tx = await I_GeneralTransferManager.modifyWhitelistSigned( +// account_investor2, +// latestTime(), +// latestTime() + duration.days(80), +// expiryTime + duration.days(200), +// true, +// validFrom, +// validTo, +// v, +// r, +// s, +// { +// from: account_investor2, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(10000); +// // Mint some tokens + +// await I_DummySTO.generateTokens(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); + +// }); + +// it("Should fail in changing the signing address", async() => { +// let errorThrown = false; +// try { +// await I_GeneralTransferManager.changeSigningAddress(account_polymath, {from: account_investor4}); +// } catch(error) { +// console.log(` tx revert -> msg.sender is not token_owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should get the permission", async() => { +// let perm = await I_GeneralTransferManager.getPermissions.call(); +// assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "WHITELIST"); +// assert.equal(web3.utils.toAscii(perm[1]).replace(/\u0000/g, ''), "FLAGS"); +// }); + +// it("Should provide the permission and change the signing address", async() => { +// let log = await I_GeneralPermissionManager.addDelegate(account_delegate, "My details", {from: token_owner}); +// assert.equal(log.logs[0].args._delegate, account_delegate); + +// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "FLAGS", true, {from: token_owner}); + +// assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "FLAGS")); + +// let tx = await I_GeneralTransferManager.changeSigningAddress(account_polymath, {from: account_delegate}); +// assert.equal(tx.logs[0].args._signingAddress, account_polymath); +// }); + +// it("Should fail to pull fees as no budget set", async() => { + +// let errorThrown = false; +// try { +// await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> No budget set`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should set a budget for the GeneralTransferManager", async() => { +// await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, 10 * Math.pow(10, 18), {from: token_owner}); +// let errorThrown = false; +// try { +// await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> No balance on token`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// await I_PolyToken.getTokens(10 * Math.pow(10, 18), token_owner); +// await I_PolyToken.transfer(I_SecurityToken.address, 10 * Math.pow(10, 18), {from: token_owner}); +// }); + + +// it("Factory owner should pull fees - fails as not permissioned by issuer", async() => { +// let errorThrown = false; +// try { +// await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_delegate}); +// } catch(error) { +// console.log(` tx revert -> Incorrect permissions`.grey); +// errorThrown = true; +// ensureException(error); +// } +// }); + +// it("Factory owner should pull fees", async() => { +// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "FEE_ADMIN", true, {from: token_owner}); +// let balanceBefore = await I_PolyToken.balanceOf(account_polymath); +// await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_delegate}); +// let balanceAfter = await I_PolyToken.balanceOf(account_polymath); +// assert.equal(balanceBefore.add(web3.utils.toWei('1','ether')).toNumber(), balanceAfter.toNumber(), "Fee is transferred"); +// }); + +// it("Should change the white list transfer variable", async() => { +// let tx = await I_GeneralTransferManager.changeAllowAllWhitelistIssuances(true, {from : token_owner}); +// assert.isTrue(tx.logs[0].args._allowAllWhitelistIssuances); +// }); + +// it("should failed in trasfering the tokens", async() => { +// let tx = await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); +// await I_GeneralTransferManager.pause({from: token_owner}); +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2','ether'), {from: account_investor2}); +// } catch(error) { +// console.log(` tx revert -> Transfer is paused`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should change the Issuance address", async() => { +// let tx = await I_GeneralTransferManager.changeIssuanceAddress(account_investor2, {from: account_delegate}); +// assert.equal(tx.logs[0].args._issuanceAddress, account_investor2); +// }); + +// it("Should unpause the transfers", async() => { +// await I_GeneralTransferManager.unpause({from: token_owner}); + +// assert.isFalse(await I_GeneralTransferManager.paused.call()); +// }); + +// it("Should get the init function", async() => { +// let byte = await I_GeneralTransferManager.getInitFunction.call(); +// assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); +// }); + +// }); + +// describe("WhiteList that addresses", async () => { + +// it("Should fail in adding the investors in whitelist", async() => { +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(20); +// let expiryTime = toTime + duration.days(10); +// let errorThrown = false; +// try { +// await I_GeneralTransferManager.modifyWhitelistMulti( +// [account_investor3, account_investor4], +// [fromTime, fromTime], +// [toTime, toTime], +// [expiryTime, expiryTime], +// [true, true], +// { +// from: account_delegate, +// gas: 6000000 +// } +// ); +// } catch(error) { +// console.log(` tx revert -> msg.sender is not allowed to modify the whitelist`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(20); +// let expiryTime = toTime + duration.days(10); +// let errorThrown = false; +// try { +// await I_GeneralTransferManager.modifyWhitelistMulti( +// [account_investor3, account_investor4], +// [fromTime], +// [toTime, toTime], +// [expiryTime, expiryTime], +// [true, true], +// { +// from: account_delegate, +// gas: 6000000 +// } +// ); +// } catch(error) { +// console.log(` tx revert -> Array length mismatch`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(20); +// let expiryTime = toTime + duration.days(10); +// let errorThrown = false; +// try { +// await I_GeneralTransferManager.modifyWhitelistMulti( +// [account_investor3, account_investor4], +// [fromTime, fromTime], +// [toTime], +// [expiryTime, expiryTime], +// [true, true], +// { +// from: account_delegate, +// gas: 6000000 +// } +// ); +// } catch(error) { +// console.log(` tx revert -> Array length mismatch`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(20); +// let expiryTime = toTime + duration.days(10); +// let errorThrown = false; +// try { +// await I_GeneralTransferManager.modifyWhitelistMulti( +// [account_investor3, account_investor4], +// [fromTime, fromTime], +// [toTime, toTime], +// [expiryTime], +// [true, true], +// { +// from: account_delegate, +// gas: 6000000 +// } +// ); +// } catch(error) { +// console.log(` tx revert -> Array length mismatch`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully add the investors in whitelist", async() => { +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(20); +// let expiryTime = toTime + duration.days(10); +// let errorThrown = false; +// let tx = await I_GeneralTransferManager.modifyWhitelistMulti( +// [account_investor3, account_investor4], +// [fromTime, fromTime], +// [toTime, toTime], +// [expiryTime, expiryTime], +// [true, true], +// { +// from: token_owner, +// gas: 6000000 +// } +// ); +// assert.equal(tx.logs[1].args._investor, account_investor4); +// }); +// }); + +// describe("General Transfer Manager Factory test cases", async() => { + +// it("Should get the exact details of the factory", async() => { +// assert.equal(await I_GeneralTransferManagerFactory.setupCost.call(),0); +// assert.equal((await I_GeneralTransferManagerFactory.getTypes.call())[0],2); +// assert.equal(web3.utils.toAscii(await I_GeneralTransferManagerFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager", +// "Wrong Module added"); +// assert.equal(await I_GeneralTransferManagerFactory.getDescription.call(), +// "Manage transfers using a time based whitelist", +// "Wrong Module added"); +// assert.equal(await I_GeneralTransferManagerFactory.getTitle.call(), +// "General Transfer Manager", +// "Wrong Module added"); +// assert.equal(await I_GeneralTransferManagerFactory.getInstructions.call(), +// "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist, and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters.", +// "Wrong Module added"); + +// }); + +// it("Should get the tags of the factory", async() => { +// let tags = await I_GeneralTransferManagerFactory.getTags.call(); +// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "General"); +// }); +// }); + +// describe("Dummy STO Factory test cases", async() => { +// it("should get the exact details of the factory", async() => { +// assert.equal(await I_DummySTOFactory.setupCost.call(),0); +// assert.equal((await I_DummySTOFactory.getTypes.call())[0],3); +// assert.equal(web3.utils.toAscii(await I_DummySTOFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "DummySTO", +// "Wrong Module added"); +// assert.equal(await I_DummySTOFactory.getDescription.call(), +// "Dummy STO", +// "Wrong Module added"); +// assert.equal(await I_DummySTOFactory.getTitle.call(), +// "Dummy STO", +// "Wrong Module added"); +// assert.equal(await I_DummySTOFactory.getInstructions.call(), +// "Dummy STO - you can mint tokens at will", +// "Wrong Module added"); + +// }); + +// it("Should get the tags of the factory", async() => { +// let tags = await I_DummySTOFactory.getTags.call(); +// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Dummy"); +// }); +// }); + +// describe("Test cases for the get functions of the dummy sto", async() => { + +// it("Should get the raised amount of ether", async() => { +// assert.equal(await I_DummySTO.getRaised.call(0), web3.utils.toWei('0','ether')); +// }); + +// it("Should get the raised amount of poly", async() => { +// assert.equal((await I_DummySTO.getRaised.call(1)).toNumber(), web3.utils.toWei('0','ether')); +// }); + +// it("Should get the investors", async() => { +// assert.equal((await I_DummySTO.investorCount.call()).toNumber(), 2); +// }); + +// it("Should get the listed permissions", async() => { +// let tx = await I_DummySTO.getPermissions.call(); +// assert.equal(web3.utils.toAscii(tx[0]).replace(/\u0000/g, ''), "ADMIN"); +// }); +// }); + +// }); diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 8cf353dfc..012029b87 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -1,423 +1,423 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -const CappedSTO = artifacts.require('./CappedSTO.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - - -contract('Issuance', accounts => { - - - // Accounts Variable declaration - let account_polymath; - let account_investor1; - let account_issuer; - let token_owner; - let account_investor2; - let account_fundsReceiver; - let account_delegate; - let blockNo; - let balanceOfReceiver; - let message = "Transaction Should Fail!"; - const TM_Perm = "WHITELIST"; - const delegateDetails = "I am delegate" - // investor Details - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); - let expiryTime = toTime + duration.days(100); - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_CappedSTOFactory; - let I_MRProxied; - let I_STRProxied; - let I_STFactory; - let I_SecurityToken; - let I_CappedSTO; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details (Launched ST on the behalf of the issuer) - const name = "Demo Token"; - const symbol = "DET"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - - // Module key - const permissionManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - const budget = 0; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - // Capped STO details - //let startTime; // Start time will be 5000 seconds more than the latest time - //let endTime; // Add 30 days more - const cap = web3.utils.toWei("10000"); - const rate = 1000; - const fundRaiseType = [0]; - const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); - const maxCost = cappedSTOSetupCost; - const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - account_investor1 = accounts[3]; - account_investor2 = accounts[2]; - account_fundsReceiver = accounts[4]; - account_delegate = accounts[5]; - token_owner = account_issuer; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 6: Deploy the CappedSTOFactory - - I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); - - assert.notEqual( - I_CappedSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CappedSTOFactory contract was not deployed" - ); - - // Step 8: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry contract +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +// const CappedSTO = artifacts.require('./CappedSTO.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + + +// contract('Issuance', accounts => { + + +// // Accounts Variable declaration +// let account_polymath; +// let account_investor1; +// let account_issuer; +// let token_owner; +// let account_investor2; +// let account_fundsReceiver; +// let account_delegate; +// let blockNo; +// let balanceOfReceiver; +// let message = "Transaction Should Fail!"; +// const TM_Perm = "WHITELIST"; +// const delegateDetails = "I am delegate" +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(15); +// let expiryTime = toTime + duration.days(100); + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_CappedSTOFactory; +// let I_MRProxied; +// let I_STRProxied; +// let I_STFactory; +// let I_SecurityToken; +// let I_CappedSTO; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details (Launched ST on the behalf of the issuer) +// const name = "Demo Token"; +// const symbol = "DET"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; + +// // Module key +// const permissionManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; +// const budget = 0; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// // Capped STO details +// //let startTime; // Start time will be 5000 seconds more than the latest time +// //let endTime; // Add 30 days more +// const cap = web3.utils.toWei("10000"); +// const rate = 1000; +// const fundRaiseType = [0]; +// const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); +// const maxCost = cappedSTOSetupCost; +// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; +// account_investor1 = accounts[3]; +// account_investor2 = accounts[2]; +// account_fundsReceiver = accounts[4]; +// account_delegate = accounts[5]; +// token_owner = account_issuer; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 6: Deploy the CappedSTOFactory + +// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); + +// assert.notEqual( +// I_CappedSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CappedSTOFactory contract was not deployed" +// ); + +// // Step 8: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 9: Deploy the SecurityTokenRegistry contract - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); - // STEP 7: Register the Modules with the ModuleRegistry contract +// // STEP 7: Register the Modules with the ModuleRegistry contract - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - CappedSTOFactory: ${I_CappedSTOFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Launch SecurityToken & STO on the behalf of the issuer", async() => { - - describe("Create securityToken for the issuer by the polymath", async() => { - - it("POLYMATH: Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_polymath); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_polymath }); - let tx = await I_STRProxied.registerTicker(account_polymath, symbol, name, { from : account_polymath }); - assert.equal(tx.logs[0].args._owner, account_polymath); - assert.equal(tx.logs[0].args._ticker, symbol); - }); - - it("POLYMATH: Should generate the new security token with the same symbol as registered above", async () => { - console.log(name, symbol, tokenDetails, false); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_polymath }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_polymath }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), transferManagerKey); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("POLYMATH: Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - - }); - - it("POLYMATH: Should successfully attach the STO factory with the security token", async () => { - // STEP 4: Deploy the CappedSTOFactory - - I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: account_polymath }); - - assert.notEqual( - I_CappedSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CappedSTOFactory contract was not deployed" - ); - - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - - let bytesSTO = encodeModuleCall(STOParameters, [(latestTime() + duration.seconds(5000)), (latestTime() + duration.days(30)), cap, rate, fundRaiseType, account_fundsReceiver]); - - await I_PolyToken.getTokens(cappedSTOSetupCost, account_polymath); - await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: account_polymath}); - - const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: account_polymath }); - - assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "CappedSTO", - "CappedSTOFactory module was not added" - ); - I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); - }); - }); - - describe("Transfer Manager operations by the polymath_account", async() => { - it("Should modify the whitelist", async () => { - - fromTime = latestTime(); - toTime = latestTime() + duration.days(15); - expiryTime = toTime + duration.days(100); - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - fromTime + duration.days(70), - toTime + duration.days(90), - expiryTime + duration.days(50), - true, - { - from: account_polymath - }); - assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); - }); - - it("Should add the delegate with permission", async() => { - //First attach a permission manager to the token - await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: account_polymath}); - let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; - I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); - // Add permission to the deletgate (A regesteration process) - await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_polymath}); - // Providing the permission to the delegate - await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm, true, { from: account_polymath }); - - assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm)); - }); - - it("POLYMATH: Should change the ownership of the SecurityToken", async() => { - await I_SecurityToken.transferOwnership(token_owner, { from : account_polymath }); - - assert.equal(await I_SecurityToken.owner.call(), token_owner); - }); - }) - - describe("Operations on the STO", async() => { - it("Should Buy the tokens", async() => { - balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - blockNo = latestBlock(); - // Jump time - await increaseTime(5000); - // Fallback transaction - await web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO.address, - gas: 6100000, - value: web3.utils.toWei('1', 'ether') - }); - - assert.equal( - (await I_CappedSTO.getRaised.call(0)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1 - ); - - assert.equal(await I_CappedSTO.investorCount.call(), 1); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000 - ); - }); - - it("Verification of the event Token Purchase", async() => { - const log = await promisifyLogWatch(I_CappedSTO.TokenPurchase({from: blockNo}), 1); - assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); - assert.equal( - (log.args.amount) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000, - "Wrong No. token get dilivered" - ); - }); - - it("should add the investor into the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - fromTime, - toTime, - expiryTime, - true, - { - from: account_delegate, - gas: 7000000 - }); - assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - }); - - it("Should buy the token", async () => { - await web3.eth.sendTransaction({ - from: account_investor2, - to: I_CappedSTO.address, - gas: 2100000, - value: web3.utils.toWei('1', 'ether') - }); - - assert.equal( - (await I_CappedSTO.getRaised.call(0)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 2 - ); - - assert.equal(await I_CappedSTO.investorCount.call(), 2); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000 - ); - }) - }); - }); -}); +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// CappedSTOFactory: ${I_CappedSTOFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Launch SecurityToken & STO on the behalf of the issuer", async() => { + +// describe("Create securityToken for the issuer by the polymath", async() => { + +// it("POLYMATH: Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_polymath); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_polymath }); +// let tx = await I_STRProxied.registerTicker(account_polymath, symbol, name, { from : account_polymath }); +// assert.equal(tx.logs[0].args._owner, account_polymath); +// assert.equal(tx.logs[0].args._ticker, symbol); +// }); + +// it("POLYMATH: Should generate the new security token with the same symbol as registered above", async () => { +// console.log(name, symbol, tokenDetails, false); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_polymath }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_polymath }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), transferManagerKey); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("POLYMATH: Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + +// }); + +// it("POLYMATH: Should successfully attach the STO factory with the security token", async () => { +// // STEP 4: Deploy the CappedSTOFactory + +// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: account_polymath }); + +// assert.notEqual( +// I_CappedSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CappedSTOFactory contract was not deployed" +// ); + +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + +// let bytesSTO = encodeModuleCall(STOParameters, [(latestTime() + duration.seconds(5000)), (latestTime() + duration.days(30)), cap, rate, fundRaiseType, account_fundsReceiver]); + +// await I_PolyToken.getTokens(cappedSTOSetupCost, account_polymath); +// await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: account_polymath}); + +// const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: account_polymath }); + +// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[3].args._name) +// .replace(/\u0000/g, ''), +// "CappedSTO", +// "CappedSTOFactory module was not added" +// ); +// I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); +// }); +// }); + +// describe("Transfer Manager operations by the polymath_account", async() => { +// it("Should modify the whitelist", async () => { + +// fromTime = latestTime(); +// toTime = latestTime() + duration.days(15); +// expiryTime = toTime + duration.days(100); + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// fromTime + duration.days(70), +// toTime + duration.days(90), +// expiryTime + duration.days(50), +// true, +// { +// from: account_polymath +// }); +// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); +// }); + +// it("Should add the delegate with permission", async() => { +// //First attach a permission manager to the token +// await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: account_polymath}); +// let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; +// I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); +// // Add permission to the deletgate (A regesteration process) +// await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_polymath}); +// // Providing the permission to the delegate +// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm, true, { from: account_polymath }); + +// assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm)); +// }); + +// it("POLYMATH: Should change the ownership of the SecurityToken", async() => { +// await I_SecurityToken.transferOwnership(token_owner, { from : account_polymath }); + +// assert.equal(await I_SecurityToken.owner.call(), token_owner); +// }); +// }) + +// describe("Operations on the STO", async() => { +// it("Should Buy the tokens", async() => { +// balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); +// blockNo = latestBlock(); +// // Jump time +// await increaseTime(5000); +// // Fallback transaction +// await web3.eth.sendTransaction({ +// from: account_investor1, +// to: I_CappedSTO.address, +// gas: 6100000, +// value: web3.utils.toWei('1', 'ether') +// }); + +// assert.equal( +// (await I_CappedSTO.getRaised.call(0)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1 +// ); + +// assert.equal(await I_CappedSTO.investorCount.call(), 1); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000 +// ); +// }); + +// it("Verification of the event Token Purchase", async() => { +// const log = await promisifyLogWatch(I_CappedSTO.TokenPurchase({from: blockNo}), 1); +// assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); +// assert.equal( +// (log.args.amount) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000, +// "Wrong No. token get dilivered" +// ); +// }); + +// it("should add the investor into the whitelist by the delegate", async () => { +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: account_delegate, +// gas: 7000000 +// }); +// assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); +// }); + +// it("Should buy the token", async () => { +// await web3.eth.sendTransaction({ +// from: account_investor2, +// to: I_CappedSTO.address, +// gas: 2100000, +// value: web3.utils.toWei('1', 'ether') +// }); + +// assert.equal( +// (await I_CappedSTO.getRaised.call(0)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 2 +// ); + +// assert.equal(await I_CappedSTO.investorCount.call(), 2); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000 +// ); +// }) +// }); +// }); +// }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 064027246..0515b7e9c 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -1,711 +1,711 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol'); -const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); -const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); -const CountTransferManager = artifacts.require('./CountTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('ManualApprovalTransferManager', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_investor5; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_GeneralTransferManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_ManualApprovalTransferManagerFactory; - let P_ManualApprovalTransferManagerFactory; - let P_ManualApprovalTransferManager; - let I_CountTransferManagerFactory; - let I_GeneralPermissionManager; - let I_ManualApprovalTransferManager; - let I_CountTransferManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_MRProxied; - let I_STRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[6]; - account_investor2 = accounts[7]; - account_investor3 = accounts[8]; - account_investor4 = accounts[9]; - account_investor5 = accounts[5]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactoryFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 6: Deploy the ManualApprovalTransferManagerFactory - I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_ManualApprovalTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ManualApprovalTransferManagerFactory contract was not deployed" - ); - - // STEP 7: Deploy the Paid ManualApprovalTransferManagerFactory - P_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); - assert.notEqual( - P_ManualApprovalTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ManualApprovalTransferManagerFactory contract was not deployed" - ); - - // STEP 8: Deploy the CountTransferManagerFactory - I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_CountTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CountTransferManagerFactory contract was not deployed" - ); - - // Step 10: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol'); +// const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); +// const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); +// const CountTransferManager = artifacts.require('./CountTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('ManualApprovalTransferManager', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; +// let account_investor5; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_GeneralTransferManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_ManualApprovalTransferManagerFactory; +// let P_ManualApprovalTransferManagerFactory; +// let P_ManualApprovalTransferManager; +// let I_CountTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_ManualApprovalTransferManager; +// let I_CountTransferManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_MRProxied; +// let I_STRProxied; +// let I_STFactory; +// let I_SecurityToken; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; + +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; + +// account_investor1 = accounts[6]; +// account_investor2 = accounts[7]; +// account_investor3 = accounts[8]; +// account_investor4 = accounts[9]; +// account_investor5 = accounts[5]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the GeneralDelegateManagerFactoryFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 6: Deploy the ManualApprovalTransferManagerFactory +// I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); +// assert.notEqual( +// I_ManualApprovalTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "ManualApprovalTransferManagerFactory contract was not deployed" +// ); + +// // STEP 7: Deploy the Paid ManualApprovalTransferManagerFactory +// P_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); +// assert.notEqual( +// P_ManualApprovalTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "ManualApprovalTransferManagerFactory contract was not deployed" +// ); + +// // STEP 8: Deploy the CountTransferManagerFactory +// I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); +// assert.notEqual( +// I_CountTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CountTransferManagerFactory contract was not deployed" +// ); + +// // Step 10: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); - // Step 11: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 12: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 13: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 9: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the ManualApprovalTransferManagerFactory - await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the ManualApprovalTransferManagerFactory - await I_MRProxied.registerModule(P_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(P_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); - - // (D) : Register the CountTransferManagerFactory - await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - ManualApprovalTransferManagerFactory: ${I_ManualApprovalTransferManagerFactory.address} - CountTransferManagerFactory: ${I_CountTransferManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal(web3.utils.toUtf8(log.args._name), "GeneralTransferManager"); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - }); - - describe("Buy tokens using whitelist & manual approvals", async() => { - - it("Should Buy the tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('4', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('4', 'ether') - ); - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { - let errorThrown = false; - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - try { - const tx = await I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - } catch(error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the General permission manager factory with the security token", async () => { - let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "Manual Approval Transfer Manager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "ManualApprovalTransferManager", - "ManualApprovalTransferManagerFactory module was not added" - ); - P_ManualApprovalTransferManagerFactory = ManualApprovalTransferManager.at(tx.logs[3].args._module); - await revertToSnapshot(snapId); - }); - - - it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); - assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManager module was not added"); - I_ManualApprovalTransferManager = ManualApprovalTransferManager.at(tx.logs[2].args._module); - }); -//function verifyTransfer(address _from, address _to, uint256 _amount, bool _isTransfer) public returns(Result) { - it("Cannot call verifyTransfer on the TM directly if _isTransfer == true", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.verifyTransfer(account_investor4, account_investor4, web3.utils.toWei('2', 'ether'), "", true, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid not from SecurityToken`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - }); - - it("Can call verifyTransfer on the TM directly if _isTransfer == false", async() => { - await I_ManualApprovalTransferManager.verifyTransfer(account_investor4, account_investor4, web3.utils.toWei('2', 'ether'), "", false, { from: token_owner }); - }); - - it("Add a new token holder", async() => { - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Should still be able to transfer between existing token holders", async() => { - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('5', 'ether') - ); - }); - - it("Should fail to add a manual approval because invalid _from address", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.addManualApproval("", account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid _from address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail to add a manual approval because invalid _to address", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.addManualApproval(account_investor1, "", web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid _to address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail to add a manual approval because invalid expiry time", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), 99999, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid expiry time`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Add a manual approval for a 4th investor", async() => { - await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); - }); - - it("Should fail to revoke manual approval because invalid _from address", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.revokeManualApproval("", account_investor4, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid _from address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail to revoke manual approval because invalid _to address", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, "", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid _to address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should revoke manual approval", async() => { - let tx = await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { from: token_owner }); - assert.equal(tx.logs[0].args._from, account_investor1); - assert.equal(tx.logs[0].args._to, account_investor4); - assert.equal(tx.logs[0].args._addedBy, token_owner); - await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); - }); - - it("Use 50% of manual approval for transfer", async() => { - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Check verifyTransfer without actually transferring", async() => { - let verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('1', 'ether'), ""); - console.log(JSON.stringify(verified)); - assert.equal(verified, true); - - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), ""); - assert.equal(verified, false); - - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('1', 'ether'), ""); - assert.equal(verified, true); - - }); - - it("Use remaining 50% of manual approval for transfer", async() => { - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Check further transfers fail", async() => { - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> No remaining allowance`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - //Check that other transfers are still valid - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - - }); - - it("Should fail to add a manual block because invalid _from address", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.addManualBlocking("", account_investor2, latestTime() + duration.days(1), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid _from address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail to add a manual block because invalid _to address", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, "", latestTime() + duration.days(1), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid _to address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail to add a manual block because invalid expiry time", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, 99999, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid expiry time`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Add a manual block for a 2nd investor", async() => { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { from: token_owner }); - }); - - it("Check manual block causes failure", async() => { - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Manual block`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - }); - - it("Should fail to revoke manual block because invalid _from address", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.revokeManualBlocking("0x0", account_investor2, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid _from address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should fail to revoke manual block because invalid _to address", async() => { - let errorThrown = false; - try { - await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, "0x0", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> invalid _to address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Revoke manual block and check transfer works", async() => { - await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: token_owner }); - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Check manual block ignored after expiry", async() => { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { from: token_owner }); - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Manual block`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - await increaseTime(1 + (24 * 60 * 60)); - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - }); - - it("Should successfully attach the CountTransferManager with the security token (count of 1)", async () => { - let bytesCountTM = web3.eth.abi.encodeFunctionCall({ - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_maxHolderCount' - } - ] - }, [1]); - - const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); - let name = web3.utils.toUtf8(tx.logs[2].args._name); - assert.equal(name, "CountTransferManager", "CountTransferManager module was not added"); - I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); - - }); - - it("Should get the permission list", async() => { - let perm = await I_ManualApprovalTransferManager.getPermissions.call(); - assert.equal(perm.length, 1); - }); - - // it("Check manual approval has a higher priority than an INVALID result from another TM", async() => { - // //Should fail initial transfer - // let errorThrown = false; - // try { - // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - // } catch(error) { - // console.log(`Failed due to to count block`); - // ensureException(error); - // errorThrown = true; - // } - // //Add a manual approval - transfer should now work - // await I_ManualApprovalTransferManager.addManualApproval(account_investor2, account_investor5, web3.utils.toWei('1', 'ether'), latestTime() + duration.days(1), { from: token_owner }); - // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - // }); - - it("Should get the init function", async() => { - let byte = await I_ManualApprovalTransferManager.getInitFunction.call(); - assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); - }); - - }); - - describe("ManualApproval Transfer Manager Factory test cases", async() => { - - it("Should get the exact details of the factory", async() => { - assert.equal(await I_ManualApprovalTransferManagerFactory.setupCost.call(),0); - assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0],2); - let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); - assert.equal(name,"ManualApprovalTransferManager","Wrong Module added"); - let desc = await I_ManualApprovalTransferManagerFactory.getDescription.call(); - assert.equal(desc,"Manage transfers using single approvals / blocking","Wrong Module added"); - let title = await I_ManualApprovalTransferManagerFactory.getTitle.call(); - assert.equal(title,"Manual Approval Transfer Manager","Wrong Module added"); - let inst = await I_ManualApprovalTransferManagerFactory.getInstructions.call(); - assert.equal(inst,"Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.","Wrong Module added"); - }); - - it("Should get the tags of the factory", async() => { - let tags = await I_ManualApprovalTransferManagerFactory.getTags.call(); - assert.equal(web3.utils.toUtf8(tags[0]), "ManualApproval"); - }); - }); - -}); +// // Step 11: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 12: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 13: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 9: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the ManualApprovalTransferManagerFactory +// await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the ManualApprovalTransferManagerFactory +// await I_MRProxied.registerModule(P_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(P_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); + +// // (D) : Register the CountTransferManagerFactory +// await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// ManualApprovalTransferManagerFactory: ${I_ManualApprovalTransferManagerFactory.address} +// CountTransferManagerFactory: ${I_CountTransferManagerFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal(web3.utils.toUtf8(log.args._name), "GeneralTransferManager"); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); + +// }); + +// describe("Buy tokens using whitelist & manual approvals", async() => { + +// it("Should Buy the tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(5000); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('4', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('4', 'ether') +// ); +// }); + +// it("Should Buy some more tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { +// let errorThrown = false; +// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); +// try { +// const tx = await I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx -> failed because Token is not paid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the General permission manager factory with the security token", async () => { +// let snapId = await takeSnapshot(); +// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); +// const tx = await I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "Manual Approval Transfer Manager doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[3].args._name) +// .replace(/\u0000/g, ''), +// "ManualApprovalTransferManager", +// "ManualApprovalTransferManagerFactory module was not added" +// ); +// P_ManualApprovalTransferManagerFactory = ManualApprovalTransferManager.at(tx.logs[3].args._module); +// await revertToSnapshot(snapId); +// }); + + +// it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { +// const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); +// assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManager module was not added"); +// I_ManualApprovalTransferManager = ManualApprovalTransferManager.at(tx.logs[2].args._module); +// }); +// //function verifyTransfer(address _from, address _to, uint256 _amount, bool _isTransfer) public returns(Result) { +// it("Cannot call verifyTransfer on the TM directly if _isTransfer == true", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.verifyTransfer(account_investor4, account_investor4, web3.utils.toWei('2', 'ether'), "", true, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid not from SecurityToken`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Can call verifyTransfer on the TM directly if _isTransfer == false", async() => { +// await I_ManualApprovalTransferManager.verifyTransfer(account_investor4, account_investor4, web3.utils.toWei('2', 'ether'), "", false, { from: token_owner }); +// }); + +// it("Add a new token holder", async() => { + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Should still be able to transfer between existing token holders", async() => { +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('5', 'ether') +// ); +// }); + +// it("Should fail to add a manual approval because invalid _from address", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.addManualApproval("", account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid _from address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to add a manual approval because invalid _to address", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.addManualApproval(account_investor1, "", web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid _to address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to add a manual approval because invalid expiry time", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), 99999, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid expiry time`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Add a manual approval for a 4th investor", async() => { +// await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); +// }); + +// it("Should fail to revoke manual approval because invalid _from address", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.revokeManualApproval("", account_investor4, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid _from address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to revoke manual approval because invalid _to address", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, "", { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid _to address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should revoke manual approval", async() => { +// let tx = await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { from: token_owner }); +// assert.equal(tx.logs[0].args._from, account_investor1); +// assert.equal(tx.logs[0].args._to, account_investor4); +// assert.equal(tx.logs[0].args._addedBy, token_owner); +// await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); +// }); + +// it("Use 50% of manual approval for transfer", async() => { +// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Check verifyTransfer without actually transferring", async() => { +// let verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('1', 'ether'), ""); +// console.log(JSON.stringify(verified)); +// assert.equal(verified, true); + +// verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), ""); +// assert.equal(verified, false); + +// verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('1', 'ether'), ""); +// assert.equal(verified, true); + +// }); + +// it("Use remaining 50% of manual approval for transfer", async() => { +// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), +// web3.utils.toWei('2', 'ether') +// ); +// }); + +// it("Check further transfers fail", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> No remaining allowance`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// //Check that other transfers are still valid +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + +// }); + +// it("Should fail to add a manual block because invalid _from address", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.addManualBlocking("", account_investor2, latestTime() + duration.days(1), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid _from address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to add a manual block because invalid _to address", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, "", latestTime() + duration.days(1), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid _to address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to add a manual block because invalid expiry time", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, 99999, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid expiry time`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Add a manual block for a 2nd investor", async() => { +// await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { from: token_owner }); +// }); + +// it("Check manual block causes failure", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> Manual block`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Should fail to revoke manual block because invalid _from address", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.revokeManualBlocking("0x0", account_investor2, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid _from address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to revoke manual block because invalid _to address", async() => { +// let errorThrown = false; +// try { +// await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, "0x0", { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> invalid _to address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Revoke manual block and check transfer works", async() => { +// await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: token_owner }); +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('2', 'ether') +// ); +// }); + +// it("Check manual block ignored after expiry", async() => { +// await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { from: token_owner }); +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> Manual block`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// await increaseTime(1 + (24 * 60 * 60)); +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// }); + +// it("Should successfully attach the CountTransferManager with the security token (count of 1)", async () => { +// let bytesCountTM = web3.eth.abi.encodeFunctionCall({ +// name: 'configure', +// type: 'function', +// inputs: [{ +// type: 'uint256', +// name: '_maxHolderCount' +// } +// ] +// }, [1]); + +// const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); +// let name = web3.utils.toUtf8(tx.logs[2].args._name); +// assert.equal(name, "CountTransferManager", "CountTransferManager module was not added"); +// I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); + +// }); + +// it("Should get the permission list", async() => { +// let perm = await I_ManualApprovalTransferManager.getPermissions.call(); +// assert.equal(perm.length, 1); +// }); + +// // it("Check manual approval has a higher priority than an INVALID result from another TM", async() => { +// // //Should fail initial transfer +// // let errorThrown = false; +// // try { +// // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); +// // } catch(error) { +// // console.log(`Failed due to to count block`); +// // ensureException(error); +// // errorThrown = true; +// // } +// // //Add a manual approval - transfer should now work +// // await I_ManualApprovalTransferManager.addManualApproval(account_investor2, account_investor5, web3.utils.toWei('1', 'ether'), latestTime() + duration.days(1), { from: token_owner }); +// // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); +// // }); + +// it("Should get the init function", async() => { +// let byte = await I_ManualApprovalTransferManager.getInitFunction.call(); +// assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); +// }); + +// }); + +// describe("ManualApproval Transfer Manager Factory test cases", async() => { + +// it("Should get the exact details of the factory", async() => { +// assert.equal(await I_ManualApprovalTransferManagerFactory.setupCost.call(),0); +// assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0],2); +// let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); +// assert.equal(name,"ManualApprovalTransferManager","Wrong Module added"); +// let desc = await I_ManualApprovalTransferManagerFactory.getDescription.call(); +// assert.equal(desc,"Manage transfers using single approvals / blocking","Wrong Module added"); +// let title = await I_ManualApprovalTransferManagerFactory.getTitle.call(); +// assert.equal(title,"Manual Approval Transfer Manager","Wrong Module added"); +// let inst = await I_ManualApprovalTransferManagerFactory.getInstructions.call(); +// assert.equal(inst,"Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.","Wrong Module added"); +// }); + +// it("Should get the tags of the factory", async() => { +// let tags = await I_ManualApprovalTransferManagerFactory.getTags.call(); +// assert.equal(web3.utils.toUtf8(tags[0]), "ManualApproval"); +// }); +// }); + +// }); diff --git a/test/k_module_registry.js b/test/k_module_registry.js index ae5bfb434..9266b014c 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -1,684 +1,684 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -const CappedSTO = artifacts.require('./CappedSTO.sol'); -const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); -const MockFactory = artifacts.require('./MockFactory.sol'); -const TestSTOFactory = artifacts.require('./TestSTOFactory.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - - -contract('ModuleRegistry', accounts => { - - - // Accounts Variable declaration - let account_polymath; - let account_investor1; - let account_issuer; - let token_owner; - let account_investor2; - let account_fundsReceiver; - let account_delegate; - let account_temp; - - let balanceOfReceiver; - // investor Details - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); - - let ID_snap; - let message = "Transaction Should fail!"; - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_GeneralTransferManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_CappedSTOFactory1; - let I_CappedSTOFactory2; - let I_STFactory; - let I_MRProxied; - let I_SecurityToken; - let I_STRProxied; - let I_CappedSTO; - let I_PolyToken; - let I_MockFactory; - let I_TestSTOFactory; - let I_DummySTOFactory; - let I_PolymathRegistry; - let I_SecurityToken2; - - // SecurityToken Details (Launched ST on the behalf of the issuer) - const name = "Demo Token"; - const symbol = "det"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - - // Module key - const permissionManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - const budget = 0; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - // delagate details - const delegateDetails = "I am delegate .."; - const TM_Perm = 'FLAGS'; - - // Capped STO details - let startTime; - let endTime; - const cap = web3.utils.toWei("10000"); - const rate = 1000; - const fundRaiseType = [0]; - const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256','uint8[]', 'address']; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - account_investor1 = accounts[9]; - account_investor2 = accounts[6]; - account_fundsReceiver = accounts[4]; - account_delegate = accounts[5]; - account_temp = accounts[8]; - token_owner = account_issuer; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed", - ); - - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - let tx = await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - - // STEP 2: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Test cases for the ModuleRegistry", async() => { - - describe("Test case for the upgradeFromregistry", async() => { - - it("Should successfully update the registry contract address -- failed because of bad owner", async() => { - let errorThrown = false; - try { - await I_MRProxied.updateFromRegistry({from: account_temp}); - } catch(error) { - console.log(` tx -> revert because of bad owner`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully update the registry contract addresses", async() => { - await I_MRProxied.updateFromRegistry({from: account_polymath}); - assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("securityTokenRegistry")), I_SecurityTokenRegistryProxy.address); - assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("featureRegistry")), I_FeatureRegistry.address); - assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), I_PolyToken.address); - }); - - }); - - describe("Test the state variables", async() => { - - it("Should be the right owner", async() => { - let _owner = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3('owner')); - assert.equal(_owner, account_polymath, "Owner should be the correct"); - }) - - it("Should be the expected value of the paused and intialised variable", async() => { - let _paused = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); - assert.isFalse(_paused, "Should be the false"); - - let _intialised = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); - assert.isTrue(_intialised, "Values should be the true"); - }) - - it("Should be the expected value of the polymath registry", async() => { - let _polymathRegistry = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); - assert.equal(_polymathRegistry, I_PolymathRegistry.address, "Should be the right value of the address of the polymath registry"); - }); - }); - - describe("Test cases for the registering the module", async() => { - - it("Should fail to register the module -- when registerModule is paused", async() => { - await I_MRProxied.pause({from: account_polymath}); - let errorThrown = false; - try { - let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_delegate}); - } catch(error) { - console.log(` tx -> revert because already registered modules are not allowed`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - await I_MRProxied.unpause({from: account_polymath}); - }) - - it("Should register the module with the Module Registry", async() => { - let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); - assert.equal(tx.logs[0].args._moduleFactory, I_GeneralTransferManagerFactory.address, "Should be the same address"); - assert.equal(tx.logs[0].args._owner, account_polymath, "Should be the right owner"); - - let _list = await I_MRProxied.getModulesByType(transferManagerKey); - assert.equal(_list.length, 1, "Length should be 1"); - assert.equal(_list[0], I_GeneralTransferManagerFactory.address); - - let _reputation = await I_MRProxied.getReputationByFactory(I_GeneralTransferManagerFactory.address); - assert.equal(_reputation.length, 0); - }); - - it("Should fail the register the module -- Already registered module", async() => { - let errorThrown = false; - try { - let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert because already registered modules are not allowed`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should fail in registering the module-- type = 0", async() => { - I_MockFactory = await MockFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); - let errorThrown = false; - try { - await I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath }); - } catch(error) { - console.log(` tx revert -> Module factory of 0 type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - }); - - describe("Test case for verifyModule", async() => { - - it("Should fail in calling the verify module. Because msg.sender should be account_polymath", async () => { - let errorThrown = false; - try { - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_temp }); - } catch(error) { - console.log(` tx revert -> msg.sender should be account_polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully verify the module -- true", async() => { - let tx = await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - assert.equal( - tx.logs[0].args._moduleFactory, - I_GeneralTransferManagerFactory.address, - "Failed in verifying the module" - ); - assert.equal( - tx.logs[0].args._verified, - true, - "Failed in verifying the module" - ); - }); - - it("Should successfully verify the module -- false", async() => { - I_CappedSTOFactory1 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); - await I_MRProxied.registerModule(I_CappedSTOFactory1.address, {from: account_polymath}); - let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory1.address, false, { from: account_polymath }); - assert.equal( - tx.logs[0].args._moduleFactory, - I_CappedSTOFactory1.address, - "Failed in verifying the module" - ); - assert.equal( - tx.logs[0].args._verified, - false, - "Failed in verifying the module" - ); - }); - - it("Should fail in verifying the module. Because the module is not registered", async() => { - let errorThrown = false; - try { - await I_MRProxied.verifyModule(I_MockFactory.address, true, { from: account_polymath }); - } catch(error) { - console.log(` tx revert -> Module is not registered`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - }) - - describe("Test cases for the useModule function of the module registry", async() => { - - it("Deploy the securityToken", async() => { - await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); - await I_STRProxied.registerTicker(account_issuer, symbol, name, {from: account_issuer}); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, true, {from: account_issuer}); - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase()); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - }); - - it("Should fail in adding module. Because module is un-verified", async() => { - startTime = latestTime() + duration.seconds(5000); - endTime = startTime + duration.days(30); - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - let errorThrown = false; - try { - const tx = await I_SecurityToken.addModule(I_CappedSTOFactory1.address, bytesSTO, 0, 0, { from: token_owner}); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Module is un-verified`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to register module because custom modules not allowed", async() => { - I_CappedSTOFactory2 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); - - assert.notEqual( - I_CappedSTOFactory2.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CappedSTOFactory contract was not deployed" - ); - - - let errorThrown = false; - try { - let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Module is un-verified`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); - - }); - - it("Should switch customModulesAllowed to true", async() => { - assert.equal(false, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be dissabled by default."); - let tx = await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", true, { from: account_polymath }); - assert.equal(true, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be switched to true."); - }); - - it("Should successfully add module because custom modules switched on", async() => { - startTime = latestTime() + duration.seconds(5000); - endTime = startTime + duration.days(30); - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); - tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, 0, 0, { from: token_owner}); - - assert.equal(tx.logs[2].args._types[0], stoKey, "CappedSTO doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "CappedSTO", - "CappedSTOFactory module was not added" - ); - let _reputation = await I_MRProxied.getReputationByFactory.call(I_CappedSTOFactory2.address); - assert.equal(_reputation.length, 1); - }); - - it("Should successfully add verified module", async() => { - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, {from: account_polymath}); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, {from: account_polymath}); - let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0], permissionManagerKey, "module doesn't get deployed"); - }); - - it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --lower", async() => { - I_TestSTOFactory = await TestSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); - await I_MRProxied.registerModule(I_TestSTOFactory.address, {from: account_polymath}); - await I_MRProxied.verifyModule(I_TestSTOFactory.address, true, {from: account_polymath}); - // Taking the snapshot the revert the changes from here - let id = await takeSnapshot(); - await I_TestSTOFactory.changeSTVersionBounds("lowerBound", [0,1,0], {from: account_polymath}); - let _lstVersion = await I_TestSTOFactory.getLowerSTVersionBounds.call() - assert.equal(_lstVersion[2],0); - assert.equal(_lstVersion[1],1); - let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); - let errorThrown = false; - try { - let tx = await I_SecurityToken.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Incompatible with the lower bound of the Module factory`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); - await revertToSnapshot(id); - }) - - it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --upper", async() => { - await I_TestSTOFactory.changeSTVersionBounds("upperBound", [0,0,1], {from: account_polymath}); - let _ustVersion = await I_TestSTOFactory.getUpperSTVersionBounds.call() - assert.equal(_ustVersion[0],0); - assert.equal(_ustVersion[2],1); - await I_STRProxied.setProtocolVersion(I_STFactory.address, 1, 0, 1); - - // Generate the new securityToken - let newSymbol = "toro"; - await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); - await I_STRProxied.registerTicker(account_issuer, newSymbol, name, {from: account_issuer}); - let tx = await I_STRProxied.generateSecurityToken(name, newSymbol, tokenDetails, true, {from: account_issuer}); - assert.equal(tx.logs[1].args._ticker, newSymbol.toUpperCase()); - I_SecurityToken2 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - - let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); - let errorThrown = false; - try { - let tx = await I_SecurityToken2.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Incompatible with the upper bound of the Module factory`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - }); - - describe("Test case for the getModulesByTypeAndToken()", async() => { - - it("Should get the list of available modules when the customModulesAllowed", async() => { - let _list = await I_MRProxied.getModulesByTypeAndToken.call(3, I_SecurityToken.address); - assert.equal(_list[0], I_CappedSTOFactory2.address); - }) - - it("Should get the list of available modules when the customModulesAllowed is not allowed", async() => { - await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", false, { from: account_polymath }); - let _list = await I_MRProxied.getModulesByTypeAndToken.call(3, I_SecurityToken.address); - assert.equal(_list.length, 0); - }) - }) - - describe("Test cases for getters", async() => { - - it("Check getter - ", async() => { - console.log("getModulesByType:") - for (let i = 0; i < 5; i++) { - let _list = await I_MRProxied.getModulesByType.call(i); - console.log("Type: " + i + ":" + _list); - } - console.log("getModulesByTypeAndToken:") - for (let i = 0; i < 5; i++) { - let _list = await I_MRProxied.getModulesByTypeAndToken.call(i, I_SecurityToken.address); - console.log("Type: " + i + ":" + _list); - } - console.log("getTagsByType:") - for (let i = 0; i < 5; i++) { - let _list = await I_MRProxied.getTagsByType.call(i); - console.log("Type: " + i + ":" + _list[1]); - console.log("Type: " + i + ":" + _list[0].map(x => web3.utils.toAscii(x))); - } - console.log("getTagsByTypeAndToken:") - for (let i = 0; i < 5; i++) { - let _list = await I_MRProxied.getTagsByTypeAndToken.call(i, I_SecurityToken.address); - console.log("Type: " + i + ":" + _list[1]); - console.log("Type: " + i + ":" + _list[0].map(x => web3.utils.toAscii(x))); - } - }) - - }); - - describe("Test cases for removeModule()", async() => { - - it("Should fail if msg.sender not curator or owner", async() => { - let errorThrown = false; - try { - await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_temp }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Module is un-verified`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully remove module and delete data if msg.sender is curator", async() => { - let snap = await takeSnapshot(); - - let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; - let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; - - assert.equal(sto1,I_CappedSTOFactory1.address); - assert.equal(sto2,I_CappedSTOFactory2.address); - assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); - - let tx = await I_MRProxied.removeModule(sto1, { from: account_polymath }); - - assert.equal(tx.logs[0].args._moduleFactory, sto1, "Event is not properly emitted for _moduleFactory"); - assert.equal(tx.logs[0].args._decisionMaker, account_polymath, "Event is not properly emitted for _decisionMaker"); - - let sto2_end = (await I_MRProxied.getModulesByType.call(3))[1]; - - // re-ordering - assert.equal(sto2_end,sto2); - // delete related data - assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto1)), 0); - assert.equal(await I_MRProxied.getReputationByFactory.call(sto1), 0); - assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); - assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto1)), false); - - await revertToSnapshot(snap); - }); - - it("Should successfully remove module and delete data if msg.sender is owner", async() => { - let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; - let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; - - assert.equal(sto1,I_CappedSTOFactory1.address); - assert.equal(sto2,I_CappedSTOFactory2.address); - assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); - - let tx = await I_MRProxied.removeModule(sto2, { from: token_owner }); - - assert.equal(tx.logs[0].args._moduleFactory, sto2, "Event is not properly emitted for _moduleFactory"); - assert.equal(tx.logs[0].args._decisionMaker, token_owner, "Event is not properly emitted for _decisionMaker"); - - let sto1_end = (await I_MRProxied.getModulesByType.call(3))[0]; - - // re-ordering - assert.equal(sto1_end,sto1); - // delete related data - assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto2)), 0); - assert.equal(await I_MRProxied.getReputationByFactory.call(sto2), 0); - assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); - assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto2)), false); - }); - - it("Should fail if module already removed", async() => { - let errorThrown = false; - try { - await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_polymath }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Module is un-verified`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - }); - - describe("Test cases for IRegistry functionality", async() => { - - describe("Test cases for reclaiming funds", async() => { - - it("Should successfully reclaim POLY tokens", async() => { - await I_PolyToken.getTokens(web3.utils.toWei("1"), I_MRProxied.address); - let bal1 = await I_PolyToken.balanceOf.call(account_polymath); - await I_MRProxied.reclaimERC20(I_PolyToken.address); - let bal2 = await I_PolyToken.balanceOf.call(account_polymath); - assert.isAtLeast(bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), bal2.dividedBy(new BigNumber(10).pow(18)).toNumber()); - }); - - }); - - describe("Test cases for pausing the contract", async() => { - - it("Should fail to pause if msg.sender is not owner", async() => { - let errorThrown = false; - try { - await I_MRProxied.pause({ from: account_temp }); - } catch(error) { - console.log(` tx revert -> msg.sender should be account_polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully pause the contract", async() => { - await I_MRProxied.pause({ from: account_polymath }); - let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); - assert.isOk(status); - }); - - it("Should fail to unpause if msg.sender is not owner", async() => { - let errorThrown = false; - try { - await I_MRProxied.unpause({ from: account_temp }); - } catch(error) { - console.log(` tx revert -> msg.sender should be account_polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully unpause the contract", async() => { - await I_MRProxied.unpause({ from: account_polymath }); - let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); - assert.isNotOk(status); - }); - - }); - - }); - }); - -}); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +// const CappedSTO = artifacts.require('./CappedSTO.sol'); +// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); +// const MockFactory = artifacts.require('./MockFactory.sol'); +// const TestSTOFactory = artifacts.require('./TestSTOFactory.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + + +// contract('ModuleRegistry', accounts => { + + +// // Accounts Variable declaration +// let account_polymath; +// let account_investor1; +// let account_issuer; +// let token_owner; +// let account_investor2; +// let account_fundsReceiver; +// let account_delegate; +// let account_temp; + +// let balanceOfReceiver; +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(15); + +// let ID_snap; +// let message = "Transaction Should fail!"; +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_GeneralTransferManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_CappedSTOFactory1; +// let I_CappedSTOFactory2; +// let I_STFactory; +// let I_MRProxied; +// let I_SecurityToken; +// let I_STRProxied; +// let I_CappedSTO; +// let I_PolyToken; +// let I_MockFactory; +// let I_TestSTOFactory; +// let I_DummySTOFactory; +// let I_PolymathRegistry; +// let I_SecurityToken2; + +// // SecurityToken Details (Launched ST on the behalf of the issuer) +// const name = "Demo Token"; +// const symbol = "det"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; + +// // Module key +// const permissionManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; +// const budget = 0; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// // delagate details +// const delegateDetails = "I am delegate .."; +// const TM_Perm = 'FLAGS'; + +// // Capped STO details +// let startTime; +// let endTime; +// const cap = web3.utils.toWei("10000"); +// const rate = 1000; +// const fundRaiseType = [0]; +// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256','uint8[]', 'address']; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; +// account_investor1 = accounts[9]; +// account_investor2 = accounts[6]; +// account_fundsReceiver = accounts[4]; +// account_delegate = accounts[5]; +// account_temp = accounts[8]; +// token_owner = account_issuer; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + +// assert.notEqual( +// I_ModuleRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "ModuleRegistry contract was not deployed", +// ); + +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// let tx = await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + +// // STEP 2: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 9: Deploy the SecurityTokenRegistry + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: update the registries addresses from the PolymathRegistry contract +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + + +// assert.notEqual( +// I_FeatureRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "FeatureRegistry contract was not deployed", +// ); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Test cases for the ModuleRegistry", async() => { + +// describe("Test case for the upgradeFromregistry", async() => { + +// it("Should successfully update the registry contract address -- failed because of bad owner", async() => { +// let errorThrown = false; +// try { +// await I_MRProxied.updateFromRegistry({from: account_temp}); +// } catch(error) { +// console.log(` tx -> revert because of bad owner`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully update the registry contract addresses", async() => { +// await I_MRProxied.updateFromRegistry({from: account_polymath}); +// assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("securityTokenRegistry")), I_SecurityTokenRegistryProxy.address); +// assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("featureRegistry")), I_FeatureRegistry.address); +// assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), I_PolyToken.address); +// }); + +// }); + +// describe("Test the state variables", async() => { + +// it("Should be the right owner", async() => { +// let _owner = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3('owner')); +// assert.equal(_owner, account_polymath, "Owner should be the correct"); +// }) + +// it("Should be the expected value of the paused and intialised variable", async() => { +// let _paused = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); +// assert.isFalse(_paused, "Should be the false"); + +// let _intialised = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); +// assert.isTrue(_intialised, "Values should be the true"); +// }) + +// it("Should be the expected value of the polymath registry", async() => { +// let _polymathRegistry = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); +// assert.equal(_polymathRegistry, I_PolymathRegistry.address, "Should be the right value of the address of the polymath registry"); +// }); +// }); + +// describe("Test cases for the registering the module", async() => { + +// it("Should fail to register the module -- when registerModule is paused", async() => { +// await I_MRProxied.pause({from: account_polymath}); +// let errorThrown = false; +// try { +// let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_delegate}); +// } catch(error) { +// console.log(` tx -> revert because already registered modules are not allowed`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// await I_MRProxied.unpause({from: account_polymath}); +// }) + +// it("Should register the module with the Module Registry", async() => { +// let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); +// assert.equal(tx.logs[0].args._moduleFactory, I_GeneralTransferManagerFactory.address, "Should be the same address"); +// assert.equal(tx.logs[0].args._owner, account_polymath, "Should be the right owner"); + +// let _list = await I_MRProxied.getModulesByType(transferManagerKey); +// assert.equal(_list.length, 1, "Length should be 1"); +// assert.equal(_list[0], I_GeneralTransferManagerFactory.address); + +// let _reputation = await I_MRProxied.getReputationByFactory(I_GeneralTransferManagerFactory.address); +// assert.equal(_reputation.length, 0); +// }); + +// it("Should fail the register the module -- Already registered module", async() => { +// let errorThrown = false; +// try { +// let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert because already registered modules are not allowed`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should fail in registering the module-- type = 0", async() => { +// I_MockFactory = await MockFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); +// let errorThrown = false; +// try { +// await I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath }); +// } catch(error) { +// console.log(` tx revert -> Module factory of 0 type`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); +// }); + +// describe("Test case for verifyModule", async() => { + +// it("Should fail in calling the verify module. Because msg.sender should be account_polymath", async () => { +// let errorThrown = false; +// try { +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> msg.sender should be account_polymath`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully verify the module -- true", async() => { +// let tx = await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); +// assert.equal( +// tx.logs[0].args._moduleFactory, +// I_GeneralTransferManagerFactory.address, +// "Failed in verifying the module" +// ); +// assert.equal( +// tx.logs[0].args._verified, +// true, +// "Failed in verifying the module" +// ); +// }); + +// it("Should successfully verify the module -- false", async() => { +// I_CappedSTOFactory1 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); +// await I_MRProxied.registerModule(I_CappedSTOFactory1.address, {from: account_polymath}); +// let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory1.address, false, { from: account_polymath }); +// assert.equal( +// tx.logs[0].args._moduleFactory, +// I_CappedSTOFactory1.address, +// "Failed in verifying the module" +// ); +// assert.equal( +// tx.logs[0].args._verified, +// false, +// "Failed in verifying the module" +// ); +// }); + +// it("Should fail in verifying the module. Because the module is not registered", async() => { +// let errorThrown = false; +// try { +// await I_MRProxied.verifyModule(I_MockFactory.address, true, { from: account_polymath }); +// } catch(error) { +// console.log(` tx revert -> Module is not registered`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); +// }) + +// describe("Test cases for the useModule function of the module registry", async() => { + +// it("Deploy the securityToken", async() => { +// await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); +// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); +// await I_STRProxied.registerTicker(account_issuer, symbol, name, {from: account_issuer}); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, true, {from: account_issuer}); +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase()); +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); +// }); + +// it("Should fail in adding module. Because module is un-verified", async() => { +// startTime = latestTime() + duration.seconds(5000); +// endTime = startTime + duration.days(30); +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); +// let errorThrown = false; +// try { +// const tx = await I_SecurityToken.addModule(I_CappedSTOFactory1.address, bytesSTO, 0, 0, { from: token_owner}); +// } catch(error) { +// errorThrown = true; +// console.log(` tx revert -> Module is un-verified`.grey); +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to register module because custom modules not allowed", async() => { +// I_CappedSTOFactory2 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); + +// assert.notEqual( +// I_CappedSTOFactory2.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CappedSTOFactory contract was not deployed" +// ); + + +// let errorThrown = false; +// try { +// let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); +// } catch(error) { +// errorThrown = true; +// console.log(` tx revert -> Module is un-verified`.grey); +// ensureException(error); +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Should switch customModulesAllowed to true", async() => { +// assert.equal(false, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be dissabled by default."); +// let tx = await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", true, { from: account_polymath }); +// assert.equal(true, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be switched to true."); +// }); + +// it("Should successfully add module because custom modules switched on", async() => { +// startTime = latestTime() + duration.seconds(5000); +// endTime = startTime + duration.days(30); +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); +// let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); +// tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, 0, 0, { from: token_owner}); + +// assert.equal(tx.logs[2].args._types[0], stoKey, "CappedSTO doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "CappedSTO", +// "CappedSTOFactory module was not added" +// ); +// let _reputation = await I_MRProxied.getReputationByFactory.call(I_CappedSTOFactory2.address); +// assert.equal(_reputation.length, 1); +// }); + +// it("Should successfully add verified module", async() => { +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, {from: account_polymath}); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, {from: account_polymath}); +// let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0], permissionManagerKey, "module doesn't get deployed"); +// }); + +// it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --lower", async() => { +// I_TestSTOFactory = await TestSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); +// await I_MRProxied.registerModule(I_TestSTOFactory.address, {from: account_polymath}); +// await I_MRProxied.verifyModule(I_TestSTOFactory.address, true, {from: account_polymath}); +// // Taking the snapshot the revert the changes from here +// let id = await takeSnapshot(); +// await I_TestSTOFactory.changeSTVersionBounds("lowerBound", [0,1,0], {from: account_polymath}); +// let _lstVersion = await I_TestSTOFactory.getLowerSTVersionBounds.call() +// assert.equal(_lstVersion[2],0); +// assert.equal(_lstVersion[1],1); +// let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); +// let errorThrown = false; +// try { +// let tx = await I_SecurityToken.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); +// } catch(error) { +// errorThrown = true; +// console.log(` tx revert -> Incompatible with the lower bound of the Module factory`.grey); +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// await revertToSnapshot(id); +// }) + +// it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --upper", async() => { +// await I_TestSTOFactory.changeSTVersionBounds("upperBound", [0,0,1], {from: account_polymath}); +// let _ustVersion = await I_TestSTOFactory.getUpperSTVersionBounds.call() +// assert.equal(_ustVersion[0],0); +// assert.equal(_ustVersion[2],1); +// await I_STRProxied.setProtocolVersion(I_STFactory.address, 1, 0, 1); + +// // Generate the new securityToken +// let newSymbol = "toro"; +// await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); +// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); +// await I_STRProxied.registerTicker(account_issuer, newSymbol, name, {from: account_issuer}); +// let tx = await I_STRProxied.generateSecurityToken(name, newSymbol, tokenDetails, true, {from: account_issuer}); +// assert.equal(tx.logs[1].args._ticker, newSymbol.toUpperCase()); +// I_SecurityToken2 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + +// let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); +// let errorThrown = false; +// try { +// let tx = await I_SecurityToken2.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); +// } catch(error) { +// errorThrown = true; +// console.log(` tx revert -> Incompatible with the upper bound of the Module factory`.grey); +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// }); + +// describe("Test case for the getModulesByTypeAndToken()", async() => { + +// it("Should get the list of available modules when the customModulesAllowed", async() => { +// let _list = await I_MRProxied.getModulesByTypeAndToken.call(3, I_SecurityToken.address); +// assert.equal(_list[0], I_CappedSTOFactory2.address); +// }) + +// it("Should get the list of available modules when the customModulesAllowed is not allowed", async() => { +// await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", false, { from: account_polymath }); +// let _list = await I_MRProxied.getModulesByTypeAndToken.call(3, I_SecurityToken.address); +// assert.equal(_list.length, 0); +// }) +// }) + +// describe("Test cases for getters", async() => { + +// it("Check getter - ", async() => { +// console.log("getModulesByType:") +// for (let i = 0; i < 5; i++) { +// let _list = await I_MRProxied.getModulesByType.call(i); +// console.log("Type: " + i + ":" + _list); +// } +// console.log("getModulesByTypeAndToken:") +// for (let i = 0; i < 5; i++) { +// let _list = await I_MRProxied.getModulesByTypeAndToken.call(i, I_SecurityToken.address); +// console.log("Type: " + i + ":" + _list); +// } +// console.log("getTagsByType:") +// for (let i = 0; i < 5; i++) { +// let _list = await I_MRProxied.getTagsByType.call(i); +// console.log("Type: " + i + ":" + _list[1]); +// console.log("Type: " + i + ":" + _list[0].map(x => web3.utils.toAscii(x))); +// } +// console.log("getTagsByTypeAndToken:") +// for (let i = 0; i < 5; i++) { +// let _list = await I_MRProxied.getTagsByTypeAndToken.call(i, I_SecurityToken.address); +// console.log("Type: " + i + ":" + _list[1]); +// console.log("Type: " + i + ":" + _list[0].map(x => web3.utils.toAscii(x))); +// } +// }) + +// }); + +// describe("Test cases for removeModule()", async() => { + +// it("Should fail if msg.sender not curator or owner", async() => { +// let errorThrown = false; +// try { +// await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_temp }); +// } catch(error) { +// errorThrown = true; +// console.log(` tx revert -> Module is un-verified`.grey); +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully remove module and delete data if msg.sender is curator", async() => { +// let snap = await takeSnapshot(); + +// let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; +// let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; + +// assert.equal(sto1,I_CappedSTOFactory1.address); +// assert.equal(sto2,I_CappedSTOFactory2.address); +// assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); + +// let tx = await I_MRProxied.removeModule(sto1, { from: account_polymath }); + +// assert.equal(tx.logs[0].args._moduleFactory, sto1, "Event is not properly emitted for _moduleFactory"); +// assert.equal(tx.logs[0].args._decisionMaker, account_polymath, "Event is not properly emitted for _decisionMaker"); + +// let sto2_end = (await I_MRProxied.getModulesByType.call(3))[1]; + +// // re-ordering +// assert.equal(sto2_end,sto2); +// // delete related data +// assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto1)), 0); +// assert.equal(await I_MRProxied.getReputationByFactory.call(sto1), 0); +// assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); +// assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto1)), false); + +// await revertToSnapshot(snap); +// }); + +// it("Should successfully remove module and delete data if msg.sender is owner", async() => { +// let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; +// let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; + +// assert.equal(sto1,I_CappedSTOFactory1.address); +// assert.equal(sto2,I_CappedSTOFactory2.address); +// assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); + +// let tx = await I_MRProxied.removeModule(sto2, { from: token_owner }); + +// assert.equal(tx.logs[0].args._moduleFactory, sto2, "Event is not properly emitted for _moduleFactory"); +// assert.equal(tx.logs[0].args._decisionMaker, token_owner, "Event is not properly emitted for _decisionMaker"); + +// let sto1_end = (await I_MRProxied.getModulesByType.call(3))[0]; + +// // re-ordering +// assert.equal(sto1_end,sto1); +// // delete related data +// assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto2)), 0); +// assert.equal(await I_MRProxied.getReputationByFactory.call(sto2), 0); +// assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); +// assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto2)), false); +// }); + +// it("Should fail if module already removed", async() => { +// let errorThrown = false; +// try { +// await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_polymath }); +// } catch(error) { +// errorThrown = true; +// console.log(` tx revert -> Module is un-verified`.grey); +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// }); + +// describe("Test cases for IRegistry functionality", async() => { + +// describe("Test cases for reclaiming funds", async() => { + +// it("Should successfully reclaim POLY tokens", async() => { +// await I_PolyToken.getTokens(web3.utils.toWei("1"), I_MRProxied.address); +// let bal1 = await I_PolyToken.balanceOf.call(account_polymath); +// await I_MRProxied.reclaimERC20(I_PolyToken.address); +// let bal2 = await I_PolyToken.balanceOf.call(account_polymath); +// assert.isAtLeast(bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), bal2.dividedBy(new BigNumber(10).pow(18)).toNumber()); +// }); + +// }); + +// describe("Test cases for pausing the contract", async() => { + +// it("Should fail to pause if msg.sender is not owner", async() => { +// let errorThrown = false; +// try { +// await I_MRProxied.pause({ from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> msg.sender should be account_polymath`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully pause the contract", async() => { +// await I_MRProxied.pause({ from: account_polymath }); +// let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); +// assert.isOk(status); +// }); + +// it("Should fail to unpause if msg.sender is not owner", async() => { +// let errorThrown = false; +// try { +// await I_MRProxied.unpause({ from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> msg.sender should be account_polymath`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully unpause the contract", async() => { +// await I_MRProxied.unpause({ from: account_polymath }); +// let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); +// assert.isNotOk(status); +// }); + +// }); + +// }); +// }); + +// }); diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index 95b56bc68..0bd37009b 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -1,507 +1,507 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol'); -const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('PercentageTransferManager', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let P_PercentageTransferManagerFactory; - let I_SecurityTokenRegistryProxy; - let P_PercentageTransferManager; - let I_GeneralTransferManagerFactory; - let I_PercentageTransferManagerFactory; - let I_GeneralPermissionManager; - let I_PercentageTransferManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STRProxied; - let I_MRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - // PercentageTransferManager details - const holderPercentage = 70 * 10**16; // Maximum number of token holders - - let bytesSTO = web3.eth.abi.encodeFunctionCall({ - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_maxHolderPercentage' - },{ - type: 'bool', - name: '_allowPrimaryIssuance' - } - ] - }, [holderPercentage, false]); - - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[7]; - account_investor2 = accounts[8]; - account_investor3 = accounts[9]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4(a): Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 4(b): Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 4(c): Deploy the PercentageTransferManager - I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_PercentageTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "PercentageTransferManagerFactory contract was not deployed" - ); - - // STEP 4(d): Deploy the PercentageTransferManager - P_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); - assert.notEqual( - P_PercentageTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "PercentageTransferManagerFactory contract was not deployed" - ); - - - // Step 6: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 7: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 8: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol'); +// const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('PercentageTransferManager', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let P_PercentageTransferManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let P_PercentageTransferManager; +// let I_GeneralTransferManagerFactory; +// let I_PercentageTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_PercentageTransferManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_STRProxied; +// let I_MRProxied; +// let I_STFactory; +// let I_SecurityToken; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; + +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// // PercentageTransferManager details +// const holderPercentage = 70 * 10**16; // Maximum number of token holders + +// let bytesSTO = web3.eth.abi.encodeFunctionCall({ +// name: 'configure', +// type: 'function', +// inputs: [{ +// type: 'uint256', +// name: '_maxHolderPercentage' +// },{ +// type: 'bool', +// name: '_allowPrimaryIssuance' +// } +// ] +// }, [holderPercentage, false]); + +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; + +// account_investor1 = accounts[7]; +// account_investor2 = accounts[8]; +// account_investor3 = accounts[9]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4(a): Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 4(b): Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 4(c): Deploy the PercentageTransferManager +// I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); +// assert.notEqual( +// I_PercentageTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "PercentageTransferManagerFactory contract was not deployed" +// ); + +// // STEP 4(d): Deploy the PercentageTransferManager +// P_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); +// assert.notEqual( +// P_PercentageTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "PercentageTransferManagerFactory contract was not deployed" +// ); + + +// // Step 6: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 7: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 8: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 9: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); +// // Step 9: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); - // STEP 5: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the PercentageTransferManagerFactory - await I_MRProxied.registerModule(I_PercentageTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_PercentageTransferManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the Paid PercentageTransferManagerFactory - await I_MRProxied.registerModule(P_PercentageTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(P_PercentageTransferManagerFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - PercentageTransferManagerFactory: ${I_PercentageTransferManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - }); - - describe("Buy tokens using on-chain whitelist", async() => { - - it("Should Buy the tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Should successfully attach the PercentageTransferManager factory with the security token - failed payment", async () => { - let errorThrown = false; - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - try { - const tx = await I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - } catch(error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the PercentageTransferManager factory with the security token", async () => { - let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManagerFactory doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "PercentageTransferManager", - "PercentageTransferManagerFactory module was not added" - ); - P_PercentageTransferManager = PercentageTransferManager.at(tx.logs[3].args._module); - await revertToSnapshot(snapId); - }); - - it("Should successfully attach the PercentageTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "PercentageTransferManager", - "PercentageTransferManager module was not added" - ); - I_PercentageTransferManager = PercentageTransferManager.at(tx.logs[2].args._module); - }); - - it("Add a new token holder", async() => { - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Should pause the tranfers at transferManager level", async() => { - let tx = await I_PercentageTransferManager.pause({from: token_owner}); - }); - - it("Should still be able to transfer between existing token holders up to limit", async() => { - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should unpause the tranfers at transferManager level", async() => { - await I_PercentageTransferManager.unpause({from: token_owner}); - }) - - it("Should not be able to mint token amount over limit", async() => { - let errorThrown = false; - try { - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Too high minting`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Allow unlimited primary issuance and remint", async() => { - let snapId = await takeSnapshot(); - await I_PercentageTransferManager.setAllowPrimaryIssuance(true, { from: token_owner }); - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner }); - await revertToSnapshot(snapId); - }); - - it("Should not be able to transfer between existing token holders over limit", async() => { - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Too many holders`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Modify holder percentage to 100", async() => { - // Add the Investor in to the whitelist - // Mint some tokens - await I_PercentageTransferManager.changeHolderPercentage(100 * 10**16, { from: token_owner }); - - assert.equal( - (await I_PercentageTransferManager.maxHolderPercentage()).toNumber(), - 100 * 10**16 - ); - }); - - it("Should be able to transfer between existing token holders up to limit", async() => { - await I_PercentageTransferManager.modifyWhitelist(account_investor3, false, { from: token_owner }); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); - }); - - it("Should be able to whitelist address and then transfer regardless of holders", async() => { - await I_PercentageTransferManager.changeHolderPercentage(30 * 10**16, { from: token_owner }); - await I_PercentageTransferManager.modifyWhitelist(account_investor1, true, { from: token_owner }); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor3 }); - }); - - it("Should get the permission", async() => { - let perm = await I_PercentageTransferManager.getPermissions.call(); - assert.equal(perm.length, 2); - }); - - }); - - describe("Percentage Transfer Manager Factory test cases", async() => { - - it("Should get the exact details of the factory", async() => { - assert.equal(await I_PercentageTransferManagerFactory.setupCost.call(),0); - assert.equal((await I_PercentageTransferManagerFactory.getTypes.call())[0],2); - assert.equal(web3.utils.toAscii(await I_PercentageTransferManagerFactory.getName.call()) - .replace(/\u0000/g, ''), - "PercentageTransferManager", - "Wrong Module added"); - assert.equal(await I_PercentageTransferManagerFactory.getDescription.call(), - "Restrict the number of investors", - "Wrong Module added"); - assert.equal(await I_PercentageTransferManagerFactory.getTitle.call(), - "Percentage Transfer Manager", - "Wrong Module added"); - assert.equal(await I_PercentageTransferManagerFactory.getInstructions.call(), - "Allows an issuer to restrict the total number of non-zero token holders", - "Wrong Module added"); - - }); - - it("Should get the tags of the factory", async() => { - let tags = await I_PercentageTransferManagerFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Percentage"); - }); - }); - -}); +// // STEP 5: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the PercentageTransferManagerFactory +// await I_MRProxied.registerModule(I_PercentageTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_PercentageTransferManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the Paid PercentageTransferManagerFactory +// await I_MRProxied.registerModule(P_PercentageTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(P_PercentageTransferManagerFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// PercentageTransferManagerFactory: ${I_PercentageTransferManagerFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); + +// }); + +// describe("Buy tokens using on-chain whitelist", async() => { + +// it("Should Buy the tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(5000); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Should Buy some more tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Should successfully attach the PercentageTransferManager factory with the security token - failed payment", async () => { +// let errorThrown = false; +// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); +// try { +// const tx = await I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx -> failed because Token is not paid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the PercentageTransferManager factory with the security token", async () => { +// let snapId = await takeSnapshot(); +// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); +// const tx = await I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManagerFactory doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[3].args._name) +// .replace(/\u0000/g, ''), +// "PercentageTransferManager", +// "PercentageTransferManagerFactory module was not added" +// ); +// P_PercentageTransferManager = PercentageTransferManager.at(tx.logs[3].args._module); +// await revertToSnapshot(snapId); +// }); + +// it("Should successfully attach the PercentageTransferManager with the security token", async () => { +// const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "PercentageTransferManager", +// "PercentageTransferManager module was not added" +// ); +// I_PercentageTransferManager = PercentageTransferManager.at(tx.logs[2].args._module); +// }); + +// it("Add a new token holder", async() => { + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Should pause the tranfers at transferManager level", async() => { +// let tx = await I_PercentageTransferManager.pause({from: token_owner}); +// }); + +// it("Should still be able to transfer between existing token holders up to limit", async() => { +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('2', 'ether') +// ); +// }); + +// it("Should unpause the tranfers at transferManager level", async() => { +// await I_PercentageTransferManager.unpause({from: token_owner}); +// }) + +// it("Should not be able to mint token amount over limit", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Too high minting`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Allow unlimited primary issuance and remint", async() => { +// let snapId = await takeSnapshot(); +// await I_PercentageTransferManager.setAllowPrimaryIssuance(true, { from: token_owner }); +// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner }); +// await revertToSnapshot(snapId); +// }); + +// it("Should not be able to transfer between existing token holders over limit", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> Too many holders`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Modify holder percentage to 100", async() => { +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_PercentageTransferManager.changeHolderPercentage(100 * 10**16, { from: token_owner }); + +// assert.equal( +// (await I_PercentageTransferManager.maxHolderPercentage()).toNumber(), +// 100 * 10**16 +// ); +// }); + +// it("Should be able to transfer between existing token holders up to limit", async() => { +// await I_PercentageTransferManager.modifyWhitelist(account_investor3, false, { from: token_owner }); +// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); +// }); + +// it("Should be able to whitelist address and then transfer regardless of holders", async() => { +// await I_PercentageTransferManager.changeHolderPercentage(30 * 10**16, { from: token_owner }); +// await I_PercentageTransferManager.modifyWhitelist(account_investor1, true, { from: token_owner }); +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor3 }); +// }); + +// it("Should get the permission", async() => { +// let perm = await I_PercentageTransferManager.getPermissions.call(); +// assert.equal(perm.length, 2); +// }); + +// }); + +// describe("Percentage Transfer Manager Factory test cases", async() => { + +// it("Should get the exact details of the factory", async() => { +// assert.equal(await I_PercentageTransferManagerFactory.setupCost.call(),0); +// assert.equal((await I_PercentageTransferManagerFactory.getTypes.call())[0],2); +// assert.equal(web3.utils.toAscii(await I_PercentageTransferManagerFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "PercentageTransferManager", +// "Wrong Module added"); +// assert.equal(await I_PercentageTransferManagerFactory.getDescription.call(), +// "Restrict the number of investors", +// "Wrong Module added"); +// assert.equal(await I_PercentageTransferManagerFactory.getTitle.call(), +// "Percentage Transfer Manager", +// "Wrong Module added"); +// assert.equal(await I_PercentageTransferManagerFactory.getInstructions.call(), +// "Allows an issuer to restrict the total number of non-zero token holders", +// "Wrong Module added"); + +// }); + +// it("Should get the tags of the factory", async() => { +// let tags = await I_PercentageTransferManagerFactory.getTags.call(); +// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Percentage"); +// }); +// }); + +// }); diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index 81ed48fd7..2ee41f30f 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -1,477 +1,477 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); -const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('PreSaleSTO', accounts => { - // Accounts Variable declaration - let account_polymath; - let account_investor1; - let account_issuer; - let token_owner; - let account_investor2; - let account_investor3; - let account_fundsReceiver; - - let balanceOfReceiver; - let message = "Transaction Should Fail!"; - // investor Details - let fromTime; - let toTime; - let expiryTime; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_PreSaleSTOFactory; - let I_STFactory; - let I_SecurityToken; - let I_MRProxied; - let I_STRProxied; - let I_PreSaleSTO; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details for funds raise Type ETH - const name = "Team"; - const symbol = "SAP"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - - // SecurityToken Details for funds raise Type POLY - const P_name = "Team Poly"; - const P_symbol = "PAS"; - const P_tokenDetails = "This is equity type of issuance"; - const P_decimals = 18; - - // Module key - const transferManagerKey = 2; - const stoKey = 3; - const budget = 0; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - let endTime; - const STOParameters = ['uint256']; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - account_investor1 = accounts[4]; - account_investor2 = accounts[3]; - account_investor3 = accounts[5]; - account_fundsReceiver = accounts[2]; - token_owner = account_issuer; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 2: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 3: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 4: Deploy the PreSaleSTOFactory - - I_PreSaleSTOFactory = await PreSaleSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); - - assert.notEqual( - I_PreSaleSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "PreSaleSTOFactory contract was not deployed" - ); - - // Step 8: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 5: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - PreSaleSTOFactory: ${I_PreSaleSTOFactory.address} - LatestTime: ${latestTime()}\n - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), transferManagerKey); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - - it("Should fail to launch the STO due to endTime is 0", async () => { - let bytesSTO = encodeModuleCall(STOParameters, [0]); - let errorThrown = false; - try { - const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Rate is ${0}. Test Passed Successfully`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the STO factory with the security token", async () => { - endTime = latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time - let bytesSTO = encodeModuleCall(STOParameters, [endTime]); - - const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); - - assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "PreSaleSTO", - "PreSaleSTOFactory module was not added" - ); - I_PreSaleSTO = PreSaleSTO.at(tx.logs[2].args._module); - }); - }); - - describe("verify the data of STO", async () => { - - it("Should verify the configuration of the STO", async() => { - assert.equal( - (await I_PreSaleSTO.endTime.call()).toNumber(), - endTime, - "STO Configuration doesn't set as expected" - ); - }); - - it("Should get the permissions", async() => { - let perm = await I_PreSaleSTO.getPermissions.call(); - assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "PRE_SALE_ADMIN"); - }); - }); - - describe("Buy tokens", async() => { - - it("Should allocate the tokens -- failed due to investor not on whitelist", async () => { - let errorThrown = false; - try { - await I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei('1', 'ether'), 0); - } catch(error) { - console.log(` tx revert -> Investor is not on whitelist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should Buy the tokens", async() => { - fromTime = latestTime(); - toTime = fromTime + duration.days(100); - expiryTime = toTime + duration.days(100); - - // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - fromTime, - toTime, - expiryTime, - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(duration.days(1)); - await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether'), 0, {from: account_issuer }); - - assert.equal( - (await I_PreSaleSTO.getRaised.call(0)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1 - ); - console.log(await I_PreSaleSTO.getNumberInvestors.call()); - assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 1); - // assert.isTrue(false); - - }); - - it("Should allocate the tokens -- failed due to msg.sender is not pre sale admin", async () => { - let errorThrown = false; - try { - await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether'), 0, {from: account_fundsReceiver }); - } catch(error) { - console.log(` tx revert -> msg.sender is not pre sale admin`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should allocate tokens to multiple investors", async() => { - fromTime = latestTime(); - toTime = fromTime + duration.days(100); - expiryTime = toTime + duration.days(100); - - // Add the Investor in to the whitelist - let tx1 = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - fromTime, - toTime, - expiryTime, - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx1.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - - // Add the Investor in to the whitelist - let tx2 = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - fromTime, - toTime, - expiryTime, - true, - { - from: account_issuer, - gas: 6000000 - }); - - assert.equal(tx2.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); - - await I_PreSaleSTO.allocateTokensMulti([account_investor2, account_investor3], [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], [0,0], [web3.utils.toWei('1000', 'ether'), web3.utils.toWei('1000', 'ether')], {from: account_issuer }); - - assert.equal( - (await I_PreSaleSTO.getRaised.call(1)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 2000 - ); - assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 3); - }); - - it("Should failed at the time of buying the tokens -- Because STO has started", async() => { - await increaseTime(duration.days(100)); // increased beyond the end time of the STO - let errorThrown = false; - try { - // Fallback transaction - await I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei('1', 'ether'), 0, {from: account_issuer}); - } catch(error) { - console.log(` tx revert -> STO has started`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - }); - - describe("Reclaim poly sent to STO by mistake", async() => { - - it("Should fail to reclaim POLY because token contract address is 0 address", async() => { - let value = web3.utils.toWei('100','ether'); - await I_PolyToken.getTokens(value, account_investor1); - await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); - - let errorThrown = false; - try { - await I_PreSaleSTO.reclaimERC20('0x0000000000000000000000000000000000000000', { from: token_owner }); - } catch(error) { - console.log(` tx revert -> token contract address is 0 address`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should successfully reclaim POLY", async() => { - let value = web3.utils.toWei('100','ether'); - await I_PolyToken.getTokens(value, account_investor1); - let initInvestorBalance = await I_PolyToken.balanceOf(account_investor1); - let initOwnerBalance = await I_PolyToken.balanceOf(token_owner); - let initContractBalance = await I_PolyToken.balanceOf(I_PreSaleSTO.address); - - await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); - await I_PreSaleSTO.reclaimERC20(I_PolyToken.address, { from: token_owner }); - assert.equal((await I_PolyToken.balanceOf(account_investor1)).toNumber(), initInvestorBalance.sub(value).toNumber(), "tokens are not transfered out from investor account"); - assert.equal((await I_PolyToken.balanceOf(token_owner)).toNumber(), initOwnerBalance.add(value).add(initContractBalance).toNumber(), "tokens are not added to the owner account"); - assert.equal((await I_PolyToken.balanceOf(I_PreSaleSTO.address)).toNumber(), 0, "tokens are not trandfered out from STO contract"); - }); - }); - - describe("Test cases for the PresaleSTOFactory", async() => { - it("should get the exact details of the factory", async() => { - assert.equal(await I_PreSaleSTOFactory.setupCost.call(),0); - assert.equal((await I_PreSaleSTOFactory.getTypes.call())[0],3); - assert.equal(web3.utils.toAscii(await I_PreSaleSTOFactory.getName.call()) - .replace(/\u0000/g, ''), - "PreSaleSTO", - "Wrong Module added"); - assert.equal(await I_PreSaleSTOFactory.getDescription.call(), - "Allows Issuer to configure pre-sale token allocations", - "Wrong Module added"); - assert.equal(await I_PreSaleSTOFactory.getTitle.call(), - "PreSale STO", - "Wrong Module added"); - assert.equal(await I_PreSaleSTOFactory.getInstructions.call(), - "Configure and track pre-sale token allocations", - "Wrong Module added"); - let tags = await I_PreSaleSTOFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Presale"); - }); - }); - -}); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); +// const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('PreSaleSTO', accounts => { +// // Accounts Variable declaration +// let account_polymath; +// let account_investor1; +// let account_issuer; +// let token_owner; +// let account_investor2; +// let account_investor3; +// let account_fundsReceiver; + +// let balanceOfReceiver; +// let message = "Transaction Should Fail!"; +// // investor Details +// let fromTime; +// let toTime; +// let expiryTime; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_PreSaleSTOFactory; +// let I_STFactory; +// let I_SecurityToken; +// let I_MRProxied; +// let I_STRProxied; +// let I_PreSaleSTO; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details for funds raise Type ETH +// const name = "Team"; +// const symbol = "SAP"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; + +// // SecurityToken Details for funds raise Type POLY +// const P_name = "Team Poly"; +// const P_symbol = "PAS"; +// const P_tokenDetails = "This is equity type of issuance"; +// const P_decimals = 18; + +// // Module key +// const transferManagerKey = 2; +// const stoKey = 3; +// const budget = 0; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); +// let endTime; +// const STOParameters = ['uint256']; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { + +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; +// account_investor1 = accounts[4]; +// account_investor2 = accounts[3]; +// account_investor3 = accounts[5]; +// account_fundsReceiver = accounts[2]; +// token_owner = account_issuer; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 2: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 3: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the PreSaleSTOFactory + +// I_PreSaleSTOFactory = await PreSaleSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); + +// assert.notEqual( +// I_PreSaleSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "PreSaleSTOFactory contract was not deployed" +// ); + +// // Step 8: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 9: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 5: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// PreSaleSTOFactory: ${I_PreSaleSTOFactory.address} +// LatestTime: ${latestTime()}\n +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), transferManagerKey); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); +// }); + +// it("Should fail to launch the STO due to endTime is 0", async () => { +// let bytesSTO = encodeModuleCall(STOParameters, [0]); +// let errorThrown = false; +// try { +// const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Rate is ${0}. Test Passed Successfully`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the STO factory with the security token", async () => { +// endTime = latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time +// let bytesSTO = encodeModuleCall(STOParameters, [endTime]); + +// const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); + +// assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "PreSaleSTO", +// "PreSaleSTOFactory module was not added" +// ); +// I_PreSaleSTO = PreSaleSTO.at(tx.logs[2].args._module); +// }); +// }); + +// describe("verify the data of STO", async () => { + +// it("Should verify the configuration of the STO", async() => { +// assert.equal( +// (await I_PreSaleSTO.endTime.call()).toNumber(), +// endTime, +// "STO Configuration doesn't set as expected" +// ); +// }); + +// it("Should get the permissions", async() => { +// let perm = await I_PreSaleSTO.getPermissions.call(); +// assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "PRE_SALE_ADMIN"); +// }); +// }); + +// describe("Buy tokens", async() => { + +// it("Should allocate the tokens -- failed due to investor not on whitelist", async () => { +// let errorThrown = false; +// try { +// await I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei('1', 'ether'), 0); +// } catch(error) { +// console.log(` tx revert -> Investor is not on whitelist`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should Buy the tokens", async() => { +// fromTime = latestTime(); +// toTime = fromTime + duration.days(100); +// expiryTime = toTime + duration.days(100); + +// // Add the Investor in to the whitelist +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(duration.days(1)); +// await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether'), 0, {from: account_issuer }); + +// assert.equal( +// (await I_PreSaleSTO.getRaised.call(0)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1 +// ); +// console.log(await I_PreSaleSTO.getNumberInvestors.call()); +// assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 1); +// // assert.isTrue(false); + +// }); + +// it("Should allocate the tokens -- failed due to msg.sender is not pre sale admin", async () => { +// let errorThrown = false; +// try { +// await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether'), 0, {from: account_fundsReceiver }); +// } catch(error) { +// console.log(` tx revert -> msg.sender is not pre sale admin`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should allocate tokens to multiple investors", async() => { +// fromTime = latestTime(); +// toTime = fromTime + duration.days(100); +// expiryTime = toTime + duration.days(100); + +// // Add the Investor in to the whitelist +// let tx1 = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx1.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + +// // Add the Investor in to the whitelist +// let tx2 = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: account_issuer, +// gas: 6000000 +// }); + +// assert.equal(tx2.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); + +// await I_PreSaleSTO.allocateTokensMulti([account_investor2, account_investor3], [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], [0,0], [web3.utils.toWei('1000', 'ether'), web3.utils.toWei('1000', 'ether')], {from: account_issuer }); + +// assert.equal( +// (await I_PreSaleSTO.getRaised.call(1)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 2000 +// ); +// assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 3); +// }); + +// it("Should failed at the time of buying the tokens -- Because STO has started", async() => { +// await increaseTime(duration.days(100)); // increased beyond the end time of the STO +// let errorThrown = false; +// try { +// // Fallback transaction +// await I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei('1', 'ether'), 0, {from: account_issuer}); +// } catch(error) { +// console.log(` tx revert -> STO has started`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// }); + +// describe("Reclaim poly sent to STO by mistake", async() => { + +// it("Should fail to reclaim POLY because token contract address is 0 address", async() => { +// let value = web3.utils.toWei('100','ether'); +// await I_PolyToken.getTokens(value, account_investor1); +// await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); + +// let errorThrown = false; +// try { +// await I_PreSaleSTO.reclaimERC20('0x0000000000000000000000000000000000000000', { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> token contract address is 0 address`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully reclaim POLY", async() => { +// let value = web3.utils.toWei('100','ether'); +// await I_PolyToken.getTokens(value, account_investor1); +// let initInvestorBalance = await I_PolyToken.balanceOf(account_investor1); +// let initOwnerBalance = await I_PolyToken.balanceOf(token_owner); +// let initContractBalance = await I_PolyToken.balanceOf(I_PreSaleSTO.address); + +// await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); +// await I_PreSaleSTO.reclaimERC20(I_PolyToken.address, { from: token_owner }); +// assert.equal((await I_PolyToken.balanceOf(account_investor1)).toNumber(), initInvestorBalance.sub(value).toNumber(), "tokens are not transfered out from investor account"); +// assert.equal((await I_PolyToken.balanceOf(token_owner)).toNumber(), initOwnerBalance.add(value).add(initContractBalance).toNumber(), "tokens are not added to the owner account"); +// assert.equal((await I_PolyToken.balanceOf(I_PreSaleSTO.address)).toNumber(), 0, "tokens are not trandfered out from STO contract"); +// }); +// }); + +// describe("Test cases for the PresaleSTOFactory", async() => { +// it("should get the exact details of the factory", async() => { +// assert.equal(await I_PreSaleSTOFactory.setupCost.call(),0); +// assert.equal((await I_PreSaleSTOFactory.getTypes.call())[0],3); +// assert.equal(web3.utils.toAscii(await I_PreSaleSTOFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "PreSaleSTO", +// "Wrong Module added"); +// assert.equal(await I_PreSaleSTOFactory.getDescription.call(), +// "Allows Issuer to configure pre-sale token allocations", +// "Wrong Module added"); +// assert.equal(await I_PreSaleSTOFactory.getTitle.call(), +// "PreSale STO", +// "Wrong Module added"); +// assert.equal(await I_PreSaleSTOFactory.getInstructions.call(), +// "Configure and track pre-sale token allocations", +// "Wrong Module added"); +// let tags = await I_PreSaleSTOFactory.getTags.call(); +// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Presale"); +// }); +// }); + +// }); diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index 7c47e12a9..3ab004e66 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -1,1248 +1,1248 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -const DummySTO = artifacts.require('./DummySTO.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryMock = artifacts.require('./SecurityTokenRegistryMock.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyToken = artifacts.require('./PolyToken.sol'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - - -contract('SecurityTokenRegistry', accounts => { - - - // Accounts Variable declaration - let account_polymath; - let account_investor1; - let account_issuer; - let token_owner; - let account_investor2; - let account_fundsReceiver; - let account_delegate; - let account_temp; - let dummy_token; - - let balanceOfReceiver; - // investor Details - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(100); - - let ID_snap; - const message = "Transaction Should Fail!!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_SecurityTokenRegistryV2; - let I_DummySTOFactory; - let I_STVersion; - let I_SecurityToken; - let I_DummySTO; - let I_PolyToken; - let I_STFactory; - let I_STFactory002; - let I_SecurityToken002; - let I_STFactory003; - let I_PolymathRegistry; - let I_SecurityTokenRegistryProxy; - let I_STRProxied; - let I_MRProxied; - - // SecurityToken Details (Launched ST on the behalf of the issuer) - const name = "Demo Token"; - const symbol = "DET"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - - //Security Token Detials (Version 2) - const name2 = "Demo2 Token"; - const symbol2 = "DET2"; - const tokenDetails2 = "This is equity type of issuance"; - - // Module key - const permissionManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - const budget = 0; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - const newRegFee = web3.utils.toWei("300"); - - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; - - // Capped STO details - const cap = web3.utils.toWei("10000"); - const someString = "Hello string"; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - account_investor1 = accounts[9]; - account_investor2 = accounts[6]; - account_fundsReceiver = accounts[4]; - account_delegate = accounts[5]; - account_temp = accounts[8]; - token_owner = account_issuer; - dummy_token = accounts[3]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 2: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 3: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - - // Step 6: Deploy the STversionProxy contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +// const DummySTO = artifacts.require('./DummySTO.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryMock = artifacts.require('./SecurityTokenRegistryMock.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyToken = artifacts.require('./PolyToken.sol'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + + +// contract('SecurityTokenRegistry', accounts => { + + +// // Accounts Variable declaration +// let account_polymath; +// let account_investor1; +// let account_issuer; +// let token_owner; +// let account_investor2; +// let account_fundsReceiver; +// let account_delegate; +// let account_temp; +// let dummy_token; + +// let balanceOfReceiver; +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(100); + +// let ID_snap; +// const message = "Transaction Should Fail!!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_GeneralTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_SecurityTokenRegistryV2; +// let I_DummySTOFactory; +// let I_STVersion; +// let I_SecurityToken; +// let I_DummySTO; +// let I_PolyToken; +// let I_STFactory; +// let I_STFactory002; +// let I_SecurityToken002; +// let I_STFactory003; +// let I_PolymathRegistry; +// let I_SecurityTokenRegistryProxy; +// let I_STRProxied; +// let I_MRProxied; + +// // SecurityToken Details (Launched ST on the behalf of the issuer) +// const name = "Demo Token"; +// const symbol = "DET"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; + +// //Security Token Detials (Version 2) +// const name2 = "Demo2 Token"; +// const symbol2 = "DET2"; +// const tokenDetails2 = "This is equity type of issuance"; + +// // Module key +// const permissionManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; +// const budget = 0; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); +// const newRegFee = web3.utils.toWei("300"); + +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; +// const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; + +// // Capped STO details +// const cap = web3.utils.toWei("10000"); +// const someString = "Hello string"; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; +// account_investor1 = accounts[9]; +// account_investor2 = accounts[6]; +// account_fundsReceiver = accounts[4]; +// account_delegate = accounts[5]; +// account_temp = accounts[8]; +// token_owner = account_issuer; +// dummy_token = accounts[3]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 2: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 3: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + + +// // Step 6: Deploy the STversionProxy contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); - // STEP 8: Deploy the CappedSTOFactory +// // STEP 8: Deploy the CappedSTOFactory - I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 1000 * Math.pow(10, 18), 0, 0,{ from: token_owner }); +// I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 1000 * Math.pow(10, 18), 0, 0,{ from: token_owner }); - assert.notEqual( - I_DummySTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "TestSTOFactory contract was not deployed" - ); +// assert.notEqual( +// I_DummySTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "TestSTOFactory contract was not deployed" +// ); - // Step 9: Deploy the SecurityTokenRegistry +// // Step 9: Deploy the SecurityTokenRegistry - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 9 (a): Deploy the proxy - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - //Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 4: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); - - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - DummySTOFactory: ${I_DummySTOFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - - describe(" Test cases of the registerTicker", async() => { - - it("verify the intial parameters", async() => { - let intialised = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); - assert.isTrue(intialised, "Should be true"); - - let expiry = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit")); - assert.equal(expiry.toNumber(), 5184000, "Expiry limit should be equal to 60 days"); - - let polytoken = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")); - assert.equal(polytoken, I_PolyToken.address, "Should be the polytoken address"); - - let stlaunchFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("stLaunchFee")); - assert.equal(stlaunchFee.toNumber(), initRegFee, "Should be provided reg fee"); - - let tickerRegFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee")); - assert.equal(tickerRegFee.toNumber(), tickerRegFee, "Should be provided reg fee"); - - let polymathRegistry = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); - assert.equal(polymathRegistry, I_PolymathRegistry.address, "Should be the address of the polymath registry"); - - let owner = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("owner")); - assert.equal(owner, account_polymath, "Should be the address of the registry owner"); - }); - - it("Can't call the intialize function again", async() => { - let errorThrown = false; - try { - await I_STRProxied.initialize(I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath); - } catch(error) { - console.log(` tx revert -> Can't call the intialize function again`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should fail to register ticker if tickerRegFee not approved", async() => { - let errorThrown = false; - try { - let tx = await I_STRProxied.registerTicker(account_temp, symbol, name, { from: account_temp }); - } catch(error) { - console.log(` tx revert -> POLY allowance not provided for registration fee`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to register ticker if owner is 0x", async() => { - let errorThrown = false; - try { - await I_PolyToken.getTokens(initRegFee, account_temp); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); - let tx = await I_STRProxied.registerTicker("0x0000000000000000000000000000000000000000", symbol, name, { from: account_temp }); - } catch(error) { - console.log(` tx revert -> owner should not be 0x`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to register ticker due to the symbol length is 0", async() => { - let errorThrown = false; - try { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); - let tx = await I_STRProxied.registerTicker(account_temp, "", name, { from: account_temp }); - } catch(error) { - console.log(` tx revert -> Symbol Length is 0`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to register ticker due to the symbol length is greater than 10", async() => { - let errorThrown = false; - try { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); - let tx = await I_STRProxied.registerTicker(account_temp, "POLYMATHNET", name, { from: account_temp }); - } catch(error) { - console.log(` tx revert -> Symbol Length is greater than 10`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should register the ticker before the generation of the security token", async () => { - let tx = await I_STRProxied.registerTicker(account_temp, symbol, name, { from: account_temp }); - assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); - assert.equal(tx.logs[0].args._ticker, symbol, `Symbol should be ${symbol}`); - }); - - it("Should fail to register same symbol again", async() => { - // Give POLY to token issuer - await I_PolyToken.getTokens(initRegFee, token_owner); - - // Call registration function - let errorThrown = false; - try { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Symbol is already alloted to someone else`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully register pre registerd ticker if expiry is reached", async() => { - await increaseTime(5184000 + 100); // 60(5184000) days of expiry + 100 sec for buffer - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner, `Owner should be the ${token_owner}`); - assert.equal(tx.logs[0].args._ticker, symbol, `Symbol should be ${symbol}`); - }); - - it("Should fail to register ticker if registration is paused", async() => { - let errorThrown = false; - try { - await I_STRProxied.pause({ from: account_polymath}); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Registration is paused`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to pause if already paused", async() => { - let errorThrown = false; - try { - await I_STRProxied.pause({ from: account_polymath}); - } catch(error) { - console.log(` tx revert -> Registration is already paused`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully register ticker if registration is unpaused", async() => { - await I_STRProxied.unpause({ from: account_polymath}); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner, `Owner should be the ${token_owner}`); - assert.equal(tx.logs[0].args._ticker, "AAA", `Symbol should be AAA`); - }); - - it("Should fail to unpause if already unpaused", async() => { - let errorThrown = false; - try { - await I_STRProxied.unpause({ from: account_polymath}); - } catch(error) { - console.log(` tx revert -> Registration is already unpaused`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - }); - - describe("Test cases for the expiry limit", async() => { - - it("Should fail to set the expiry limit because msg.sender is not owner", async() => { - let errorThrown = false; - try { - let tx = await I_STRProxied.changeExpiryLimit(duration.days(10), {from: account_temp}); - } catch(error) { - console.log(` tx revert -> msg.sender is not owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully set the expiry limit", async() => { - await I_STRProxied.changeExpiryLimit(duration.days(10), {from: account_polymath}); - assert.equal( - (await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))) - .toNumber(), - duration.days(10), - "Failed to change the expiry limit"); - }); - - it("Should fail to set the expiry limit because new expiry limit is lesser than one day", async() => { - let errorThrown = false; - try { - let tx = await I_STRProxied.changeExpiryLimit(duration.seconds(5000), {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> New expiry limit is lesser than one day`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - }); - - describe("Test cases for the getTickerDetails", async() => { - - it("Should get the details of the symbol", async() => { - let tx = await I_STRProxied.getTickerDetails.call(symbol); - assert.equal(tx[0], token_owner, "Should equal to the rightful owner of the ticker"); - assert.equal(tx[3], name, `Name of the token should equal to ${name}`); - assert.equal(tx[4], false, "Status if the symbol should be undeployed -- false"); - }); - - it("Should get the details of unregistered token", async() => { - let tx = await I_STRProxied.getTickerDetails.call("TORO"); - assert.equal(tx[0], "0x0000000000000000000000000000000000000000", "Should be 0x as ticker is not exists in the registry"); - assert.equal(tx[3], "", "Should be an empty string"); - assert.equal(tx[4], false, "Status if the symbol should be undeployed -- false"); - }); - }); - - describe("Generate SecurityToken", async() => { - - it("Should get the ticker details successfully and prove the data is not storing in to the logic contract", async() => { - let data = await I_STRProxied.getTickerDetails(symbol, {from: token_owner}); - assert.equal(data[0], token_owner, "Token owner should be equal"); - assert.equal(data[3], name, "Name of the token should match with the registered symbol infor"); - assert.equal(data[4], false, "Token is not launched yet so it should return False"); - data = await I_SecurityTokenRegistry.getTickerDetails(symbol, {from:token_owner}); - console.log("This is the data from the original securityTokenRegistry contract"); - assert.equal(data[0], '0x0000000000000000000000000000000000000000', "Token owner should be 0x"); - }) - - it("Should fail to generate new security token if fee not provided", async() => { - let errorThrown = false; - await I_PolyToken.approve(I_STRProxied.address, 0, { from: token_owner}); - try { - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> POLY allowance not provided for registration fee`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to generate token if registration is paused", async() => { - let errorThrown = false; - await I_STRProxied.pause({ from: account_polymath}); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - try { - await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Registration is paused`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to generate the securityToken -- Because ticker length is 0", async() => { - let errorThrown = false; - await I_STRProxied.unpause({ from: account_polymath}); - try { - await I_STRProxied.generateSecurityToken(name, "", tokenDetails, false, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Zero ticker length is not allowed`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should fail to generate the securityToken -- Because name length is 0", async() => { - let errorThrown = false; - try { - await I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> 0 name length is not allowed`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should fail to generate the securityToken -- Because msg.sender is not the rightful owner of the ticker", async() => { - let errorThrown = false; - try { - await I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: account_temp }); - } catch(error) { - console.log(` tx revert -> Because msg.sender is not the rightful owner of the ticker`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should generate the new security token with the same symbol as registered above", async () => { - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTrasnferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), transferManagerKey, `Should be equal to the ${transferManagerKey}`); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should fail to generate the SecurityToken when token is already deployed with the same symbol", async() => { - let errorThrown = false; - try { - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Because ticker is already in use`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - }); - - describe("Generate SecurityToken v2", async() => { - - it("Should deploy the st version 2", async() => { - // Step 7: Deploy the STFactory contract - - I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory002.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory002 contract was not deployed", - ); - await I_STRProxied.setProtocolVersion(I_STFactory002.address, 0, 2, 0, { from: account_polymath }); - let _protocol = await I_STRProxied.getProtocolVersion.call(); - assert.equal(_protocol[0], 0); - assert.equal(_protocol[1], 2); - assert.equal(_protocol[2], 0); - }); - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, symbol2, name2, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner, `Token owner should be ${token_owner}`); - assert.equal(tx.logs[0].args._ticker, symbol2, `Symbol should be ${symbol2}`); - }); - - it("Should generate the new security token with version 2", async() => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol2, "SecurityToken doesn't get deployed"); - - I_SecurityToken002 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - let tokens = await I_STRProxied.getTokensByOwner.call(token_owner); - assert.equal(tokens[0], I_SecurityToken.address); - assert.equal(tokens[1], I_SecurityToken002.address); - - const log = await promisifyLogWatch(I_SecurityToken002.ModuleAdded({from: _blockNo}), 1); - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), transferManagerKey); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - }); - - describe("Deploy the new SecurityTokenRegistry", async() => { - - it("Should deploy the new SecurityTokenRegistry contract logic", async() => { - I_SecurityTokenRegistryV2 = await SecurityTokenRegistryMock.new({ from: account_polymath }); - assert.notEqual( - I_SecurityTokenRegistryV2.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - }); - - it("Should fail to upgrade the logic contract of the STRProxy -- bad owner", async() => { - let errorThrown = false; - await I_STRProxied.pause({from: account_polymath}); - try { - await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, {from: account_temp}); - } catch(error) { - console.log(` tx revert -> bad owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should upgrade the logic contract into the STRProxy", async() =>{ - await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - assert.isTrue(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); - }); - - it("Should check the old data persist or not", async() => { - let data = await I_STRProxied.getTickerDetails.call(symbol); - assert.equal(data[0], token_owner, "Should be equal to the token owner address"); - assert.equal(data[3], name, "Should be equal to the name of the token that is provided earlier"); - assert.isTrue(data[4], "Token status should be deployed == true"); - }); - - it("Should unpause the logic contract", async() => { - await I_STRProxied.unpause({from: account_polymath}); - assert.isFalse(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); - }); - }) - - describe("Generate custom tokens", async() => { - - it("Should fail if msg.sender is not polymath", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_delegate}); - } catch(error) { - console.log(` tx revert -> msg.sender is not polymath account`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to generate the custom security token -- name should not be 0 length ", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifySecurityToken("", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> name should not be 0 length `.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail if ST address is 0 address", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, 0, "I am custom ST", latestTime(), {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> Security token address is 0`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail if symbol length is 0", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifySecurityToken("", "", account_temp, dummy_token, "I am custom ST",latestTime(), {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> zero length of the symbol is not allowed`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to generate the custom ST -- deployedAt param is 0", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifySecurityToken(name2, symbol2, token_owner, dummy_token, "I am custom ST", 0, {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> because deployedAt param is 0`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully generate custom token", async() => { - // Register the new ticker -- Fulfiling the TickerStatus.ON condition - await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); - let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); - console.log(tickersListArray); - await I_STRProxied.registerTicker(account_temp, "LOG", "LOGAN", { from : account_temp }); - tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); - console.log(tickersListArray); - // Generating the ST - let tx = await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); - tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); - console.log(tickersListArray); - assert.equal(tx.logs[1].args._ticker, "LOG", "Symbol should match with the registered symbol"); - assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token,`Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); - let symbolDetails = await I_STRProxied.getTickerDetails("LOG"); - assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); - assert.equal(symbolDetails[3], "LOGAN", `Name of the symbol should be LOGAN`); - }); - - it("Should successfully generate the custom token", async() => { - // Fulfilling the TickerStatus.NN condition - // let errorThrown = false; - // try { - // await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); - // } catch(error) { - // console.log(` tx revert -> because ticker not registered`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(10), false, {from: account_polymath}); - // await increaseTime(duration.days(1)); - let tx = await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); - assert.equal(tx.logs[1].args._ticker, "LOG2", "Symbol should match with the registered symbol"); - assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token, `Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); - assert.equal(tx.logs[0].args._owner, account_temp, `Token owner should be ${account_temp}`); - assert.equal(tx.logs[0].args._ticker, "LOG2", `Symbol should be LOG2`); - let symbolDetails = await I_STRProxied.getTickerDetails("LOG2"); - assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); - assert.equal(symbolDetails[3], "LOGAN2", `Name of the symbol should be LOGAN`); - }); - - }); - - describe("Test case for modifyTicker", async() => { - - it("Should add the custom ticker --failed because of bad owner", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() + duration.days(10)), false, {from: account_temp}) - } catch(error) { - console.log(` tx revert -> failed beacause ticker length should not be 0`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should add the custom ticker --fail ticker length should not be 0", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifyTicker(token_owner, "", "Ether", latestTime(), (latestTime() + duration.days(10)), false, {from: account_polymath}) - } catch(error) { - console.log(` tx revert -> failed beacause ticker length should not be 0`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should add the custom ticker --failed because time should not be 0", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", 0, (latestTime() + duration.days(10)), false, {from: account_polymath}) - } catch(error) { - console.log(` tx revert -> failed because time should not be 0`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should add the custom ticker --failed because registeration date is greater than the expiryDate", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() - duration.minutes(10)), false, {from: account_polymath}) - } catch(error) { - console.log(` tx revert -> failed because registeration date is greater than the expiryDate`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should add the custom ticker --failed because owner should not be 0x", async() => { - let errorThrown = false; - try { - await I_STRProxied.modifyTicker("0x000000000000000000000000000000000000000000", "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}) - } catch(error) { - console.log(` tx revert -> failed because owner should not be 0x`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should add the new custom ticker", async() => { - let tx = await I_STRProxied.modifyTicker(account_temp, "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); - assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); - assert.equal(tx.logs[0].args._ticker, "ETH", "Should be equal to ETH"); - }) - - it("Should change the details of the existing ticker", async() => { - let tx = await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); - assert.equal(tx.logs[0].args._owner, token_owner); - }); - - }); - - describe("Test cases for the transferTickerOwnership()", async() => { - - it("Should able to transfer the ticker ownership -- failed because token is not deployed having the same ticker", async() => { - let errorThrown = false; - try { - await I_STRProxied.transferTickerOwnership(account_issuer, "ETH", {from: account_temp}); - } catch(error) { - console.log(` tx revert -> failed because token is not deployed having the same ticker`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should able to transfer the ticker ownership -- failed because new owner is 0x", async() => { - let errorThrown = false; - await I_SecurityToken002.transferOwnership(account_temp, {from: token_owner}); - try { - await I_STRProxied.transferTickerOwnership("0x00000000000000000000000000000000000000000", symbol2, {from: token_owner}); - } catch(error) { - console.log(` tx revert -> failed because new owner is 0x`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should able to transfer the ticker ownership -- failed because ticker is of zero length", async() => { - let errorThrown = false; - try { - await I_STRProxied.transferTickerOwnership(account_temp, "", {from: token_owner}); - } catch(error) { - console.log(` tx revert -> failed because ticker is of zero length`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should able to transfer the ticker ownership", async() => { - let tx = await I_STRProxied.transferTickerOwnership(account_temp, symbol2, {from: token_owner, gas: 5000000 }); - assert.equal(tx.logs[0].args._newOwner, account_temp); - let symbolDetails = await I_STRProxied.getTickerDetails.call(symbol2); - assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); - assert.equal(symbolDetails[3], name2, `Name of the symbol should be ${name2}`); - }) - }) - - describe("Test case for the changeSecurityLaunchFee()", async() => { - - it("Should able to change the STLaunchFee-- failed because of bad owner", async() => { - let errorThrown = false; - try { - await I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), {from: account_temp}); - } catch(error) { - console.log(` tx revert -> failed because of bad owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should able to change the STLaunchFee-- failed because of putting the same fee", async() => { - let errorThrown = false; - try { - await I_STRProxied.changeSecurityLaunchFee(initRegFee, {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> failed because of putting the same fee`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should able to change the STLaunchFee", async() => { - let tx = await I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), {from: account_polymath}); - assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("500")); - let stLaunchFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("stLaunchFee")); - assert.equal(stLaunchFee, web3.utils.toWei("500")); - }); - - }) - - describe("Test cases for the changeExpiryLimit()", async() => { - - it("Should able to change the ExpiryLimit-- failed because of bad owner", async() => { - let errorThrown = false; - try { - await I_STRProxied.changeExpiryLimit(duration.days(15), {from: account_temp}); - } catch(error) { - console.log(` tx revert -> failed because of bad owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should able to change the ExpiryLimit-- failed because expirylimit is less than 1 day", async() => { - let errorThrown = false; - try { - await I_STRProxied.changeExpiryLimit(duration.minutes(50), {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> failed because expirylimit is less than 1 day`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should able to change the ExpiryLimit", async() => { - let tx = await I_STRProxied.changeExpiryLimit(duration.days(20), {from: account_polymath}); - assert.equal(tx.logs[0].args._newExpiry, duration.days(20)); - let expiry = await I_STRProxied.getUintValues(web3.utils.soliditySha3("expiryLimit")); - assert.equal(expiry, duration.days(20)); - }); - }) - - describe("Test cases for the changeTickerRegistrationFee()", async() => { - - it("Should able to change the TickerRegFee-- failed because of bad owner", async() => { - let errorThrown = false; - try { - await I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("500"), {from: account_temp}); - } catch(error) { - console.log(` tx revert -> failed because of bad owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should able to change the TickerRegFee-- failed because of putting the same fee", async() => { - let errorThrown = false; - try { - await I_STRProxied.changeTickerRegistrationFee(initRegFee, {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> failed because of putting the same fee`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should able to change the TickerRegFee", async() => { - let tx = await I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("400"), {from: account_polymath}); - assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("400")); - let tickerRegFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("tickerRegFee")); - assert.equal(tickerRegFee, web3.utils.toWei("400")); - }); - - it("Should fail to register the ticker with the old fee", async () => { - let errorThrown = false; - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - try { - await I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from : token_owner }); - } catch(error) { - console.log(` tx revert -> failed because of ticker registeration fee gets change`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should register the ticker with the new fee", async() => { - await I_PolyToken.getTokens(web3.utils.toWei("1000"), token_owner); - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner, `Token owner should be ${token_owner}`); - assert.equal(tx.logs[0].args._ticker, "POLY", `Symbol should be POLY`); - }); - - it("Should fail to launch the securityToken with the old launch fee", async() => { - let errorThrown = false; - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - try { - await I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> failed because of old launch fee`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should launch the the securityToken", async() => { - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner}); - let tx = await I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, "POLY", "SecurityToken doesn't get deployed"); - }); - }); - - describe("Test case for the update poly token", async() => { - - it("Should change the polytoken address -- failed because of bad owner", async() => { - let errorThrown = false; - try { - await I_STRProxied.updatePolyTokenAddress(dummy_token, {from: account_temp}); - } catch(error) { - console.log(` tx revert -> failed because of bad owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should change the polytoken address -- failed because of 0x address", async() => { - let errorThrown = false; - try { - await I_STRProxied.updatePolyTokenAddress("0x0000000000000000000000000000000000000000000", {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> failed because 0x address`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should successfully change the polytoken address", async() => { - let _id = await takeSnapshot(); - await I_STRProxied.updatePolyTokenAddress(dummy_token, {from: account_polymath}); - assert.equal(await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), dummy_token); - await revertToSnapshot(_id); - }); - }) - - describe("Test cases for getters", async() => { - - it("Should get the security token address", async() => { - let address = await I_STRProxied.getSecurityTokenAddress.call(symbol); - assert.equal(address, I_SecurityToken.address); - }); - - it("Should get the security token data", async() => { - let data = await I_STRProxied.getSecurityTokenData.call(I_SecurityToken.address); - assert.equal(data[0], symbol); - assert.equal(data[1], token_owner); - }); - - it("Should get the tickers by owner", async() => { - let tickersList = await I_STRProxied.getTickersByOwner.call(token_owner); - assert.equal(tickersList.length, 4); - let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); - console.log(tickersListArray); - assert.equal(tickersListArray.length, 3); - }); - - }); - - describe("Test case for the Removing the ticker", async() => { - - it("Should remove the ticker from the polymath ecosystem -- bad owner", async() => { - let errorThrown = false; - try { - await I_STRProxied.removeTicker(symbol2, {from: account_investor1}); - } catch(error) { - console.log(` tx revert -> failed because msg.sender should be account_polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should remove the ticker from the polymath ecosystem -- fail because ticker doesn't exist in the ecosystem", async() => { - let errorThrown = false; - try { - await I_STRProxied.removeTicker("HOLA", {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> failed because ticker doesn't exist in the polymath ecosystem`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should successfully remove the ticker from the polymath ecosystem", async() => { - let tx = await I_STRProxied.removeTicker(symbol2, {from: account_polymath}); - assert.equal(tx.logs[0].args._ticker, symbol2, "Ticker doesn't get deleted successfully"); - }); - }) - - describe(" Test cases of the registerTicker", async() => { - - it("Should register the ticker 1", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); - let tx = await I_STRProxied.registerTicker(account_temp, "TOK1", "", { from: account_temp }); - assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); - assert.equal(tx.logs[0].args._ticker, "TOK1", `Symbol should be TOK1`); - console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); - }); - - it("Should register the ticker 2", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); - let tx = await I_STRProxied.registerTicker(account_temp, "TOK2", "", { from: account_temp }); - assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); - assert.equal(tx.logs[0].args._ticker, "TOK2", `Symbol should be TOK2`); - console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); - }); - - it("Should register the ticker 3", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); - let tx = await I_STRProxied.registerTicker(account_temp, "TOK3", "", { from: account_temp }); - assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); - assert.equal(tx.logs[0].args._ticker, "TOK3", `Symbol should be TOK3`); - console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); - }); - - it("Should successfully remove the ticker 2", async() => { - let tx = await I_STRProxied.removeTicker("TOK2", {from: account_polymath}); - assert.equal(tx.logs[0].args._ticker, "TOK2", "Ticker doesn't get deleted successfully"); - console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); - }); - - it("Should modify ticker 1", async() => { - let tx = await I_STRProxied.modifyTicker(account_temp, "TOK1", "TOKEN 1", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); - assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); - assert.equal(tx.logs[0].args._ticker, "TOK1", "Should be equal to TOK1"); - assert.equal(tx.logs[0].args._name, "TOKEN 1", "Should be equal to TOKEN 1"); - console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); - }) - - it("Should modify ticker 3", async() => { - let tx = await I_STRProxied.modifyTicker(account_temp, "TOK3", "TOKEN 3", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); - assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); - assert.equal(tx.logs[0].args._ticker, "TOK3", "Should be equal to TOK3"); - assert.equal(tx.logs[0].args._name, "TOKEN 3", "Should be equal to TOKEN 3"); - console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); - }) - - }); - describe("Test cases for IRegistry functionality", async() => { - - describe("Test cases for reclaiming funds", async() => { - - it("Should successfully reclaim POLY tokens", async() => { - I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); - let bal1 = await I_PolyToken.balanceOf.call(account_polymath); - await I_STRProxied.reclaimERC20(I_PolyToken.address); - let bal2 = await I_PolyToken.balanceOf.call(account_polymath); - assert.isAtLeast(bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), bal2.dividedBy(new BigNumber(10).pow(18)).toNumber()); - }); - - }); - - describe("Test cases for pausing the contract", async() => { - - it("Should fail to pause if msg.sender is not owner", async() => { - let errorThrown = false; - try { - await I_STRProxied.pause({ from: account_temp }); - } catch(error) { - console.log(` tx revert -> msg.sender should be account_polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully pause the contract", async() => { - await I_STRProxied.pause({ from: account_polymath }); - let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); - assert.isOk(status); - }); - - it("Should fail to unpause if msg.sender is not owner", async() => { - let errorThrown = false; - try { - await I_STRProxied.unpause({ from: account_temp }); - } catch(error) { - console.log(` tx revert -> msg.sender should be account_polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully unpause the contract", async() => { - await I_STRProxied.unpause({ from: account_polymath }); - let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); - assert.isNotOk(status); - }); - - }); - - }); - -}); +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 9 (a): Deploy the proxy +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 10: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// assert.notEqual( +// I_FeatureRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "FeatureRegistry contract was not deployed", +// ); + +// //Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 4: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); + +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// DummySTOFactory: ${I_DummySTOFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + + +// describe(" Test cases of the registerTicker", async() => { + +// it("verify the intial parameters", async() => { +// let intialised = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); +// assert.isTrue(intialised, "Should be true"); + +// let expiry = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit")); +// assert.equal(expiry.toNumber(), 5184000, "Expiry limit should be equal to 60 days"); + +// let polytoken = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")); +// assert.equal(polytoken, I_PolyToken.address, "Should be the polytoken address"); + +// let stlaunchFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("stLaunchFee")); +// assert.equal(stlaunchFee.toNumber(), initRegFee, "Should be provided reg fee"); + +// let tickerRegFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee")); +// assert.equal(tickerRegFee.toNumber(), tickerRegFee, "Should be provided reg fee"); + +// let polymathRegistry = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); +// assert.equal(polymathRegistry, I_PolymathRegistry.address, "Should be the address of the polymath registry"); + +// let owner = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("owner")); +// assert.equal(owner, account_polymath, "Should be the address of the registry owner"); +// }); + +// it("Can't call the intialize function again", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.initialize(I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath); +// } catch(error) { +// console.log(` tx revert -> Can't call the intialize function again`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should fail to register ticker if tickerRegFee not approved", async() => { +// let errorThrown = false; +// try { +// let tx = await I_STRProxied.registerTicker(account_temp, symbol, name, { from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> POLY allowance not provided for registration fee`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to register ticker if owner is 0x", async() => { +// let errorThrown = false; +// try { +// await I_PolyToken.getTokens(initRegFee, account_temp); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); +// let tx = await I_STRProxied.registerTicker("0x0000000000000000000000000000000000000000", symbol, name, { from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> owner should not be 0x`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to register ticker due to the symbol length is 0", async() => { +// let errorThrown = false; +// try { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); +// let tx = await I_STRProxied.registerTicker(account_temp, "", name, { from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> Symbol Length is 0`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to register ticker due to the symbol length is greater than 10", async() => { +// let errorThrown = false; +// try { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); +// let tx = await I_STRProxied.registerTicker(account_temp, "POLYMATHNET", name, { from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> Symbol Length is greater than 10`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should register the ticker before the generation of the security token", async () => { +// let tx = await I_STRProxied.registerTicker(account_temp, symbol, name, { from: account_temp }); +// assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); +// assert.equal(tx.logs[0].args._ticker, symbol, `Symbol should be ${symbol}`); +// }); + +// it("Should fail to register same symbol again", async() => { +// // Give POLY to token issuer +// await I_PolyToken.getTokens(initRegFee, token_owner); + +// // Call registration function +// let errorThrown = false; +// try { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Symbol is already alloted to someone else`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully register pre registerd ticker if expiry is reached", async() => { +// await increaseTime(5184000 + 100); // 60(5184000) days of expiry + 100 sec for buffer +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner, `Owner should be the ${token_owner}`); +// assert.equal(tx.logs[0].args._ticker, symbol, `Symbol should be ${symbol}`); +// }); + +// it("Should fail to register ticker if registration is paused", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.pause({ from: account_polymath}); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Registration is paused`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to pause if already paused", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.pause({ from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> Registration is already paused`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully register ticker if registration is unpaused", async() => { +// await I_STRProxied.unpause({ from: account_polymath}); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner, `Owner should be the ${token_owner}`); +// assert.equal(tx.logs[0].args._ticker, "AAA", `Symbol should be AAA`); +// }); + +// it("Should fail to unpause if already unpaused", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.unpause({ from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> Registration is already unpaused`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); +// }); + +// describe("Test cases for the expiry limit", async() => { + +// it("Should fail to set the expiry limit because msg.sender is not owner", async() => { +// let errorThrown = false; +// try { +// let tx = await I_STRProxied.changeExpiryLimit(duration.days(10), {from: account_temp}); +// } catch(error) { +// console.log(` tx revert -> msg.sender is not owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully set the expiry limit", async() => { +// await I_STRProxied.changeExpiryLimit(duration.days(10), {from: account_polymath}); +// assert.equal( +// (await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))) +// .toNumber(), +// duration.days(10), +// "Failed to change the expiry limit"); +// }); + +// it("Should fail to set the expiry limit because new expiry limit is lesser than one day", async() => { +// let errorThrown = false; +// try { +// let tx = await I_STRProxied.changeExpiryLimit(duration.seconds(5000), {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> New expiry limit is lesser than one day`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); +// }); + +// describe("Test cases for the getTickerDetails", async() => { + +// it("Should get the details of the symbol", async() => { +// let tx = await I_STRProxied.getTickerDetails.call(symbol); +// assert.equal(tx[0], token_owner, "Should equal to the rightful owner of the ticker"); +// assert.equal(tx[3], name, `Name of the token should equal to ${name}`); +// assert.equal(tx[4], false, "Status if the symbol should be undeployed -- false"); +// }); + +// it("Should get the details of unregistered token", async() => { +// let tx = await I_STRProxied.getTickerDetails.call("TORO"); +// assert.equal(tx[0], "0x0000000000000000000000000000000000000000", "Should be 0x as ticker is not exists in the registry"); +// assert.equal(tx[3], "", "Should be an empty string"); +// assert.equal(tx[4], false, "Status if the symbol should be undeployed -- false"); +// }); +// }); + +// describe("Generate SecurityToken", async() => { + +// it("Should get the ticker details successfully and prove the data is not storing in to the logic contract", async() => { +// let data = await I_STRProxied.getTickerDetails(symbol, {from: token_owner}); +// assert.equal(data[0], token_owner, "Token owner should be equal"); +// assert.equal(data[3], name, "Name of the token should match with the registered symbol infor"); +// assert.equal(data[4], false, "Token is not launched yet so it should return False"); +// data = await I_SecurityTokenRegistry.getTickerDetails(symbol, {from:token_owner}); +// console.log("This is the data from the original securityTokenRegistry contract"); +// assert.equal(data[0], '0x0000000000000000000000000000000000000000', "Token owner should be 0x"); +// }) + +// it("Should fail to generate new security token if fee not provided", async() => { +// let errorThrown = false; +// await I_PolyToken.approve(I_STRProxied.address, 0, { from: token_owner}); +// try { +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> POLY allowance not provided for registration fee`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to generate token if registration is paused", async() => { +// let errorThrown = false; +// await I_STRProxied.pause({ from: account_polymath}); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// try { +// await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Registration is paused`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to generate the securityToken -- Because ticker length is 0", async() => { +// let errorThrown = false; +// await I_STRProxied.unpause({ from: account_polymath}); +// try { +// await I_STRProxied.generateSecurityToken(name, "", tokenDetails, false, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Zero ticker length is not allowed`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should fail to generate the securityToken -- Because name length is 0", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> 0 name length is not allowed`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should fail to generate the securityToken -- Because msg.sender is not the rightful owner of the ticker", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> Because msg.sender is not the rightful owner of the ticker`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTrasnferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), transferManagerKey, `Should be equal to the ${transferManagerKey}`); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should fail to generate the SecurityToken when token is already deployed with the same symbol", async() => { +// let errorThrown = false; +// try { +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> Because ticker is already in use`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// }); + +// describe("Generate SecurityToken v2", async() => { + +// it("Should deploy the st version 2", async() => { +// // Step 7: Deploy the STFactory contract + +// I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory002.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory002 contract was not deployed", +// ); +// await I_STRProxied.setProtocolVersion(I_STFactory002.address, 0, 2, 0, { from: account_polymath }); +// let _protocol = await I_STRProxied.getProtocolVersion.call(); +// assert.equal(_protocol[0], 0); +// assert.equal(_protocol[1], 2); +// assert.equal(_protocol[2], 0); +// }); + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol2, name2, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner, `Token owner should be ${token_owner}`); +// assert.equal(tx.logs[0].args._ticker, symbol2, `Symbol should be ${symbol2}`); +// }); + +// it("Should generate the new security token with version 2", async() => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol2, "SecurityToken doesn't get deployed"); + +// I_SecurityToken002 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); +// let tokens = await I_STRProxied.getTokensByOwner.call(token_owner); +// assert.equal(tokens[0], I_SecurityToken.address); +// assert.equal(tokens[1], I_SecurityToken002.address); + +// const log = await promisifyLogWatch(I_SecurityToken002.ModuleAdded({from: _blockNo}), 1); +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), transferManagerKey); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// }); + +// describe("Deploy the new SecurityTokenRegistry", async() => { + +// it("Should deploy the new SecurityTokenRegistry contract logic", async() => { +// I_SecurityTokenRegistryV2 = await SecurityTokenRegistryMock.new({ from: account_polymath }); +// assert.notEqual( +// I_SecurityTokenRegistryV2.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); +// }); + +// it("Should fail to upgrade the logic contract of the STRProxy -- bad owner", async() => { +// let errorThrown = false; +// await I_STRProxied.pause({from: account_polymath}); +// try { +// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, {from: account_temp}); +// } catch(error) { +// console.log(` tx revert -> bad owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should upgrade the logic contract into the STRProxy", async() =>{ +// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); +// assert.isTrue(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); +// }); + +// it("Should check the old data persist or not", async() => { +// let data = await I_STRProxied.getTickerDetails.call(symbol); +// assert.equal(data[0], token_owner, "Should be equal to the token owner address"); +// assert.equal(data[3], name, "Should be equal to the name of the token that is provided earlier"); +// assert.isTrue(data[4], "Token status should be deployed == true"); +// }); + +// it("Should unpause the logic contract", async() => { +// await I_STRProxied.unpause({from: account_polymath}); +// assert.isFalse(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); +// }); +// }) + +// describe("Generate custom tokens", async() => { + +// it("Should fail if msg.sender is not polymath", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_delegate}); +// } catch(error) { +// console.log(` tx revert -> msg.sender is not polymath account`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to generate the custom security token -- name should not be 0 length ", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifySecurityToken("", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> name should not be 0 length `.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail if ST address is 0 address", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, 0, "I am custom ST", latestTime(), {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> Security token address is 0`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail if symbol length is 0", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifySecurityToken("", "", account_temp, dummy_token, "I am custom ST",latestTime(), {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> zero length of the symbol is not allowed`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to generate the custom ST -- deployedAt param is 0", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifySecurityToken(name2, symbol2, token_owner, dummy_token, "I am custom ST", 0, {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> because deployedAt param is 0`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully generate custom token", async() => { +// // Register the new ticker -- Fulfiling the TickerStatus.ON condition +// await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); +// let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); +// console.log(tickersListArray); +// await I_STRProxied.registerTicker(account_temp, "LOG", "LOGAN", { from : account_temp }); +// tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); +// console.log(tickersListArray); +// // Generating the ST +// let tx = await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); +// tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); +// console.log(tickersListArray); +// assert.equal(tx.logs[1].args._ticker, "LOG", "Symbol should match with the registered symbol"); +// assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token,`Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); +// let symbolDetails = await I_STRProxied.getTickerDetails("LOG"); +// assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); +// assert.equal(symbolDetails[3], "LOGAN", `Name of the symbol should be LOGAN`); +// }); + +// it("Should successfully generate the custom token", async() => { +// // Fulfilling the TickerStatus.NN condition +// // let errorThrown = false; +// // try { +// // await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); +// // } catch(error) { +// // console.log(` tx revert -> because ticker not registered`.grey); +// // errorThrown = true; +// // ensureException(error); +// // } +// // assert.ok(errorThrown, message); +// // await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(10), false, {from: account_polymath}); +// // await increaseTime(duration.days(1)); +// let tx = await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); +// assert.equal(tx.logs[1].args._ticker, "LOG2", "Symbol should match with the registered symbol"); +// assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token, `Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); +// assert.equal(tx.logs[0].args._owner, account_temp, `Token owner should be ${account_temp}`); +// assert.equal(tx.logs[0].args._ticker, "LOG2", `Symbol should be LOG2`); +// let symbolDetails = await I_STRProxied.getTickerDetails("LOG2"); +// assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); +// assert.equal(symbolDetails[3], "LOGAN2", `Name of the symbol should be LOGAN`); +// }); + +// }); + +// describe("Test case for modifyTicker", async() => { + +// it("Should add the custom ticker --failed because of bad owner", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() + duration.days(10)), false, {from: account_temp}) +// } catch(error) { +// console.log(` tx revert -> failed beacause ticker length should not be 0`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should add the custom ticker --fail ticker length should not be 0", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifyTicker(token_owner, "", "Ether", latestTime(), (latestTime() + duration.days(10)), false, {from: account_polymath}) +// } catch(error) { +// console.log(` tx revert -> failed beacause ticker length should not be 0`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should add the custom ticker --failed because time should not be 0", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", 0, (latestTime() + duration.days(10)), false, {from: account_polymath}) +// } catch(error) { +// console.log(` tx revert -> failed because time should not be 0`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should add the custom ticker --failed because registeration date is greater than the expiryDate", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() - duration.minutes(10)), false, {from: account_polymath}) +// } catch(error) { +// console.log(` tx revert -> failed because registeration date is greater than the expiryDate`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should add the custom ticker --failed because owner should not be 0x", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.modifyTicker("0x000000000000000000000000000000000000000000", "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}) +// } catch(error) { +// console.log(` tx revert -> failed because owner should not be 0x`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should add the new custom ticker", async() => { +// let tx = await I_STRProxied.modifyTicker(account_temp, "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); +// assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); +// assert.equal(tx.logs[0].args._ticker, "ETH", "Should be equal to ETH"); +// }) + +// it("Should change the details of the existing ticker", async() => { +// let tx = await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); +// assert.equal(tx.logs[0].args._owner, token_owner); +// }); + +// }); + +// describe("Test cases for the transferTickerOwnership()", async() => { + +// it("Should able to transfer the ticker ownership -- failed because token is not deployed having the same ticker", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.transferTickerOwnership(account_issuer, "ETH", {from: account_temp}); +// } catch(error) { +// console.log(` tx revert -> failed because token is not deployed having the same ticker`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should able to transfer the ticker ownership -- failed because new owner is 0x", async() => { +// let errorThrown = false; +// await I_SecurityToken002.transferOwnership(account_temp, {from: token_owner}); +// try { +// await I_STRProxied.transferTickerOwnership("0x00000000000000000000000000000000000000000", symbol2, {from: token_owner}); +// } catch(error) { +// console.log(` tx revert -> failed because new owner is 0x`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should able to transfer the ticker ownership -- failed because ticker is of zero length", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.transferTickerOwnership(account_temp, "", {from: token_owner}); +// } catch(error) { +// console.log(` tx revert -> failed because ticker is of zero length`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should able to transfer the ticker ownership", async() => { +// let tx = await I_STRProxied.transferTickerOwnership(account_temp, symbol2, {from: token_owner, gas: 5000000 }); +// assert.equal(tx.logs[0].args._newOwner, account_temp); +// let symbolDetails = await I_STRProxied.getTickerDetails.call(symbol2); +// assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); +// assert.equal(symbolDetails[3], name2, `Name of the symbol should be ${name2}`); +// }) +// }) + +// describe("Test case for the changeSecurityLaunchFee()", async() => { + +// it("Should able to change the STLaunchFee-- failed because of bad owner", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), {from: account_temp}); +// } catch(error) { +// console.log(` tx revert -> failed because of bad owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should able to change the STLaunchFee-- failed because of putting the same fee", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.changeSecurityLaunchFee(initRegFee, {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> failed because of putting the same fee`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should able to change the STLaunchFee", async() => { +// let tx = await I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), {from: account_polymath}); +// assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("500")); +// let stLaunchFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("stLaunchFee")); +// assert.equal(stLaunchFee, web3.utils.toWei("500")); +// }); + +// }) + +// describe("Test cases for the changeExpiryLimit()", async() => { + +// it("Should able to change the ExpiryLimit-- failed because of bad owner", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.changeExpiryLimit(duration.days(15), {from: account_temp}); +// } catch(error) { +// console.log(` tx revert -> failed because of bad owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should able to change the ExpiryLimit-- failed because expirylimit is less than 1 day", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.changeExpiryLimit(duration.minutes(50), {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> failed because expirylimit is less than 1 day`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should able to change the ExpiryLimit", async() => { +// let tx = await I_STRProxied.changeExpiryLimit(duration.days(20), {from: account_polymath}); +// assert.equal(tx.logs[0].args._newExpiry, duration.days(20)); +// let expiry = await I_STRProxied.getUintValues(web3.utils.soliditySha3("expiryLimit")); +// assert.equal(expiry, duration.days(20)); +// }); +// }) + +// describe("Test cases for the changeTickerRegistrationFee()", async() => { + +// it("Should able to change the TickerRegFee-- failed because of bad owner", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("500"), {from: account_temp}); +// } catch(error) { +// console.log(` tx revert -> failed because of bad owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should able to change the TickerRegFee-- failed because of putting the same fee", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.changeTickerRegistrationFee(initRegFee, {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> failed because of putting the same fee`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should able to change the TickerRegFee", async() => { +// let tx = await I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("400"), {from: account_polymath}); +// assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("400")); +// let tickerRegFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("tickerRegFee")); +// assert.equal(tickerRegFee, web3.utils.toWei("400")); +// }); + +// it("Should fail to register the ticker with the old fee", async () => { +// let errorThrown = false; +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// try { +// await I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from : token_owner }); +// } catch(error) { +// console.log(` tx revert -> failed because of ticker registeration fee gets change`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should register the ticker with the new fee", async() => { +// await I_PolyToken.getTokens(web3.utils.toWei("1000"), token_owner); +// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner, `Token owner should be ${token_owner}`); +// assert.equal(tx.logs[0].args._ticker, "POLY", `Symbol should be POLY`); +// }); + +// it("Should fail to launch the securityToken with the old launch fee", async() => { +// let errorThrown = false; +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// try { +// await I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> failed because of old launch fee`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should launch the the securityToken", async() => { +// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner}); +// let tx = await I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, "POLY", "SecurityToken doesn't get deployed"); +// }); +// }); + +// describe("Test case for the update poly token", async() => { + +// it("Should change the polytoken address -- failed because of bad owner", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.updatePolyTokenAddress(dummy_token, {from: account_temp}); +// } catch(error) { +// console.log(` tx revert -> failed because of bad owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should change the polytoken address -- failed because of 0x address", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.updatePolyTokenAddress("0x0000000000000000000000000000000000000000000", {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> failed because 0x address`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should successfully change the polytoken address", async() => { +// let _id = await takeSnapshot(); +// await I_STRProxied.updatePolyTokenAddress(dummy_token, {from: account_polymath}); +// assert.equal(await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), dummy_token); +// await revertToSnapshot(_id); +// }); +// }) + +// describe("Test cases for getters", async() => { + +// it("Should get the security token address", async() => { +// let address = await I_STRProxied.getSecurityTokenAddress.call(symbol); +// assert.equal(address, I_SecurityToken.address); +// }); + +// it("Should get the security token data", async() => { +// let data = await I_STRProxied.getSecurityTokenData.call(I_SecurityToken.address); +// assert.equal(data[0], symbol); +// assert.equal(data[1], token_owner); +// }); + +// it("Should get the tickers by owner", async() => { +// let tickersList = await I_STRProxied.getTickersByOwner.call(token_owner); +// assert.equal(tickersList.length, 4); +// let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); +// console.log(tickersListArray); +// assert.equal(tickersListArray.length, 3); +// }); + +// }); + +// describe("Test case for the Removing the ticker", async() => { + +// it("Should remove the ticker from the polymath ecosystem -- bad owner", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.removeTicker(symbol2, {from: account_investor1}); +// } catch(error) { +// console.log(` tx revert -> failed because msg.sender should be account_polymath`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should remove the ticker from the polymath ecosystem -- fail because ticker doesn't exist in the ecosystem", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.removeTicker("HOLA", {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> failed because ticker doesn't exist in the polymath ecosystem`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should successfully remove the ticker from the polymath ecosystem", async() => { +// let tx = await I_STRProxied.removeTicker(symbol2, {from: account_polymath}); +// assert.equal(tx.logs[0].args._ticker, symbol2, "Ticker doesn't get deleted successfully"); +// }); +// }) + +// describe(" Test cases of the registerTicker", async() => { + +// it("Should register the ticker 1", async () => { +// await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); +// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); +// let tx = await I_STRProxied.registerTicker(account_temp, "TOK1", "", { from: account_temp }); +// assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); +// assert.equal(tx.logs[0].args._ticker, "TOK1", `Symbol should be TOK1`); +// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); +// }); + +// it("Should register the ticker 2", async () => { +// await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); +// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); +// let tx = await I_STRProxied.registerTicker(account_temp, "TOK2", "", { from: account_temp }); +// assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); +// assert.equal(tx.logs[0].args._ticker, "TOK2", `Symbol should be TOK2`); +// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); +// }); + +// it("Should register the ticker 3", async () => { +// await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); +// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); +// let tx = await I_STRProxied.registerTicker(account_temp, "TOK3", "", { from: account_temp }); +// assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); +// assert.equal(tx.logs[0].args._ticker, "TOK3", `Symbol should be TOK3`); +// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); +// }); + +// it("Should successfully remove the ticker 2", async() => { +// let tx = await I_STRProxied.removeTicker("TOK2", {from: account_polymath}); +// assert.equal(tx.logs[0].args._ticker, "TOK2", "Ticker doesn't get deleted successfully"); +// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); +// }); + +// it("Should modify ticker 1", async() => { +// let tx = await I_STRProxied.modifyTicker(account_temp, "TOK1", "TOKEN 1", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); +// assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); +// assert.equal(tx.logs[0].args._ticker, "TOK1", "Should be equal to TOK1"); +// assert.equal(tx.logs[0].args._name, "TOKEN 1", "Should be equal to TOKEN 1"); +// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); +// }) + +// it("Should modify ticker 3", async() => { +// let tx = await I_STRProxied.modifyTicker(account_temp, "TOK3", "TOKEN 3", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); +// assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); +// assert.equal(tx.logs[0].args._ticker, "TOK3", "Should be equal to TOK3"); +// assert.equal(tx.logs[0].args._name, "TOKEN 3", "Should be equal to TOKEN 3"); +// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); +// }) + +// }); +// describe("Test cases for IRegistry functionality", async() => { + +// describe("Test cases for reclaiming funds", async() => { + +// it("Should successfully reclaim POLY tokens", async() => { +// I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); +// let bal1 = await I_PolyToken.balanceOf.call(account_polymath); +// await I_STRProxied.reclaimERC20(I_PolyToken.address); +// let bal2 = await I_PolyToken.balanceOf.call(account_polymath); +// assert.isAtLeast(bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), bal2.dividedBy(new BigNumber(10).pow(18)).toNumber()); +// }); + +// }); + +// describe("Test cases for pausing the contract", async() => { + +// it("Should fail to pause if msg.sender is not owner", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.pause({ from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> msg.sender should be account_polymath`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully pause the contract", async() => { +// await I_STRProxied.pause({ from: account_polymath }); +// let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); +// assert.isOk(status); +// }); + +// it("Should fail to unpause if msg.sender is not owner", async() => { +// let errorThrown = false; +// try { +// await I_STRProxied.unpause({ from: account_temp }); +// } catch(error) { +// console.log(` tx revert -> msg.sender should be account_polymath`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully unpause the contract", async() => { +// await I_STRProxied.unpause({ from: account_polymath }); +// let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); +// assert.isNotOk(status); +// }); + +// }); + +// }); + +// }); diff --git a/test/o_security_token.js b/test/o_security_token.js index acbb830cf..7453264bd 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -1,1405 +1,1405 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -const CappedSTO = artifacts.require('./CappedSTO.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - - -contract('SecurityToken', accounts => { - - - // Accounts Variable declaration - let account_polymath; - let account_investor1; - let account_issuer; - let token_owner; - let account_investor2; - let account_investor3; - let account_affiliate1; - let account_affiliate2; - let account_fundsReceiver; - let account_delegate; - let account_temp; - let account_controller; - let address_zero = "0x0000000000000000000000000000000000000000"; - - let balanceOfReceiver; - // investor Details - let fromTime; - let toTime; - let expiryTime; - - let ID_snap; - const message = "Transaction Should Fail!!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_CappedSTOFactory; - let I_STFactory; - let I_SecurityToken; - let I_STRProxied; - let I_MRProxied; - let I_CappedSTO; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details (Launched ST on the behalf of the issuer) - const name = "Demo Token"; - const symbol = "DET"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - let snap_Id; - // Module key - const permissionManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - const budget = 0; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - // delagate details - const delegateDetails = "I am delegate .."; - const TM_Perm = 'FLAGS'; - const TM_Perm_Whitelist = 'WHITELIST'; - - // Capped STO details - let startTime; - let endTime; - const cap = web3.utils.toWei("10000"); - const rate = 1000; - const fundRaiseType = [0]; - const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); - const maxCost = cappedSTOSetupCost; - const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - account_affiliate1 = accounts[2]; - account_affiliate2 = accounts[3]; - account_fundsReceiver = accounts[4]; - account_delegate = accounts[5]; - account_investor2 = accounts[6]; - account_investor3 = accounts[7]; - account_temp = accounts[8]; - account_investor1 = accounts[9]; - - token_owner = account_issuer; - account_controller = account_temp; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4 (a): Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - address_zero, - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 4 (b): Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - address_zero, - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 4 (c): Deploy the CappedSTOFactory - - I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); - - assert.notEqual( - I_CappedSTOFactory.address.valueOf(), - address_zero, - "CappedSTOFactory contract was not deployed" - ); - - // STEP 5: Register the Modules with the ModuleRegistry contract - - // Step 6: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 7: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 8: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 9: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - CappedSTOFactory: ${I_CappedSTOFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - console.log(log.args); - assert.equal(log.args._types[0].toNumber(), transferManagerKey); - assert.equal(web3.utils.toUtf8(log.args._name),"GeneralTransferManager"); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - assert.notEqual( - I_GeneralTransferManager.address.valueOf(), - address_zero, - "GeneralTransferManager contract was not deployed", - ); - - }); - - it("Should mint the tokens before attaching the STO -- fail only be called by the owner", async() => { - let errorThrown = false; - let fromTime = latestTime(); - let toTime = fromTime + duration.days(100); - let expiryTime = toTime + duration.days(100); - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_affiliate1, - fromTime, - toTime, - expiryTime, - true, - { - from: token_owner, - gas: 6000000 - }); - assert.equal(tx.logs[0].args._investor, account_affiliate1, "Failed in adding the investor in whitelist"); - try { - await I_SecurityToken.mint(account_investor1, (100 * Math.pow(10, 18)), {from: account_delegate}); - } catch(error) { - console.log(` tx revert -> Mint only be called by the owner of the SecurityToken`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should mint the tokens before attaching the STO", async() => { - await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); - let balance = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); - }); - - it("Should mint the multi tokens before attaching the STO -- fail only be called by the owner", async() => { - let errorThrown = false; - let fromTime = latestTime(); - let toTime = fromTime + duration.days(100); - let expiryTime = toTime + duration.days(100); - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_affiliate2, - fromTime, - toTime, - expiryTime, - true, - { - from: token_owner, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor, account_affiliate2, "Failed in adding the investor in whitelist"); - try { - await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: account_delegate, gas: 500000}); - } catch(error) { - console.log(` tx revert -> Mint only be called by the owner of the SecurityToken`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should mintMulti", async() => { - let errorThrown = false; - try { - await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); - } catch(error) { - console.log(` tx revert -> Array length are un-equal`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should mint the tokens for multiple afiliated investors before attaching the STO", async() => { - await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); - let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 200); - let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); - assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 110); - }); - - it("Should finish the minting -- fail because feature is not activated", async() => { - let errorThrown = false; - try { - await I_SecurityToken.freezeMinting({from: token_owner}); - } catch(error) { - console.log(` tx revert -> freezeMinting cannot be called before activated by polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should finish the minting -- fail to activate the feature because msg.sender is not polymath", async() => { - let errorThrown = false; - try { - await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: token_owner}); - } catch(error) { - console.log(` tx revert -> allowFreezeMinting must be called by polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should finish the minting -- successfully activate the feature", async() => { - let errorThrown1 = false; - try { - await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", false, {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> must change state`.grey); - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, message); - - assert.equal(false, await I_FeatureRegistry.getFeatureStatus("freezeMintingAllowed", {from: account_temp})); - await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: account_polymath}); - assert.equal(true, await I_FeatureRegistry.getFeatureStatus("freezeMintingAllowed", {from: account_temp})); - - let errorThrown2 = false; - try { - await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> must change state`.grey); - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, message); - }); - - it("Should finish the minting -- fail because msg.sender is not the owner", async() => { - let errorThrown = false; - try { - await I_SecurityToken.freezeMinting({from: account_temp}); - } catch(error) { - console.log(` tx revert -> freezeMinting only be called by the owner of the SecurityToken`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should finish minting & restrict the further minting", async() => { - let id = await takeSnapshot(); - await I_SecurityToken.freezeMinting({from: token_owner}); - let errorThrown = false; - try { - await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); - } catch(error) { - console.log(` tx revert -> Minting is finished`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - await revertToSnapshot(id); - }); - - it("Should fail to attach the STO factory because not enough poly in contract", async () => { - startTime = latestTime() + duration.seconds(5000); - endTime = startTime + duration.days(30); - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - let errorThrown = false; - try { - let tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - } catch (error) { - console.log(` tx revert -> not enough poly in contract`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to attach the STO factory because max cost too small", async () => { - startTime = latestTime() + duration.seconds(5000); - endTime = startTime + duration.days(30); - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); - await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); - let errorThrown = false; - try { - let tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, web3.utils.toWei("1000","ether"), 0, { from: token_owner }); - } catch (error) { - console.log(` tx revert -> max cost too small`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the STO factory with the security token", async () => { - startTime = latestTime() + duration.seconds(5000); - endTime = startTime + duration.days(30); - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - - await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); - await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); - - const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - - assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); - assert.equal(web3.utils.toUtf8(tx.logs[3].args._name), "CappedSTO", "CappedSTOFactory module was not added"); - I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); - }); - - it("Should successfully mint tokens while STO attached", async () => { - await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); - let balance = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 300); - }); - - it("Should fail to mint tokens while STO attached after freezeMinting called", async () => { - let id = await takeSnapshot(); - await I_SecurityToken.freezeMinting({from: token_owner}); - let errorThrown = false; - try { - await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); - } catch(error) { - console.log(` tx revert -> Minting is finished`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - await revertToSnapshot(id); - }); - - }); - - describe("Module related functions", async() => { - it("Should get the modules of the securityToken by index", async () => { - let moduleData = await I_SecurityToken.getModule.call(I_CappedSTO.address); - assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "CappedSTO"); - assert.equal(moduleData[1], I_CappedSTO.address); - assert.equal(moduleData[2], I_CappedSTOFactory.address); - assert.equal(moduleData[3], false); - assert.equal(moduleData[4][0], 3); - }); - - it("Should get the modules of the securityToken by index (not added into the security token yet)", async () => { - let moduleData = await I_SecurityToken.getModule.call(token_owner); - assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), ""); - assert.equal(moduleData[1], address_zero); - }); - - it("Should get the modules of the securityToken by name", async () => { - let moduleList = await I_SecurityToken.getModulesByName.call("CappedSTO"); - assert.isTrue(moduleList.length == 1, "Only one STO"); - let moduleData = await I_SecurityToken.getModule.call(moduleList[0]); - assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "CappedSTO"); - assert.equal(moduleData[1], I_CappedSTO.address); - }); - - it("Should get the modules of the securityToken by name (not added into the security token yet)", async () => { - let moduleData = await I_SecurityToken.getModulesByName.call("GeneralPermissionManager"); - assert.isTrue(moduleData.length == 0, "No Permission Manager"); - }); - - it("Should get the modules of the securityToken by name (not added into the security token yet)", async () => { - let moduleData = await I_SecurityToken.getModulesByName.call("CountTransferManager"); - assert.isTrue(moduleData.length == 0, "No Permission Manager"); - }); - - it("Should fail in updating the token details", async() => { - let errorThrown = false; - try { - let log = await I_SecurityToken.updateTokenDetails("new token details", {from: account_delegate}); - } catch (error) { - console.log(` tx revert -> msg.sender should be the owner of the token`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should update the token details", async() => { - let log = await I_SecurityToken.updateTokenDetails("new token details", {from: token_owner}); - assert.equal(log.logs[0].args._newDetails, "new token details"); - }); - - it("Should fail to remove the module - module not archived", async() => { - let errorThrown = false; - try { - let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); - } catch (error) { - console.log(` tx -> Failed because address doesn't exist`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should successfully remove the general transfer manager module from the securityToken -- fails msg.sender should be Owner", async() => { - let errorThrown = false; - try { - let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : account_temp }); - } catch (error) { - console.log(`Test Case passed by restricting the unknown account to call removeModule of the securityToken`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to remove the module - incorrect address", async() => { - let errorThrown = false; - try { - let tx = await I_SecurityToken.removeModule(0, { from : token_owner }); - } catch (error) { - console.log(` tx -> Failed because address doesn't exist`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should successfully remove the general transfer manager module from the securityToken", async() => { - let key = await takeSnapshot(); - await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); - let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); - assert.equal(tx.logs[0].args._types[0], transferManagerKey); - assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); - await revertToSnapshot(key); - }); - - it("Should verify the revertion of snapshot works properly", async() => { - let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); - assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); - assert.equal(moduleData[1], I_GeneralTransferManager.address); - }); - - - it("Should successfully archive the general transfer manager module from the securityToken", async() => { - let tx = await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); - assert.equal(tx.logs[0].args._types[0], transferManagerKey); - assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); - let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); - assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); - assert.equal(moduleData[1], I_GeneralTransferManager.address); - assert.equal(moduleData[2], I_GeneralTransferManagerFactory.address); - assert.equal(moduleData[3], true); - }); - - it("Should successfully mint tokens while GTM archived", async () => { - let key = await takeSnapshot(); - await I_SecurityToken.mint(1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); - let balance = await I_SecurityToken.balanceOf(1); - assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); - await revertToSnapshot(key); - }); - - it("Should successfully unarchive the general transfer manager module from the securityToken", async() => { - let tx = await I_SecurityToken.unarchiveModule(I_GeneralTransferManager.address, { from : token_owner }); - assert.equal(tx.logs[0].args._types[0], transferManagerKey); - assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); - let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); - assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); - assert.equal(moduleData[1], I_GeneralTransferManager.address); - assert.equal(moduleData[2], I_GeneralTransferManagerFactory.address); - assert.equal(moduleData[3], false); - }); - - it("Should fail to mint tokens while GTM unarchived", async () => { - let errorThrown = false; - try { - await I_SecurityToken.mint(1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); - } catch(error) { - console.log(` tx -> Failed because GTM`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - - }); - - it("Should change the budget of the module - fail incorrect address", async() => { - let errorThrown = false; - try { - let tx = await I_SecurityToken.changeModuleBudget(0, (100 * Math.pow(10, 18)),{ from : token_owner}); - } catch(error) { - console.log(` tx -> Failed because address is 0`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - - it("Should change the budget of the module", async() => { - let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, (100 * Math.pow(10, 18)),{ from : token_owner}); - assert.equal(tx.logs[1].args._moduleTypes[0], stoKey); - assert.equal(tx.logs[1].args._module, I_CappedSTO.address); - assert.equal(tx.logs[1].args._budget.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); - }); - - }); - - describe("General Transfer manager Related test cases", async () => { - - it("Should Buy the tokens", async() => { - balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - // Add the Investor in to the whitelist - - fromTime = latestTime(); - toTime = fromTime + duration.days(100); - expiryTime = toTime + duration.days(100); - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - fromTime, - toTime, - expiryTime, - true, - { - from: token_owner, - gas: 6000000 - }); - assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); - // Jump time - await increaseTime(5000); - // Fallback transaction - console.log("BEFORE"); - await web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO.address, - gas: 2100000, - value: web3.utils.toWei('1', 'ether') - }); - console.log("AFTER"); - assert.equal( - (await I_CappedSTO.getRaised.call(0)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1 - ); - - assert.equal(await I_CappedSTO.investorCount.call(), 1); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000 - ); - }); - - it("Should Fail in transferring the token from one whitelist investor 1 to non whitelist investor 2", async() => { - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, (10 * Math.pow(10, 18)), { from : account_investor1}); - } catch(error) { - console.log(` tx revert -> Investor 2 is not in the whitelist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to provide the permission to the delegate to change the transfer bools", async () => { - let errorThrown = false; - // Add permission to the deletgate (A regesteration process) - await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: token_owner}); - let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; - I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); - try { - await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_temp }); - } catch (error) { - console.log(`${account_temp} doesn't have permissions to register the delegate`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should provide the permission to the delegate to change the transfer bools", async () => { - // Add permission to the deletgate (A regesteration process) - await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); - // Providing the permission to the delegate - await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm, true, { from: token_owner }); - - assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm)); - }); - - - it("Should fail to activate the bool allowAllTransfer", async() => { - let errorThrown = false; - try { - let tx = await I_GeneralTransferManager.changeAllowAllTransfers(true, { from : account_temp }); - } catch (error) { - console.log(`${account_temp} doesn't have permissions to activate the bool allowAllTransfer`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should activate the bool allowAllTransfer", async() => { - ID_snap = await takeSnapshot(); - let tx = await I_GeneralTransferManager.changeAllowAllTransfers(true, { from : account_delegate }); - - assert.isTrue(tx.logs[0].args._allowAllTransfers, "AllowTransfer variable is not successfully updated"); - }); - - - it("Should fail to send tokens with the wrong granularity", async() => { - let errorThrown = false; - try { - await I_SecurityToken.transfer(accounts[7], Math.pow(10, 17), { from : account_investor1}); - } catch (error) { - console.log(' tx revert -> Incorrect token granularity - expected'.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should adjust granularity", async() => { - let errorThrown = false; - try { - await I_SecurityToken.changeGranularity(0, {from: token_owner }); - } catch(error) { - console.log(' tx revert -> Incorrect token granularity - expected'.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should adjust granularity", async() => { - let errorThrown = false; - await I_SecurityToken.changeGranularity(Math.pow(10, 17), {from: token_owner }); - await I_SecurityToken.transfer(accounts[7], Math.pow(10, 17), { from : account_investor1, gas: 2500000 }); - await I_SecurityToken.transfer(account_investor1, Math.pow(10, 17), { from : accounts[7], gas: 2500000}); - }); - - it("Should transfer from whitelist investor to non-whitelist investor in first tx and in 2nd tx non-whitelist to non-whitelist transfer", async() => { - await I_SecurityToken.transfer(accounts[7], (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); - - assert.equal( - (await I_SecurityToken.balanceOf(accounts[7])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), - 10, - "Transfer doesn't take place properly" - ); - - await I_SecurityToken.transfer(account_temp, (5 * Math.pow(10, 18)), { from : accounts[7], gas: 2500000}); - - assert.equal( - (await I_SecurityToken.balanceOf(account_temp)) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), - 5, - "Transfer doesn't take place properly" - ); - await revertToSnapshot(ID_snap); - }); - - it("Should bool allowAllTransfer value is false", async() => { - assert.isFalse(await I_GeneralTransferManager.allowAllTransfers.call(), "reverting of snapshot doesn't works properly"); - }); - - it("Should change the bool allowAllWhitelistTransfers to true", async () => { - ID_snap = await takeSnapshot(); - let tx = await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, { from : account_delegate }); - - assert.isTrue(tx.logs[0].args._allowAllWhitelistTransfers, "allowAllWhitelistTransfers variable is not successfully updated"); - }); - - it("Should transfer from whitelist investor1 to whitelist investor 2", async() => { - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - fromTime, - toTime, - expiryTime, - true, - { - from: token_owner, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - - await I_SecurityToken.transfer(account_investor2, (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), - 10, - "Transfer doesn't take place properly" - ); - }); - - it("Should transfer from whitelist investor1 to whitelist investor 2 -- value = 0", async() => { - let tx = await I_SecurityToken.transfer(account_investor2, 0, { from : account_investor1, gas: 2500000}); - assert.equal((tx.logs[0].args.value).toNumber(),0); - }); - - it("Should transferFrom from one investor to other", async() => { - await I_SecurityToken.approve(account_investor1, (2 * Math.pow(10, 18)),{from: account_investor2}); - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - fromTime, - toTime, - expiryTime, - true, - { - from: token_owner, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); - let log = await I_SecurityToken.transferFrom(account_investor2, account_investor3, (2 * Math.pow(10, 18)), {from: account_investor1}); - assert.equal((log.logs[0].args.value).toNumber(), (2 * Math.pow(10, 18))); - }); - - it("Should Fail in trasferring from whitelist investor1 to non-whitelist investor", async() => { - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_temp, (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); - } catch(error) { - console.log(`non-whitelist investor is not allowed`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - await revertToSnapshot(ID_snap); - }); - - it("Should successfully mint tokens while STO attached", async () => { - await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); - let balance = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 400); - }); - - it("Should mint the tokens for multiple afiliated investors while STO attached", async() => { - await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); - let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 500); - let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); - assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 220); - }); - - it("Should provide more permissions to the delegate", async() => { - // Providing the permission to the delegate - await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm_Whitelist, true, { from: token_owner }); - - assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm_Whitelist)); - }); - - it("Should add the investor in the whitelist by the delegate", async() => { - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_temp, - fromTime, - toTime, - expiryTime, - true, - { - from: account_delegate, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor, account_temp, "Failed in adding the investor in whitelist"); - }); - - it("should account_temp successfully buy the token", async() => { - // Fallback transaction - await web3.eth.sendTransaction({ - from: account_temp, - to: I_CappedSTO.address, - gas: 2100000, - value: web3.utils.toWei('1', 'ether') - }); - - assert.equal( - (await I_CappedSTO.getRaised.call(0)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 2 - ); - - assert.equal(await I_CappedSTO.investorCount.call(), 2); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000 - ); - }); - - it("STO should fail to mint tokens after minting is frozen", async() => { - let id = await takeSnapshot(); - await I_SecurityToken.freezeMinting({from: token_owner}); - let errorThrown = false; - try { - await web3.eth.sendTransaction({ - from: account_temp, - to: I_CappedSTO.address, - gas: 2100000, - value: web3.utils.toWei('1', 'ether') - }); - } catch(error) { - console.log(` tx revert -> Minting is finished`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - await revertToSnapshot(id); - }); - - it("Should remove investor from the whitelist by the delegate", async() => { - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_temp, - 0, - 0, - 0, - true, - { - from: account_delegate, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor, account_temp, "Failed in removing the investor from whitelist"); - }); - - it("should account_temp fail in buying the token", async() => { - let errorThrown = false; - try { - // Fallback transaction - await web3.eth.sendTransaction({ - from: account_temp, - to: I_CappedSTO.address, - gas: 2100000, - value: web3.utils.toWei('1', 'ether') - }); - - } catch (error) { - console.log(`non-whitelist investor is not allowed`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should freeze the transfers", async() => { - let tx = await I_SecurityToken.freezeTransfers({from: token_owner}); - assert.isTrue(tx.logs[0].args._status); - }); - - it("Should fail to freeze the transfers", async() => { - let errorThrown = false; - try { - await I_SecurityToken.freezeTransfers({from: token_owner}); - } catch(error) { - console.log(` tx -> Revert because freeze is already true`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in buying to tokens", async() => { - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_temp, - fromTime, - toTime, - expiryTime, - true, - { - from: account_delegate, - gas: 6000000 - }); - - assert.equal(tx.logs[0].args._investor, account_temp, "Failed in adding the investor in whitelist"); - - let errorThrown = false; - try { - // Fallback transaction - await web3.eth.sendTransaction({ - from: account_temp, - to: I_CappedSTO.address, - gas: 2100000, - value: web3.utils.toWei('1', 'ether') - }); - - } catch (error) { - console.log(`Because all transfers get freezed`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in trasfering the tokens from one user to another", async() => { - await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); - console.log(await I_SecurityToken.balanceOf(account_investor1)); - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); - } catch(error) { - console.log(' tx revert -> All transfers are at hold'.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should unfreeze all the transfers", async() => { - let tx = await I_SecurityToken.unfreezeTransfers({from: token_owner}); - assert.isFalse(tx.logs[0].args._status); - }); - - it("Should freeze the transfers", async() => { - let errorThrown = false; - try { - await I_SecurityToken.unfreezeTransfers({from: token_owner}); - } catch(error) { - console.log(` tx -> Revert because freeze is already false`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should able to transfers the tokens from one user to another", async() => { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); - }); - - it("Should check that the list of investors is correct", async ()=> { - // Hardcode list of expected accounts based on transfers above - - let investors = await I_SecurityToken.getInvestors(); - let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1, account_temp]; - for (let i = 0; i < expectedAccounts.length; i++) { - assert.equal(investors[i], expectedAccounts[i]); - } - assert.equal(investors.length, 4); - console.log("Total Seen Investors: " + investors.length); - }); - it("Should fail to set controller status because msg.sender not owner", async() => { - let errorThrown = false; - try { - await I_SecurityToken.setController(account_controller, {from: account_controller}); - } catch (error) { - console.log(` tx revert -> msg.sender not owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully set controller", async() => { - let tx1 = await I_SecurityToken.setController(account_controller, {from: token_owner}); - - // check event - assert.equal(address_zero, tx1.logs[0].args._oldController, "Event not emitted as expected"); - assert.equal(account_controller, tx1.logs[0].args._newController, "Event not emitted as expected"); - - let tx2 = await I_SecurityToken.setController(address_zero, {from: token_owner}); - - // check event - assert.equal(account_controller, tx2.logs[0].args._oldController, "Event not emitted as expected"); - assert.equal(address_zero, tx2.logs[0].args._newController, "Event not emitted as expected"); - - let tx3 = await I_SecurityToken.setController(account_controller, {from: token_owner}); - - // check event - assert.equal(address_zero, tx3.logs[0].args._oldController, "Event not emitted as expected"); - assert.equal(account_controller, tx3.logs[0].args._newController, "Event not emitted as expected"); - - // check status - let controller = await I_SecurityToken.controller.call(); - assert.equal(account_controller, controller, "Status not set correctly"); - }); - - it("Should force burn the tokens - value too high", async ()=> { - let errorThrown = false; - await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); - let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); - let currentBalance = await I_SecurityToken.balanceOf(account_temp); - try { - let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance + web3.utils.toWei("500", "ether"), "", "", { from: account_controller }); - } catch(error) { - console.log(` tx revert -> value is greater than its current balance`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - it("Should force burn the tokens - wrong caller", async ()=> { - let errorThrown = false; - await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); - let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); - let currentBalance = await I_SecurityToken.balanceOf(account_temp); - try { - let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", "", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> not owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should burn the tokens", async ()=> { - let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); - let currentBalance = await I_SecurityToken.balanceOf(account_temp); - // console.log(currentInvestorCount.toString(), currentBalance.toString()); - let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", "", { from: account_controller }); - // console.log(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); - assert.equal(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); - let newInvestorCount = await I_SecurityToken.getInvestorCount.call(); - // console.log(newInvestorCount.toString()); - assert.equal(newInvestorCount.toNumber() + 1, currentInvestorCount.toNumber(), "Investor count drops by one"); - }); - - it("Should prune investor length", async ()=> { - await I_SecurityToken.pruneInvestors(0, 10, {from: token_owner}); - // Hardcode list of expected accounts based on transfers above - - let investors = await I_SecurityToken.getInvestors.call(); - let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1]; - for (let i = 0; i < expectedAccounts.length; i++) { - assert.equal(investors[i], expectedAccounts[i]); - } - assert.equal(investors.length, 3); - }); - - it("Should check the balance of investor at checkpoint", async() => { - let errorThrown = false; - try { - await I_SecurityToken.balanceOfAt(account_investor1, 5); - } catch(error) { - console.log(` tx -> Revert checkpoint ID is greator than current checkpoint`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should check the balance of investor at checkpoint", async() => { - let balance = await I_SecurityToken.balanceOfAt(account_investor1, 0); - assert.equal(balance.toNumber(), 0); - }); - }); - - describe("Withdraw Poly", async() => { - - it("Should successfully withdraw the poly", async() => { - let errorThrown = false; - try { - await I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), {from: account_temp}); - } catch (error) { - console.log(` tx revert -> withdrawPoly function can only be called by the owner of the seucrity token`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) - - it("Should successfully withdraw the poly", async() => { - let balanceBefore = await I_PolyToken.balanceOf(token_owner); - await I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), {from: token_owner}); - let balanceAfter = await I_PolyToken.balanceOf(token_owner); - assert.equal((BigNumber(balanceAfter).sub(BigNumber(balanceBefore))).toNumber(), web3.utils.toWei("20000", "ether")); - }); - - it("Should successfully withdraw the poly", async() => { - let errorThrown = false; - try { - await I_SecurityToken.withdrawPoly(web3.utils.toWei("10", "ether"), {from: token_owner}); - } catch (error) { - console.log(` tx revert -> token doesn't have any POLY`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - }); - - describe("Force Transfer", async() => { - - it("Should fail to forceTransfer because not approved controller", async() => { - let errorThrown1 = false; - try { - await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_investor1}); - } catch (error) { - console.log(` tx revert -> not approved controller`.grey); - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, message); - }); - - it("Should fail to forceTransfer because insufficient balance", async() => { - let errorThrown = false; - try { - await I_SecurityToken.forceTransfer(account_investor2, account_investor1, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); - } catch (error) { - console.log(` tx revert -> insufficient balance`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to forceTransfer because recipient is zero address", async() => { - let errorThrown = false; - try { - await I_SecurityToken.forceTransfer(account_investor1, address_zero, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); - } catch (error) { - console.log(` tx revert -> recipient is zero address`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully forceTransfer", async() => { - let sender = account_investor1; - let receiver = account_investor2; - - let start_investorCount = await I_SecurityToken.getInvestorCount.call(); - let start_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); - let start_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); - - let tx = await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); - - let end_investorCount = await I_SecurityToken.getInvestorCount.call(); - let end_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); - let end_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); - - assert.equal(start_investorCount.add(1).toNumber(), end_investorCount.toNumber(), "Investor count not changed"); - assert.equal(start_balInv1.sub(web3.utils.toWei("10", "ether")).toNumber(), end_balInv1.toNumber(), "Investor balance not changed"); - assert.equal(start_balInv2.add(web3.utils.toWei("10", "ether")).toNumber(), end_balInv2.toNumber(), "Investor balance not changed"); - console.log(tx.logs[0].args); - console.log(tx.logs[1].args); - assert.equal(account_controller, tx.logs[0].args._controller, "Event not emitted as expected"); - assert.equal(account_investor1, tx.logs[0].args._from, "Event not emitted as expected"); - assert.equal(account_investor2, tx.logs[0].args._to, "Event not emitted as expected"); - assert.equal(web3.utils.toWei("10", "ether"), tx.logs[0].args._value, "Event not emitted as expected"); - console.log(tx.logs[0].args._verifyTransfer); - assert.equal(false, tx.logs[0].args._verifyTransfer, "Event not emitted as expected"); - assert.equal("reason", web3.utils.hexToUtf8(tx.logs[0].args._data), "Event not emitted as expected"); - - assert.equal(account_investor1, tx.logs[1].args.from, "Event not emitted as expected"); - assert.equal(account_investor2, tx.logs[1].args.to, "Event not emitted as expected"); - assert.equal(web3.utils.toWei("10", "ether"), tx.logs[1].args.value, "Event not emitted as expected"); - }); - - it("Should fail to freeze controller functionality because not owner", async() => { - let errorThrown = false; - try { - await I_SecurityToken.disableController({from: account_investor1}); - } catch (error) { - console.log(` tx revert -> not owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to freeze controller functionality because disableControllerAllowed not activated", async() => { - let errorThrown = false; - try { - await I_SecurityToken.disableController({from: token_owner}); - } catch (error) { - console.log(` tx revert -> disableControllerAllowed not activated`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully freeze controller functionality", async() => { - let tx1 = await I_FeatureRegistry.setFeatureStatus("disableControllerAllowed", true, {from: account_polymath}); - - // check event - assert.equal("disableControllerAllowed", tx1.logs[0].args._nameKey, "Event not emitted as expected"); - assert.equal(true, tx1.logs[0].args._newStatus, "Event not emitted as expected"); - - let tx2 = await I_SecurityToken.disableController({from: token_owner}); - - // check state - assert.equal(address_zero, await I_SecurityToken.controller.call(), "State not changed"); - assert.equal(true, await I_SecurityToken.controllerDisabled.call(), "State not changed"); - }); - - it("Should fail to freeze controller functionality because already frozen", async() => { - let errorThrown = false; - try { - await I_SecurityToken.disableController({from: token_owner}); - } catch (error) { - console.log(` tx revert -> already frozen`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to set controller because controller functionality frozen", async() => { - let errorThrown = false; - try { - await I_SecurityToken.setController(account_controller, {from: token_owner}); - } catch (error) { - console.log(` tx revert -> msg.sender not owner`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail to forceTransfer because controller functionality frozen", async() => { - let errorThrown = false; - try { - await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); - } catch (error) { - console.log(` tx revert -> recipient is zero address`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - }); - - }); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +// const CappedSTO = artifacts.require('./CappedSTO.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + + +// contract('SecurityToken', accounts => { + + +// // Accounts Variable declaration +// let account_polymath; +// let account_investor1; +// let account_issuer; +// let token_owner; +// let account_investor2; +// let account_investor3; +// let account_affiliate1; +// let account_affiliate2; +// let account_fundsReceiver; +// let account_delegate; +// let account_temp; +// let account_controller; +// let address_zero = "0x0000000000000000000000000000000000000000"; + +// let balanceOfReceiver; +// // investor Details +// let fromTime; +// let toTime; +// let expiryTime; + +// let ID_snap; +// const message = "Transaction Should Fail!!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_CappedSTOFactory; +// let I_STFactory; +// let I_SecurityToken; +// let I_STRProxied; +// let I_MRProxied; +// let I_CappedSTO; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details (Launched ST on the behalf of the issuer) +// const name = "Demo Token"; +// const symbol = "DET"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// let snap_Id; +// // Module key +// const permissionManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; +// const budget = 0; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// // delagate details +// const delegateDetails = "I am delegate .."; +// const TM_Perm = 'FLAGS'; +// const TM_Perm_Whitelist = 'WHITELIST'; + +// // Capped STO details +// let startTime; +// let endTime; +// const cap = web3.utils.toWei("10000"); +// const rate = 1000; +// const fundRaiseType = [0]; +// const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); +// const maxCost = cappedSTOSetupCost; +// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { + +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; +// account_affiliate1 = accounts[2]; +// account_affiliate2 = accounts[3]; +// account_fundsReceiver = accounts[4]; +// account_delegate = accounts[5]; +// account_investor2 = accounts[6]; +// account_investor3 = accounts[7]; +// account_temp = accounts[8]; +// account_investor1 = accounts[9]; + +// token_owner = account_issuer; +// account_controller = account_temp; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4 (a): Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// address_zero, +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 4 (b): Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// address_zero, +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 4 (c): Deploy the CappedSTOFactory + +// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); + +// assert.notEqual( +// I_CappedSTOFactory.address.valueOf(), +// address_zero, +// "CappedSTOFactory contract was not deployed" +// ); + +// // STEP 5: Register the Modules with the ModuleRegistry contract + +// // Step 6: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 7: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 8: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 9: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// ModuleRegistry: ${ModuleRegistry.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// CappedSTOFactory: ${I_CappedSTOFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// console.log(log.args); +// assert.equal(log.args._types[0].toNumber(), transferManagerKey); +// assert.equal(web3.utils.toUtf8(log.args._name),"GeneralTransferManager"); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// assert.notEqual( +// I_GeneralTransferManager.address.valueOf(), +// address_zero, +// "GeneralTransferManager contract was not deployed", +// ); + +// }); + +// it("Should mint the tokens before attaching the STO -- fail only be called by the owner", async() => { +// let errorThrown = false; +// let fromTime = latestTime(); +// let toTime = fromTime + duration.days(100); +// let expiryTime = toTime + duration.days(100); + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_affiliate1, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: token_owner, +// gas: 6000000 +// }); +// assert.equal(tx.logs[0].args._investor, account_affiliate1, "Failed in adding the investor in whitelist"); +// try { +// await I_SecurityToken.mint(account_investor1, (100 * Math.pow(10, 18)), {from: account_delegate}); +// } catch(error) { +// console.log(` tx revert -> Mint only be called by the owner of the SecurityToken`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should mint the tokens before attaching the STO", async() => { +// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); +// let balance = await I_SecurityToken.balanceOf(account_affiliate1); +// assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); +// }); + +// it("Should mint the multi tokens before attaching the STO -- fail only be called by the owner", async() => { +// let errorThrown = false; +// let fromTime = latestTime(); +// let toTime = fromTime + duration.days(100); +// let expiryTime = toTime + duration.days(100); + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_affiliate2, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: token_owner, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_affiliate2, "Failed in adding the investor in whitelist"); +// try { +// await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: account_delegate, gas: 500000}); +// } catch(error) { +// console.log(` tx revert -> Mint only be called by the owner of the SecurityToken`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should mintMulti", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); +// } catch(error) { +// console.log(` tx revert -> Array length are un-equal`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should mint the tokens for multiple afiliated investors before attaching the STO", async() => { +// await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); +// let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); +// assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 200); +// let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); +// assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 110); +// }); + +// it("Should finish the minting -- fail because feature is not activated", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.freezeMinting({from: token_owner}); +// } catch(error) { +// console.log(` tx revert -> freezeMinting cannot be called before activated by polymath`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should finish the minting -- fail to activate the feature because msg.sender is not polymath", async() => { +// let errorThrown = false; +// try { +// await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: token_owner}); +// } catch(error) { +// console.log(` tx revert -> allowFreezeMinting must be called by polymath`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should finish the minting -- successfully activate the feature", async() => { +// let errorThrown1 = false; +// try { +// await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", false, {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> must change state`.grey); +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, message); + +// assert.equal(false, await I_FeatureRegistry.getFeatureStatus("freezeMintingAllowed", {from: account_temp})); +// await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: account_polymath}); +// assert.equal(true, await I_FeatureRegistry.getFeatureStatus("freezeMintingAllowed", {from: account_temp})); + +// let errorThrown2 = false; +// try { +// await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: account_polymath}); +// } catch(error) { +// console.log(` tx revert -> must change state`.grey); +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, message); +// }); + +// it("Should finish the minting -- fail because msg.sender is not the owner", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.freezeMinting({from: account_temp}); +// } catch(error) { +// console.log(` tx revert -> freezeMinting only be called by the owner of the SecurityToken`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should finish minting & restrict the further minting", async() => { +// let id = await takeSnapshot(); +// await I_SecurityToken.freezeMinting({from: token_owner}); +// let errorThrown = false; +// try { +// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); +// } catch(error) { +// console.log(` tx revert -> Minting is finished`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// await revertToSnapshot(id); +// }); + +// it("Should fail to attach the STO factory because not enough poly in contract", async () => { +// startTime = latestTime() + duration.seconds(5000); +// endTime = startTime + duration.days(30); +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); +// let errorThrown = false; +// try { +// let tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); +// } catch (error) { +// console.log(` tx revert -> not enough poly in contract`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to attach the STO factory because max cost too small", async () => { +// startTime = latestTime() + duration.seconds(5000); +// endTime = startTime + duration.days(30); +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); +// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); +// await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); +// let errorThrown = false; +// try { +// let tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, web3.utils.toWei("1000","ether"), 0, { from: token_owner }); +// } catch (error) { +// console.log(` tx revert -> max cost too small`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the STO factory with the security token", async () => { +// startTime = latestTime() + duration.seconds(5000); +// endTime = startTime + duration.days(30); +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + +// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); +// await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); + +// const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + +// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); +// assert.equal(web3.utils.toUtf8(tx.logs[3].args._name), "CappedSTO", "CappedSTOFactory module was not added"); +// I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); +// }); + +// it("Should successfully mint tokens while STO attached", async () => { +// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); +// let balance = await I_SecurityToken.balanceOf(account_affiliate1); +// assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 300); +// }); + +// it("Should fail to mint tokens while STO attached after freezeMinting called", async () => { +// let id = await takeSnapshot(); +// await I_SecurityToken.freezeMinting({from: token_owner}); +// let errorThrown = false; +// try { +// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); +// } catch(error) { +// console.log(` tx revert -> Minting is finished`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// await revertToSnapshot(id); +// }); + +// }); + +// describe("Module related functions", async() => { +// it("Should get the modules of the securityToken by index", async () => { +// let moduleData = await I_SecurityToken.getModule.call(I_CappedSTO.address); +// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "CappedSTO"); +// assert.equal(moduleData[1], I_CappedSTO.address); +// assert.equal(moduleData[2], I_CappedSTOFactory.address); +// assert.equal(moduleData[3], false); +// assert.equal(moduleData[4][0], 3); +// }); + +// it("Should get the modules of the securityToken by index (not added into the security token yet)", async () => { +// let moduleData = await I_SecurityToken.getModule.call(token_owner); +// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), ""); +// assert.equal(moduleData[1], address_zero); +// }); + +// it("Should get the modules of the securityToken by name", async () => { +// let moduleList = await I_SecurityToken.getModulesByName.call("CappedSTO"); +// assert.isTrue(moduleList.length == 1, "Only one STO"); +// let moduleData = await I_SecurityToken.getModule.call(moduleList[0]); +// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "CappedSTO"); +// assert.equal(moduleData[1], I_CappedSTO.address); +// }); + +// it("Should get the modules of the securityToken by name (not added into the security token yet)", async () => { +// let moduleData = await I_SecurityToken.getModulesByName.call("GeneralPermissionManager"); +// assert.isTrue(moduleData.length == 0, "No Permission Manager"); +// }); + +// it("Should get the modules of the securityToken by name (not added into the security token yet)", async () => { +// let moduleData = await I_SecurityToken.getModulesByName.call("CountTransferManager"); +// assert.isTrue(moduleData.length == 0, "No Permission Manager"); +// }); + +// it("Should fail in updating the token details", async() => { +// let errorThrown = false; +// try { +// let log = await I_SecurityToken.updateTokenDetails("new token details", {from: account_delegate}); +// } catch (error) { +// console.log(` tx revert -> msg.sender should be the owner of the token`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should update the token details", async() => { +// let log = await I_SecurityToken.updateTokenDetails("new token details", {from: token_owner}); +// assert.equal(log.logs[0].args._newDetails, "new token details"); +// }); + +// it("Should fail to remove the module - module not archived", async() => { +// let errorThrown = false; +// try { +// let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); +// } catch (error) { +// console.log(` tx -> Failed because address doesn't exist`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should successfully remove the general transfer manager module from the securityToken -- fails msg.sender should be Owner", async() => { +// let errorThrown = false; +// try { +// let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : account_temp }); +// } catch (error) { +// console.log(`Test Case passed by restricting the unknown account to call removeModule of the securityToken`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to remove the module - incorrect address", async() => { +// let errorThrown = false; +// try { +// let tx = await I_SecurityToken.removeModule(0, { from : token_owner }); +// } catch (error) { +// console.log(` tx -> Failed because address doesn't exist`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should successfully remove the general transfer manager module from the securityToken", async() => { +// let key = await takeSnapshot(); +// await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); +// let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); +// assert.equal(tx.logs[0].args._types[0], transferManagerKey); +// assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); +// await revertToSnapshot(key); +// }); + +// it("Should verify the revertion of snapshot works properly", async() => { +// let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); +// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); +// assert.equal(moduleData[1], I_GeneralTransferManager.address); +// }); + + +// it("Should successfully archive the general transfer manager module from the securityToken", async() => { +// let tx = await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); +// assert.equal(tx.logs[0].args._types[0], transferManagerKey); +// assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); +// let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); +// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); +// assert.equal(moduleData[1], I_GeneralTransferManager.address); +// assert.equal(moduleData[2], I_GeneralTransferManagerFactory.address); +// assert.equal(moduleData[3], true); +// }); + +// it("Should successfully mint tokens while GTM archived", async () => { +// let key = await takeSnapshot(); +// await I_SecurityToken.mint(1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); +// let balance = await I_SecurityToken.balanceOf(1); +// assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); +// await revertToSnapshot(key); +// }); + +// it("Should successfully unarchive the general transfer manager module from the securityToken", async() => { +// let tx = await I_SecurityToken.unarchiveModule(I_GeneralTransferManager.address, { from : token_owner }); +// assert.equal(tx.logs[0].args._types[0], transferManagerKey); +// assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); +// let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); +// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); +// assert.equal(moduleData[1], I_GeneralTransferManager.address); +// assert.equal(moduleData[2], I_GeneralTransferManagerFactory.address); +// assert.equal(moduleData[3], false); +// }); + +// it("Should fail to mint tokens while GTM unarchived", async () => { +// let errorThrown = false; +// try { +// await I_SecurityToken.mint(1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); +// } catch(error) { +// console.log(` tx -> Failed because GTM`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); + +// }); + +// it("Should change the budget of the module - fail incorrect address", async() => { +// let errorThrown = false; +// try { +// let tx = await I_SecurityToken.changeModuleBudget(0, (100 * Math.pow(10, 18)),{ from : token_owner}); +// } catch(error) { +// console.log(` tx -> Failed because address is 0`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + + +// it("Should change the budget of the module", async() => { +// let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, (100 * Math.pow(10, 18)),{ from : token_owner}); +// assert.equal(tx.logs[1].args._moduleTypes[0], stoKey); +// assert.equal(tx.logs[1].args._module, I_CappedSTO.address); +// assert.equal(tx.logs[1].args._budget.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); +// }); + +// }); + +// describe("General Transfer manager Related test cases", async () => { + +// it("Should Buy the tokens", async() => { +// balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); +// // Add the Investor in to the whitelist + +// fromTime = latestTime(); +// toTime = fromTime + duration.days(100); +// expiryTime = toTime + duration.days(100); + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: token_owner, +// gas: 6000000 +// }); +// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); +// // Jump time +// await increaseTime(5000); +// // Fallback transaction +// console.log("BEFORE"); +// await web3.eth.sendTransaction({ +// from: account_investor1, +// to: I_CappedSTO.address, +// gas: 2100000, +// value: web3.utils.toWei('1', 'ether') +// }); +// console.log("AFTER"); +// assert.equal( +// (await I_CappedSTO.getRaised.call(0)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1 +// ); + +// assert.equal(await I_CappedSTO.investorCount.call(), 1); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000 +// ); +// }); + +// it("Should Fail in transferring the token from one whitelist investor 1 to non whitelist investor 2", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, (10 * Math.pow(10, 18)), { from : account_investor1}); +// } catch(error) { +// console.log(` tx revert -> Investor 2 is not in the whitelist`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to provide the permission to the delegate to change the transfer bools", async () => { +// let errorThrown = false; +// // Add permission to the deletgate (A regesteration process) +// await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: token_owner}); +// let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; +// I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); +// try { +// await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_temp }); +// } catch (error) { +// console.log(`${account_temp} doesn't have permissions to register the delegate`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should provide the permission to the delegate to change the transfer bools", async () => { +// // Add permission to the deletgate (A regesteration process) +// await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); +// // Providing the permission to the delegate +// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm, true, { from: token_owner }); + +// assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm)); +// }); + + +// it("Should fail to activate the bool allowAllTransfer", async() => { +// let errorThrown = false; +// try { +// let tx = await I_GeneralTransferManager.changeAllowAllTransfers(true, { from : account_temp }); +// } catch (error) { +// console.log(`${account_temp} doesn't have permissions to activate the bool allowAllTransfer`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should activate the bool allowAllTransfer", async() => { +// ID_snap = await takeSnapshot(); +// let tx = await I_GeneralTransferManager.changeAllowAllTransfers(true, { from : account_delegate }); + +// assert.isTrue(tx.logs[0].args._allowAllTransfers, "AllowTransfer variable is not successfully updated"); +// }); + + +// it("Should fail to send tokens with the wrong granularity", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(accounts[7], Math.pow(10, 17), { from : account_investor1}); +// } catch (error) { +// console.log(' tx revert -> Incorrect token granularity - expected'.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should adjust granularity", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.changeGranularity(0, {from: token_owner }); +// } catch(error) { +// console.log(' tx revert -> Incorrect token granularity - expected'.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should adjust granularity", async() => { +// let errorThrown = false; +// await I_SecurityToken.changeGranularity(Math.pow(10, 17), {from: token_owner }); +// await I_SecurityToken.transfer(accounts[7], Math.pow(10, 17), { from : account_investor1, gas: 2500000 }); +// await I_SecurityToken.transfer(account_investor1, Math.pow(10, 17), { from : accounts[7], gas: 2500000}); +// }); + +// it("Should transfer from whitelist investor to non-whitelist investor in first tx and in 2nd tx non-whitelist to non-whitelist transfer", async() => { +// await I_SecurityToken.transfer(accounts[7], (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); + +// assert.equal( +// (await I_SecurityToken.balanceOf(accounts[7])) +// .dividedBy(new BigNumber(10).pow(18)).toNumber(), +// 10, +// "Transfer doesn't take place properly" +// ); + +// await I_SecurityToken.transfer(account_temp, (5 * Math.pow(10, 18)), { from : accounts[7], gas: 2500000}); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_temp)) +// .dividedBy(new BigNumber(10).pow(18)).toNumber(), +// 5, +// "Transfer doesn't take place properly" +// ); +// await revertToSnapshot(ID_snap); +// }); + +// it("Should bool allowAllTransfer value is false", async() => { +// assert.isFalse(await I_GeneralTransferManager.allowAllTransfers.call(), "reverting of snapshot doesn't works properly"); +// }); + +// it("Should change the bool allowAllWhitelistTransfers to true", async () => { +// ID_snap = await takeSnapshot(); +// let tx = await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, { from : account_delegate }); + +// assert.isTrue(tx.logs[0].args._allowAllWhitelistTransfers, "allowAllWhitelistTransfers variable is not successfully updated"); +// }); + +// it("Should transfer from whitelist investor1 to whitelist investor 2", async() => { +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: token_owner, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + +// await I_SecurityToken.transfer(account_investor2, (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)) +// .dividedBy(new BigNumber(10).pow(18)).toNumber(), +// 10, +// "Transfer doesn't take place properly" +// ); +// }); + +// it("Should transfer from whitelist investor1 to whitelist investor 2 -- value = 0", async() => { +// let tx = await I_SecurityToken.transfer(account_investor2, 0, { from : account_investor1, gas: 2500000}); +// assert.equal((tx.logs[0].args.value).toNumber(),0); +// }); + +// it("Should transferFrom from one investor to other", async() => { +// await I_SecurityToken.approve(account_investor1, (2 * Math.pow(10, 18)),{from: account_investor2}); +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: token_owner, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); +// let log = await I_SecurityToken.transferFrom(account_investor2, account_investor3, (2 * Math.pow(10, 18)), {from: account_investor1}); +// assert.equal((log.logs[0].args.value).toNumber(), (2 * Math.pow(10, 18))); +// }); + +// it("Should Fail in trasferring from whitelist investor1 to non-whitelist investor", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_temp, (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); +// } catch(error) { +// console.log(`non-whitelist investor is not allowed`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// await revertToSnapshot(ID_snap); +// }); + +// it("Should successfully mint tokens while STO attached", async () => { +// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); +// let balance = await I_SecurityToken.balanceOf(account_affiliate1); +// assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 400); +// }); + +// it("Should mint the tokens for multiple afiliated investors while STO attached", async() => { +// await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); +// let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); +// assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 500); +// let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); +// assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 220); +// }); + +// it("Should provide more permissions to the delegate", async() => { +// // Providing the permission to the delegate +// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm_Whitelist, true, { from: token_owner }); + +// assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm_Whitelist)); +// }); + +// it("Should add the investor in the whitelist by the delegate", async() => { +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_temp, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: account_delegate, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_temp, "Failed in adding the investor in whitelist"); +// }); + +// it("should account_temp successfully buy the token", async() => { +// // Fallback transaction +// await web3.eth.sendTransaction({ +// from: account_temp, +// to: I_CappedSTO.address, +// gas: 2100000, +// value: web3.utils.toWei('1', 'ether') +// }); + +// assert.equal( +// (await I_CappedSTO.getRaised.call(0)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 2 +// ); + +// assert.equal(await I_CappedSTO.investorCount.call(), 2); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000 +// ); +// }); + +// it("STO should fail to mint tokens after minting is frozen", async() => { +// let id = await takeSnapshot(); +// await I_SecurityToken.freezeMinting({from: token_owner}); +// let errorThrown = false; +// try { +// await web3.eth.sendTransaction({ +// from: account_temp, +// to: I_CappedSTO.address, +// gas: 2100000, +// value: web3.utils.toWei('1', 'ether') +// }); +// } catch(error) { +// console.log(` tx revert -> Minting is finished`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// await revertToSnapshot(id); +// }); + +// it("Should remove investor from the whitelist by the delegate", async() => { +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_temp, +// 0, +// 0, +// 0, +// true, +// { +// from: account_delegate, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_temp, "Failed in removing the investor from whitelist"); +// }); + +// it("should account_temp fail in buying the token", async() => { +// let errorThrown = false; +// try { +// // Fallback transaction +// await web3.eth.sendTransaction({ +// from: account_temp, +// to: I_CappedSTO.address, +// gas: 2100000, +// value: web3.utils.toWei('1', 'ether') +// }); + +// } catch (error) { +// console.log(`non-whitelist investor is not allowed`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should freeze the transfers", async() => { +// let tx = await I_SecurityToken.freezeTransfers({from: token_owner}); +// assert.isTrue(tx.logs[0].args._status); +// }); + +// it("Should fail to freeze the transfers", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.freezeTransfers({from: token_owner}); +// } catch(error) { +// console.log(` tx -> Revert because freeze is already true`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in buying to tokens", async() => { +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_temp, +// fromTime, +// toTime, +// expiryTime, +// true, +// { +// from: account_delegate, +// gas: 6000000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_temp, "Failed in adding the investor in whitelist"); + +// let errorThrown = false; +// try { +// // Fallback transaction +// await web3.eth.sendTransaction({ +// from: account_temp, +// to: I_CappedSTO.address, +// gas: 2100000, +// value: web3.utils.toWei('1', 'ether') +// }); + +// } catch (error) { +// console.log(`Because all transfers get freezed`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail in trasfering the tokens from one user to another", async() => { +// await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); +// console.log(await I_SecurityToken.balanceOf(account_investor1)); +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); +// } catch(error) { +// console.log(' tx revert -> All transfers are at hold'.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should unfreeze all the transfers", async() => { +// let tx = await I_SecurityToken.unfreezeTransfers({from: token_owner}); +// assert.isFalse(tx.logs[0].args._status); +// }); + +// it("Should freeze the transfers", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.unfreezeTransfers({from: token_owner}); +// } catch(error) { +// console.log(` tx -> Revert because freeze is already false`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should able to transfers the tokens from one user to another", async() => { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); +// }); + +// it("Should check that the list of investors is correct", async ()=> { +// // Hardcode list of expected accounts based on transfers above + +// let investors = await I_SecurityToken.getInvestors(); +// let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1, account_temp]; +// for (let i = 0; i < expectedAccounts.length; i++) { +// assert.equal(investors[i], expectedAccounts[i]); +// } +// assert.equal(investors.length, 4); +// console.log("Total Seen Investors: " + investors.length); +// }); +// it("Should fail to set controller status because msg.sender not owner", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.setController(account_controller, {from: account_controller}); +// } catch (error) { +// console.log(` tx revert -> msg.sender not owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully set controller", async() => { +// let tx1 = await I_SecurityToken.setController(account_controller, {from: token_owner}); + +// // check event +// assert.equal(address_zero, tx1.logs[0].args._oldController, "Event not emitted as expected"); +// assert.equal(account_controller, tx1.logs[0].args._newController, "Event not emitted as expected"); + +// let tx2 = await I_SecurityToken.setController(address_zero, {from: token_owner}); + +// // check event +// assert.equal(account_controller, tx2.logs[0].args._oldController, "Event not emitted as expected"); +// assert.equal(address_zero, tx2.logs[0].args._newController, "Event not emitted as expected"); + +// let tx3 = await I_SecurityToken.setController(account_controller, {from: token_owner}); + +// // check event +// assert.equal(address_zero, tx3.logs[0].args._oldController, "Event not emitted as expected"); +// assert.equal(account_controller, tx3.logs[0].args._newController, "Event not emitted as expected"); + +// // check status +// let controller = await I_SecurityToken.controller.call(); +// assert.equal(account_controller, controller, "Status not set correctly"); +// }); + +// it("Should force burn the tokens - value too high", async ()=> { +// let errorThrown = false; +// await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); +// let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); +// let currentBalance = await I_SecurityToken.balanceOf(account_temp); +// try { +// let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance + web3.utils.toWei("500", "ether"), "", "", { from: account_controller }); +// } catch(error) { +// console.log(` tx revert -> value is greater than its current balance`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); +// it("Should force burn the tokens - wrong caller", async ()=> { +// let errorThrown = false; +// await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); +// let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); +// let currentBalance = await I_SecurityToken.balanceOf(account_temp); +// try { +// let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", "", { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> not owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should burn the tokens", async ()=> { +// let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); +// let currentBalance = await I_SecurityToken.balanceOf(account_temp); +// // console.log(currentInvestorCount.toString(), currentBalance.toString()); +// let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", "", { from: account_controller }); +// // console.log(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); +// assert.equal(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); +// let newInvestorCount = await I_SecurityToken.getInvestorCount.call(); +// // console.log(newInvestorCount.toString()); +// assert.equal(newInvestorCount.toNumber() + 1, currentInvestorCount.toNumber(), "Investor count drops by one"); +// }); + +// it("Should prune investor length", async ()=> { +// await I_SecurityToken.pruneInvestors(0, 10, {from: token_owner}); +// // Hardcode list of expected accounts based on transfers above + +// let investors = await I_SecurityToken.getInvestors.call(); +// let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1]; +// for (let i = 0; i < expectedAccounts.length; i++) { +// assert.equal(investors[i], expectedAccounts[i]); +// } +// assert.equal(investors.length, 3); +// }); + +// it("Should check the balance of investor at checkpoint", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.balanceOfAt(account_investor1, 5); +// } catch(error) { +// console.log(` tx -> Revert checkpoint ID is greator than current checkpoint`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should check the balance of investor at checkpoint", async() => { +// let balance = await I_SecurityToken.balanceOfAt(account_investor1, 0); +// assert.equal(balance.toNumber(), 0); +// }); +// }); + +// describe("Withdraw Poly", async() => { + +// it("Should successfully withdraw the poly", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), {from: account_temp}); +// } catch (error) { +// console.log(` tx revert -> withdrawPoly function can only be called by the owner of the seucrity token`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }) + +// it("Should successfully withdraw the poly", async() => { +// let balanceBefore = await I_PolyToken.balanceOf(token_owner); +// await I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), {from: token_owner}); +// let balanceAfter = await I_PolyToken.balanceOf(token_owner); +// assert.equal((BigNumber(balanceAfter).sub(BigNumber(balanceBefore))).toNumber(), web3.utils.toWei("20000", "ether")); +// }); + +// it("Should successfully withdraw the poly", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.withdrawPoly(web3.utils.toWei("10", "ether"), {from: token_owner}); +// } catch (error) { +// console.log(` tx revert -> token doesn't have any POLY`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); +// }); + +// describe("Force Transfer", async() => { + +// it("Should fail to forceTransfer because not approved controller", async() => { +// let errorThrown1 = false; +// try { +// await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_investor1}); +// } catch (error) { +// console.log(` tx revert -> not approved controller`.grey); +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, message); +// }); + +// it("Should fail to forceTransfer because insufficient balance", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.forceTransfer(account_investor2, account_investor1, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); +// } catch (error) { +// console.log(` tx revert -> insufficient balance`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to forceTransfer because recipient is zero address", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.forceTransfer(account_investor1, address_zero, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); +// } catch (error) { +// console.log(` tx revert -> recipient is zero address`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully forceTransfer", async() => { +// let sender = account_investor1; +// let receiver = account_investor2; + +// let start_investorCount = await I_SecurityToken.getInvestorCount.call(); +// let start_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); +// let start_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); + +// let tx = await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); + +// let end_investorCount = await I_SecurityToken.getInvestorCount.call(); +// let end_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); +// let end_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); + +// assert.equal(start_investorCount.add(1).toNumber(), end_investorCount.toNumber(), "Investor count not changed"); +// assert.equal(start_balInv1.sub(web3.utils.toWei("10", "ether")).toNumber(), end_balInv1.toNumber(), "Investor balance not changed"); +// assert.equal(start_balInv2.add(web3.utils.toWei("10", "ether")).toNumber(), end_balInv2.toNumber(), "Investor balance not changed"); +// console.log(tx.logs[0].args); +// console.log(tx.logs[1].args); +// assert.equal(account_controller, tx.logs[0].args._controller, "Event not emitted as expected"); +// assert.equal(account_investor1, tx.logs[0].args._from, "Event not emitted as expected"); +// assert.equal(account_investor2, tx.logs[0].args._to, "Event not emitted as expected"); +// assert.equal(web3.utils.toWei("10", "ether"), tx.logs[0].args._value, "Event not emitted as expected"); +// console.log(tx.logs[0].args._verifyTransfer); +// assert.equal(false, tx.logs[0].args._verifyTransfer, "Event not emitted as expected"); +// assert.equal("reason", web3.utils.hexToUtf8(tx.logs[0].args._data), "Event not emitted as expected"); + +// assert.equal(account_investor1, tx.logs[1].args.from, "Event not emitted as expected"); +// assert.equal(account_investor2, tx.logs[1].args.to, "Event not emitted as expected"); +// assert.equal(web3.utils.toWei("10", "ether"), tx.logs[1].args.value, "Event not emitted as expected"); +// }); + +// it("Should fail to freeze controller functionality because not owner", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.disableController({from: account_investor1}); +// } catch (error) { +// console.log(` tx revert -> not owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to freeze controller functionality because disableControllerAllowed not activated", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.disableController({from: token_owner}); +// } catch (error) { +// console.log(` tx revert -> disableControllerAllowed not activated`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully freeze controller functionality", async() => { +// let tx1 = await I_FeatureRegistry.setFeatureStatus("disableControllerAllowed", true, {from: account_polymath}); + +// // check event +// assert.equal("disableControllerAllowed", tx1.logs[0].args._nameKey, "Event not emitted as expected"); +// assert.equal(true, tx1.logs[0].args._newStatus, "Event not emitted as expected"); + +// let tx2 = await I_SecurityToken.disableController({from: token_owner}); + +// // check state +// assert.equal(address_zero, await I_SecurityToken.controller.call(), "State not changed"); +// assert.equal(true, await I_SecurityToken.controllerDisabled.call(), "State not changed"); +// }); + +// it("Should fail to freeze controller functionality because already frozen", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.disableController({from: token_owner}); +// } catch (error) { +// console.log(` tx revert -> already frozen`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to set controller because controller functionality frozen", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.setController(account_controller, {from: token_owner}); +// } catch (error) { +// console.log(` tx revert -> msg.sender not owner`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should fail to forceTransfer because controller functionality frozen", async() => { +// let errorThrown = false; +// try { +// await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); +// } catch (error) { +// console.log(` tx revert -> recipient is zero address`.grey); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// }); + +// }); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 20656b0bc..0ba8056d0 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1,3517 +1,3517 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); -const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); -const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); -const MockOracle = artifacts.require('./MockOracle.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port - -contract('USDTieredSTO', accounts => { - // Accounts Variable declaration - let POLYMATH; - let ISSUER; - let WALLET; - let RESERVEWALLET; - let INVESTOR1; - let INVESTOR2; - let INVESTOR3; - let INVESTOR4; - let ACCREDITED1; - let ACCREDITED2; - let NONACCREDITED1; - let NONACCREDITED2; - let ETH = 0; - let POLY = 1; - let DAI = 2; - - let MESSAGE = "Transaction Should Fail!"; - const GAS_PRICE = 0; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_USDTieredSTOProxyFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ModuleRegistry; - let I_ModuleRegistryProxy; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_USDTieredSTOFactory; - let I_USDOracle; - let I_POLYOracle; - let I_STFactory; - let I_SecurityToken; - let I_STRProxied; - let I_MRProxied; - let I_USDTieredSTO_Array = []; - let I_PolyToken; - let I_DaiToken; - let I_PolymathRegistry; - - // SecurityToken Details for funds raise Type ETH - const NAME = "Team"; - const SYMBOL = "SAP"; - const TOKENDETAILS = "This is equity type of issuance"; - const DECIMALS = 18; - - // Module key - const TMKEY = 2; - const STOKEY = 3; - - // Initial fee for ticker registry and security token registry - const REGFEE = web3.utils.toWei("250"); - const STOSetupCost = 0; - - // MockOracle USD prices - const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH - const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY - - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - // STO Configuration Arrays - let _startTime = []; - let _endTime = []; - let _ratePerTier = []; - let _ratePerTierDiscountPoly = []; - let _tokensPerTierTotal = []; - let _tokensPerTierDiscountPoly = []; - let _nonAccreditedLimitUSD = []; - let _minimumInvestmentUSD = []; - let _fundRaiseTypes = []; - let _wallet = []; - let _reserveWallet = []; - let _usdToken = []; - - /* function configure( - uint256 _startTime, - uint256 _endTime, - uint256[] _ratePerTier, - uint256[] _ratePerTierDiscountPoly, - uint256[] _tokensPerTier, - uint256[] _tokensPerTierDiscountPoly, - uint256 _nonAccreditedLimitUSD, - uint256 _minimumInvestmentUSD, - uint8[] _fundRaiseTypes, - address _wallet, - address _reserveWallet, - address _usdToken - ) */ - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256[]', - name: '_ratePerTier' - },{ - type: 'uint256[]', - name: '_ratePerTierDiscountPoly' - },{ - type: 'uint256[]', - name: '_tokensPerTier' - },{ - type: 'uint256[]', - name: '_tokensPerTierDiscountPoly' - },{ - type: 'uint256', - name: '_nonAccreditedLimitUSD' - },{ - type: 'uint256', - name: '_minimumInvestmentUSD' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes' - },{ - type: 'address', - name: '_wallet' - },{ - type: 'address', - name: '_reserveWallet' - },{ - type: 'address', - name: '_usdToken' - }] - }; - - async function convert(_stoID, _tier, _discount, _currencyFrom, _currencyTo, _amount) { - let USDTOKEN; - if (_discount) - USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTierDiscountPoly.call(_tier); - else - USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTier.call(_tier); - if (_currencyFrom == "TOKEN") { - let tokenToUSD = _amount.div(10**18).mul(USDTOKEN.div(10**18)).mul(10**18); // TOKEN * USD/TOKEN = USD - if (_currencyTo == "USD") - return tokenToUSD; - if (_currencyTo == "ETH") { - return await I_USDTieredSTO_Array[_stoID].convertFromUSD(ETH, tokenToUSD); - } else if (_currencyTo == "POLY") { - return await I_USDTieredSTO_Array[_stoID].convertFromUSD(POLY, tokenToUSD); - } - } - if (_currencyFrom == "USD") { - if (_currencyTo == "TOKEN") - return _amount.div(USDTOKEN).mul(10**18); // USD / USD/TOKEN = TOKEN - if (_currencyTo == "ETH" || _currencyTo == "POLY") - return await I_USDTieredSTO_Array[_stoID].convertFromUSD((_currencyTo == "ETH" ? ETH : POLY), _amount); - } - if (_currencyFrom == "ETH" || _currencyFrom == "POLY") { - let ethToUSD = await I_USDTieredSTO_Array[_stoID].convertToUSD((_currencyTo == "ETH" ? ETH : POLY), _amount); - if (_currencyTo == "USD") - return ethToUSD; - if (_currencyTo == "TOKEN") - return ethToUSD.div(USDTOKEN).mul(10**18); // USD / USD/TOKEN = TOKEN - } - return 0; - } - - before(async() => { - // Accounts setup - POLYMATH = accounts[0]; - ISSUER = accounts[1]; - WALLET = accounts[2]; - RESERVEWALLET = WALLET; - ACCREDITED1 = accounts[3]; - ACCREDITED2 = accounts[4]; - NONACCREDITED1 = accounts[5]; - NONACCREDITED2 = accounts[6]; - INVESTOR1 = accounts[7]; - INVESTOR2 = accounts[8]; - INVESTOR3 = accounts[9]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - I_DaiToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: POLYMATH - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 3: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 4: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the proxy - I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); - - // STEP 6: Deploy the USDTieredSTOFactory - - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); - - assert.notEqual( - I_USDTieredSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "USDTieredSTOFactory contract was not deployed" - ); - - // Step 8: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); - await I_MRProxied.updateFromRegistry({from: POLYMATH}); - - - // STEP 7: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); - - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); - await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); - - // Step 12: Deploy & Register Mock Oracles - I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY - I_POLYOracle = await MockOracle.new(I_PolyToken.address, "POLY", "USD", USDPOLY, { from: POLYMATH }); // 25 cents per POLY - await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); - await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - USDOracle: ${I_USDOracle.address} - POLYOracle: ${I_POLYOracle.address} - USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} - USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.getTokens(REGFEE, ISSUER); - await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); - let tx = await I_STRProxied.registerTicker(ISSUER, SYMBOL, NAME, { from : ISSUER }); - assert.equal(tx.logs[0].args._owner, ISSUER); - assert.equal(tx.logs[0].args._ticker, SYMBOL); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.getTokens(REGFEE, ISSUER); - await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); - assert.equal(tx.logs[1].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), TMKEY); - assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - }); - - describe("Test sto deployment", async() => { - - it("Should successfully attach the first STO module to the security token", async () => { - let stoId = 0; // No discount - - _startTime.push(latestTime() + duration.days(2)); - _endTime.push(_startTime[stoId] + duration.days(100)); - _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] - _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(15*10**16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] - _tokensPerTierTotal.push([BigNumber(100000000).mul(BigNumber(10**18)), BigNumber(200000000).mul(BigNumber(10**18))]); // [ 100m Token, 200m Token ] - _tokensPerTierDiscountPoly.push([BigNumber(0),BigNumber(0)]); // [ 0, 0 ] - _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); // 10k USD - _minimumInvestmentUSD.push(BigNumber(5*10**18)); // 5 USD - _fundRaiseTypes.push([0, 1, 2]); - _wallet.push(WALLET); - _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address); - - let config = [ - _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], - _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], - _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] - ]; - - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); - console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); - I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); - - assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); - for (var i = 0; i < _ratePerTier[stoId].length; i++) { - assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); - } - assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].usdToken.call()), _usdToken[stoId], "Incorrect _usdToken in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].getNumberOfTiers()), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); - assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); - }); - - it("Should successfully attach the second STO module to the security token", async () => { - let stoId = 1; // No discount - - _startTime.push(latestTime() + duration.days(2)); - _endTime.push(_startTime[stoId] + duration.days(100)); - _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16)]); - _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16)]); - _tokensPerTierTotal.push([BigNumber(5*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(50*10**18)]); - _tokensPerTierDiscountPoly.push([BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0)]); - _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); - _minimumInvestmentUSD.push(BigNumber(0)); - _fundRaiseTypes.push([0, 1, 2]); - _wallet.push(WALLET); - _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address); - - let config = [ - _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], - _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], - _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] - ]; - - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); - console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); - I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); - - assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); - for (var i = 0; i < _ratePerTier[stoId].length; i++) { - assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); - } - assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].usdToken.call()), _usdToken[stoId], "Incorrect _usdToken in config"); - assert.equal(await I_USDTieredSTO_Array[stoId].getNumberOfTiers(), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); - assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); - }); - - it("Should successfully attach the third STO module to the security token", async () => { - let stoId = 2; // Poly discount - - _startTime.push(latestTime() + duration.days(2)); - _endTime.push(_startTime[stoId] + duration.days(100)); - _ratePerTier.push([BigNumber(1*10**18), BigNumber(1.5*10**18)]); // [ 1 USD/Token, 1.5 USD/Token ] - _ratePerTierDiscountPoly.push([BigNumber(0.5*10**18), BigNumber(1*10**18)]); // [ 0.5 USD/Token, 1.5 USD/Token ] - _tokensPerTierTotal.push([BigNumber(100*10**18), BigNumber(50*10**18)]); // [ 100 Token, 50 Token ] - _tokensPerTierDiscountPoly.push([BigNumber(100*10**18),BigNumber(25*10**18)]); // [ 100 Token, 25 Token ] - _nonAccreditedLimitUSD.push(BigNumber(25*10**18)); // [ 25 USD ] - _minimumInvestmentUSD.push(BigNumber(5)); - _fundRaiseTypes.push([0, 1, 2]); - _wallet.push(WALLET); - _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address) - - let config = [ - _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], - _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], - _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] - ]; - - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); - console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); - I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); - }); - - it("Should successfully attach the fourth STO module to the security token", async () => { - let stoId = 3; - - _startTime.push(latestTime()+ duration.days(0.1)); - _endTime.push(_startTime[stoId] + duration.days(0.1)); - _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16)]); - _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(12*10**16)]); - _tokensPerTierTotal.push([BigNumber(100*10**18), BigNumber(200*10**18)]); - _tokensPerTierDiscountPoly.push([BigNumber(0),BigNumber(50*10**18)]); - _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); - _minimumInvestmentUSD.push(BigNumber(0)); - _fundRaiseTypes.push([0, 1, 2]); - _wallet.push(WALLET); - _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address); - - let config = [ - _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], - _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], - _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] - ]; - - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); - console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); - I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); - }); - - it("Should fail because rates and tier array of different length", async() => { - let stoId = 0; - - let ratePerTier = [10]; - let ratePerTierDiscountPoly = [10]; - let tokensPerTierTotal = [10]; - let tokensPerTierDiscountPoly = [10]; - let config = [ - [_startTime[stoId], _endTime[stoId], ratePerTier, _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], - [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], ratePerTierDiscountPoly, _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], - [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], tokensPerTierTotal, _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], - [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], tokensPerTierDiscountPoly, _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]] - ]; - for (var i = 0; i < config.length; i++) { - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config[i]); - let errorThrown = false; - try { - await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); - } catch(error) { - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, MESSAGE); - } - }); - - it("Should fail because rate of token should be greater than 0", async() => { - let stoId = 0; - - let ratePerTier = [BigNumber(10*10**16), BigNumber(0)]; - let config = [_startTime[stoId], _endTime[stoId], ratePerTier, _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let errorThrown = false; - try { - await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); - } catch(error) { - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, MESSAGE); - }); - - it("Should fail because Zero address is not permitted for wallet", async() => { - let stoId = 0; - - let wallet = "0x0000000000000000000000000000000000000000"; - let config = [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], wallet, _reserveWallet[stoId], _usdToken[stoId]]; - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let errorThrown = false; - try { - await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); - } catch(error) { - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, MESSAGE); - }); - - it("Should fail because Zero address is not permitted for reserveWallet", async() => { - let stoId = 0; - - let reserveWallet = "0x0000000000000000000000000000000000000000"; - let config = [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], reserveWallet]; - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let errorThrown = false; - try { - await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); - } catch(error) { - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, MESSAGE); - }); - - it("Should fail because end time before start time", async() => { - let stoId = 0; - - let startTime = latestTime() + duration.days(35); - let endTime = latestTime() + duration.days(1); - let config = [startTime, endTime, _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let errorThrown = false; - try { - await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); - } catch(error) { - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, MESSAGE); - }); - - it("Should fail because start time is in the past", async() => { - let stoId = 0; - - let startTime = latestTime() - duration.days(35); - let endTime = startTime + duration.days(50); - let config = [startTime, endTime, _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let errorThrown = false; - try { - await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); - } catch(error) { - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, MESSAGE); - }); - }); - - describe("Test modifying configuration", async() => { - - it("Should successfully change config before startTime - funding", async() => { - let stoId = 3; - await I_USDTieredSTO_Array[stoId].modifyFunding([0], { from: ISSUER }); - assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),true,"STO Configuration doesn't set as expected"); - assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),false,"STO Configuration doesn't set as expected"); - - await I_USDTieredSTO_Array[stoId].modifyFunding([1], { from: ISSUER }); - assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),false,"STO Configuration doesn't set as expected"); - assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),true,"STO Configuration doesn't set as expected"); - - await I_USDTieredSTO_Array[stoId].modifyFunding([0,1], { from: ISSUER }); - assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),true,"STO Configuration doesn't set as expected"); - assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),true,"STO Configuration doesn't set as expected"); - - - }); - - it("Should successfully change config before startTime - limits and tiers, times, addresses", async() => { - let stoId = 3; - - await I_USDTieredSTO_Array[stoId].modifyLimits(BigNumber(1*10**18), BigNumber(15*10**18), { from: ISSUER }); - assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(),BigNumber(15*10**18).toNumber(),"STO Configuration doesn't set as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(),BigNumber(1*10**18).toNumber(),"STO Configuration doesn't set as expected"); - - await I_USDTieredSTO_Array[stoId].modifyTiers([BigNumber(15*10**18)], [BigNumber(13*10**18)], [BigNumber(15*10**20)], [BigNumber(15*10**20)], { from: ISSUER }); - assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(0)).toNumber(),BigNumber(15*10**18).toNumber(),"STO Configuration doesn't set as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(0)).toNumber(),BigNumber(13*10**18).toNumber(),"STO Configuration doesn't set as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(0)),BigNumber(15*10**20).toNumber(),"STO Configuration doesn't set as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(0)),BigNumber(15*10**20).toNumber(),"STO Configuration doesn't set as expected"); - - let tempTime1 = latestTime() + duration.days(0.1); - let tempTime2 = latestTime() + duration.days(0.2); - - await I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER }); - assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(),tempTime1,"STO Configuration doesn't set as expected"); - assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(),tempTime2,"STO Configuration doesn't set as expected"); - - await I_USDTieredSTO_Array[stoId].modifyAddresses("0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", "0x0000000000000000000000000000000000000000", { from: ISSUER }); - assert.equal(await I_USDTieredSTO_Array[stoId].wallet.call(),"0x0000000000000000000000000400000000000000","STO Configuration doesn't set as expected"); - assert.equal(await I_USDTieredSTO_Array[stoId].reserveWallet.call(),"0x0000000000000000000003000000000000000000","STO Configuration doesn't set as expected"); - assert.equal(await I_USDTieredSTO_Array[stoId].usdToken.call(),"0x0000000000000000000000000000000000000000","STO Configuration doesn't set as expected"); - }); - - it("Should fail to change config after endTime", async() => { - let stoId = 3; - - let snapId = await takeSnapshot(); - await increaseTime(duration.days(1)); - - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].modifyFunding([0,1], { from: ISSUER }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, MESSAGE); - - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].modifyLimits(BigNumber(15*10**18), BigNumber(1*10**18), { from: ISSUER }); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, MESSAGE); - - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].modifyTiers([BigNumber(15*10**18)], [BigNumber(13*10**18)], [BigNumber(15*10**20)], [BigNumber(15*10**20)], { from: ISSUER }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, MESSAGE); - - let tempTime1 = latestTime(); - let tempTime2 = latestTime() + duration.days(3); - - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER }); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, MESSAGE); - - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].modifyAddresses("0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", I_DaiToken.address, { from: ISSUER }); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, MESSAGE); - - await revertToSnapshot(snapId); - }); - }); - - describe("Test buying failure conditions", async() => { - - it("should fail if before STO start time", async() => { - let stoId = 0; - let snapId = await takeSnapshot(); - - assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - - // Whitelist - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); - let expiryTime = toTime + duration.days(100); - let whitelisted = true; - - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - - // // Advance time to after STO start - // await increaseTime(duration.days(3)); - - // Set as accredited - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - - // Prep for investments - let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH - let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY - await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); - await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - - // NONACCREDITED ETH - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - - // NONACCREDITED POLY - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - - // NONACCREDITED DAI - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, 'NONACCREDITED POLY investment succeeded when it should not'); - - // ACCREDITED ETH - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - - // ACCREDITED POLY - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - - // ACCREDITED DAI - let errorThrown6 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); - } catch(error) { - errorThrown6 = true; - ensureException(error); - } - assert.ok(errorThrown6, 'ACCREDITED POLY investment succeeded when it should not'); - - await revertToSnapshot(snapId); - }); - - it("should fail if not whitelisted", async() => { - let stoId = 0; - let snapId = await takeSnapshot(); - - // // Whitelist - // let fromTime = latestTime(); - // let toTime = latestTime() + duration.days(15); - // let expiryTime = toTime + duration.days(100); - // let whitelisted = true; - // - // await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - // await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - - // Advance time to after STO start - await increaseTime(duration.days(3)); - - // Set as accredited - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - - // Prep for investments - let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH - let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY - await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); - await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - - // NONACCREDITED ETH - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - - // NONACCREDITED POLY - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - - // NONACCREDITED DAI - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - - // ACCREDITED ETH - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - - // ACCREDITED POLY - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - - // ACCREDITED DAI - let errorThrown6 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); - } catch(error) { - errorThrown6 = true; - ensureException(error); - } - assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - - await revertToSnapshot(snapId); - }); - - it("should fail if minimumInvestmentUSD not met", async() => { - let stoId = 0; - let tierId = 0; - let snapId = await takeSnapshot(); - - // Whitelist - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); - let expiryTime = toTime + duration.days(100); - let whitelisted = true; - - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - - // Advance time to after STO start - await increaseTime(duration.days(3)); - - // Set as accredited - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - - let investment_USD = BigNumber(2).mul(10**18); - let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); - let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); - let investment_DAI = investment_USD; - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - - - await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); - await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - - // NONACCREDITED ETH - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - - // NONACCREDITED POLY - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - - // NONACCREDITED DAI - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - - // ACCREDITED ETH - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - - // ACCREDITED POLY - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - - // ACCREDITED DAI - let errorThrown6 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); - } catch(error) { - errorThrown6 = true; - ensureException(error); - } - assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - - await revertToSnapshot(snapId); - }); - - it("should successfully pause the STO and make investments fail, then unpause and succeed", async() => { - let stoId = 0; - let snapId = await takeSnapshot(); - - // Whitelist - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); - let expiryTime = toTime + duration.days(100); - let whitelisted = true; - - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - - // Advance time to after STO start - await increaseTime(duration.days(3)); - - // Set as accredited - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - - // Pause the STO - await I_USDTieredSTO_Array[stoId].pause({ from: ISSUER }); - assert.equal(await I_USDTieredSTO_Array[stoId].paused.call(), true, 'STO did not pause successfully'); - - // Prep for investments - let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH - let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - - let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY - await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); - await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - - // NONACCREDITED ETH - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - - // NONACCREDITED POLY - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - - // NONACCREDITED DAI - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - - // ACCREDITED ETH - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - - // ACCREDITED POLY - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - - - // ACCREDITED DAI - let errorThrown6 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); - } catch(error) { - errorThrown6 = true; - ensureException(error); - } - assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - - // Unpause the STO - await I_USDTieredSTO_Array[stoId].unpause({ from: ISSUER }); - assert.equal(await I_USDTieredSTO_Array[stoId].paused.call(), false, 'STO did not unpause successfully'); - - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); - await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); - - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); - await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); - - await revertToSnapshot(snapId); - }); - - it("should fail if after STO end time", async() => { - let stoId = 3; - let snapId = await takeSnapshot(); - - // Whitelist - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); - let expiryTime = toTime + duration.days(100); - let whitelisted = true; - - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - - // Advance time to after STO end - await increaseTime(duration.days(3)); - - assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - - // Set as accredited - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - - // Prep for investments - let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH - let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY - await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); - await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - - - // NONACCREDITED ETH - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - - // NONACCREDITED POLY - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - - // NONACCREDITED DAI - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - - // ACCREDITED ETH - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - - // ACCREDITED POLY - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - - // ACCREDITED DAI - let errorThrown6 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); - } catch(error) { - errorThrown6 = true; - ensureException(error); - } - assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - - await revertToSnapshot(snapId); - }); - - it("should fail if finalized", async() => { - let stoId = 0; - let snapId = await takeSnapshot(); - - // Whitelist - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(100); - let whitelisted = true; - - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(RESERVEWALLET, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - - // Advance time to after STO start - await increaseTime(duration.days(3)); - - // Set as accredited - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - - // Finalize STO - await I_USDTieredSTO_Array[stoId].finalize({ from: ISSUER }); - assert.equal(await I_USDTieredSTO_Array[stoId].isFinalized.call(), true, "STO has not been finalized"); - assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - - // Attempt to call function again - let errorThrown = false; - try { - await I_USDTieredSTO_Array[stoId].finalize({ from: ISSUER }); - } catch(error) { - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, 'STO was finalized a second time'); - - // Prep for investments - let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH - let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY - await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); - await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - - // NONACCREDITED ETH - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - - // NONACCREDITED POLY - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - - // NONACCREDITED DAI - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - - // ACCREDITED ETH - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - - // ACCREDITED POLY - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - - // ACCREDITED DAI - let errorThrown6 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); - } catch(error) { - errorThrown6 = true; - ensureException(error); - } - assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - - await revertToSnapshot(snapId); - }); - }); - - describe("Prep STO", async() => { - - it("should jump forward to after STO start", async() => { - let stoId = 0; - await increaseTime(duration.days(3)); - assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),true,"STO is not showing correct status"); - }); - - it("should whitelist ACCREDITED1 and NONACCREDITED1", async() => { - let stoId = 0; - - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); - let expiryTime = toTime + duration.days(100); - let whitelisted = true; - - const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - assert.equal(tx1.logs[0].args._investor, NONACCREDITED1, "Failed in adding the investor in whitelist"); - const tx2 = await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - assert.equal(tx2.logs[0].args._investor, ACCREDITED1, "Failed in adding the investor in whitelist"); - }); - - it("should successfully modify accredited addresses for first STO", async() => { - let stoId = 0; - - let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); - assert.equal(status1, false, "Initial accreditation is set to true"); - - await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1], [true], { from: ISSUER }); - let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); - assert.equal(status2, true, "Failed to set single address"); - - await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); - let status3 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); - assert.equal(status3, false, "Failed to set multiple addresses"); - let status4 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); - assert.equal(status4, true, "Failed to set multiple addresses"); - - let errorThrown = false; - try { - await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [true], { from: ISSUER }); - } catch(error) { - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, "Set accreditation despite input array of different size"); - }); - - it("should successfully modify accredited addresses for second STO", async() => { - let stoId = 1; - - await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); - let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); - let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); - assert.equal(status1, false, "Failed to set multiple address"); - assert.equal(status2, true, "Failed to set multiple address"); - }); - }); - - describe("Buy Tokens with no discount", async() => { - - it("should successfully buy using fallback at tier 0 for NONACCREDITED1", async() => { - let stoId = 0; - let tierId = 0; - - let investment_Token = BigNumber(50).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await web3.eth.sendTransaction({ from: NONACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); - console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), "Raised USD not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional checks on getters - assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 1, "Investor count not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), investment_Token.toNumber(), "getTokensSold not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), investment_Token.toNumber(), "getTokensMinted not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), investment_Token.toNumber(), "getTokensSoldForETH not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), 0, "getTokensSoldForPOLY not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), investment_USD.toNumber(), "investorInvestedUSD not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), investment_ETH.toNumber(), "investorInvestedETH not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), 0, "investorInvestedPOLY not changed as expected"); - }); - - it("should successfully buy using buyWithETH at tier 0 for NONACCREDITED1", async() => { - let stoId = 0; - let tierId = 0; - - let investment_Token = BigNumber(50).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised DAI not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should successfully buy using buyWithPOLY at tier 0 for NONACCREDITED1", async() => { - let stoId = 0; - let tierId = 0; - - let investment_Token = BigNumber(50).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - // Buy With POLY - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should successfully buy using buyWithUSD at tier 0 for NONACCREDITED1", async() => { - let stoId = 0; - let tierId = 0; - - let investment_Token = BigNumber(50).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - let investment_DAI = investment_USD; - - await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_InvestorDAIBal = await I_DaiToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - - // Buy With DAI - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithUSD: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_InvestorDAIBal = await I_DaiToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), "Investor DAI Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - assert.equal(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), "Wallet DAI Balance not changed as expected"); - }); - - it("should successfully buy using fallback at tier 0 for ACCREDITED1", async() => { - let stoId = 0; - let tierId = 0; - - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - - let investment_Token = BigNumber(50).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await web3.eth.sendTransaction({ from: ACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); - console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should successfully buy using buyWithETH at tier 0 for ACCREDITED1", async() => { - let stoId = 0; - let tierId = 0; - - let investment_Token = BigNumber(50).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should successfully buy using buyWithPOLY at tier 0 for ACCREDITED1", async() => { - let stoId = 0; - let tierId = 0; - - let investment_Token = BigNumber(50).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - - // Additional checks on getters - let init_getTokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_getTokensMinted = await I_USDTieredSTO_Array[stoId].getTokensMinted(); - let init_getTokensSoldForETH = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH); - let init_getTokensSoldForPOLY = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY); - let init_investorInvestedUSD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1); - let init_investorInvestedETH = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH); - let init_investorInvestedPOLY = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - // Buy With POLY - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional checks on getters - assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 2, "Investor count not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), init_getTokensSold.add(investment_Token).toNumber(), "getTokensSold not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), init_getTokensMinted.add(investment_Token).toNumber(), "getTokensMinted not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), init_getTokensSoldForETH.toNumber(), "getTokensSoldForETH not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), init_getTokensSoldForPOLY.add(investment_Token).toNumber(), "getTokensSoldForPOLY not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), init_investorInvestedUSD.add(investment_USD).toNumber(), "investorInvestedUSD not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), init_investorInvestedETH.toNumber(), "investorInvestedETH not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), init_investorInvestedPOLY.add(investment_POLY).toNumber(), "investorInvestedPOLY not changed as expected"); - }); - - it("should successfully modify NONACCREDITED cap for NONACCREDITED1", async() => { - let stoId = 0; - let tierId = 0; - console.log("Current investment: " + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber()); - await I_USDTieredSTO_Array[stoId].changeNonAccreditedLimit([NONACCREDITED1], [_nonAccreditedLimitUSD[stoId].div(2)], {from: ISSUER}); - console.log("Current limit: " + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1)).toNumber()); - }); - - it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async() => { - let stoId = 0; - let tierId = 0; - - let investment_USD = (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1));//_nonAccreditedLimitUSD[stoId]; - let investment_Token = await convert(stoId, tierId, false, "USD", "TOKEN", investment_USD); - let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); - let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); - - let refund_USD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); - let refund_Token = await convert(stoId, tierId, false, "USD", "TOKEN", refund_USD); - let refund_ETH = await convert(stoId, tierId, false, "USD", "ETH", refund_USD); - let refund_POLY = await convert(stoId, tierId, false, "USD", "POLY", refund_USD); - - console.log("Expected refund in tokens: " + refund_Token.toNumber()); - - let snap = await takeSnapshot(); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - // Buy with ETH - let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).add(refund_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).sub(refund_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).sub(refund_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - - await revertToSnapshot(snap); - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - - init_TokenSupply = await I_SecurityToken.totalSupply(); - init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - // Buy With POLY - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - final_TokenSupply = await I_SecurityToken.totalSupply(); - final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).add(refund_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).sub(refund_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).sub(refund_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should fail and revert when NONACCREDITED cap reached", async() => { - let stoId = 0; - let tierId = 0; - - let investment_Token = BigNumber(50).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1, gasPrice: GAS_PRICE}); - - // Buy with ETH NONACCREDITED - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, MESSAGE); - }); - - it("should fail and revert despite oracle price change when NONACCREDITED cap reached", async() => { - let stoId = 0; - let tierId; - - // set new exchange rates - let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH - let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY - let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH - let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY - - let investment_USD = BigNumber(web3.utils.toWei('50')); // USD - let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH - let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH - let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - - await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); - - // Change exchange rates up - await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); - - // Buy with ETH NONACCREDITED - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, MESSAGE); - - // Change exchange rates down - await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); - - // Buy with ETH NONACCREDITED - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, MESSAGE); - - // Reset exchange rates - await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); - }); - - it("should successfully buy across tiers for NONACCREDITED ETH", async() => { - let stoId = 1; - let startTier = 0; - let endTier = 1; - - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - - let delta_Token = BigNumber(5).mul(10**18); - let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); - let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); - - let investment_Token = delta_Token.add(delta_Token); // 10 Token - let investment_ETH = ethTier0.add(ethTier1); // 0.0025 ETH - - // Process investment - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional Checks - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); - }); - - it("should successfully buy across tiers for NONACCREDITED POLY", async() => { - let stoId = 1; - let startTier = 1; - let endTier = 2; - - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - - let delta_Token = BigNumber(5).mul(10**18); // Token - let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); - let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); - - let investment_Token = delta_Token.add(delta_Token); // 10 Token - let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - - // Process investment - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional Checks - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); - }); - - it("should successfully buy across tiers for ACCREDITED ETH", async() => { - let stoId = 1; - let startTier = 2; - let endTier = 3; - - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - - let delta_Token = BigNumber(5).mul(10**18); // Token - let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); - let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); - - let investment_Token = delta_Token.add(delta_Token); // 10 Token - let investment_ETH = ethTier0.add(ethTier1); // 0.0025 ETH - - // Process investment - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional Checks - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); - }); - - it("should successfully buy across tiers for ACCREDITED DAI", async() => { - - let stoId = 1; - let startTier = 3; - let endTier = 4; - - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - - let delta_Token = BigNumber(5).mul(10**18); // Token - let daiTier0 = await convert(stoId, startTier, false, "TOKEN", "USD", delta_Token); - let daiTier1 = await convert(stoId, endTier, false, "TOKEN", "USD", delta_Token); - - let investment_Token = delta_Token.add(delta_Token); // 10 Token - let investment_DAI = daiTier0.add(daiTier1); - - await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - - // Process investment - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_InvestorDAIBal = await I_DaiToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithUSD: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_InvestorDAIBal = await I_DaiToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), "Raised DAI not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - assert.equal(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional Checks - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); - - }); - - it("should successfully buy across tiers for ACCREDITED POLY", async() => { - let stoId = 1; - let startTier = 4; - let endTier = 5; - - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - - let delta_Token = BigNumber(5).mul(10**18); // Token - let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); - let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); - - let investment_Token = delta_Token.add(delta_Token); // 10 Token - let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH - - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - - // Process investment - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional Checks - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); - }); - - it("should buy out the rest of the sto", async() => { - let stoId = 1; - let tierId = 5; - - let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); - console.log(minted.toNumber() + ":"+ _tokensPerTierTotal[stoId][tierId]); - let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); - console.log(investment_Token.toNumber()); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - - let tx = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - console.log(" Gas buyWithETH: ".grey+tx.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - // assert.equal((await I_USDTieredSTO_Array[1].getTokensMinted()).toNumber(), _tokensPerTierTotal[1].reduce((a, b) => a + b, 0).toNumber(), "STO Token Sold not changed as expected"); - }); - - it("should fail and revert when all tiers sold out", async() => { - let stoId = 1; - let tierId = 4; - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - let investment_DAI = investment_USD; - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - - await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - - assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - - // Buy with ETH NONACCREDITED - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, MESSAGE); - - // Buy with DAI NONACCREDITED - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, MESSAGE); - - // Buy with ETH ACCREDITED - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, MESSAGE); - - // Buy with POLY ACCREDITED - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, MESSAGE); - - // Buy with DAI ACCREDITED - let errorThrown6 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown6 = true; - ensureException(error); - } - assert.ok(errorThrown6, MESSAGE); - }); - - it("should fail and revert when all tiers sold out despite oracle price change", async() => { - let stoId = 1; - let tierId = 4; - - // set new exchange rates - let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH - let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY - let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH - let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY - - let investment_USD = BigNumber(web3.utils.toWei('50')); // USD - let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH - let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH - let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - - await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); - await I_PolyToken.getTokens(investment_POLY_low, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: ACCREDITED1}); - - // Change exchange rates up - await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); - - // Buy with ETH NONACCREDITED - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, MESSAGE); - - // Buy with ETH ACCREDITED - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, MESSAGE); - - // Buy with POLY ACCREDITED - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_high, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, MESSAGE); - - // Change exchange rates down - await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); - - // Buy with ETH NONACCREDITED - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown6 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown6 = true; - ensureException(error); - } - assert.ok(errorThrown6, MESSAGE); - - // Buy with ETH ACCREDITED - let errorThrown7 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown7 = true; - ensureException(error); - } - assert.ok(errorThrown7, MESSAGE); - - // Buy with POLY ACCREDITED - let errorThrown8 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_low, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown8 = true; - ensureException(error); - } - assert.ok(errorThrown8, MESSAGE); - - // Reset exchange rates - await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); - }); - }); - - describe("Buy Tokens with POLY discount", async() => { - - it("should successfully buy using fallback at tier 0 for NONACCREDITED1", async() => { - let stoId = 2; - let tierId = 0; - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await web3.eth.sendTransaction({ from: NONACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); - console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), "Raised USD not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional checks on getters - assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 1, "Investor count not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), investment_Token.toNumber(), "getTokensSold not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), investment_Token.toNumber(), "getTokensMinted not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), investment_Token.toNumber(), "getTokensSoldForETH not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), 0, "getTokensSoldForPOLY not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), investment_USD.toNumber(), "investorInvestedUSD not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), investment_ETH.toNumber(), "investorInvestedETH not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), 0, "investorInvestedPOLY not changed as expected"); - }); - - it("should successfully buy using buyWithETH at tier 0 for NONACCREDITED1", async() => { - let stoId = 2; - let tierId = 0; - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should successfully buy using buyWithPOLY at tier 0 for NONACCREDITED1", async() => { - let stoId = 2; - let tierId = 0; - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - // Buy With POLY - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should successfully buy using fallback at tier 0 for ACCREDITED1", async() => { - let stoId = 2; - let tierId = 0; - - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await web3.eth.sendTransaction({ from: ACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); - console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should successfully buy using buyWithETH at tier 0 for ACCREDITED1", async() => { - let stoId = 2; - let tierId = 0; - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should successfully buy using buyWithPOLY at tier 0 for ACCREDITED1", async() => { - let stoId = 2; - let tierId = 0; - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); - - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - - // Additional checks on getters - let init_getTokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_getTokensMinted = await I_USDTieredSTO_Array[stoId].getTokensMinted(); - let init_getTokensSoldForETH = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH); - let init_getTokensSoldForPOLY = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY); - let init_investorInvestedUSD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1); - let init_investorInvestedETH = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH); - let init_investorInvestedPOLY = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - // Buy With POLY - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional checks on getters - assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 2, "Investor count not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), init_getTokensSold.add(investment_Token).toNumber(), "getTokensSold not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), init_getTokensMinted.add(investment_Token).toNumber(), "getTokensMinted not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), init_getTokensSoldForETH.toNumber(), "getTokensSoldForETH not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), init_getTokensSoldForPOLY.add(investment_Token).toNumber(), "getTokensSoldForPOLY not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), init_investorInvestedUSD.add(investment_USD).toNumber(), "investorInvestedUSD not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), init_investorInvestedETH.toNumber(), "investorInvestedETH not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), init_investorInvestedPOLY.add(investment_POLY).toNumber(), "investorInvestedPOLY not changed as expected"); - }); - - it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async() => { - let stoId = 2; - let tierId = 0; - - let investment_USD = _nonAccreditedLimitUSD[stoId]; - let investment_Token = await convert(stoId, tierId, true, "USD", "TOKEN", investment_USD); - let investment_ETH = await convert(stoId, tierId, true, "USD", "ETH", investment_USD); - let investment_POLY = await convert(stoId, tierId, true, "USD", "POLY", investment_USD); - - let refund_USD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); - let refund_Token = await convert(stoId, tierId, true, "USD", "TOKEN", refund_USD); - let refund_ETH = await convert(stoId, tierId, true, "USD", "ETH", refund_USD); - let refund_POLY = await convert(stoId, tierId, true, "USD", "POLY", refund_USD); - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - // Buy With POLY - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).add(refund_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).sub(refund_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).sub(refund_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should fail and revert when NONACCREDITED cap reached", async() => { - let stoId = 2; - let tierId = 0; - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1, gasPrice: GAS_PRICE}); - - // Buy with ETH NONACCREDITED - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, MESSAGE); - }); - - it("should fail and revert despite oracle price change when NONACCREDITED cap reached", async() => { - let stoId = 2; - let tierId = 0; - - // set new exchange rates - let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH - let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY - let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH - let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); - - let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH - let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH - let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - - await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); - - // Change exchange rates up - await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); - - // Buy with ETH NONACCREDITED - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, MESSAGE); - - // Change exchange rates down - await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); - - // Buy with ETH NONACCREDITED - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, MESSAGE); - - // Reset exchange rates - await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); - }); - - it("should successfully buy across tiers for POLY", async() => { - let stoId = 2; - let startTier = 0; - let endTier = 1; - - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - - let delta_Token = BigNumber(5).mul(10**18); // Token - let polyTier0 = await convert(stoId, startTier, true, "TOKEN", "POLY", delta_Token); - let polyTier1 = await convert(stoId, endTier, true, "TOKEN", "POLY", delta_Token); - let investment_Token = delta_Token.add(delta_Token); // 10 Token - let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH - - let tokensRemaining = (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier)); - let prep_Token = tokensRemaining.sub(delta_Token); - let prep_POLY = await convert(stoId, startTier, true, "TOKEN", "POLY", prep_Token); - - await I_PolyToken.getTokens(prep_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, prep_POLY, {from: ACCREDITED1}); - let tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, prep_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - console.log(" Gas buyWithPOLY: ".grey+tx.receipt.gasUsed.toString().grey); - - let Tier0Token = (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier)); - let Tier0Minted = (await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier)); - assert.equal(Tier0Minted.toNumber(), Tier0Token.sub(delta_Token).toNumber()); - - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - - // Process investment - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - - // Additional Checks - assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); - }); - - it("should successfully buy across the discount cap", async() => { - let stoId = 2; - let tierId = 1; - - let discount_Token = BigNumber(20).mul(10**18); - let discount_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", discount_Token); - - let regular_Token = BigNumber(10).mul(10**18); - let regular_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", regular_Token); - - let investment_Token = discount_Token.add(regular_Token); - let investment_POLY = discount_POLY.add(regular_POLY); - - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - // Buy With POLY - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); - assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); - assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); - assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); - assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - }); - - it("should buy out the rest of the sto", async() => { - let stoId = 2; - let tierId = 1; - - let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); - let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - - // Buy With POLY - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - - assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); - assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); - assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); - }); - - it("should fail and revert when all tiers sold out", async() => { - let stoId = 2; - let tierId = 1; - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); - let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - - await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - - assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - - // Buy with ETH NONACCREDITED - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, MESSAGE); - - // Buy with ETH ACCREDITED - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, MESSAGE); - - // Buy with POLY ACCREDITED - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, MESSAGE); - }); - - it("should fail and revert when all tiers sold out despite oracle price change", async() => { - let stoId = 2; - let tierId = 1; - - // set new exchange rates - let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH - let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY - let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH - let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY - - let investment_Token = BigNumber(5).mul(10**18); - let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); - - let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH - let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH - let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - - await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); - await I_PolyToken.getTokens(investment_POLY_low, ACCREDITED1); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: ACCREDITED1}); - - // Change exchange rates up - await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); - - // Buy with ETH NONACCREDITED - let errorThrown1 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown1 = true; - ensureException(error); - } - assert.ok(errorThrown1, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown2 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown2 = true; - ensureException(error); - } - assert.ok(errorThrown2, MESSAGE); - - // Buy with ETH ACCREDITED - let errorThrown3 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown3 = true; - ensureException(error); - } - assert.ok(errorThrown3, MESSAGE); - - // Buy with POLY ACCREDITED - let errorThrown4 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_high, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown4 = true; - ensureException(error); - } - assert.ok(errorThrown4, MESSAGE); - - // Change exchange rates down - await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); - - // Buy with ETH NONACCREDITED - let errorThrown5 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown5 = true; - ensureException(error); - } - assert.ok(errorThrown5, MESSAGE); - - // Buy with POLY NONACCREDITED - let errorThrown6 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown6 = true; - ensureException(error); - } - assert.ok(errorThrown6, MESSAGE); - - // Buy with ETH ACCREDITED - let errorThrown7 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown7 = true; - ensureException(error); - } - assert.ok(errorThrown7, MESSAGE); - - // Buy with POLY ACCREDITED - let errorThrown8 = false; - try { - await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_low, { from: ACCREDITED1, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown8 = true; - ensureException(error); - } - assert.ok(errorThrown8, MESSAGE); - - // Reset exchange rates - await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); - }); - }); - - describe("Test getter functions", async() => { - - describe("Generic", async() => { - - it("should get the right number of investors", async() => { - assert.equal((await I_USDTieredSTO_Array[0].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[0].investorCount()).toNumber(), "Investor count not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[1].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[1].investorCount()).toNumber(), "Investor count not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[2].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[2].investorCount()).toNumber(), "Investor count not changed as expected"); - }); - - it("should get the right amounts invested", async() => { - assert.equal((await I_USDTieredSTO_Array[0].fundsRaised.call(ETH)).toNumber(), (await I_USDTieredSTO_Array[0].getRaised(0)).toNumber(), "getRaisedEther not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[0].fundsRaised.call(POLY)).toNumber(), (await I_USDTieredSTO_Array[0].getRaised(1)).toNumber(), "getRaisedPOLY not changed as expected"); - assert.equal((await I_USDTieredSTO_Array[0].fundsRaisedUSD.call()).toNumber(), (await I_USDTieredSTO_Array[0].fundsRaisedUSD()).toNumber(), "fundsRaisedUSD not changed as expected"); - }); - }); - - describe("convertToUSD", async() => { - - it("should reset exchange rates", async() => { - // Reset exchange rates - await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); - await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); - }); - - it("should get the right conversion for ETH to USD", async() => { - // 20 ETH to 10000 USD - let ethInWei = BigNumber(web3.utils.toWei('20', 'ether')); - let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(ETH, ethInWei); - assert.equal(usdInWei.div(10**18).toNumber(), ethInWei.div(10**18).mul(USDETH.div(10**18)).toNumber()); - }); - - it("should get the right conversion for POLY to USD", async() => { - // 40000 POLY to 10000 USD - let polyInWei = BigNumber(web3.utils.toWei('40000', 'ether')); - let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(POLY, polyInWei); - assert.equal(usdInWei.div(10**18).toNumber(), polyInWei.div(10**18).mul(USDPOLY.div(10**18)).toNumber()); - }); - }); - - describe("convertFromUSD", async() => { - - it("should get the right conversion for USD to ETH", async() => { - // 10000 USD to 20 ETH - let usdInWei = BigNumber(web3.utils.toWei('10000', 'ether')); - let ethInWei = await I_USDTieredSTO_Array[0].convertFromUSD(ETH, usdInWei); - assert.equal(ethInWei.div(10**18).toNumber(), usdInWei.div(10**18).div(USDETH.div(10**18)).toNumber()); - }); - - it("should get the right conversion for USD to POLY", async() => { - // 10000 USD to 40000 POLY - let usdInWei = BigNumber(web3.utils.toWei('10000', 'ether')); - let polyInWei = await I_USDTieredSTO_Array[0].convertFromUSD(POLY, usdInWei); - assert.equal(polyInWei.div(10**18).toNumber(), usdInWei.div(10**18).div(USDPOLY.div(10**18)).toNumber()); - }); - }); - }); - - describe("Test cases for the USDTieredSTOFactory", async() => { - it("should get the exact details of the factory", async() => { - assert.equal((await I_USDTieredSTOFactory.setupCost.call()).toNumber(), STOSetupCost); - assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0],3); - assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), - "USDTieredSTO", - "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.getDescription.call(), - "USD Tiered STO", - "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.getTitle.call(), - "USD Tiered STO", - "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.getInstructions.call(), - "Initialises a USD tiered STO.", - "Wrong Module added"); - let tags = await I_USDTieredSTOFactory.getTags.call(); - assert.equal(web3.utils.hexToString(tags[0]),"USD"); - assert.equal(web3.utils.hexToString(tags[1]),"Tiered"); - assert.equal(web3.utils.hexToString(tags[2]),"POLY"); - assert.equal(web3.utils.hexToString(tags[3]),"ETH"); - - }); - }); -}); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); +// const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); +// const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); +// const MockOracle = artifacts.require('./MockOracle.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port + +// contract('USDTieredSTO', accounts => { +// // Accounts Variable declaration +// let POLYMATH; +// let ISSUER; +// let WALLET; +// let RESERVEWALLET; +// let INVESTOR1; +// let INVESTOR2; +// let INVESTOR3; +// let INVESTOR4; +// let ACCREDITED1; +// let ACCREDITED2; +// let NONACCREDITED1; +// let NONACCREDITED2; +// let ETH = 0; +// let POLY = 1; +// let DAI = 2; + +// let MESSAGE = "Transaction Should Fail!"; +// const GAS_PRICE = 0; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let I_USDTieredSTOProxyFactory; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistry; +// let I_ModuleRegistryProxy; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_USDTieredSTOFactory; +// let I_USDOracle; +// let I_POLYOracle; +// let I_STFactory; +// let I_SecurityToken; +// let I_STRProxied; +// let I_MRProxied; +// let I_USDTieredSTO_Array = []; +// let I_PolyToken; +// let I_DaiToken; +// let I_PolymathRegistry; + +// // SecurityToken Details for funds raise Type ETH +// const NAME = "Team"; +// const SYMBOL = "SAP"; +// const TOKENDETAILS = "This is equity type of issuance"; +// const DECIMALS = 18; + +// // Module key +// const TMKEY = 2; +// const STOKEY = 3; + +// // Initial fee for ticker registry and security token registry +// const REGFEE = web3.utils.toWei("250"); +// const STOSetupCost = 0; + +// // MockOracle USD prices +// const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH +// const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY + +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// // STO Configuration Arrays +// let _startTime = []; +// let _endTime = []; +// let _ratePerTier = []; +// let _ratePerTierDiscountPoly = []; +// let _tokensPerTierTotal = []; +// let _tokensPerTierDiscountPoly = []; +// let _nonAccreditedLimitUSD = []; +// let _minimumInvestmentUSD = []; +// let _fundRaiseTypes = []; +// let _wallet = []; +// let _reserveWallet = []; +// let _usdToken = []; + +// /* function configure( +// uint256 _startTime, +// uint256 _endTime, +// uint256[] _ratePerTier, +// uint256[] _ratePerTierDiscountPoly, +// uint256[] _tokensPerTier, +// uint256[] _tokensPerTierDiscountPoly, +// uint256 _nonAccreditedLimitUSD, +// uint256 _minimumInvestmentUSD, +// uint8[] _fundRaiseTypes, +// address _wallet, +// address _reserveWallet, +// address _usdToken +// ) */ +// const functionSignature = { +// name: 'configure', +// type: 'function', +// inputs: [{ +// type: 'uint256', +// name: '_startTime' +// },{ +// type: 'uint256', +// name: '_endTime' +// },{ +// type: 'uint256[]', +// name: '_ratePerTier' +// },{ +// type: 'uint256[]', +// name: '_ratePerTierDiscountPoly' +// },{ +// type: 'uint256[]', +// name: '_tokensPerTier' +// },{ +// type: 'uint256[]', +// name: '_tokensPerTierDiscountPoly' +// },{ +// type: 'uint256', +// name: '_nonAccreditedLimitUSD' +// },{ +// type: 'uint256', +// name: '_minimumInvestmentUSD' +// },{ +// type: 'uint8[]', +// name: '_fundRaiseTypes' +// },{ +// type: 'address', +// name: '_wallet' +// },{ +// type: 'address', +// name: '_reserveWallet' +// },{ +// type: 'address', +// name: '_usdToken' +// }] +// }; + +// async function convert(_stoID, _tier, _discount, _currencyFrom, _currencyTo, _amount) { +// let USDTOKEN; +// if (_discount) +// USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTierDiscountPoly.call(_tier); +// else +// USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTier.call(_tier); +// if (_currencyFrom == "TOKEN") { +// let tokenToUSD = _amount.div(10**18).mul(USDTOKEN.div(10**18)).mul(10**18); // TOKEN * USD/TOKEN = USD +// if (_currencyTo == "USD") +// return tokenToUSD; +// if (_currencyTo == "ETH") { +// return await I_USDTieredSTO_Array[_stoID].convertFromUSD(ETH, tokenToUSD); +// } else if (_currencyTo == "POLY") { +// return await I_USDTieredSTO_Array[_stoID].convertFromUSD(POLY, tokenToUSD); +// } +// } +// if (_currencyFrom == "USD") { +// if (_currencyTo == "TOKEN") +// return _amount.div(USDTOKEN).mul(10**18); // USD / USD/TOKEN = TOKEN +// if (_currencyTo == "ETH" || _currencyTo == "POLY") +// return await I_USDTieredSTO_Array[_stoID].convertFromUSD((_currencyTo == "ETH" ? ETH : POLY), _amount); +// } +// if (_currencyFrom == "ETH" || _currencyFrom == "POLY") { +// let ethToUSD = await I_USDTieredSTO_Array[_stoID].convertToUSD((_currencyTo == "ETH" ? ETH : POLY), _amount); +// if (_currencyTo == "USD") +// return ethToUSD; +// if (_currencyTo == "TOKEN") +// return ethToUSD.div(USDTOKEN).mul(10**18); // USD / USD/TOKEN = TOKEN +// } +// return 0; +// } + +// before(async() => { +// // Accounts setup +// POLYMATH = accounts[0]; +// ISSUER = accounts[1]; +// WALLET = accounts[2]; +// RESERVEWALLET = WALLET; +// ACCREDITED1 = accounts[3]; +// ACCREDITED2 = accounts[4]; +// NONACCREDITED1 = accounts[5]; +// NONACCREDITED2 = accounts[6]; +// INVESTOR1 = accounts[7]; +// INVESTOR2 = accounts[8]; +// INVESTOR3 = accounts[9]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// I_DaiToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: POLYMATH +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 3: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the proxy +// I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); + +// // STEP 6: Deploy the USDTieredSTOFactory + +// I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); + +// assert.notEqual( +// I_USDTieredSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "USDTieredSTOFactory contract was not deployed" +// ); + +// // Step 8: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 9: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); +// await I_MRProxied.updateFromRegistry({from: POLYMATH}); + + +// // STEP 7: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); + +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); +// await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); + +// // Step 12: Deploy & Register Mock Oracles +// I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY +// I_POLYOracle = await MockOracle.new(I_PolyToken.address, "POLY", "USD", USDPOLY, { from: POLYMATH }); // 25 cents per POLY +// await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); +// await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// USDOracle: ${I_USDOracle.address} +// POLYOracle: ${I_POLYOracle.address} +// USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} +// USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.getTokens(REGFEE, ISSUER); +// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); +// let tx = await I_STRProxied.registerTicker(ISSUER, SYMBOL, NAME, { from : ISSUER }); +// assert.equal(tx.logs[0].args._owner, ISSUER); +// assert.equal(tx.logs[0].args._ticker, SYMBOL); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.getTokens(REGFEE, ISSUER); +// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); +// assert.equal(tx.logs[1].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), TMKEY); +// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); +// }); + +// describe("Test sto deployment", async() => { + +// it("Should successfully attach the first STO module to the security token", async () => { +// let stoId = 0; // No discount + +// _startTime.push(latestTime() + duration.days(2)); +// _endTime.push(_startTime[stoId] + duration.days(100)); +// _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] +// _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(15*10**16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] +// _tokensPerTierTotal.push([BigNumber(100000000).mul(BigNumber(10**18)), BigNumber(200000000).mul(BigNumber(10**18))]); // [ 100m Token, 200m Token ] +// _tokensPerTierDiscountPoly.push([BigNumber(0),BigNumber(0)]); // [ 0, 0 ] +// _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); // 10k USD +// _minimumInvestmentUSD.push(BigNumber(5*10**18)); // 5 USD +// _fundRaiseTypes.push([0, 1, 2]); +// _wallet.push(WALLET); +// _reserveWallet.push(RESERVEWALLET); +// _usdToken.push(I_DaiToken.address); + +// let config = [ +// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], +// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], +// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] +// ]; + +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); +// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); +// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); +// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + +// assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); +// for (var i = 0; i < _ratePerTier[stoId].length; i++) { +// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); +// } +// assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].usdToken.call()), _usdToken[stoId], "Incorrect _usdToken in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getNumberOfTiers()), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); +// }); + +// it("Should successfully attach the second STO module to the security token", async () => { +// let stoId = 1; // No discount + +// _startTime.push(latestTime() + duration.days(2)); +// _endTime.push(_startTime[stoId] + duration.days(100)); +// _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16)]); +// _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16)]); +// _tokensPerTierTotal.push([BigNumber(5*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(50*10**18)]); +// _tokensPerTierDiscountPoly.push([BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0)]); +// _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); +// _minimumInvestmentUSD.push(BigNumber(0)); +// _fundRaiseTypes.push([0, 1, 2]); +// _wallet.push(WALLET); +// _reserveWallet.push(RESERVEWALLET); +// _usdToken.push(I_DaiToken.address); + +// let config = [ +// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], +// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], +// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] +// ]; + +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); +// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); +// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); +// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + +// assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); +// for (var i = 0; i < _ratePerTier[stoId].length; i++) { +// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); +// } +// assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].usdToken.call()), _usdToken[stoId], "Incorrect _usdToken in config"); +// assert.equal(await I_USDTieredSTO_Array[stoId].getNumberOfTiers(), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); +// }); + +// it("Should successfully attach the third STO module to the security token", async () => { +// let stoId = 2; // Poly discount + +// _startTime.push(latestTime() + duration.days(2)); +// _endTime.push(_startTime[stoId] + duration.days(100)); +// _ratePerTier.push([BigNumber(1*10**18), BigNumber(1.5*10**18)]); // [ 1 USD/Token, 1.5 USD/Token ] +// _ratePerTierDiscountPoly.push([BigNumber(0.5*10**18), BigNumber(1*10**18)]); // [ 0.5 USD/Token, 1.5 USD/Token ] +// _tokensPerTierTotal.push([BigNumber(100*10**18), BigNumber(50*10**18)]); // [ 100 Token, 50 Token ] +// _tokensPerTierDiscountPoly.push([BigNumber(100*10**18),BigNumber(25*10**18)]); // [ 100 Token, 25 Token ] +// _nonAccreditedLimitUSD.push(BigNumber(25*10**18)); // [ 25 USD ] +// _minimumInvestmentUSD.push(BigNumber(5)); +// _fundRaiseTypes.push([0, 1, 2]); +// _wallet.push(WALLET); +// _reserveWallet.push(RESERVEWALLET); +// _usdToken.push(I_DaiToken.address) + +// let config = [ +// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], +// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], +// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] +// ]; + +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); +// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); +// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); +// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); +// }); + +// it("Should successfully attach the fourth STO module to the security token", async () => { +// let stoId = 3; + +// _startTime.push(latestTime()+ duration.days(0.1)); +// _endTime.push(_startTime[stoId] + duration.days(0.1)); +// _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16)]); +// _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(12*10**16)]); +// _tokensPerTierTotal.push([BigNumber(100*10**18), BigNumber(200*10**18)]); +// _tokensPerTierDiscountPoly.push([BigNumber(0),BigNumber(50*10**18)]); +// _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); +// _minimumInvestmentUSD.push(BigNumber(0)); +// _fundRaiseTypes.push([0, 1, 2]); +// _wallet.push(WALLET); +// _reserveWallet.push(RESERVEWALLET); +// _usdToken.push(I_DaiToken.address); + +// let config = [ +// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], +// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], +// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] +// ]; + +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); +// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); +// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); +// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); +// }); + +// it("Should fail because rates and tier array of different length", async() => { +// let stoId = 0; + +// let ratePerTier = [10]; +// let ratePerTierDiscountPoly = [10]; +// let tokensPerTierTotal = [10]; +// let tokensPerTierDiscountPoly = [10]; +// let config = [ +// [_startTime[stoId], _endTime[stoId], ratePerTier, _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], +// [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], ratePerTierDiscountPoly, _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], +// [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], tokensPerTierTotal, _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], +// [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], tokensPerTierDiscountPoly, _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]] +// ]; +// for (var i = 0; i < config.length; i++) { +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config[i]); +// let errorThrown = false; +// try { +// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, MESSAGE); +// } +// }); + +// it("Should fail because rate of token should be greater than 0", async() => { +// let stoId = 0; + +// let ratePerTier = [BigNumber(10*10**16), BigNumber(0)]; +// let config = [_startTime[stoId], _endTime[stoId], ratePerTier, _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let errorThrown = false; +// try { +// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, MESSAGE); +// }); + +// it("Should fail because Zero address is not permitted for wallet", async() => { +// let stoId = 0; + +// let wallet = "0x0000000000000000000000000000000000000000"; +// let config = [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], wallet, _reserveWallet[stoId], _usdToken[stoId]]; +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let errorThrown = false; +// try { +// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, MESSAGE); +// }); + +// it("Should fail because Zero address is not permitted for reserveWallet", async() => { +// let stoId = 0; + +// let reserveWallet = "0x0000000000000000000000000000000000000000"; +// let config = [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], reserveWallet]; +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let errorThrown = false; +// try { +// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, MESSAGE); +// }); + +// it("Should fail because end time before start time", async() => { +// let stoId = 0; + +// let startTime = latestTime() + duration.days(35); +// let endTime = latestTime() + duration.days(1); +// let config = [startTime, endTime, _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let errorThrown = false; +// try { +// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, MESSAGE); +// }); + +// it("Should fail because start time is in the past", async() => { +// let stoId = 0; + +// let startTime = latestTime() - duration.days(35); +// let endTime = startTime + duration.days(50); +// let config = [startTime, endTime, _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let errorThrown = false; +// try { +// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, MESSAGE); +// }); +// }); + +// describe("Test modifying configuration", async() => { + +// it("Should successfully change config before startTime - funding", async() => { +// let stoId = 3; +// await I_USDTieredSTO_Array[stoId].modifyFunding([0], { from: ISSUER }); +// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),true,"STO Configuration doesn't set as expected"); +// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),false,"STO Configuration doesn't set as expected"); + +// await I_USDTieredSTO_Array[stoId].modifyFunding([1], { from: ISSUER }); +// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),false,"STO Configuration doesn't set as expected"); +// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),true,"STO Configuration doesn't set as expected"); + +// await I_USDTieredSTO_Array[stoId].modifyFunding([0,1], { from: ISSUER }); +// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),true,"STO Configuration doesn't set as expected"); +// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),true,"STO Configuration doesn't set as expected"); + + +// }); + +// it("Should successfully change config before startTime - limits and tiers, times, addresses", async() => { +// let stoId = 3; + +// await I_USDTieredSTO_Array[stoId].modifyLimits(BigNumber(1*10**18), BigNumber(15*10**18), { from: ISSUER }); +// assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(),BigNumber(15*10**18).toNumber(),"STO Configuration doesn't set as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(),BigNumber(1*10**18).toNumber(),"STO Configuration doesn't set as expected"); + +// await I_USDTieredSTO_Array[stoId].modifyTiers([BigNumber(15*10**18)], [BigNumber(13*10**18)], [BigNumber(15*10**20)], [BigNumber(15*10**20)], { from: ISSUER }); +// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(0)).toNumber(),BigNumber(15*10**18).toNumber(),"STO Configuration doesn't set as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(0)).toNumber(),BigNumber(13*10**18).toNumber(),"STO Configuration doesn't set as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(0)),BigNumber(15*10**20).toNumber(),"STO Configuration doesn't set as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(0)),BigNumber(15*10**20).toNumber(),"STO Configuration doesn't set as expected"); + +// let tempTime1 = latestTime() + duration.days(0.1); +// let tempTime2 = latestTime() + duration.days(0.2); + +// await I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER }); +// assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(),tempTime1,"STO Configuration doesn't set as expected"); +// assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(),tempTime2,"STO Configuration doesn't set as expected"); + +// await I_USDTieredSTO_Array[stoId].modifyAddresses("0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", "0x0000000000000000000000000000000000000000", { from: ISSUER }); +// assert.equal(await I_USDTieredSTO_Array[stoId].wallet.call(),"0x0000000000000000000000000400000000000000","STO Configuration doesn't set as expected"); +// assert.equal(await I_USDTieredSTO_Array[stoId].reserveWallet.call(),"0x0000000000000000000003000000000000000000","STO Configuration doesn't set as expected"); +// assert.equal(await I_USDTieredSTO_Array[stoId].usdToken.call(),"0x0000000000000000000000000000000000000000","STO Configuration doesn't set as expected"); +// }); + +// it("Should fail to change config after endTime", async() => { +// let stoId = 3; + +// let snapId = await takeSnapshot(); +// await increaseTime(duration.days(1)); + +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].modifyFunding([0,1], { from: ISSUER }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, MESSAGE); + +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].modifyLimits(BigNumber(15*10**18), BigNumber(1*10**18), { from: ISSUER }); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, MESSAGE); + +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].modifyTiers([BigNumber(15*10**18)], [BigNumber(13*10**18)], [BigNumber(15*10**20)], [BigNumber(15*10**20)], { from: ISSUER }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, MESSAGE); + +// let tempTime1 = latestTime(); +// let tempTime2 = latestTime() + duration.days(3); + +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER }); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, MESSAGE); + +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].modifyAddresses("0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", I_DaiToken.address, { from: ISSUER }); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, MESSAGE); + +// await revertToSnapshot(snapId); +// }); +// }); + +// describe("Test buying failure conditions", async() => { + +// it("should fail if before STO start time", async() => { +// let stoId = 0; +// let snapId = await takeSnapshot(); + +// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + +// // Whitelist +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(15); +// let expiryTime = toTime + duration.days(100); +// let whitelisted = true; + +// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + +// // // Advance time to after STO start +// // await increaseTime(duration.days(3)); + +// // Set as accredited +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + +// // Prep for investments +// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH +// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); +// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY +// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); +// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + +// // NONACCREDITED ETH +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + +// // NONACCREDITED POLY +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + +// // NONACCREDITED DAI +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, 'NONACCREDITED POLY investment succeeded when it should not'); + +// // ACCREDITED ETH +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + +// // ACCREDITED POLY +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + +// // ACCREDITED DAI +// let errorThrown6 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown6 = true; +// ensureException(error); +// } +// assert.ok(errorThrown6, 'ACCREDITED POLY investment succeeded when it should not'); + +// await revertToSnapshot(snapId); +// }); + +// it("should fail if not whitelisted", async() => { +// let stoId = 0; +// let snapId = await takeSnapshot(); + +// // // Whitelist +// // let fromTime = latestTime(); +// // let toTime = latestTime() + duration.days(15); +// // let expiryTime = toTime + duration.days(100); +// // let whitelisted = true; +// // +// // await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); +// // await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + +// // Advance time to after STO start +// await increaseTime(duration.days(3)); + +// // Set as accredited +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + +// // Prep for investments +// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH +// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); +// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY +// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); +// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + +// // NONACCREDITED ETH +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + +// // NONACCREDITED POLY +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + +// // NONACCREDITED DAI +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + +// // ACCREDITED ETH +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + +// // ACCREDITED POLY +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + +// // ACCREDITED DAI +// let errorThrown6 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown6 = true; +// ensureException(error); +// } +// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + +// await revertToSnapshot(snapId); +// }); + +// it("should fail if minimumInvestmentUSD not met", async() => { +// let stoId = 0; +// let tierId = 0; +// let snapId = await takeSnapshot(); + +// // Whitelist +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(15); +// let expiryTime = toTime + duration.days(100); +// let whitelisted = true; + +// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + +// // Advance time to after STO start +// await increaseTime(duration.days(3)); + +// // Set as accredited +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + +// let investment_USD = BigNumber(2).mul(10**18); +// let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); +// let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); +// let investment_DAI = investment_USD; + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + + +// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); +// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + +// // NONACCREDITED ETH +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + +// // NONACCREDITED POLY +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + +// // NONACCREDITED DAI +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + +// // ACCREDITED ETH +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + +// // ACCREDITED POLY +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + +// // ACCREDITED DAI +// let errorThrown6 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown6 = true; +// ensureException(error); +// } +// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + +// await revertToSnapshot(snapId); +// }); + +// it("should successfully pause the STO and make investments fail, then unpause and succeed", async() => { +// let stoId = 0; +// let snapId = await takeSnapshot(); + +// // Whitelist +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(15); +// let expiryTime = toTime + duration.days(100); +// let whitelisted = true; + +// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + +// // Advance time to after STO start +// await increaseTime(duration.days(3)); + +// // Set as accredited +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + +// // Pause the STO +// await I_USDTieredSTO_Array[stoId].pause({ from: ISSUER }); +// assert.equal(await I_USDTieredSTO_Array[stoId].paused.call(), true, 'STO did not pause successfully'); + +// // Prep for investments +// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH +// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + +// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY +// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); +// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + +// // NONACCREDITED ETH +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + +// // NONACCREDITED POLY +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + +// // NONACCREDITED DAI +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + +// // ACCREDITED ETH +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + +// // ACCREDITED POLY +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + + +// // ACCREDITED DAI +// let errorThrown6 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown6 = true; +// ensureException(error); +// } +// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + +// // Unpause the STO +// await I_USDTieredSTO_Array[stoId].unpause({ from: ISSUER }); +// assert.equal(await I_USDTieredSTO_Array[stoId].paused.call(), false, 'STO did not unpause successfully'); + +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); +// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); + +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); +// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); + +// await revertToSnapshot(snapId); +// }); + +// it("should fail if after STO end time", async() => { +// let stoId = 3; +// let snapId = await takeSnapshot(); + +// // Whitelist +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(15); +// let expiryTime = toTime + duration.days(100); +// let whitelisted = true; + +// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + +// // Advance time to after STO end +// await increaseTime(duration.days(3)); + +// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + +// // Set as accredited +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + +// // Prep for investments +// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH +// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); +// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY +// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); +// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + + +// // NONACCREDITED ETH +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + +// // NONACCREDITED POLY +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + +// // NONACCREDITED DAI +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + +// // ACCREDITED ETH +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + +// // ACCREDITED POLY +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + +// // ACCREDITED DAI +// let errorThrown6 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown6 = true; +// ensureException(error); +// } +// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + +// await revertToSnapshot(snapId); +// }); + +// it("should fail if finalized", async() => { +// let stoId = 0; +// let snapId = await takeSnapshot(); + +// // Whitelist +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(100); +// let whitelisted = true; + +// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(RESERVEWALLET, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + +// // Advance time to after STO start +// await increaseTime(duration.days(3)); + +// // Set as accredited +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + +// // Finalize STO +// await I_USDTieredSTO_Array[stoId].finalize({ from: ISSUER }); +// assert.equal(await I_USDTieredSTO_Array[stoId].isFinalized.call(), true, "STO has not been finalized"); +// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + +// // Attempt to call function again +// let errorThrown = false; +// try { +// await I_USDTieredSTO_Array[stoId].finalize({ from: ISSUER }); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, 'STO was finalized a second time'); + +// // Prep for investments +// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH +// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); +// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY +// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); +// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + +// // NONACCREDITED ETH +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + +// // NONACCREDITED POLY +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + +// // NONACCREDITED DAI +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + +// // ACCREDITED ETH +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + +// // ACCREDITED POLY +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + +// // ACCREDITED DAI +// let errorThrown6 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); +// } catch(error) { +// errorThrown6 = true; +// ensureException(error); +// } +// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + +// await revertToSnapshot(snapId); +// }); +// }); + +// describe("Prep STO", async() => { + +// it("should jump forward to after STO start", async() => { +// let stoId = 0; +// await increaseTime(duration.days(3)); +// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),true,"STO is not showing correct status"); +// }); + +// it("should whitelist ACCREDITED1 and NONACCREDITED1", async() => { +// let stoId = 0; + +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(15); +// let expiryTime = toTime + duration.days(100); +// let whitelisted = true; + +// const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); +// assert.equal(tx1.logs[0].args._investor, NONACCREDITED1, "Failed in adding the investor in whitelist"); +// const tx2 = await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); +// assert.equal(tx2.logs[0].args._investor, ACCREDITED1, "Failed in adding the investor in whitelist"); +// }); + +// it("should successfully modify accredited addresses for first STO", async() => { +// let stoId = 0; + +// let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); +// assert.equal(status1, false, "Initial accreditation is set to true"); + +// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1], [true], { from: ISSUER }); +// let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); +// assert.equal(status2, true, "Failed to set single address"); + +// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); +// let status3 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); +// assert.equal(status3, false, "Failed to set multiple addresses"); +// let status4 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); +// assert.equal(status4, true, "Failed to set multiple addresses"); + +// let errorThrown = false; +// try { +// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [true], { from: ISSUER }); +// } catch(error) { +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, "Set accreditation despite input array of different size"); +// }); + +// it("should successfully modify accredited addresses for second STO", async() => { +// let stoId = 1; + +// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); +// let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); +// let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); +// assert.equal(status1, false, "Failed to set multiple address"); +// assert.equal(status2, true, "Failed to set multiple address"); +// }); +// }); + +// describe("Buy Tokens with no discount", async() => { + +// it("should successfully buy using fallback at tier 0 for NONACCREDITED1", async() => { +// let stoId = 0; +// let tierId = 0; + +// let investment_Token = BigNumber(50).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await web3.eth.sendTransaction({ from: NONACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); +// console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), "Raised USD not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional checks on getters +// assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 1, "Investor count not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), investment_Token.toNumber(), "getTokensSold not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), investment_Token.toNumber(), "getTokensMinted not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), investment_Token.toNumber(), "getTokensSoldForETH not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), 0, "getTokensSoldForPOLY not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), investment_USD.toNumber(), "investorInvestedUSD not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), investment_ETH.toNumber(), "investorInvestedETH not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), 0, "investorInvestedPOLY not changed as expected"); +// }); + +// it("should successfully buy using buyWithETH at tier 0 for NONACCREDITED1", async() => { +// let stoId = 0; +// let tierId = 0; + +// let investment_Token = BigNumber(50).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); +// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised DAI not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should successfully buy using buyWithPOLY at tier 0 for NONACCREDITED1", async() => { +// let stoId = 0; +// let tierId = 0; + +// let investment_Token = BigNumber(50).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// // Buy With POLY +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should successfully buy using buyWithUSD at tier 0 for NONACCREDITED1", async() => { +// let stoId = 0; +// let tierId = 0; + +// let investment_Token = BigNumber(50).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); +// let investment_DAI = investment_USD; + +// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_InvestorDAIBal = await I_DaiToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); +// let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + +// // Buy With DAI +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithUSD: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_InvestorDAIBal = await I_DaiToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); +// let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), "Investor DAI Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); +// assert.equal(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), "Wallet DAI Balance not changed as expected"); +// }); + +// it("should successfully buy using fallback at tier 0 for ACCREDITED1", async() => { +// let stoId = 0; +// let tierId = 0; + +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + +// let investment_Token = BigNumber(50).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await web3.eth.sendTransaction({ from: ACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); +// console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should successfully buy using buyWithETH at tier 0 for ACCREDITED1", async() => { +// let stoId = 0; +// let tierId = 0; + +// let investment_Token = BigNumber(50).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); +// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should successfully buy using buyWithPOLY at tier 0 for ACCREDITED1", async() => { +// let stoId = 0; +// let tierId = 0; + +// let investment_Token = BigNumber(50).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + +// // Additional checks on getters +// let init_getTokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_getTokensMinted = await I_USDTieredSTO_Array[stoId].getTokensMinted(); +// let init_getTokensSoldForETH = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH); +// let init_getTokensSoldForPOLY = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY); +// let init_investorInvestedUSD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1); +// let init_investorInvestedETH = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH); +// let init_investorInvestedPOLY = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// // Buy With POLY +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional checks on getters +// assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 2, "Investor count not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), init_getTokensSold.add(investment_Token).toNumber(), "getTokensSold not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), init_getTokensMinted.add(investment_Token).toNumber(), "getTokensMinted not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), init_getTokensSoldForETH.toNumber(), "getTokensSoldForETH not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), init_getTokensSoldForPOLY.add(investment_Token).toNumber(), "getTokensSoldForPOLY not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), init_investorInvestedUSD.add(investment_USD).toNumber(), "investorInvestedUSD not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), init_investorInvestedETH.toNumber(), "investorInvestedETH not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), init_investorInvestedPOLY.add(investment_POLY).toNumber(), "investorInvestedPOLY not changed as expected"); +// }); + +// it("should successfully modify NONACCREDITED cap for NONACCREDITED1", async() => { +// let stoId = 0; +// let tierId = 0; +// console.log("Current investment: " + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber()); +// await I_USDTieredSTO_Array[stoId].changeNonAccreditedLimit([NONACCREDITED1], [_nonAccreditedLimitUSD[stoId].div(2)], {from: ISSUER}); +// console.log("Current limit: " + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1)).toNumber()); +// }); + +// it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async() => { +// let stoId = 0; +// let tierId = 0; + +// let investment_USD = (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1));//_nonAccreditedLimitUSD[stoId]; +// let investment_Token = await convert(stoId, tierId, false, "USD", "TOKEN", investment_USD); +// let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); +// let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); + +// let refund_USD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); +// let refund_Token = await convert(stoId, tierId, false, "USD", "TOKEN", refund_USD); +// let refund_ETH = await convert(stoId, tierId, false, "USD", "ETH", refund_USD); +// let refund_POLY = await convert(stoId, tierId, false, "USD", "POLY", refund_USD); + +// console.log("Expected refund in tokens: " + refund_Token.toNumber()); + +// let snap = await takeSnapshot(); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// // Buy with ETH +// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); +// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).add(refund_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).sub(refund_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).sub(refund_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + +// await revertToSnapshot(snap); + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + +// init_TokenSupply = await I_SecurityToken.totalSupply(); +// init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// // Buy With POLY +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// final_TokenSupply = await I_SecurityToken.totalSupply(); +// final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).add(refund_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).sub(refund_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).sub(refund_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should fail and revert when NONACCREDITED cap reached", async() => { +// let stoId = 0; +// let tierId = 0; + +// let investment_Token = BigNumber(50).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1, gasPrice: GAS_PRICE}); + +// // Buy with ETH NONACCREDITED +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, MESSAGE); +// }); + +// it("should fail and revert despite oracle price change when NONACCREDITED cap reached", async() => { +// let stoId = 0; +// let tierId; + +// // set new exchange rates +// let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH +// let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY +// let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH +// let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY + +// let investment_USD = BigNumber(web3.utils.toWei('50')); // USD +// let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH +// let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY +// let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH +// let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + +// await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); + +// // Change exchange rates up +// await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); + +// // Buy with ETH NONACCREDITED +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, MESSAGE); + +// // Change exchange rates down +// await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); + +// // Buy with ETH NONACCREDITED +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, MESSAGE); + +// // Reset exchange rates +// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); +// }); + +// it("should successfully buy across tiers for NONACCREDITED ETH", async() => { +// let stoId = 1; +// let startTier = 0; +// let endTier = 1; + +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + +// let delta_Token = BigNumber(5).mul(10**18); +// let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); +// let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); + +// let investment_Token = delta_Token.add(delta_Token); // 10 Token +// let investment_ETH = ethTier0.add(ethTier1); // 0.0025 ETH + +// // Process investment +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); +// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional Checks +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); +// }); + +// it("should successfully buy across tiers for NONACCREDITED POLY", async() => { +// let stoId = 1; +// let startTier = 1; +// let endTier = 2; + +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + +// let delta_Token = BigNumber(5).mul(10**18); // Token +// let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); +// let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); + +// let investment_Token = delta_Token.add(delta_Token); // 10 Token +// let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + +// // Process investment +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional Checks +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); +// }); + +// it("should successfully buy across tiers for ACCREDITED ETH", async() => { +// let stoId = 1; +// let startTier = 2; +// let endTier = 3; + +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + +// let delta_Token = BigNumber(5).mul(10**18); // Token +// let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); +// let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); + +// let investment_Token = delta_Token.add(delta_Token); // 10 Token +// let investment_ETH = ethTier0.add(ethTier1); // 0.0025 ETH + +// // Process investment +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); +// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional Checks +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); +// }); + +// it("should successfully buy across tiers for ACCREDITED DAI", async() => { + +// let stoId = 1; +// let startTier = 3; +// let endTier = 4; + +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + +// let delta_Token = BigNumber(5).mul(10**18); // Token +// let daiTier0 = await convert(stoId, startTier, false, "TOKEN", "USD", delta_Token); +// let daiTier1 = await convert(stoId, endTier, false, "TOKEN", "USD", delta_Token); + +// let investment_Token = delta_Token.add(delta_Token); // 10 Token +// let investment_DAI = daiTier0.add(daiTier1); + +// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + +// // Process investment +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_InvestorDAIBal = await I_DaiToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); +// let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithUSD: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_InvestorDAIBal = await I_DaiToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); +// let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), "Raised DAI not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); +// assert.equal(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional Checks +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); + +// }); + +// it("should successfully buy across tiers for ACCREDITED POLY", async() => { +// let stoId = 1; +// let startTier = 4; +// let endTier = 5; + +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + +// let delta_Token = BigNumber(5).mul(10**18); // Token +// let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); +// let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); + +// let investment_Token = delta_Token.add(delta_Token); // 10 Token +// let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH + +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + +// // Process investment +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional Checks +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); +// }); + +// it("should buy out the rest of the sto", async() => { +// let stoId = 1; +// let tierId = 5; + +// let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); +// console.log(minted.toNumber() + ":"+ _tokensPerTierTotal[stoId][tierId]); +// let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); +// console.log(investment_Token.toNumber()); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + +// let tx = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// console.log(" Gas buyWithETH: ".grey+tx.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// // assert.equal((await I_USDTieredSTO_Array[1].getTokensMinted()).toNumber(), _tokensPerTierTotal[1].reduce((a, b) => a + b, 0).toNumber(), "STO Token Sold not changed as expected"); +// }); + +// it("should fail and revert when all tiers sold out", async() => { +// let stoId = 1; +// let tierId = 4; + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); +// let investment_DAI = investment_USD; + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + +// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + +// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + +// // Buy with ETH NONACCREDITED +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, MESSAGE); + +// // Buy with DAI NONACCREDITED +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, MESSAGE); + +// // Buy with ETH ACCREDITED +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, MESSAGE); + +// // Buy with POLY ACCREDITED +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, MESSAGE); + +// // Buy with DAI ACCREDITED +// let errorThrown6 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown6 = true; +// ensureException(error); +// } +// assert.ok(errorThrown6, MESSAGE); +// }); + +// it("should fail and revert when all tiers sold out despite oracle price change", async() => { +// let stoId = 1; +// let tierId = 4; + +// // set new exchange rates +// let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH +// let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY +// let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH +// let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY + +// let investment_USD = BigNumber(web3.utils.toWei('50')); // USD +// let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH +// let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY +// let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH +// let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + +// await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); +// await I_PolyToken.getTokens(investment_POLY_low, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: ACCREDITED1}); + +// // Change exchange rates up +// await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); + +// // Buy with ETH NONACCREDITED +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, MESSAGE); + +// // Buy with ETH ACCREDITED +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, MESSAGE); + +// // Buy with POLY ACCREDITED +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_high, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, MESSAGE); + +// // Change exchange rates down +// await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); + +// // Buy with ETH NONACCREDITED +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown6 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown6 = true; +// ensureException(error); +// } +// assert.ok(errorThrown6, MESSAGE); + +// // Buy with ETH ACCREDITED +// let errorThrown7 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown7 = true; +// ensureException(error); +// } +// assert.ok(errorThrown7, MESSAGE); + +// // Buy with POLY ACCREDITED +// let errorThrown8 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_low, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown8 = true; +// ensureException(error); +// } +// assert.ok(errorThrown8, MESSAGE); + +// // Reset exchange rates +// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); +// }); +// }); + +// describe("Buy Tokens with POLY discount", async() => { + +// it("should successfully buy using fallback at tier 0 for NONACCREDITED1", async() => { +// let stoId = 2; +// let tierId = 0; + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await web3.eth.sendTransaction({ from: NONACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); +// console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), "Raised USD not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional checks on getters +// assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 1, "Investor count not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), investment_Token.toNumber(), "getTokensSold not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), investment_Token.toNumber(), "getTokensMinted not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), investment_Token.toNumber(), "getTokensSoldForETH not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), 0, "getTokensSoldForPOLY not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), investment_USD.toNumber(), "investorInvestedUSD not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), investment_ETH.toNumber(), "investorInvestedETH not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), 0, "investorInvestedPOLY not changed as expected"); +// }); + +// it("should successfully buy using buyWithETH at tier 0 for NONACCREDITED1", async() => { +// let stoId = 2; +// let tierId = 0; + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); +// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should successfully buy using buyWithPOLY at tier 0 for NONACCREDITED1", async() => { +// let stoId = 2; +// let tierId = 0; + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// // Buy With POLY +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should successfully buy using fallback at tier 0 for ACCREDITED1", async() => { +// let stoId = 2; +// let tierId = 0; + +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await web3.eth.sendTransaction({ from: ACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); +// console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should successfully buy using buyWithETH at tier 0 for ACCREDITED1", async() => { +// let stoId = 2; +// let tierId = 0; + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); +// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should successfully buy using buyWithPOLY at tier 0 for ACCREDITED1", async() => { +// let stoId = 2; +// let tierId = 0; + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); + +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + +// // Additional checks on getters +// let init_getTokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_getTokensMinted = await I_USDTieredSTO_Array[stoId].getTokensMinted(); +// let init_getTokensSoldForETH = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH); +// let init_getTokensSoldForPOLY = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY); +// let init_investorInvestedUSD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1); +// let init_investorInvestedETH = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH); +// let init_investorInvestedPOLY = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// // Buy With POLY +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional checks on getters +// assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 2, "Investor count not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), init_getTokensSold.add(investment_Token).toNumber(), "getTokensSold not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), init_getTokensMinted.add(investment_Token).toNumber(), "getTokensMinted not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), init_getTokensSoldForETH.toNumber(), "getTokensSoldForETH not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), init_getTokensSoldForPOLY.add(investment_Token).toNumber(), "getTokensSoldForPOLY not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), init_investorInvestedUSD.add(investment_USD).toNumber(), "investorInvestedUSD not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), init_investorInvestedETH.toNumber(), "investorInvestedETH not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), init_investorInvestedPOLY.add(investment_POLY).toNumber(), "investorInvestedPOLY not changed as expected"); +// }); + +// it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async() => { +// let stoId = 2; +// let tierId = 0; + +// let investment_USD = _nonAccreditedLimitUSD[stoId]; +// let investment_Token = await convert(stoId, tierId, true, "USD", "TOKEN", investment_USD); +// let investment_ETH = await convert(stoId, tierId, true, "USD", "ETH", investment_USD); +// let investment_POLY = await convert(stoId, tierId, true, "USD", "POLY", investment_USD); + +// let refund_USD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); +// let refund_Token = await convert(stoId, tierId, true, "USD", "TOKEN", refund_USD); +// let refund_ETH = await convert(stoId, tierId, true, "USD", "ETH", refund_USD); +// let refund_POLY = await convert(stoId, tierId, true, "USD", "POLY", refund_USD); + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// // Buy With POLY +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).add(refund_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).sub(refund_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).sub(refund_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should fail and revert when NONACCREDITED cap reached", async() => { +// let stoId = 2; +// let tierId = 0; + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1, gasPrice: GAS_PRICE}); + +// // Buy with ETH NONACCREDITED +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, MESSAGE); +// }); + +// it("should fail and revert despite oracle price change when NONACCREDITED cap reached", async() => { +// let stoId = 2; +// let tierId = 0; + +// // set new exchange rates +// let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH +// let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY +// let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH +// let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); + +// let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH +// let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY +// let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH +// let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + +// await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); + +// // Change exchange rates up +// await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); + +// // Buy with ETH NONACCREDITED +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, MESSAGE); + +// // Change exchange rates down +// await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); + +// // Buy with ETH NONACCREDITED +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, MESSAGE); + +// // Reset exchange rates +// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); +// }); + +// it("should successfully buy across tiers for POLY", async() => { +// let stoId = 2; +// let startTier = 0; +// let endTier = 1; + +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + +// let delta_Token = BigNumber(5).mul(10**18); // Token +// let polyTier0 = await convert(stoId, startTier, true, "TOKEN", "POLY", delta_Token); +// let polyTier1 = await convert(stoId, endTier, true, "TOKEN", "POLY", delta_Token); +// let investment_Token = delta_Token.add(delta_Token); // 10 Token +// let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH + +// let tokensRemaining = (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier)); +// let prep_Token = tokensRemaining.sub(delta_Token); +// let prep_POLY = await convert(stoId, startTier, true, "TOKEN", "POLY", prep_Token); + +// await I_PolyToken.getTokens(prep_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, prep_POLY, {from: ACCREDITED1}); +// let tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, prep_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// console.log(" Gas buyWithPOLY: ".grey+tx.receipt.gasUsed.toString().grey); + +// let Tier0Token = (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier)); +// let Tier0Minted = (await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier)); +// assert.equal(Tier0Minted.toNumber(), Tier0Token.sub(delta_Token).toNumber()); + +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + +// // Process investment +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + +// // Additional Checks +// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); +// }); + +// it("should successfully buy across the discount cap", async() => { +// let stoId = 2; +// let tierId = 1; + +// let discount_Token = BigNumber(20).mul(10**18); +// let discount_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", discount_Token); + +// let regular_Token = BigNumber(10).mul(10**18); +// let regular_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", regular_Token); + +// let investment_Token = discount_Token.add(regular_Token); +// let investment_POLY = discount_POLY.add(regular_POLY); + +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// // Buy With POLY +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); +// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); +// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); +// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); +// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); +// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); +// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); +// }); + +// it("should buy out the rest of the sto", async() => { +// let stoId = 2; +// let tierId = 1; + +// let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); +// let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + +// // Buy With POLY +// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); +// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + +// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); +// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); +// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); +// }); + +// it("should fail and revert when all tiers sold out", async() => { +// let stoId = 2; +// let tierId = 1; + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); +// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); +// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + +// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + +// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + +// // Buy with ETH NONACCREDITED +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, MESSAGE); + +// // Buy with ETH ACCREDITED +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, MESSAGE); + +// // Buy with POLY ACCREDITED +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, MESSAGE); +// }); + +// it("should fail and revert when all tiers sold out despite oracle price change", async() => { +// let stoId = 2; +// let tierId = 1; + +// // set new exchange rates +// let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH +// let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY +// let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH +// let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY + +// let investment_Token = BigNumber(5).mul(10**18); +// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); + +// let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH +// let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY +// let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH +// let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + +// await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); +// await I_PolyToken.getTokens(investment_POLY_low, ACCREDITED1); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: ACCREDITED1}); + +// // Change exchange rates up +// await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); + +// // Buy with ETH NONACCREDITED +// let errorThrown1 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown1 = true; +// ensureException(error); +// } +// assert.ok(errorThrown1, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown2 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown2 = true; +// ensureException(error); +// } +// assert.ok(errorThrown2, MESSAGE); + +// // Buy with ETH ACCREDITED +// let errorThrown3 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown3 = true; +// ensureException(error); +// } +// assert.ok(errorThrown3, MESSAGE); + +// // Buy with POLY ACCREDITED +// let errorThrown4 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_high, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown4 = true; +// ensureException(error); +// } +// assert.ok(errorThrown4, MESSAGE); + +// // Change exchange rates down +// await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); + +// // Buy with ETH NONACCREDITED +// let errorThrown5 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown5 = true; +// ensureException(error); +// } +// assert.ok(errorThrown5, MESSAGE); + +// // Buy with POLY NONACCREDITED +// let errorThrown6 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown6 = true; +// ensureException(error); +// } +// assert.ok(errorThrown6, MESSAGE); + +// // Buy with ETH ACCREDITED +// let errorThrown7 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown7 = true; +// ensureException(error); +// } +// assert.ok(errorThrown7, MESSAGE); + +// // Buy with POLY ACCREDITED +// let errorThrown8 = false; +// try { +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_low, { from: ACCREDITED1, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown8 = true; +// ensureException(error); +// } +// assert.ok(errorThrown8, MESSAGE); + +// // Reset exchange rates +// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); +// }); +// }); + +// describe("Test getter functions", async() => { + +// describe("Generic", async() => { + +// it("should get the right number of investors", async() => { +// assert.equal((await I_USDTieredSTO_Array[0].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[0].investorCount()).toNumber(), "Investor count not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[1].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[1].investorCount()).toNumber(), "Investor count not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[2].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[2].investorCount()).toNumber(), "Investor count not changed as expected"); +// }); + +// it("should get the right amounts invested", async() => { +// assert.equal((await I_USDTieredSTO_Array[0].fundsRaised.call(ETH)).toNumber(), (await I_USDTieredSTO_Array[0].getRaised(0)).toNumber(), "getRaisedEther not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[0].fundsRaised.call(POLY)).toNumber(), (await I_USDTieredSTO_Array[0].getRaised(1)).toNumber(), "getRaisedPOLY not changed as expected"); +// assert.equal((await I_USDTieredSTO_Array[0].fundsRaisedUSD.call()).toNumber(), (await I_USDTieredSTO_Array[0].fundsRaisedUSD()).toNumber(), "fundsRaisedUSD not changed as expected"); +// }); +// }); + +// describe("convertToUSD", async() => { + +// it("should reset exchange rates", async() => { +// // Reset exchange rates +// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); +// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); +// }); + +// it("should get the right conversion for ETH to USD", async() => { +// // 20 ETH to 10000 USD +// let ethInWei = BigNumber(web3.utils.toWei('20', 'ether')); +// let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(ETH, ethInWei); +// assert.equal(usdInWei.div(10**18).toNumber(), ethInWei.div(10**18).mul(USDETH.div(10**18)).toNumber()); +// }); + +// it("should get the right conversion for POLY to USD", async() => { +// // 40000 POLY to 10000 USD +// let polyInWei = BigNumber(web3.utils.toWei('40000', 'ether')); +// let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(POLY, polyInWei); +// assert.equal(usdInWei.div(10**18).toNumber(), polyInWei.div(10**18).mul(USDPOLY.div(10**18)).toNumber()); +// }); +// }); + +// describe("convertFromUSD", async() => { + +// it("should get the right conversion for USD to ETH", async() => { +// // 10000 USD to 20 ETH +// let usdInWei = BigNumber(web3.utils.toWei('10000', 'ether')); +// let ethInWei = await I_USDTieredSTO_Array[0].convertFromUSD(ETH, usdInWei); +// assert.equal(ethInWei.div(10**18).toNumber(), usdInWei.div(10**18).div(USDETH.div(10**18)).toNumber()); +// }); + +// it("should get the right conversion for USD to POLY", async() => { +// // 10000 USD to 40000 POLY +// let usdInWei = BigNumber(web3.utils.toWei('10000', 'ether')); +// let polyInWei = await I_USDTieredSTO_Array[0].convertFromUSD(POLY, usdInWei); +// assert.equal(polyInWei.div(10**18).toNumber(), usdInWei.div(10**18).div(USDPOLY.div(10**18)).toNumber()); +// }); +// }); +// }); + +// describe("Test cases for the USDTieredSTOFactory", async() => { +// it("should get the exact details of the factory", async() => { +// assert.equal((await I_USDTieredSTOFactory.setupCost.call()).toNumber(), STOSetupCost); +// assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0],3); +// assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), +// "USDTieredSTO", +// "Wrong Module added"); +// assert.equal(await I_USDTieredSTOFactory.getDescription.call(), +// "USD Tiered STO", +// "Wrong Module added"); +// assert.equal(await I_USDTieredSTOFactory.getTitle.call(), +// "USD Tiered STO", +// "Wrong Module added"); +// assert.equal(await I_USDTieredSTOFactory.getInstructions.call(), +// "Initialises a USD tiered STO.", +// "Wrong Module added"); +// let tags = await I_USDTieredSTOFactory.getTags.call(); +// assert.equal(web3.utils.hexToString(tags[0]),"USD"); +// assert.equal(web3.utils.hexToString(tags[1]),"Tiered"); +// assert.equal(web3.utils.hexToString(tags[2]),"POLY"); +// assert.equal(web3.utils.hexToString(tags[3]),"ETH"); + +// }); +// }); +// }); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 96015926d..738373341 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -1,775 +1,775 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); -const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); -const MockOracle = artifacts.require('./MockOracle.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port - -const TOLERANCE = 2; // Allow balances to be off by 2 WEI for rounding purposes - -contract('USDTieredSTO Sim', accounts => { - // Accounts Variable declaration - let POLYMATH; - let ISSUER; - let WALLET; - let RESERVEWALLET; - let INVESTOR1; - let ACCREDITED1; - let ACCREDITED2; - let NONACCREDITED1; - let NONACCREDITED2; - let NOTWHITELISTED; - let NOTAPPROVED; - - let MESSAGE = "Transaction Should Fail!"; - const GAS_PRICE = 10000000000; // 10 GWEI - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_GeneralTransferManagerFactory; - let I_USDTieredSTOProxyFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_USDTieredSTOFactory; - let I_USDOracle; - let I_POLYOracle; - let I_STFactory; - let I_MRProxied; - let I_STRProxied; - let I_SecurityToken; - let I_USDTieredSTO_Array = []; - let I_PolyToken; - let I_DaiToken; - let I_PolymathRegistry; - - // SecurityToken Details for funds raise Type ETH - const NAME = "Team"; - const SYMBOL = "SAP"; - const TOKENDETAILS = "This is equity type of issuance"; - const DECIMALS = 18; - - // Module key - const TMKEY = 2; - const STOKEY = 3; - - // Initial fee for ticker registry and security token registry - const REGFEE = web3.utils.toWei("250"); - const STOSetupCost = 0; - - // MockOracle USD prices - const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH - const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY - - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - // STO Configuration Arrays - let _startTime = []; - let _endTime = []; - let _ratePerTier = []; - let _ratePerTierDiscountPoly = []; - let _tokensPerTierTotal = []; - let _tokensPerTierDiscountPoly = []; - let _nonAccreditedLimitUSD = []; - let _minimumInvestmentUSD = []; - let _fundRaiseTypes = []; - let _wallet = []; - let _reserveWallet = []; - let _usdToken = []; - - /* function configure( - uint256 _startTime, - uint256 _endTime, - uint256[] _ratePerTier, - uint256[] _ratePerTierDiscountPoly, - uint256[] _tokensPerTier, - uint256[] _tokensPerTierDiscountPoly, - uint256 _nonAccreditedLimitUSD, - uint256 _minimumInvestmentUSD, - uint8[] _fundRaiseTypes, - address _wallet, - address _reserveWallet, - address _usdToken - ) */ - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256[]', - name: '_ratePerTier' - },{ - type: 'uint256[]', - name: '_ratePerTierDiscountPoly' - },{ - type: 'uint256[]', - name: '_tokensPerTier' - },{ - type: 'uint256[]', - name: '_tokensPerTierDiscountPoly' - },{ - type: 'uint256', - name: '_nonAccreditedLimitUSD' - },{ - type: 'uint256', - name: '_minimumInvestmentUSD' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes' - },{ - type: 'address', - name: '_wallet' - },{ - type: 'address', - name: '_reserveWallet' - },{ - type: 'address', - name: '_usdToken' - }] - }; - - function getRandomInt(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; - } - - before(async() => { - // Accounts setup - POLYMATH = accounts[0]; - ISSUER = accounts[1]; - WALLET = accounts[2]; - RESERVEWALLET = WALLET; - ACCREDITED1 = accounts[3]; - ACCREDITED2 = accounts[4]; - NONACCREDITED1 = accounts[5]; - NONACCREDITED2 = accounts[6]; - NOTWHITELISTED = accounts[7]; - NOTAPPROVED = accounts[8]; - INVESTOR1 = accounts[9]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - I_DaiToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: POLYMATH - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - - // STEP 3: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 4: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the proxy - I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); - - // STEP 6: Deploy the USDTieredSTOFactory - - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); - - assert.notEqual( - I_USDTieredSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "USDTieredSTOFactory contract was not deployed" - ); - - - - // Step 8: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); - await I_MRProxied.updateFromRegistry({from: POLYMATH}); - - // STEP 7: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); - - // (C) : Register the STOFactory - await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); - await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); - - // Step 12: Deploy & Register Mock Oracles - I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY - I_POLYOracle = await MockOracle.new(I_PolyToken.address, "POLY", "USD", USDPOLY, { from: POLYMATH }); // 25 cents per POLY - await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); - await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - USDOracle: ${I_USDOracle.address} - POLYOracle: ${I_POLYOracle.address} - USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} - USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Deploy the STO", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.getTokens(REGFEE, ISSUER); - await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); - let tx = await I_STRProxied.registerTicker(ISSUER, SYMBOL, NAME, { from : ISSUER }); - assert.equal(tx.logs[0].args._owner, ISSUER); - assert.equal(tx.logs[0].args._ticker, SYMBOL); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.getTokens(REGFEE, ISSUER); - await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); - assert.equal(tx.logs[1].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), TMKEY); - assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - it("Should successfully attach the first STO module to the security token", async () => { - let stoId = 0; - - _startTime.push(latestTime() + duration.days(2)); - _endTime.push(_startTime[stoId] + duration.days(100)); - _ratePerTier.push([ - BigNumber(0.05*10**18), BigNumber(0.13*10**18), BigNumber(0.17*10**18) - ]); // [ 0.05 USD/Token, 0.10 USD/Token, 0.15 USD/Token ] - _ratePerTierDiscountPoly.push([ - BigNumber(0.05*10**18), BigNumber(0.08*10**18), BigNumber(0.13*10**18) - ]); // [ 0.05 USD/Token, 0.08 USD/Token, 0.13 USD/Token ] - _tokensPerTierTotal.push([ - BigNumber(200*10**18), BigNumber(500*10**18), BigNumber(300*10**18) - ]); // [ 1000 Token, 2000 Token, 1500 Token ] - _tokensPerTierDiscountPoly.push([ - BigNumber(0), BigNumber(50*10**18), BigNumber(300*10**18) - ]); // [ 0 Token, 1000 Token, 1500 Token ] - _nonAccreditedLimitUSD.push(BigNumber(10*10**18)); // 20 USD - _minimumInvestmentUSD.push(BigNumber(0)); // 1 wei USD - _fundRaiseTypes.push([0,1,2]); - _wallet.push(WALLET); - _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address); - - let config = [ - _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], - _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], - _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] - ]; - - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); - console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); - I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); - - assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); - for (var i = 0; i < _ratePerTier[stoId].length; i++) { - assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); - } - assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); - assert.equal((await I_USDTieredSTO_Array[stoId].getNumberOfTiers()), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); - assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); - }); - - it("Should successfully prepare the STO", async() => { - let stoId = 0; - - // Start STO - await increaseTime(duration.days(3)); - - // Whitelist - let fromTime = latestTime() + duration.days(15); - let toTime = latestTime() + duration.days(15); - let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = true; - - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, { from: ISSUER }); - - await increaseTime(duration.days(3)); - - // Accreditation - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1, ACCREDITED2], [true, true], { from: ISSUER }); - await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, NONACCREDITED2], [false, false], { from: ISSUER }); - }); - }); - - describe("Simulate purchasing", async() => { - - it("Should successfully complete simulation", async() => { - let stoId = 0; - - console.log(` - ------------------- Investor Addresses ------------------- - ACCREDITED1: ${ACCREDITED1} - ACCREDITED2: ${ACCREDITED2} - NONACCREDITED1: ${NONACCREDITED1} - NONACCREDITED2: ${NONACCREDITED2} - NOTWHITELISTED: ${NOTWHITELISTED} - NOTAPPROVED: ${NOTAPPROVED} - ---------------------------------------------------------- - `); - - let totalTokens = BigNumber(0); - for (var i = 0; i < _tokensPerTierTotal[stoId].length; i++) { - totalTokens = totalTokens.add(_tokensPerTierTotal[stoId][i]); - } - console.log('totalTokens: '+totalTokens.div(10**18).toNumber()); - let tokensSold = BigNumber(0); - while (true) { - switch (getRandomInt(0,5)) { - case 0: // ACCREDITED1 - await invest(ACCREDITED1, true); - break; - case 1: // ACCREDITED2 - await invest(ACCREDITED2, true); - break; - case 2: // NONACCREDITED1 - let usd_NONACCREDITED1 = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); - if (_nonAccreditedLimitUSD[stoId].gt(usd_NONACCREDITED1)) // under non-accredited cap - await invest(NONACCREDITED1, false); - else // over non-accredited cap - await investFAIL(NONACCREDITED1); - break; - case 3: // NONACCREDITED2 - let usd_NONACCREDITED2 = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED2); - if (_nonAccreditedLimitUSD[stoId].gt(usd_NONACCREDITED2)) // under non-accredited cap - await invest(NONACCREDITED2, false); - else // over non-accredited cap - await investFAIL(NONACCREDITED2); - break; - case 4: // NOTWHITELISTED - await investFAIL(NOTWHITELISTED); - break; - case 5: // NOTAPPROVED - await investFAIL(NOTAPPROVED); - break; - } - console.log("Next round"); - tokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - console.log("Tokens Sold: " + tokensSold.toString()); - if (tokensSold.gte(totalTokens.sub(1*10**18))) { - console.log(`${tokensSold} tokens sold, simulation completed successfully!`.green); - break; - } - } - - async function invest(_investor, _isAccredited) { // need to add check if reached non-accredited cap - let USD_remaining; - if (!_isAccredited) { - let USD_to_date = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(_investor); - USD_remaining = _nonAccreditedLimitUSD[stoId].sub(USD_to_date); - } else { - USD_remaining = totalTokens.mul(2); - } - - let log_remaining = USD_remaining; - let isPoly = Math.random() >= 0.33; - let isDai = Math.random() >= 0.33; - - let Token_counter = BigNumber(getRandomInt(1*10**10,50*10**10)).mul(10**8); - let investment_USD = BigNumber(0); - let investment_ETH = BigNumber(0); - let investment_POLY = BigNumber(0); - let investment_DAI = BigNumber(0); - let investment_Token = BigNumber(0); - - let Tokens_total = []; - let Tokens_discount = []; - for (var i = 0; i < _ratePerTier[stoId].length; i++) { - Tokens_total.push((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(i))); - Tokens_discount.push((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierDiscountPoly.call(i))); - } - - let tier = 0; - let Token_Tier; - let USD_Tier; - let POLY_Tier; - let ETH_Tier; - let DAI_Tier; - - - let USD_overflow; - let Token_overflow; - - while (Token_counter.gt(0)) { - if (tier == _ratePerTier[stoId].length) { - break; - } - if (Tokens_total[tier].gt(0)) { - if (isPoly) { - // 1. POLY and discount (consume up to cap then move to regular) - if (Tokens_discount[tier].gt(0)) { - Token_Tier = BigNumber.min([Tokens_total[tier], Tokens_discount[tier], Token_counter]); - USD_Tier = Token_Tier.mul(_ratePerTierDiscountPoly[stoId][tier].div(10**18)); - if (USD_Tier.gte(USD_remaining)) { - USD_overflow = USD_Tier.sub(USD_remaining); - Token_overflow = USD_overflow.mul(10**18).div(_ratePerTierDiscountPoly[stoId][tier]); - USD_Tier = USD_Tier.sub(USD_overflow); - Token_Tier = Token_Tier.sub(Token_overflow); - Token_counter = BigNumber(0); - } - POLY_Tier = USD_Tier.mul(10**18).round(0).div(USDPOLY).round(0); - USD_remaining = USD_remaining.sub(USD_Tier); - Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); - Tokens_discount[tier] = Tokens_discount[tier].sub(Token_Tier); - Token_counter = Token_counter.sub(Token_Tier); - investment_Token = investment_Token.add(Token_Tier); - investment_USD = investment_USD.add(USD_Tier); - investment_POLY = investment_POLY.add(POLY_Tier); - } - // 2. POLY and regular (consume up to cap then skip to next tier) - if (Tokens_total[tier].gt(0) && Token_counter.gt(0)) { - Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); - USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); - if (USD_Tier.gte(USD_remaining)) { - USD_overflow = USD_Tier.sub(USD_remaining); - Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); - USD_Tier = USD_Tier.sub(USD_overflow); - Token_Tier = Token_Tier.sub(Token_overflow); - Token_counter = BigNumber(0); - } - POLY_Tier = USD_Tier.mul(10**18).round(0).div(USDPOLY).round(0); - USD_remaining = USD_remaining.sub(USD_Tier); - Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); - Token_counter = Token_counter.sub(Token_Tier); - investment_Token = investment_Token.add(Token_Tier); - investment_USD = investment_USD.add(USD_Tier); - investment_POLY = investment_POLY.add(POLY_Tier); - } - } else if (isDai) { - // 3. DAI (consume up to cap then skip to next tier) - Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); - USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); - if (USD_Tier.gte(USD_remaining)) { - USD_overflow = USD_Tier.sub(USD_remaining); - Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); - USD_Tier = USD_Tier.sub(USD_overflow); - Token_Tier = Token_Tier.sub(Token_overflow); - Token_counter = BigNumber(0); - } - DAI_Tier = USD_Tier.round(0); - USD_remaining = USD_remaining.sub(USD_Tier); - Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); - Token_counter = Token_counter.sub(Token_Tier); - investment_Token = investment_Token.add(Token_Tier); - investment_USD = investment_USD.add(USD_Tier); - investment_DAI = investment_USD; - } else { - // 4. ETH (consume up to cap then skip to next tier) - Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); - USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); - if (USD_Tier.gte(USD_remaining)) { - USD_overflow = USD_Tier.sub(USD_remaining); - Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); - USD_Tier = USD_Tier.sub(USD_overflow); - Token_Tier = Token_Tier.sub(Token_overflow); - Token_counter = BigNumber(0); - } - ETH_Tier = USD_Tier.mul(10**18).round(0).div(USDETH).round(0); - USD_remaining = USD_remaining.sub(USD_Tier); - Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); - Token_counter = Token_counter.sub(Token_Tier); - investment_Token = investment_Token.add(Token_Tier); - investment_USD = investment_USD.add(USD_Tier); - investment_ETH = investment_ETH.add(ETH_Tier); - } - } - tier++ - } - - await processInvestment(_investor, investment_Token, investment_USD, investment_POLY, investment_DAI, investment_ETH, isPoly, isDai, log_remaining, Tokens_total, Tokens_discount, tokensSold); - } - - async function investFAIL(_investor) { - let isPoly = Math.random() >= 0.3; - let isDAI = Math.random() >= 0.3; - let investment_POLY = BigNumber(40*10**18); // 10 USD = 40 POLY - let investment_ETH = BigNumber(0.02*10**18); // 10 USD = 0.02 ETH - let investment_DAI = BigNumber(10*10**18); // 10 USD = DAI DAI - - let errorThrown = false; - try { - if (isPoly) { - await I_PolyToken.getTokens(investment_POLY, _investor); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: _investor}); - await I_USDTieredSTO_Array[stoId].buyWithPOLY(_investor, investment_POLY, { from: _investor, gasPrice: GAS_PRICE }); - } else if (isDAI) { - await I_DaiToken.getTokens(investment_DAI, _investor); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: _investor}); - await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); - } else await I_USDTieredSTO_Array[stoId].buyWithETH(_investor, { from: _investor, value: investment_ETH, gasPrice: GAS_PRICE }); - } catch(error) { - errorThrown = true; - console.log(`Purchase failed as expected: ${_investor}`.yellow); - ensureException(error); - } - assert.ok(errorThrown, MESSAGE); - } - - async function processInvestment(_investor, investment_Token, investment_USD, investment_POLY, investment_DAI, investment_ETH, isPoly, isDai, log_remaining, Tokens_total, Tokens_discount, tokensSold) { - investment_Token = investment_Token.round(0); - investment_USD = investment_USD.round(0); - investment_POLY = investment_POLY.round(0); - investment_DAI = investment_DAI.round(0); - investment_ETH = investment_ETH.round(0); - console.log(` - ------------------- New Investment ------------------- - Investor: ${_investor} - N-A USD Remaining: ${log_remaining.div(10**18)} - Total Cap Remaining: ${Tokens_total} - Discount Cap Remaining: ${Tokens_discount} - Total Tokens Sold: ${tokensSold.div(10**18)} - Token Investment: ${investment_Token.div(10**18)} - USD Investment: ${investment_USD.div(10**18)} - POLY Investment: ${investment_POLY.div(10**18)} - DAI Investment: ${investment_DAI.div(10**18)} - ETH Investment: ${investment_ETH.div(10**18)} - ------------------------------------------------------ - `); - - if (isPoly) { - await I_PolyToken.getTokens(investment_POLY, _investor); - await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: _investor}); - } else if (isDai) { - await I_DaiToken.getTokens(investment_DAI, _investor); - await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: _investor}); - } - - // console.log(await I_USDTieredSTO_Array[stoId].isOpen()); - - let init_TokenSupply = await I_SecurityToken.totalSupply(); - let init_InvestorTokenBal = await I_SecurityToken.balanceOf(_investor); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(_investor)); - let init_InvestorPOLYBal = await I_PolyToken.balanceOf(_investor); - let init_InvestorDAIBal = await I_DaiToken.balanceOf(_investor); - let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_STODAIBal = await I_DaiToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); - let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(0); - let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(1); - let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(2); - let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - - let tx; - let gasCost = BigNumber(0); - - if (isPoly && investment_POLY.gt(10)) { - tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(_investor, investment_POLY, { from: _investor, gasPrice: GAS_PRICE }); - gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); - console.log(`buyWithPOLY: ${investment_Token.div(10**18)} tokens for ${investment_POLY.div(10**18)} POLY by ${_investor}`.yellow); - } else if (isDai && investment_DAI.gt(10)) { - tx = await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); - gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); - console.log(`buyWithUSD: ${investment_Token.div(10**18)} tokens for ${investment_DAI.div(10**18)} DAI by ${_investor}`.yellow); - } else if (investment_ETH.gt(0)) { - tx = await I_USDTieredSTO_Array[stoId].buyWithETH(_investor, { from: _investor, value: investment_ETH, gasPrice: GAS_PRICE }); - gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); - console.log(`buyWithETH: ${investment_Token.div(10**18)} tokens for ${investment_ETH.div(10**18)} ETH by ${_investor}`.yellow); - } - console.log(investment_POLY.toNumber()); - - let final_TokenSupply = await I_SecurityToken.totalSupply(); - let final_InvestorTokenBal = await I_SecurityToken.balanceOf(_investor); - let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(_investor)); - let final_InvestorPOLYBal = await I_PolyToken.balanceOf(_investor); - let final_InvestorDAIBal = await I_DaiToken.balanceOf(_investor); - let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); - let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_STODAIBal = await I_DaiToken.balanceOf(I_USDTieredSTO_Array[stoId].address); - let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); - let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(0); - let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(1); - let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(2); - let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); - let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - - // console.log('init_TokenSupply: '+init_TokenSupply.div(10**18).toNumber()); - // console.log('final_TokenSupply: '+final_TokenSupply.div(10**18).toNumber()); - - if (isPoly) { - assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); - assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); - assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); - assert.closeTo(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), TOLERANCE, "Investor POLY Balance not changed as expected"); - assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); - assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); - assert.closeTo(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), TOLERANCE, "STO POLY Balance not changed as expected"); - assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); - assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), TOLERANCE, "Raised ETH not changed as expected"); - assert.closeTo(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), TOLERANCE, "Raised POLY not changed as expected"); - assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); - assert.closeTo(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), TOLERANCE, "Wallet POLY Balance not changed as expected"); - } else if (isDai) { - assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); - assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); - assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); - assert.closeTo(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), TOLERANCE, "Investor DAI Balance not changed as expected"); - assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); - assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); - assert.closeTo(final_STODAIBal.toNumber(), init_STODAIBal.toNumber(), TOLERANCE, "STO DAI Balance not changed as expected"); - assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); - assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), TOLERANCE, "Raised ETH not changed as expected"); - assert.closeTo(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), TOLERANCE, "Raised DAI not changed as expected"); - assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); - assert.closeTo(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), TOLERANCE, "Wallet DAI Balance not changed as expected"); - } else { - assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); - assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); - assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).sub(investment_ETH).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); - assert.closeTo(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), TOLERANCE, "Investor POLY Balance not changed as expected"); - assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); - assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); - assert.closeTo(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), TOLERANCE, "STO POLY Balance not changed as expected"); - assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); - assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), TOLERANCE, "Raised ETH not changed as expected"); - assert.closeTo(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), TOLERANCE, "Raised POLY not changed as expected"); - assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); - assert.closeTo(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), TOLERANCE, "Wallet POLY Balance not changed as expected"); - } - } - }); - }); -}); - -function near(x, y, message) { - assert.isAtMost(x, y) - -} +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); +// const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); +// const MockOracle = artifacts.require('./MockOracle.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port + +// const TOLERANCE = 2; // Allow balances to be off by 2 WEI for rounding purposes + +// contract('USDTieredSTO Sim', accounts => { +// // Accounts Variable declaration +// let POLYMATH; +// let ISSUER; +// let WALLET; +// let RESERVEWALLET; +// let INVESTOR1; +// let ACCREDITED1; +// let ACCREDITED2; +// let NONACCREDITED1; +// let NONACCREDITED2; +// let NOTWHITELISTED; +// let NOTAPPROVED; + +// let MESSAGE = "Transaction Should Fail!"; +// const GAS_PRICE = 10000000000; // 10 GWEI + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_GeneralTransferManagerFactory; +// let I_USDTieredSTOProxyFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_USDTieredSTOFactory; +// let I_USDOracle; +// let I_POLYOracle; +// let I_STFactory; +// let I_MRProxied; +// let I_STRProxied; +// let I_SecurityToken; +// let I_USDTieredSTO_Array = []; +// let I_PolyToken; +// let I_DaiToken; +// let I_PolymathRegistry; + +// // SecurityToken Details for funds raise Type ETH +// const NAME = "Team"; +// const SYMBOL = "SAP"; +// const TOKENDETAILS = "This is equity type of issuance"; +// const DECIMALS = 18; + +// // Module key +// const TMKEY = 2; +// const STOKEY = 3; + +// // Initial fee for ticker registry and security token registry +// const REGFEE = web3.utils.toWei("250"); +// const STOSetupCost = 0; + +// // MockOracle USD prices +// const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH +// const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY + +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// // STO Configuration Arrays +// let _startTime = []; +// let _endTime = []; +// let _ratePerTier = []; +// let _ratePerTierDiscountPoly = []; +// let _tokensPerTierTotal = []; +// let _tokensPerTierDiscountPoly = []; +// let _nonAccreditedLimitUSD = []; +// let _minimumInvestmentUSD = []; +// let _fundRaiseTypes = []; +// let _wallet = []; +// let _reserveWallet = []; +// let _usdToken = []; + +// /* function configure( +// uint256 _startTime, +// uint256 _endTime, +// uint256[] _ratePerTier, +// uint256[] _ratePerTierDiscountPoly, +// uint256[] _tokensPerTier, +// uint256[] _tokensPerTierDiscountPoly, +// uint256 _nonAccreditedLimitUSD, +// uint256 _minimumInvestmentUSD, +// uint8[] _fundRaiseTypes, +// address _wallet, +// address _reserveWallet, +// address _usdToken +// ) */ +// const functionSignature = { +// name: 'configure', +// type: 'function', +// inputs: [{ +// type: 'uint256', +// name: '_startTime' +// },{ +// type: 'uint256', +// name: '_endTime' +// },{ +// type: 'uint256[]', +// name: '_ratePerTier' +// },{ +// type: 'uint256[]', +// name: '_ratePerTierDiscountPoly' +// },{ +// type: 'uint256[]', +// name: '_tokensPerTier' +// },{ +// type: 'uint256[]', +// name: '_tokensPerTierDiscountPoly' +// },{ +// type: 'uint256', +// name: '_nonAccreditedLimitUSD' +// },{ +// type: 'uint256', +// name: '_minimumInvestmentUSD' +// },{ +// type: 'uint8[]', +// name: '_fundRaiseTypes' +// },{ +// type: 'address', +// name: '_wallet' +// },{ +// type: 'address', +// name: '_reserveWallet' +// },{ +// type: 'address', +// name: '_usdToken' +// }] +// }; + +// function getRandomInt(min, max) { +// return Math.floor(Math.random() * (max - min + 1)) + min; +// } + +// before(async() => { +// // Accounts setup +// POLYMATH = accounts[0]; +// ISSUER = accounts[1]; +// WALLET = accounts[2]; +// RESERVEWALLET = WALLET; +// ACCREDITED1 = accounts[3]; +// ACCREDITED2 = accounts[4]; +// NONACCREDITED1 = accounts[5]; +// NONACCREDITED2 = accounts[6]; +// NOTWHITELISTED = accounts[7]; +// NOTAPPROVED = accounts[8]; +// INVESTOR1 = accounts[9]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// I_DaiToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: POLYMATH +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + +// // STEP 3: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the proxy +// I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); + +// // STEP 6: Deploy the USDTieredSTOFactory + +// I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); + +// assert.notEqual( +// I_USDTieredSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "USDTieredSTOFactory contract was not deployed" +// ); + + + +// // Step 8: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 9: Deploy the SecurityTokenRegistry + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: update the registries addresses from the PolymathRegistry contract +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); +// await I_MRProxied.updateFromRegistry({from: POLYMATH}); + +// // STEP 7: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); + +// // (C) : Register the STOFactory +// await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); +// await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); + +// // Step 12: Deploy & Register Mock Oracles +// I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY +// I_POLYOracle = await MockOracle.new(I_PolyToken.address, "POLY", "USD", USDPOLY, { from: POLYMATH }); // 25 cents per POLY +// await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); +// await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// ModuleRegistry: ${ModuleRegistry.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// USDOracle: ${I_USDOracle.address} +// POLYOracle: ${I_POLYOracle.address} +// USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} +// USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Deploy the STO", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.getTokens(REGFEE, ISSUER); +// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); +// let tx = await I_STRProxied.registerTicker(ISSUER, SYMBOL, NAME, { from : ISSUER }); +// assert.equal(tx.logs[0].args._owner, ISSUER); +// assert.equal(tx.logs[0].args._ticker, SYMBOL); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.getTokens(REGFEE, ISSUER); +// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); +// assert.equal(tx.logs[1].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), TMKEY); +// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); + +// it("Should successfully attach the first STO module to the security token", async () => { +// let stoId = 0; + +// _startTime.push(latestTime() + duration.days(2)); +// _endTime.push(_startTime[stoId] + duration.days(100)); +// _ratePerTier.push([ +// BigNumber(0.05*10**18), BigNumber(0.13*10**18), BigNumber(0.17*10**18) +// ]); // [ 0.05 USD/Token, 0.10 USD/Token, 0.15 USD/Token ] +// _ratePerTierDiscountPoly.push([ +// BigNumber(0.05*10**18), BigNumber(0.08*10**18), BigNumber(0.13*10**18) +// ]); // [ 0.05 USD/Token, 0.08 USD/Token, 0.13 USD/Token ] +// _tokensPerTierTotal.push([ +// BigNumber(200*10**18), BigNumber(500*10**18), BigNumber(300*10**18) +// ]); // [ 1000 Token, 2000 Token, 1500 Token ] +// _tokensPerTierDiscountPoly.push([ +// BigNumber(0), BigNumber(50*10**18), BigNumber(300*10**18) +// ]); // [ 0 Token, 1000 Token, 1500 Token ] +// _nonAccreditedLimitUSD.push(BigNumber(10*10**18)); // 20 USD +// _minimumInvestmentUSD.push(BigNumber(0)); // 1 wei USD +// _fundRaiseTypes.push([0,1,2]); +// _wallet.push(WALLET); +// _reserveWallet.push(RESERVEWALLET); +// _usdToken.push(I_DaiToken.address); + +// let config = [ +// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], +// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], +// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] +// ]; + +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); +// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); +// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); +// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); +// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + +// assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); +// for (var i = 0; i < _ratePerTier[stoId].length; i++) { +// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); +// } +// assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getNumberOfTiers()), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); +// assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); +// }); + +// it("Should successfully prepare the STO", async() => { +// let stoId = 0; + +// // Start STO +// await increaseTime(duration.days(3)); + +// // Whitelist +// let fromTime = latestTime() + duration.days(15); +// let toTime = latestTime() + duration.days(15); +// let expiryTime = toTime + duration.days(100); +// let canBuyFromSTO = true; + +// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); +// await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, { from: ISSUER }); + +// await increaseTime(duration.days(3)); + +// // Accreditation +// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1, ACCREDITED2], [true, true], { from: ISSUER }); +// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, NONACCREDITED2], [false, false], { from: ISSUER }); +// }); +// }); + +// describe("Simulate purchasing", async() => { + +// it("Should successfully complete simulation", async() => { +// let stoId = 0; + +// console.log(` +// ------------------- Investor Addresses ------------------- +// ACCREDITED1: ${ACCREDITED1} +// ACCREDITED2: ${ACCREDITED2} +// NONACCREDITED1: ${NONACCREDITED1} +// NONACCREDITED2: ${NONACCREDITED2} +// NOTWHITELISTED: ${NOTWHITELISTED} +// NOTAPPROVED: ${NOTAPPROVED} +// ---------------------------------------------------------- +// `); + +// let totalTokens = BigNumber(0); +// for (var i = 0; i < _tokensPerTierTotal[stoId].length; i++) { +// totalTokens = totalTokens.add(_tokensPerTierTotal[stoId][i]); +// } +// console.log('totalTokens: '+totalTokens.div(10**18).toNumber()); +// let tokensSold = BigNumber(0); +// while (true) { +// switch (getRandomInt(0,5)) { +// case 0: // ACCREDITED1 +// await invest(ACCREDITED1, true); +// break; +// case 1: // ACCREDITED2 +// await invest(ACCREDITED2, true); +// break; +// case 2: // NONACCREDITED1 +// let usd_NONACCREDITED1 = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); +// if (_nonAccreditedLimitUSD[stoId].gt(usd_NONACCREDITED1)) // under non-accredited cap +// await invest(NONACCREDITED1, false); +// else // over non-accredited cap +// await investFAIL(NONACCREDITED1); +// break; +// case 3: // NONACCREDITED2 +// let usd_NONACCREDITED2 = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED2); +// if (_nonAccreditedLimitUSD[stoId].gt(usd_NONACCREDITED2)) // under non-accredited cap +// await invest(NONACCREDITED2, false); +// else // over non-accredited cap +// await investFAIL(NONACCREDITED2); +// break; +// case 4: // NOTWHITELISTED +// await investFAIL(NOTWHITELISTED); +// break; +// case 5: // NOTAPPROVED +// await investFAIL(NOTAPPROVED); +// break; +// } +// console.log("Next round"); +// tokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// console.log("Tokens Sold: " + tokensSold.toString()); +// if (tokensSold.gte(totalTokens.sub(1*10**18))) { +// console.log(`${tokensSold} tokens sold, simulation completed successfully!`.green); +// break; +// } +// } + +// async function invest(_investor, _isAccredited) { // need to add check if reached non-accredited cap +// let USD_remaining; +// if (!_isAccredited) { +// let USD_to_date = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(_investor); +// USD_remaining = _nonAccreditedLimitUSD[stoId].sub(USD_to_date); +// } else { +// USD_remaining = totalTokens.mul(2); +// } + +// let log_remaining = USD_remaining; +// let isPoly = Math.random() >= 0.33; +// let isDai = Math.random() >= 0.33; + +// let Token_counter = BigNumber(getRandomInt(1*10**10,50*10**10)).mul(10**8); +// let investment_USD = BigNumber(0); +// let investment_ETH = BigNumber(0); +// let investment_POLY = BigNumber(0); +// let investment_DAI = BigNumber(0); +// let investment_Token = BigNumber(0); + +// let Tokens_total = []; +// let Tokens_discount = []; +// for (var i = 0; i < _ratePerTier[stoId].length; i++) { +// Tokens_total.push((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(i))); +// Tokens_discount.push((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierDiscountPoly.call(i))); +// } + +// let tier = 0; +// let Token_Tier; +// let USD_Tier; +// let POLY_Tier; +// let ETH_Tier; +// let DAI_Tier; + + +// let USD_overflow; +// let Token_overflow; + +// while (Token_counter.gt(0)) { +// if (tier == _ratePerTier[stoId].length) { +// break; +// } +// if (Tokens_total[tier].gt(0)) { +// if (isPoly) { +// // 1. POLY and discount (consume up to cap then move to regular) +// if (Tokens_discount[tier].gt(0)) { +// Token_Tier = BigNumber.min([Tokens_total[tier], Tokens_discount[tier], Token_counter]); +// USD_Tier = Token_Tier.mul(_ratePerTierDiscountPoly[stoId][tier].div(10**18)); +// if (USD_Tier.gte(USD_remaining)) { +// USD_overflow = USD_Tier.sub(USD_remaining); +// Token_overflow = USD_overflow.mul(10**18).div(_ratePerTierDiscountPoly[stoId][tier]); +// USD_Tier = USD_Tier.sub(USD_overflow); +// Token_Tier = Token_Tier.sub(Token_overflow); +// Token_counter = BigNumber(0); +// } +// POLY_Tier = USD_Tier.mul(10**18).round(0).div(USDPOLY).round(0); +// USD_remaining = USD_remaining.sub(USD_Tier); +// Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); +// Tokens_discount[tier] = Tokens_discount[tier].sub(Token_Tier); +// Token_counter = Token_counter.sub(Token_Tier); +// investment_Token = investment_Token.add(Token_Tier); +// investment_USD = investment_USD.add(USD_Tier); +// investment_POLY = investment_POLY.add(POLY_Tier); +// } +// // 2. POLY and regular (consume up to cap then skip to next tier) +// if (Tokens_total[tier].gt(0) && Token_counter.gt(0)) { +// Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); +// USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); +// if (USD_Tier.gte(USD_remaining)) { +// USD_overflow = USD_Tier.sub(USD_remaining); +// Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); +// USD_Tier = USD_Tier.sub(USD_overflow); +// Token_Tier = Token_Tier.sub(Token_overflow); +// Token_counter = BigNumber(0); +// } +// POLY_Tier = USD_Tier.mul(10**18).round(0).div(USDPOLY).round(0); +// USD_remaining = USD_remaining.sub(USD_Tier); +// Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); +// Token_counter = Token_counter.sub(Token_Tier); +// investment_Token = investment_Token.add(Token_Tier); +// investment_USD = investment_USD.add(USD_Tier); +// investment_POLY = investment_POLY.add(POLY_Tier); +// } +// } else if (isDai) { +// // 3. DAI (consume up to cap then skip to next tier) +// Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); +// USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); +// if (USD_Tier.gte(USD_remaining)) { +// USD_overflow = USD_Tier.sub(USD_remaining); +// Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); +// USD_Tier = USD_Tier.sub(USD_overflow); +// Token_Tier = Token_Tier.sub(Token_overflow); +// Token_counter = BigNumber(0); +// } +// DAI_Tier = USD_Tier.round(0); +// USD_remaining = USD_remaining.sub(USD_Tier); +// Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); +// Token_counter = Token_counter.sub(Token_Tier); +// investment_Token = investment_Token.add(Token_Tier); +// investment_USD = investment_USD.add(USD_Tier); +// investment_DAI = investment_USD; +// } else { +// // 4. ETH (consume up to cap then skip to next tier) +// Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); +// USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); +// if (USD_Tier.gte(USD_remaining)) { +// USD_overflow = USD_Tier.sub(USD_remaining); +// Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); +// USD_Tier = USD_Tier.sub(USD_overflow); +// Token_Tier = Token_Tier.sub(Token_overflow); +// Token_counter = BigNumber(0); +// } +// ETH_Tier = USD_Tier.mul(10**18).round(0).div(USDETH).round(0); +// USD_remaining = USD_remaining.sub(USD_Tier); +// Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); +// Token_counter = Token_counter.sub(Token_Tier); +// investment_Token = investment_Token.add(Token_Tier); +// investment_USD = investment_USD.add(USD_Tier); +// investment_ETH = investment_ETH.add(ETH_Tier); +// } +// } +// tier++ +// } + +// await processInvestment(_investor, investment_Token, investment_USD, investment_POLY, investment_DAI, investment_ETH, isPoly, isDai, log_remaining, Tokens_total, Tokens_discount, tokensSold); +// } + +// async function investFAIL(_investor) { +// let isPoly = Math.random() >= 0.3; +// let isDAI = Math.random() >= 0.3; +// let investment_POLY = BigNumber(40*10**18); // 10 USD = 40 POLY +// let investment_ETH = BigNumber(0.02*10**18); // 10 USD = 0.02 ETH +// let investment_DAI = BigNumber(10*10**18); // 10 USD = DAI DAI + +// let errorThrown = false; +// try { +// if (isPoly) { +// await I_PolyToken.getTokens(investment_POLY, _investor); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: _investor}); +// await I_USDTieredSTO_Array[stoId].buyWithPOLY(_investor, investment_POLY, { from: _investor, gasPrice: GAS_PRICE }); +// } else if (isDAI) { +// await I_DaiToken.getTokens(investment_DAI, _investor); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: _investor}); +// await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); +// } else await I_USDTieredSTO_Array[stoId].buyWithETH(_investor, { from: _investor, value: investment_ETH, gasPrice: GAS_PRICE }); +// } catch(error) { +// errorThrown = true; +// console.log(`Purchase failed as expected: ${_investor}`.yellow); +// ensureException(error); +// } +// assert.ok(errorThrown, MESSAGE); +// } + +// async function processInvestment(_investor, investment_Token, investment_USD, investment_POLY, investment_DAI, investment_ETH, isPoly, isDai, log_remaining, Tokens_total, Tokens_discount, tokensSold) { +// investment_Token = investment_Token.round(0); +// investment_USD = investment_USD.round(0); +// investment_POLY = investment_POLY.round(0); +// investment_DAI = investment_DAI.round(0); +// investment_ETH = investment_ETH.round(0); +// console.log(` +// ------------------- New Investment ------------------- +// Investor: ${_investor} +// N-A USD Remaining: ${log_remaining.div(10**18)} +// Total Cap Remaining: ${Tokens_total} +// Discount Cap Remaining: ${Tokens_discount} +// Total Tokens Sold: ${tokensSold.div(10**18)} +// Token Investment: ${investment_Token.div(10**18)} +// USD Investment: ${investment_USD.div(10**18)} +// POLY Investment: ${investment_POLY.div(10**18)} +// DAI Investment: ${investment_DAI.div(10**18)} +// ETH Investment: ${investment_ETH.div(10**18)} +// ------------------------------------------------------ +// `); + +// if (isPoly) { +// await I_PolyToken.getTokens(investment_POLY, _investor); +// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: _investor}); +// } else if (isDai) { +// await I_DaiToken.getTokens(investment_DAI, _investor); +// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: _investor}); +// } + +// // console.log(await I_USDTieredSTO_Array[stoId].isOpen()); + +// let init_TokenSupply = await I_SecurityToken.totalSupply(); +// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(_investor); +// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(_investor)); +// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(_investor); +// let init_InvestorDAIBal = await I_DaiToken.balanceOf(_investor); +// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_STODAIBal = await I_DaiToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); +// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(0); +// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(1); +// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(2); +// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); +// let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + +// let tx; +// let gasCost = BigNumber(0); + +// if (isPoly && investment_POLY.gt(10)) { +// tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(_investor, investment_POLY, { from: _investor, gasPrice: GAS_PRICE }); +// gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); +// console.log(`buyWithPOLY: ${investment_Token.div(10**18)} tokens for ${investment_POLY.div(10**18)} POLY by ${_investor}`.yellow); +// } else if (isDai && investment_DAI.gt(10)) { +// tx = await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); +// gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); +// console.log(`buyWithUSD: ${investment_Token.div(10**18)} tokens for ${investment_DAI.div(10**18)} DAI by ${_investor}`.yellow); +// } else if (investment_ETH.gt(0)) { +// tx = await I_USDTieredSTO_Array[stoId].buyWithETH(_investor, { from: _investor, value: investment_ETH, gasPrice: GAS_PRICE }); +// gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); +// console.log(`buyWithETH: ${investment_Token.div(10**18)} tokens for ${investment_ETH.div(10**18)} ETH by ${_investor}`.yellow); +// } +// console.log(investment_POLY.toNumber()); + +// let final_TokenSupply = await I_SecurityToken.totalSupply(); +// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(_investor); +// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(_investor)); +// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(_investor); +// let final_InvestorDAIBal = await I_DaiToken.balanceOf(_investor); +// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); +// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); +// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_STODAIBal = await I_DaiToken.balanceOf(I_USDTieredSTO_Array[stoId].address); +// let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); +// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(0); +// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(1); +// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(2); +// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); +// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); +// let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + +// // console.log('init_TokenSupply: '+init_TokenSupply.div(10**18).toNumber()); +// // console.log('final_TokenSupply: '+final_TokenSupply.div(10**18).toNumber()); + +// if (isPoly) { +// assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); +// assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); +// assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); +// assert.closeTo(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), TOLERANCE, "Investor POLY Balance not changed as expected"); +// assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); +// assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); +// assert.closeTo(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), TOLERANCE, "STO POLY Balance not changed as expected"); +// assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); +// assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), TOLERANCE, "Raised ETH not changed as expected"); +// assert.closeTo(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), TOLERANCE, "Raised POLY not changed as expected"); +// assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); +// assert.closeTo(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), TOLERANCE, "Wallet POLY Balance not changed as expected"); +// } else if (isDai) { +// assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); +// assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); +// assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); +// assert.closeTo(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), TOLERANCE, "Investor DAI Balance not changed as expected"); +// assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); +// assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); +// assert.closeTo(final_STODAIBal.toNumber(), init_STODAIBal.toNumber(), TOLERANCE, "STO DAI Balance not changed as expected"); +// assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); +// assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), TOLERANCE, "Raised ETH not changed as expected"); +// assert.closeTo(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), TOLERANCE, "Raised DAI not changed as expected"); +// assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); +// assert.closeTo(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), TOLERANCE, "Wallet DAI Balance not changed as expected"); +// } else { +// assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); +// assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); +// assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).sub(investment_ETH).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); +// assert.closeTo(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), TOLERANCE, "Investor POLY Balance not changed as expected"); +// assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); +// assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); +// assert.closeTo(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), TOLERANCE, "STO POLY Balance not changed as expected"); +// assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); +// assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), TOLERANCE, "Raised ETH not changed as expected"); +// assert.closeTo(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), TOLERANCE, "Raised POLY not changed as expected"); +// assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); +// assert.closeTo(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), TOLERANCE, "Wallet POLY Balance not changed as expected"); +// } +// } +// }); +// }); +// }); + +// function near(x, y, message) { +// assert.isAtMost(x, y) + +// } diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 569534cad..592c5cc1c 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -1,365 +1,365 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// Import contract ABIs -const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -const CappedSTO = artifacts.require('./CappedSTO.sol'); -const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -const DummySTO = artifacts.require('./DummySTO.sol'); -const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); -const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('Concurrent STO', accounts => { - // Accounts variable declaration - let account_polymath; - let account_issuer; - let account_fundsReceiver; - let account_investor1; - let account_investor2; - let account_investor3; - - // Contract instance declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralPermissionManager; - let I_GeneralTransferManagerFactory; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_STFactory; - let I_MRProxied; - let I_STRProxied; - let I_SecurityTokenRegistry; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // STO instance declaration - let I_CappedSTOFactory; - let I_DummySTOFactory; - let I_PreSaleSTOFactory; - let I_STO_Array = []; - - // Error message - let message = "Transaction Should Fail!"; - - // Initial fees - const initRegFee = web3.utils.toWei("250"); - const STOSetupCost = 200 * Math.pow(10, 18); - - // Module keys - const transferManagerKey = 2; - const stoKey = 3; - - // Configure function signature for STO deployment - - const CappedSTOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - const DummySTOParameters = ['uint256', 'uint256', 'uint256', 'string']; - const PresaleSTOParameters = ['uint256']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - account_fundsReceiver = accounts[2]; - account_investor1 = accounts[3]; - account_investor2 = accounts[4]; - account_investor3 = accounts[5] - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_issuer); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 2: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 3: Deploy the GeneralPermissionManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 4: Deploy the STO Factories - - I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); - I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); - I_PreSaleSTOFactory = await PreSaleSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); - - assert.notEqual( - I_CappedSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CappedSTOFactory contract was not deployed" - ); - - - // Step 8: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// // Import contract ABIs +// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +// const CappedSTO = artifacts.require('./CappedSTO.sol'); +// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +// const DummySTO = artifacts.require('./DummySTO.sol'); +// const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); +// const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('Concurrent STO', accounts => { +// // Accounts variable declaration +// let account_polymath; +// let account_issuer; +// let account_fundsReceiver; +// let account_investor1; +// let account_investor2; +// let account_investor3; + +// // Contract instance declaration +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManagerFactory; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_STFactory; +// let I_MRProxied; +// let I_STRProxied; +// let I_SecurityTokenRegistry; +// let I_SecurityToken; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // STO instance declaration +// let I_CappedSTOFactory; +// let I_DummySTOFactory; +// let I_PreSaleSTOFactory; +// let I_STO_Array = []; + +// // Error message +// let message = "Transaction Should Fail!"; + +// // Initial fees +// const initRegFee = web3.utils.toWei("250"); +// const STOSetupCost = 200 * Math.pow(10, 18); + +// // Module keys +// const transferManagerKey = 2; +// const stoKey = 3; + +// // Configure function signature for STO deployment + +// const CappedSTOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; +// const DummySTOParameters = ['uint256', 'uint256', 'uint256', 'string']; +// const PresaleSTOParameters = ['uint256']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; +// account_fundsReceiver = accounts[2]; +// account_investor1 = accounts[3]; +// account_investor2 = accounts[4]; +// account_investor3 = accounts[5] + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_issuer); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 2: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 3: Deploy the GeneralPermissionManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the STO Factories + +// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); +// I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); +// I_PreSaleSTOFactory = await PreSaleSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); + +// assert.notEqual( +// I_CappedSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CappedSTOFactory contract was not deployed" +// ); + + +// // Step 8: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); - // Step 9: Deploy the SecurityTokenRegistry contract +// // Step 9: Deploy the SecurityTokenRegistry contract - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 5: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the STO Factories - await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - - await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - - await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - - CappedSTOFactory: ${I_CappedSTOFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate Security Token", async() => { - // SecurityToken Details for funds raise Type ETH - const name = "Team"; - const symbol = "SAP"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.getTokens(initRegFee, account_issuer); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_issuer }); - let tx = await I_STRProxied.registerTicker(account_issuer, symbol, name, { from : account_issuer }); - assert.equal(tx.logs[0].args._owner, account_issuer); - assert.equal(tx.logs[0].args._ticker, symbol); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.getTokens(initRegFee, account_issuer); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_issuer}); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_issuer }); - assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), transferManagerKey); - assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - it("Should whitelist account_investor1", async() => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); - let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = true; - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - fromTime, - toTime, - expiryTime, - canBuyFromSTO, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); - }); - }); - - describe("Add STO and verify transfer", async() => { - - it("Should attach STO modules up to the max number, then fail", async() => { - const MAX_MODULES = 10; - const startTime = latestTime() + duration.days(1); - const endTime = latestTime() + duration.days(90); - const cap = web3.utils.toWei("10000"); - const rate = 1000; - const fundRaiseType = [0]; - const budget = 0; - const maxCost = STOSetupCost; - const cappedBytesSig = encodeModuleCall(CappedSTOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - const dummyBytesSig = encodeModuleCall(DummySTOParameters, [startTime, endTime, cap, 'Hello']); - const presaleBytesSig = encodeModuleCall(PresaleSTOParameters, [endTime]); - - for (var STOIndex = 0; STOIndex < MAX_MODULES; STOIndex++) { - await I_PolyToken.getTokens(STOSetupCost, account_issuer); - await I_PolyToken.transfer(I_SecurityToken.address, STOSetupCost, { from: account_issuer }); - switch (STOIndex % 3) { - case 0: - // Capped STO - let tx1 = await I_SecurityToken.addModule(I_CappedSTOFactory.address, cappedBytesSig, maxCost, budget, { from: account_issuer }); - assert.equal(tx1.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); - assert.equal(web3.utils.hexToString(tx1.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); - I_STO_Array.push(CappedSTO.at(tx1.logs[3].args._module)); - break; - case 1: - // Dummy STO - let tx2 = await I_SecurityToken.addModule(I_DummySTOFactory.address, dummyBytesSig, maxCost, budget, { from: account_issuer }); - assert.equal(tx2.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); - assert.equal(web3.utils.hexToString(tx2.logs[3].args._name),"DummySTO",`Wrong STO module added at index ${STOIndex}`); - I_STO_Array.push(DummySTO.at(tx2.logs[3].args._module)); - break; - case 2: - // Pre Sale STO - let tx3 = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, presaleBytesSig, maxCost, budget, { from: account_issuer }); - assert.equal(tx3.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); - assert.equal(web3.utils.hexToString(tx3.logs[3].args._name),"PreSaleSTO",`Wrong STO module added at index ${STOIndex}`); - I_STO_Array.push(PreSaleSTO.at(tx3.logs[3].args._module)); - break; - } - } - - }); - - it("Should successfully invest in all modules attached", async() => { - const MAX_MODULES = 10; - await increaseTime(duration.days(2)); - for (var STOIndex = 0; STOIndex < MAX_MODULES; STOIndex++) { - switch (STOIndex % 3) { - case 0: - // Capped STO ETH - await I_STO_Array[STOIndex].buyTokens(account_investor1, { from : account_investor1, value: web3.utils.toWei('1', 'ether') }); - assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(0)).toString()), 1); - assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); - break; - case 1: - // Dummy STO - await I_STO_Array[STOIndex].generateTokens(account_investor1, web3.utils.toWei('1000'), { from : account_issuer }); - assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); - assert.equal( - (await I_STO_Array[STOIndex].investors.call(account_investor1)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000 - ); - break; - case 2: - // Pre Sale STO - await I_STO_Array[STOIndex].allocateTokens(account_investor1, web3.utils.toWei('1000'), web3.utils.toWei('1'), 0, { from : account_issuer }); - assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(0)).toString()), 1); - assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(1)).toString()), 0); - assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); - assert.equal( - (await I_STO_Array[STOIndex].investors.call(account_investor1)) - .dividedBy(new BigNumber(10).pow(18)) - .toNumber(), - 1000 - ); - break; - } - } - }); - }); -}); +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 5: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the STO Factories +// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + +// await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); + +// await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + +// CappedSTOFactory: ${I_CappedSTOFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate Security Token", async() => { +// // SecurityToken Details for funds raise Type ETH +// const name = "Team"; +// const symbol = "SAP"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.getTokens(initRegFee, account_issuer); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_issuer }); +// let tx = await I_STRProxied.registerTicker(account_issuer, symbol, name, { from : account_issuer }); +// assert.equal(tx.logs[0].args._owner, account_issuer); +// assert.equal(tx.logs[0].args._ticker, symbol); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.getTokens(initRegFee, account_issuer); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_issuer}); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_issuer }); +// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), transferManagerKey); +// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); + +// it("Should whitelist account_investor1", async() => { +// let fromTime = latestTime(); +// let toTime = latestTime() + duration.days(15); +// let expiryTime = toTime + duration.days(100); +// let canBuyFromSTO = true; + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// fromTime, +// toTime, +// expiryTime, +// canBuyFromSTO, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); +// }); +// }); + +// describe("Add STO and verify transfer", async() => { + +// it("Should attach STO modules up to the max number, then fail", async() => { +// const MAX_MODULES = 10; +// const startTime = latestTime() + duration.days(1); +// const endTime = latestTime() + duration.days(90); +// const cap = web3.utils.toWei("10000"); +// const rate = 1000; +// const fundRaiseType = [0]; +// const budget = 0; +// const maxCost = STOSetupCost; +// const cappedBytesSig = encodeModuleCall(CappedSTOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); +// const dummyBytesSig = encodeModuleCall(DummySTOParameters, [startTime, endTime, cap, 'Hello']); +// const presaleBytesSig = encodeModuleCall(PresaleSTOParameters, [endTime]); + +// for (var STOIndex = 0; STOIndex < MAX_MODULES; STOIndex++) { +// await I_PolyToken.getTokens(STOSetupCost, account_issuer); +// await I_PolyToken.transfer(I_SecurityToken.address, STOSetupCost, { from: account_issuer }); +// switch (STOIndex % 3) { +// case 0: +// // Capped STO +// let tx1 = await I_SecurityToken.addModule(I_CappedSTOFactory.address, cappedBytesSig, maxCost, budget, { from: account_issuer }); +// assert.equal(tx1.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); +// assert.equal(web3.utils.hexToString(tx1.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); +// I_STO_Array.push(CappedSTO.at(tx1.logs[3].args._module)); +// break; +// case 1: +// // Dummy STO +// let tx2 = await I_SecurityToken.addModule(I_DummySTOFactory.address, dummyBytesSig, maxCost, budget, { from: account_issuer }); +// assert.equal(tx2.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); +// assert.equal(web3.utils.hexToString(tx2.logs[3].args._name),"DummySTO",`Wrong STO module added at index ${STOIndex}`); +// I_STO_Array.push(DummySTO.at(tx2.logs[3].args._module)); +// break; +// case 2: +// // Pre Sale STO +// let tx3 = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, presaleBytesSig, maxCost, budget, { from: account_issuer }); +// assert.equal(tx3.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); +// assert.equal(web3.utils.hexToString(tx3.logs[3].args._name),"PreSaleSTO",`Wrong STO module added at index ${STOIndex}`); +// I_STO_Array.push(PreSaleSTO.at(tx3.logs[3].args._module)); +// break; +// } +// } + +// }); + +// it("Should successfully invest in all modules attached", async() => { +// const MAX_MODULES = 10; +// await increaseTime(duration.days(2)); +// for (var STOIndex = 0; STOIndex < MAX_MODULES; STOIndex++) { +// switch (STOIndex % 3) { +// case 0: +// // Capped STO ETH +// await I_STO_Array[STOIndex].buyTokens(account_investor1, { from : account_investor1, value: web3.utils.toWei('1', 'ether') }); +// assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(0)).toString()), 1); +// assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); +// break; +// case 1: +// // Dummy STO +// await I_STO_Array[STOIndex].generateTokens(account_investor1, web3.utils.toWei('1000'), { from : account_issuer }); +// assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); +// assert.equal( +// (await I_STO_Array[STOIndex].investors.call(account_investor1)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000 +// ); +// break; +// case 2: +// // Pre Sale STO +// await I_STO_Array[STOIndex].allocateTokens(account_investor1, web3.utils.toWei('1000'), web3.utils.toWei('1'), 0, { from : account_issuer }); +// assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(0)).toString()), 1); +// assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(1)).toString()), 0); +// assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); +// assert.equal( +// (await I_STO_Array[STOIndex].investors.call(account_investor1)) +// .dividedBy(new BigNumber(10).pow(18)) +// .toNumber(), +// 1000 +// ); +// break; +// } +// } +// }); +// }); +// }); diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js index f4dee4bf2..ee367a2a8 100644 --- a/test/s_v130_to_v140_upgrade.js +++ b/test/s_v130_to_v140_upgrade.js @@ -1,532 +1,532 @@ -const Web3 = require('web3'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -const BigNumber = require('bignumber.js'); - -import latestTime from './helpers/latestTime'; -import { duration } from './helpers/utils'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); -const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); -const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); -const CappedSTO = artifacts.require('./CappedSTO.sol'); -const PolyOracle = artifacts.require('./PolyOracle.sol'); -const ETHOracle = artifacts.require('./MakerDAOOracle.sol'); -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); -const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol'); - -contract('Upgrade from v1.3.0 to v1.4.0', accounts => { - // Accounts Variable declaration - let POLYMATH; - let ISSUER1; - let ISSUER2; - let ISSUER3; - let MULTISIG; - - //const GAS_PRICE = 10000000000; // 10 GWEI - - let tx; - - // Initial fee for ticker registry and security token registry - const REGFEE = web3.utils.toWei("250"); - const STOSetupCost = 0; - - // Module key - const STOKEY = 3; - const TMKEY = 2; - - // SecurityToken 1 Details - const symbol1 = "TOK1"; - const name1 = "TOK1 Token"; - const tokenDetails1 = "This is equity type of issuance"; - - //SecurityToken 2 Details - const symbol2 = "TOK2"; - const name2 = "TOK2 Token"; - const tokenDetails2 = "This is equity type of issuance"; - - //SecurityToken 3 Details - const symbol3 = "TOK3"; - const name3 = "TOK3 Token"; - const tokenDetails3 = "This is equity type of issuance"; - - // Contract Instance Declaration - let I_PolymathRegistry; - let I_PolyToken; - let I_DaiToken; - let I_ModuleRegistry; - let I_ModuleRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_FeatureRegistry; - let I_STFactory; - let I_MRProxied; - let I_STRProxied; - let I_STRProxiedNew; - - let I_SecurityTokenRegistry; - //let I_UpgradedSecurityTokenRegistry - - let I_SecurityToken1; - let I_SecurityToken2; - //let I_SecurityToken3; - - let I_USDTieredSTOFactory; - let I_USDTieredSTOProxyFactory - let I_USDOracle; - let I_POLYOracle; - let I_USDTieredSTO; - - let I_CappedSTOFactory; - let I_UpgradedCappedSTOFactory; - let I_CappedSTO; - let I_ManualApprovalTransferManagerFactory; - - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; - // Prepare polymath network status - before(async() => { - // Accounts setup - POLYMATH = accounts[0]; - ISSUER1 = accounts[1]; - ISSUER2 = accounts[2]; - ISSUER3 = accounts[3]; - MULTISIG = accounts[4]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); - assert.notEqual( - I_PolymathRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "PolymathRegistry contract was not deployed" - ); - - // Step 1: Deploy the token Faucet - I_PolyToken = await PolyTokenFaucet.new({from: POLYMATH}); - I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); - assert.notEqual( - I_PolyToken.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "PolyToken contract was not deployed" - ); - tx = await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) - assert.equal(tx.logs[0].args._nameKey, "PolyToken"); - assert.equal(tx.logs[0].args._newAddress, I_PolyToken.address); - - // STEP 2: Deploy the ModuleRegistry - I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - tx = await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); - assert.equal(tx.logs[0].args._nameKey, "ModuleRegistry"); - assert.equal(tx.logs[0].args._newAddress, I_ModuleRegistryProxy.address); - - // STEP 3: Deploy the GeneralTransferManagerFactory - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 4: Deploy the GeneralDelegateManagerFactory - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the CappedSTOFactory - I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); - assert.notEqual( - I_CappedSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CappedSTOFactory contract was not deployed" - ); - - // Step 8: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: POLYMATH - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: POLYMATH}); - await I_MRProxied.updateFromRegistry({from: POLYMATH}); - - // STEP 6: Register the Modules with the ModuleRegistry contract - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); - - // (C) : Register the CappedSTOFactory - await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: POLYMATH }); - await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: POLYMATH }); - - // Step 12: Mint tokens to ISSUERs - await I_PolyToken.getTokens(REGFEE * 2, ISSUER1); - await I_PolyToken.getTokens(REGFEE * 2, ISSUER2); - await I_PolyToken.getTokens(REGFEE * 2, ISSUER3); - - // Step 13: Register tokens - // (A) : TOK1 - await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER1 }); - tx = await I_STRProxied.registerTicker(ISSUER1, symbol1, name1, { from : ISSUER1 }); - assert.equal(tx.logs[0].args._owner, ISSUER1); - assert.equal(tx.logs[0].args._ticker, symbol1); - - // (B) : TOK2 - await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER2 }); - tx = await I_STRProxied.registerTicker(ISSUER2, symbol2, name2, { from : ISSUER2 }); - assert.equal(tx.logs[0].args._owner, ISSUER2); - assert.equal(tx.logs[0].args._ticker, symbol2); - - // (C) : TOK3 - await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER3 }); - tx = await I_STRProxied.registerTicker(ISSUER3, symbol3, name3, { from : ISSUER3 }); - assert.equal(tx.logs[0].args._owner, ISSUER3); - assert.equal(tx.logs[0].args._ticker, symbol3); - - // Step 14: Deploy tokens - // (A) : TOK1 - await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER1}); - let tx = await I_STRProxied.generateSecurityToken(name1, symbol1, tokenDetails1, false, { from: ISSUER1 }); - assert.equal(tx.logs[1].args._ticker, symbol1, "SecurityToken doesn't get deployed"); - I_SecurityToken1 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - // (B) : TOK2 - await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER2}); - tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails2, false, { from: ISSUER2 }); - assert.equal(tx.logs[1].args._ticker, symbol2, "SecurityToken doesn't get deployed"); - I_SecurityToken2 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - SecurityToken TOK1: ${I_SecurityToken1.address} - SecurityToken TOK2: ${I_SecurityToken2.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("USDTieredSTOFactory deploy", async() => { - // Step 1: Deploy Oracles - // 1a - Deploy POLY Oracle - it("Should successfully deploy POLY Oracle and register on PolymathRegistry", async() => { - I_POLYOracle = await PolyOracle.new({ from: POLYMATH, value: web3.utils.toWei("1")}); - console.log(I_POLYOracle.address); - assert.notEqual( - I_POLYOracle.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "POLYOracle contract was not deployed", - ); - tx = await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); - assert.equal(tx.logs[0].args._nameKey, "PolyUsdOracle"); - assert.equal(tx.logs[0].args._newAddress, I_POLYOracle.address); - }); - // 1b - Deploy ETH Oracle - it("Should successfully deploy ETH Oracle and register on PolymathRegistry", async() => { - I_USDOracle = await ETHOracle.new("0x216d678c14be600cb88338e763bb57755ca2b1cf", "0x0000000000000000000000000000000000000000", "ETH", { from: POLYMATH }); - assert.notEqual( - I_USDOracle.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "USDOracle contract was not deployed", - ); - tx = await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); - assert.equal(tx.logs[0].args._nameKey, "EthUsdOracle"); - assert.equal(tx.logs[0].args._newAddress, I_USDOracle.address); - }); - }); - - describe("USDTieredSTOFactory deploy", async() => { - // Step 1: Deploy USDTieredSTOFactory\ - it("Should successfully deploy USDTieredSTOFactory", async() => { - I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new(); - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: POLYMATH }); - assert.notEqual( - I_USDTieredSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "USDTieredSTOFactory contract was not deployed" - ); - let setupCost = await I_USDTieredSTOFactory.setupCost({ from: POLYMATH }); - assert.equal(setupCost, STOSetupCost); - }); - // Step 2: Register and verify - it("Should successfully register and verify USDTieredSTOFactory contract", async() => { - let tx = await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); - assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); - tx = await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); - assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); - assert.isTrue(tx.logs[0].args._verified); - }); - }); - - describe("CappedSTOFactory deploy", async() => { - // Step 1: Deploy new CappedSTOFactory - it("Should successfully deploy CappedSTOFactory", async() => { - I_UpgradedCappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); - assert.notEqual( - I_UpgradedCappedSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CappedSTOFactory contract was not deployed" - ); - let setupCost = await I_UpgradedCappedSTOFactory.setupCost({ from: POLYMATH }); - assert.equal(setupCost, STOSetupCost); - }); - - // Step 2: Register and verify - it("Should successfully register and verify new CappedSTOFactory contract", async() => { - let tx = await I_MRProxied.registerModule(I_UpgradedCappedSTOFactory.address, { from: POLYMATH }); - assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); - tx = await I_MRProxied.verifyModule(I_UpgradedCappedSTOFactory.address, true, { from: POLYMATH }); - assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); - assert.isTrue(tx.logs[0].args._verified); - }); - - // Step 3: Unverify old CappedSTOFactory - it("Should successfully unverify old CappedSTOFactory contract", async() => { - let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory.address, false, { from: POLYMATH }); - assert.equal(tx.logs[0].args._moduleFactory, I_CappedSTOFactory.address); - assert.isFalse(tx.logs[0].args._verified); - }); - }); - - describe("ManualApprovalTransferManagerFactory deploy", async() => { - // Step 1: Deploy new ManualApprovalTransferManager - it("Should successfully deploy ManualApprovalTransferManagerFactory", async() => { - I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - assert.notEqual( - I_ManualApprovalTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ManualApprovalTransferManagerFactory contract was not deployed" - ); - }); - - // Step 2: Register and verify - it("Should successfully register and verify new ManualApprovalTransferManagerFactory contract", async() => { - let tx = await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: POLYMATH }); - assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); - tx = await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: POLYMATH }); - assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); - assert.isTrue(tx.logs[0].args._verified); - }); - }); - - describe("Change ownerships", async() => { - /* - // Step 1: SecurityTokenRegistry - it("Should successfully change ownership of new SecurityTokenRegistry contract", async() => { - let tx = await I_STRProxiedNew.transferOwnership(MULTISIG, { from: POLYMATH }); - assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous owner was not Polymath account"); - assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New owner is not Multisig account"); - }); - */ - - // Step 2: Oracles - it("Should successfully change ownership of both Oracles contract", async() => { - let tx = await I_USDOracle.transferOwnership(MULTISIG, { from: POLYMATH }); - assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous ETH Oracle owner was not Polymath account"); - assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New ETH Oracle owner is not Multisig account"); - - tx = await I_POLYOracle.transferOwnership(MULTISIG, { from: POLYMATH }); - assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous POLY Oracle owner was not Polymath account"); - assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New POLY Oracle owner is not Multisig account"); - }); - - // Step 3: USDTieredSTOFactory - it("Should successfully change ownership of USDTieredSTOFactory contract", async() => { - let tx = await I_USDTieredSTOFactory.transferOwnership(MULTISIG, { from: POLYMATH }); - assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous USDTieredSTOFactory owner was not Polymath account"); - assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New USDTieredSTOFactory owner is not Multisig account"); - }); - - // Step 3: CappedSTOFactory - it("Should successfully change ownership of CappedSTOFactory contract", async() => { - let tx = await I_UpgradedCappedSTOFactory.transferOwnership(MULTISIG, { from: POLYMATH }); - assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous USDTieredSTOFactory owner was not Polymath account"); - assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New USDTieredSTOFactory owner is not Multisig account"); - }); - - // Step 4: ManualApprovalTransferManagerFactory - it("Should successfully change ownership of ManualApprovalTransferManagerFactory contract", async() => { - let tx = await I_ManualApprovalTransferManagerFactory.transferOwnership(MULTISIG, { from: POLYMATH }); - assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous ManualApprovalTransferManagerFactory owner was not Polymath account"); - assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New ManualApprovalTransferManagerFactory owner is not Multisig account"); - }); - }); - - describe("Polymath network status post migration", async() => { - // Launch STO for TOK1 - it("Should successfully launch USDTieredSTO for first security token", async() => { - let _startTime = latestTime() + duration.days(1); - let _endTime = _startTime + duration.days(180); - let _ratePerTier = [BigNumber(0.1).mul(10**18), BigNumber(0.15).mul(10**18), BigNumber(0.2).mul(10**18)]; - let _ratePerTierDiscountPoly = [BigNumber(0), BigNumber(0), BigNumber(0)]; - let _tokensPerTierTotal = [BigNumber(100).mul(10**18), BigNumber(200).mul(10**18), BigNumber(300).mul(10**18)]; - let _tokensPerTierDiscountPoly = [BigNumber(0), BigNumber(0), BigNumber(0)]; - let _nonAccreditedLimitUSD = BigNumber(100).mul(10**18); - let _minimumInvestmentUSD = BigNumber(5).mul(10**18); - let _fundRaiseTypes = [0, 1]; - let _wallet = ISSUER1; - let _reserveWallet = ISSUER1; - let _usdToken = I_DaiToken.address; - - let config = [ - _startTime, _endTime, _ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, - _tokensPerTierDiscountPoly, _nonAccreditedLimitUSD, _minimumInvestmentUSD, - _fundRaiseTypes, _wallet, _reserveWallet, _usdToken - ]; - - let functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256[]', - name: '_ratePerTier' - },{ - type: 'uint256[]', - name: '_ratePerTierDiscountPoly' - },{ - type: 'uint256[]', - name: '_tokensPerTier' - },{ - type: 'uint256[]', - name: '_tokensPerTierDiscountPoly' - },{ - type: 'uint256', - name: '_nonAccreditedLimitUSD' - },{ - type: 'uint256', - name: '_minimumInvestmentUSD' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes' - },{ - type: 'address', - name: '_wallet' - },{ - type: 'address', - name: '_reserveWallet' - },{ - type: 'address', - name: '_usdToken' - }] - }; - - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - - let tx = await I_SecurityToken1.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER1 }); - assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); - I_USDTieredSTO = USDTieredSTO.at(tx.logs[2].args._module); - }); - - /* - // Deploy TOK3 - it("Should successfully deploy third security token", async() => { - await I_PolyToken.approve(I_STRProxiedNew.address, REGFEE, { from: ISSUER3}); - tx = await I_STRProxiedNew.generateSecurityToken(name3, symbol3, tokenDetails3, false, { from: ISSUER3 }); - assert.equal(tx.logs[1].args._ticker, symbol3, "SecurityToken doesn't get deployed"); - I_SecurityToken3 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - }); - */ - - // Launch NewCappedSTO for TOK2 - it("Should successfully launch CappedSTO for third security token", async() => { - let startTime = latestTime() + duration.days(1); - let endTime = startTime + duration.days(30); - let cap = web3.utils.toWei("500000"); - let rate = 1000; - let fundRaiseType = 0; - let fundsReceiver = ISSUER3; - - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [fundRaiseType], fundsReceiver]); - - let tx = await I_SecurityToken2.addModule(I_UpgradedCappedSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER2 }); - assert.equal(tx.logs[2].args._types[0], STOKEY, "CappedSTO doesn't get deployed"); - assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"CappedSTO","CappedSTOFactory module was not added"); - }); - - // Attach ManualApprovalTransferManager module for TOK2 - it("Should successfully attach the ManualApprovalTransferManagerFactory with the second token", async () => { - const tx = await I_SecurityToken2.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: ISSUER2 }); - assert.equal(tx.logs[2].args._types[0].toNumber(), TMKEY, "ManualApprovalTransferManagerFactory doesn't get deployed"); - assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManagerFactory module was not added"); - I_ManualApprovalTransferManagerFactory = ManualApprovalTransferManagerFactory.at(tx.logs[2].args._module); - }); - }); -}); +// const Web3 = require('web3'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port +// const BigNumber = require('bignumber.js'); + +// import latestTime from './helpers/latestTime'; +// import { duration } from './helpers/utils'; +// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); +// const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); +// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +// const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); +// const CappedSTO = artifacts.require('./CappedSTO.sol'); +// const PolyOracle = artifacts.require('./PolyOracle.sol'); +// const ETHOracle = artifacts.require('./MakerDAOOracle.sol'); +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); +// const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol'); + +// contract('Upgrade from v1.3.0 to v1.4.0', accounts => { +// // Accounts Variable declaration +// let POLYMATH; +// let ISSUER1; +// let ISSUER2; +// let ISSUER3; +// let MULTISIG; + +// //const GAS_PRICE = 10000000000; // 10 GWEI + +// let tx; + +// // Initial fee for ticker registry and security token registry +// const REGFEE = web3.utils.toWei("250"); +// const STOSetupCost = 0; + +// // Module key +// const STOKEY = 3; +// const TMKEY = 2; + +// // SecurityToken 1 Details +// const symbol1 = "TOK1"; +// const name1 = "TOK1 Token"; +// const tokenDetails1 = "This is equity type of issuance"; + +// //SecurityToken 2 Details +// const symbol2 = "TOK2"; +// const name2 = "TOK2 Token"; +// const tokenDetails2 = "This is equity type of issuance"; + +// //SecurityToken 3 Details +// const symbol3 = "TOK3"; +// const name3 = "TOK3 Token"; +// const tokenDetails3 = "This is equity type of issuance"; + +// // Contract Instance Declaration +// let I_PolymathRegistry; +// let I_PolyToken; +// let I_DaiToken; +// let I_ModuleRegistry; +// let I_ModuleRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_FeatureRegistry; +// let I_STFactory; +// let I_MRProxied; +// let I_STRProxied; +// let I_STRProxiedNew; + +// let I_SecurityTokenRegistry; +// //let I_UpgradedSecurityTokenRegistry + +// let I_SecurityToken1; +// let I_SecurityToken2; +// //let I_SecurityToken3; + +// let I_USDTieredSTOFactory; +// let I_USDTieredSTOProxyFactory +// let I_USDOracle; +// let I_POLYOracle; +// let I_USDTieredSTO; + +// let I_CappedSTOFactory; +// let I_UpgradedCappedSTOFactory; +// let I_CappedSTO; +// let I_ManualApprovalTransferManagerFactory; + +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; +// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; +// // Prepare polymath network status +// before(async() => { +// // Accounts setup +// POLYMATH = accounts[0]; +// ISSUER1 = accounts[1]; +// ISSUER2 = accounts[2]; +// ISSUER3 = accounts[3]; +// MULTISIG = accounts[4]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); +// assert.notEqual( +// I_PolymathRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "PolymathRegistry contract was not deployed" +// ); + +// // Step 1: Deploy the token Faucet +// I_PolyToken = await PolyTokenFaucet.new({from: POLYMATH}); +// I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); +// assert.notEqual( +// I_PolyToken.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "PolyToken contract was not deployed" +// ); +// tx = await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) +// assert.equal(tx.logs[0].args._nameKey, "PolyToken"); +// assert.equal(tx.logs[0].args._newAddress, I_PolyToken.address); + +// // STEP 2: Deploy the ModuleRegistry +// I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// tx = await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); +// assert.equal(tx.logs[0].args._nameKey, "ModuleRegistry"); +// assert.equal(tx.logs[0].args._newAddress, I_ModuleRegistryProxy.address); + +// // STEP 3: Deploy the GeneralTransferManagerFactory +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the GeneralDelegateManagerFactory +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the CappedSTOFactory +// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); +// assert.notEqual( +// I_CappedSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CappedSTOFactory contract was not deployed" +// ); + +// // Step 8: Deploy the STFactory contract +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 9: Deploy the SecurityTokenRegistry + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 10: update the registries addresses from the PolymathRegistry contract +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 10: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: POLYMATH +// }); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); + +// assert.notEqual( +// I_FeatureRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "FeatureRegistry contract was not deployed", +// ); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: POLYMATH}); +// await I_MRProxied.updateFromRegistry({from: POLYMATH}); + +// // STEP 6: Register the Modules with the ModuleRegistry contract +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); + +// // (C) : Register the CappedSTOFactory +// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: POLYMATH }); +// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: POLYMATH }); + +// // Step 12: Mint tokens to ISSUERs +// await I_PolyToken.getTokens(REGFEE * 2, ISSUER1); +// await I_PolyToken.getTokens(REGFEE * 2, ISSUER2); +// await I_PolyToken.getTokens(REGFEE * 2, ISSUER3); + +// // Step 13: Register tokens +// // (A) : TOK1 +// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER1 }); +// tx = await I_STRProxied.registerTicker(ISSUER1, symbol1, name1, { from : ISSUER1 }); +// assert.equal(tx.logs[0].args._owner, ISSUER1); +// assert.equal(tx.logs[0].args._ticker, symbol1); + +// // (B) : TOK2 +// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER2 }); +// tx = await I_STRProxied.registerTicker(ISSUER2, symbol2, name2, { from : ISSUER2 }); +// assert.equal(tx.logs[0].args._owner, ISSUER2); +// assert.equal(tx.logs[0].args._ticker, symbol2); + +// // (C) : TOK3 +// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER3 }); +// tx = await I_STRProxied.registerTicker(ISSUER3, symbol3, name3, { from : ISSUER3 }); +// assert.equal(tx.logs[0].args._owner, ISSUER3); +// assert.equal(tx.logs[0].args._ticker, symbol3); + +// // Step 14: Deploy tokens +// // (A) : TOK1 +// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER1}); +// let tx = await I_STRProxied.generateSecurityToken(name1, symbol1, tokenDetails1, false, { from: ISSUER1 }); +// assert.equal(tx.logs[1].args._ticker, symbol1, "SecurityToken doesn't get deployed"); +// I_SecurityToken1 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// // (B) : TOK2 +// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER2}); +// tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails2, false, { from: ISSUER2 }); +// assert.equal(tx.logs[1].args._ticker, symbol2, "SecurityToken doesn't get deployed"); +// I_SecurityToken2 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// ModuleRegistry: ${ModuleRegistry.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// SecurityToken TOK1: ${I_SecurityToken1.address} +// SecurityToken TOK2: ${I_SecurityToken2.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("USDTieredSTOFactory deploy", async() => { +// // Step 1: Deploy Oracles +// // 1a - Deploy POLY Oracle +// it("Should successfully deploy POLY Oracle and register on PolymathRegistry", async() => { +// I_POLYOracle = await PolyOracle.new({ from: POLYMATH, value: web3.utils.toWei("1")}); +// console.log(I_POLYOracle.address); +// assert.notEqual( +// I_POLYOracle.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "POLYOracle contract was not deployed", +// ); +// tx = await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); +// assert.equal(tx.logs[0].args._nameKey, "PolyUsdOracle"); +// assert.equal(tx.logs[0].args._newAddress, I_POLYOracle.address); +// }); +// // 1b - Deploy ETH Oracle +// it("Should successfully deploy ETH Oracle and register on PolymathRegistry", async() => { +// I_USDOracle = await ETHOracle.new("0x216d678c14be600cb88338e763bb57755ca2b1cf", "0x0000000000000000000000000000000000000000", "ETH", { from: POLYMATH }); +// assert.notEqual( +// I_USDOracle.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "USDOracle contract was not deployed", +// ); +// tx = await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); +// assert.equal(tx.logs[0].args._nameKey, "EthUsdOracle"); +// assert.equal(tx.logs[0].args._newAddress, I_USDOracle.address); +// }); +// }); + +// describe("USDTieredSTOFactory deploy", async() => { +// // Step 1: Deploy USDTieredSTOFactory\ +// it("Should successfully deploy USDTieredSTOFactory", async() => { +// I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new(); +// I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: POLYMATH }); +// assert.notEqual( +// I_USDTieredSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "USDTieredSTOFactory contract was not deployed" +// ); +// let setupCost = await I_USDTieredSTOFactory.setupCost({ from: POLYMATH }); +// assert.equal(setupCost, STOSetupCost); +// }); +// // Step 2: Register and verify +// it("Should successfully register and verify USDTieredSTOFactory contract", async() => { +// let tx = await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); +// assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); +// tx = await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); +// assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); +// assert.isTrue(tx.logs[0].args._verified); +// }); +// }); + +// describe("CappedSTOFactory deploy", async() => { +// // Step 1: Deploy new CappedSTOFactory +// it("Should successfully deploy CappedSTOFactory", async() => { +// I_UpgradedCappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); +// assert.notEqual( +// I_UpgradedCappedSTOFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "CappedSTOFactory contract was not deployed" +// ); +// let setupCost = await I_UpgradedCappedSTOFactory.setupCost({ from: POLYMATH }); +// assert.equal(setupCost, STOSetupCost); +// }); + +// // Step 2: Register and verify +// it("Should successfully register and verify new CappedSTOFactory contract", async() => { +// let tx = await I_MRProxied.registerModule(I_UpgradedCappedSTOFactory.address, { from: POLYMATH }); +// assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); +// tx = await I_MRProxied.verifyModule(I_UpgradedCappedSTOFactory.address, true, { from: POLYMATH }); +// assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); +// assert.isTrue(tx.logs[0].args._verified); +// }); + +// // Step 3: Unverify old CappedSTOFactory +// it("Should successfully unverify old CappedSTOFactory contract", async() => { +// let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory.address, false, { from: POLYMATH }); +// assert.equal(tx.logs[0].args._moduleFactory, I_CappedSTOFactory.address); +// assert.isFalse(tx.logs[0].args._verified); +// }); +// }); + +// describe("ManualApprovalTransferManagerFactory deploy", async() => { +// // Step 1: Deploy new ManualApprovalTransferManager +// it("Should successfully deploy ManualApprovalTransferManagerFactory", async() => { +// I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); +// assert.notEqual( +// I_ManualApprovalTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "ManualApprovalTransferManagerFactory contract was not deployed" +// ); +// }); + +// // Step 2: Register and verify +// it("Should successfully register and verify new ManualApprovalTransferManagerFactory contract", async() => { +// let tx = await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: POLYMATH }); +// assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); +// tx = await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: POLYMATH }); +// assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); +// assert.isTrue(tx.logs[0].args._verified); +// }); +// }); + +// describe("Change ownerships", async() => { +// /* +// // Step 1: SecurityTokenRegistry +// it("Should successfully change ownership of new SecurityTokenRegistry contract", async() => { +// let tx = await I_STRProxiedNew.transferOwnership(MULTISIG, { from: POLYMATH }); +// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous owner was not Polymath account"); +// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New owner is not Multisig account"); +// }); +// */ + +// // Step 2: Oracles +// it("Should successfully change ownership of both Oracles contract", async() => { +// let tx = await I_USDOracle.transferOwnership(MULTISIG, { from: POLYMATH }); +// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous ETH Oracle owner was not Polymath account"); +// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New ETH Oracle owner is not Multisig account"); + +// tx = await I_POLYOracle.transferOwnership(MULTISIG, { from: POLYMATH }); +// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous POLY Oracle owner was not Polymath account"); +// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New POLY Oracle owner is not Multisig account"); +// }); + +// // Step 3: USDTieredSTOFactory +// it("Should successfully change ownership of USDTieredSTOFactory contract", async() => { +// let tx = await I_USDTieredSTOFactory.transferOwnership(MULTISIG, { from: POLYMATH }); +// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous USDTieredSTOFactory owner was not Polymath account"); +// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New USDTieredSTOFactory owner is not Multisig account"); +// }); + +// // Step 3: CappedSTOFactory +// it("Should successfully change ownership of CappedSTOFactory contract", async() => { +// let tx = await I_UpgradedCappedSTOFactory.transferOwnership(MULTISIG, { from: POLYMATH }); +// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous USDTieredSTOFactory owner was not Polymath account"); +// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New USDTieredSTOFactory owner is not Multisig account"); +// }); + +// // Step 4: ManualApprovalTransferManagerFactory +// it("Should successfully change ownership of ManualApprovalTransferManagerFactory contract", async() => { +// let tx = await I_ManualApprovalTransferManagerFactory.transferOwnership(MULTISIG, { from: POLYMATH }); +// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous ManualApprovalTransferManagerFactory owner was not Polymath account"); +// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New ManualApprovalTransferManagerFactory owner is not Multisig account"); +// }); +// }); + +// describe("Polymath network status post migration", async() => { +// // Launch STO for TOK1 +// it("Should successfully launch USDTieredSTO for first security token", async() => { +// let _startTime = latestTime() + duration.days(1); +// let _endTime = _startTime + duration.days(180); +// let _ratePerTier = [BigNumber(0.1).mul(10**18), BigNumber(0.15).mul(10**18), BigNumber(0.2).mul(10**18)]; +// let _ratePerTierDiscountPoly = [BigNumber(0), BigNumber(0), BigNumber(0)]; +// let _tokensPerTierTotal = [BigNumber(100).mul(10**18), BigNumber(200).mul(10**18), BigNumber(300).mul(10**18)]; +// let _tokensPerTierDiscountPoly = [BigNumber(0), BigNumber(0), BigNumber(0)]; +// let _nonAccreditedLimitUSD = BigNumber(100).mul(10**18); +// let _minimumInvestmentUSD = BigNumber(5).mul(10**18); +// let _fundRaiseTypes = [0, 1]; +// let _wallet = ISSUER1; +// let _reserveWallet = ISSUER1; +// let _usdToken = I_DaiToken.address; + +// let config = [ +// _startTime, _endTime, _ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, +// _tokensPerTierDiscountPoly, _nonAccreditedLimitUSD, _minimumInvestmentUSD, +// _fundRaiseTypes, _wallet, _reserveWallet, _usdToken +// ]; + +// let functionSignature = { +// name: 'configure', +// type: 'function', +// inputs: [{ +// type: 'uint256', +// name: '_startTime' +// },{ +// type: 'uint256', +// name: '_endTime' +// },{ +// type: 'uint256[]', +// name: '_ratePerTier' +// },{ +// type: 'uint256[]', +// name: '_ratePerTierDiscountPoly' +// },{ +// type: 'uint256[]', +// name: '_tokensPerTier' +// },{ +// type: 'uint256[]', +// name: '_tokensPerTierDiscountPoly' +// },{ +// type: 'uint256', +// name: '_nonAccreditedLimitUSD' +// },{ +// type: 'uint256', +// name: '_minimumInvestmentUSD' +// },{ +// type: 'uint8[]', +// name: '_fundRaiseTypes' +// },{ +// type: 'address', +// name: '_wallet' +// },{ +// type: 'address', +// name: '_reserveWallet' +// },{ +// type: 'address', +// name: '_usdToken' +// }] +// }; + +// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + +// let tx = await I_SecurityToken1.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER1 }); +// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); +// I_USDTieredSTO = USDTieredSTO.at(tx.logs[2].args._module); +// }); + +// /* +// // Deploy TOK3 +// it("Should successfully deploy third security token", async() => { +// await I_PolyToken.approve(I_STRProxiedNew.address, REGFEE, { from: ISSUER3}); +// tx = await I_STRProxiedNew.generateSecurityToken(name3, symbol3, tokenDetails3, false, { from: ISSUER3 }); +// assert.equal(tx.logs[1].args._ticker, symbol3, "SecurityToken doesn't get deployed"); +// I_SecurityToken3 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); +// }); +// */ + +// // Launch NewCappedSTO for TOK2 +// it("Should successfully launch CappedSTO for third security token", async() => { +// let startTime = latestTime() + duration.days(1); +// let endTime = startTime + duration.days(30); +// let cap = web3.utils.toWei("500000"); +// let rate = 1000; +// let fundRaiseType = 0; +// let fundsReceiver = ISSUER3; + +// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [fundRaiseType], fundsReceiver]); + +// let tx = await I_SecurityToken2.addModule(I_UpgradedCappedSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER2 }); +// assert.equal(tx.logs[2].args._types[0], STOKEY, "CappedSTO doesn't get deployed"); +// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"CappedSTO","CappedSTOFactory module was not added"); +// }); + +// // Attach ManualApprovalTransferManager module for TOK2 +// it("Should successfully attach the ManualApprovalTransferManagerFactory with the second token", async () => { +// const tx = await I_SecurityToken2.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: ISSUER2 }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), TMKEY, "ManualApprovalTransferManagerFactory doesn't get deployed"); +// assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManagerFactory module was not added"); +// I_ManualApprovalTransferManagerFactory = ManualApprovalTransferManagerFactory.at(tx.logs[2].args._module); +// }); +// }); +// }); diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 7032337f7..7b2c2c54f 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -1,348 +1,348 @@ -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { encodeProxyCall } from './helpers/encodeCall'; - -const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); -const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); -const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); -const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); -const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') -const STFactory = artifacts.require('./STFactory.sol'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract ("SecurityTokenRegistryProxy", accounts => { - - - let I_SecurityTokenRegistry; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_SecurityTokenRegistryMock; - let I_STFactory; - let I_PolymathRegistry; - let I_ModuleRegistryProxy; - let I_PolyToken; - let I_STRProxied; - let I_MRProxied; - let I_SecurityToken; - let I_ModuleRegistry; - let I_FeatureRegistry; - - let account_polymath; - let account_temp; - let token_owner; - let account_polymath_new; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - const version = "1.0.0"; - const message = "Transaction Should Fail!"; - - // SecurityToken Details for funds raise Type ETH - const name = "Team"; - const symbol = "SAP"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - - const transferManagerKey = 2; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - async function readStorage(contractAddress, slot) { - return await web3.eth.getStorageAt(contractAddress, slot); - } - - before(async() => { - account_polymath = accounts[0]; - account_temp = accounts[1]; - token_owner = accounts[2]; - account_polymath_new = accounts[3]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // Register the Modules with the ModuleRegistry contract - - - // Step 3: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 4: Deploy the SecurityTokenRegistry - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Attach the implementation address", async() => { - - // Storage - // __version -- index 11 - // __implementation -- index 12 - // __upgradeabilityOwner -- index 13 - - it("Should attach the implementation and version", async() => { - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); - assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address); - assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.0.0"); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - }); - - it("Verify the initialize data", async() => { - assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), 60*24*60*60, "Should equal to 60 days"); - assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee"))).toNumber(), web3.utils.toWei("250")); - }); - - }) - - describe("Feed some data in storage", async() => { - - it("Register the ticker", async() => { - await I_PolyToken.getTokens(web3.utils.toWei("1000"), token_owner); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner, "Owner should be the same as registered with the ticker"); - assert.equal(tx.logs[0].args._ticker, symbol, "Same as the symbol registered in the registerTicker function call"); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), transferManagerKey); - assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); - }); - }) - - describe("Upgrade the imlplementation address", async() => { - - it("Should upgrade the version and implementation address -- fail bad owner", async() => { - let errorThrown = false; - I_SecurityTokenRegistryMock = await SecurityTokenRegistryMock.new({from: account_polymath}); - try { - await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryMock.address, {from: account_temp}); - } catch(error) { - console.log(` tx -> revert bad owner of the proxy contract`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- Implementaion address should be a contract address", async() => { - let errorThrown = false; - try { - await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", account_temp, {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert Implementaion address should be a contract address`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async() => { - let errorThrown = false; - try { - await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert Implemenation address should not be 0x`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- Implemenation address should not be the same address", async() => { - let errorThrown = false; - try { - await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistry.address, {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert Implemenation address should not be the same address`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- same version as previous is not allowed", async() => { - let errorThrown = false; - try { - await I_SecurityTokenRegistryProxy.upgradeTo("1.0.0", I_SecurityTokenRegistryMock.address, {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert same version as previous is not allowed`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- empty version string is not allowed", async() => { - let errorThrown = false; - try { - await I_SecurityTokenRegistryProxy.upgradeTo("", I_SecurityTokenRegistryMock.address, {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert empty version string is not allowed`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and the implementation address successfully", async() => { - await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryMock.address, {from: account_polymath}); - let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); - assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.1.0", "Version mis-match"); - assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistryMock.address, "Implemnted address is not matched"); - I_STRProxied = await SecurityTokenRegistryMock.at(I_SecurityTokenRegistryProxy.address); - }); - }); - - describe("Execute functionality of the implementation contract on the earlier storage", async() => { - - it("Should get the previous data", async() => { - let _tokenAddress = await I_STRProxied.getSecurityTokenAddress.call(symbol); - let _data = await I_STRProxied.getSecurityTokenData.call(_tokenAddress); - assert.equal(_data[0], symbol, "Symbol should match with registered symbol"); - assert.equal(_data[1], token_owner, "Owner should be the deployer of token"); - assert.equal(_data[2], tokenDetails, "Token details should matched with deployed ticker"); - }); - - it("Should alter the old storage", async() => { - await I_STRProxied.changeTheDeployedAddress(symbol, account_temp, {from: account_polymath}); - let _tokenAddress = await I_STRProxied.getSecurityTokenAddress.call(symbol); - assert.equal(_tokenAddress, account_temp, "Should match with the changed address"); - }); - }) - - describe("Transfer the ownership of the proxy contract", async() => { - - it("Should change the ownership of the contract -- because of bad owner", async()=> { - let errorThrown = false; - try { - await I_SecurityTokenRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_temp}); - } catch(error) { - console.log(` tx -> revert because of bad owner`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should change the ownership of the contract -- new address should not be 0x", async()=> { - let errorThrown = false; - try { - await I_SecurityTokenRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert because new owner address should not be 0x`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should change the ownership of the contract", async()=> { - await I_SecurityTokenRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_polymath}); - let _currentOwner = await I_SecurityTokenRegistryProxy.proxyOwner.call({from: account_polymath_new}); - assert.equal(_currentOwner, account_polymath_new, "Should equal to the new owner"); - }); - - it("Should change the implementation contract and version by the new owner", async() => { - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath}); - await I_SecurityTokenRegistryProxy.upgradeTo("1.2.0", I_SecurityTokenRegistry.address, {from: account_polymath_new}); - let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); - assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.2.0", "Version mis-match"); - assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address, "Implemnted address is not matched"); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - }); - }) - - -}) +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import { encodeProxyCall } from './helpers/encodeCall'; + +// const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); +// const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); +// const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); +// const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); +// const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') +// const STFactory = artifacts.require('./STFactory.sol'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract ("SecurityTokenRegistryProxy", accounts => { + + +// let I_SecurityTokenRegistry; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let I_SecurityTokenRegistryMock; +// let I_STFactory; +// let I_PolymathRegistry; +// let I_ModuleRegistryProxy; +// let I_PolyToken; +// let I_STRProxied; +// let I_MRProxied; +// let I_SecurityToken; +// let I_ModuleRegistry; +// let I_FeatureRegistry; + +// let account_polymath; +// let account_temp; +// let token_owner; +// let account_polymath_new; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); +// const version = "1.0.0"; +// const message = "Transaction Should Fail!"; + +// // SecurityToken Details for funds raise Type ETH +// const name = "Team"; +// const symbol = "SAP"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; + +// const transferManagerKey = 2; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// async function readStorage(contractAddress, slot) { +// return await web3.eth.getStorageAt(contractAddress, slot); +// } + +// before(async() => { +// account_polymath = accounts[0]; +// account_temp = accounts[1]; +// token_owner = accounts[2]; +// account_polymath_new = accounts[3]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // Register the Modules with the ModuleRegistry contract + + +// // Step 3: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 4: Deploy the SecurityTokenRegistry +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Attach the implementation address", async() => { + +// // Storage +// // __version -- index 11 +// // __implementation -- index 12 +// // __upgradeabilityOwner -- index 13 + +// it("Should attach the implementation and version", async() => { +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); +// assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address); +// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.0.0"); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); +// }); + +// it("Verify the initialize data", async() => { +// assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), 60*24*60*60, "Should equal to 60 days"); +// assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee"))).toNumber(), web3.utils.toWei("250")); +// }); + +// }) + +// describe("Feed some data in storage", async() => { + +// it("Register the ticker", async() => { +// await I_PolyToken.getTokens(web3.utils.toWei("1000"), token_owner); +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner, "Owner should be the same as registered with the ticker"); +// assert.equal(tx.logs[0].args._ticker, symbol, "Same as the symbol registered in the registerTicker function call"); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), transferManagerKey); +// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); +// }); +// }) + +// describe("Upgrade the imlplementation address", async() => { + +// it("Should upgrade the version and implementation address -- fail bad owner", async() => { +// let errorThrown = false; +// I_SecurityTokenRegistryMock = await SecurityTokenRegistryMock.new({from: account_polymath}); +// try { +// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryMock.address, {from: account_temp}); +// } catch(error) { +// console.log(` tx -> revert bad owner of the proxy contract`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- Implementaion address should be a contract address", async() => { +// let errorThrown = false; +// try { +// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", account_temp, {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert Implementaion address should be a contract address`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async() => { +// let errorThrown = false; +// try { +// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert Implemenation address should not be 0x`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- Implemenation address should not be the same address", async() => { +// let errorThrown = false; +// try { +// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistry.address, {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert Implemenation address should not be the same address`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- same version as previous is not allowed", async() => { +// let errorThrown = false; +// try { +// await I_SecurityTokenRegistryProxy.upgradeTo("1.0.0", I_SecurityTokenRegistryMock.address, {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert same version as previous is not allowed`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- empty version string is not allowed", async() => { +// let errorThrown = false; +// try { +// await I_SecurityTokenRegistryProxy.upgradeTo("", I_SecurityTokenRegistryMock.address, {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert empty version string is not allowed`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and the implementation address successfully", async() => { +// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryMock.address, {from: account_polymath}); +// let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); +// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.1.0", "Version mis-match"); +// assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistryMock.address, "Implemnted address is not matched"); +// I_STRProxied = await SecurityTokenRegistryMock.at(I_SecurityTokenRegistryProxy.address); +// }); +// }); + +// describe("Execute functionality of the implementation contract on the earlier storage", async() => { + +// it("Should get the previous data", async() => { +// let _tokenAddress = await I_STRProxied.getSecurityTokenAddress.call(symbol); +// let _data = await I_STRProxied.getSecurityTokenData.call(_tokenAddress); +// assert.equal(_data[0], symbol, "Symbol should match with registered symbol"); +// assert.equal(_data[1], token_owner, "Owner should be the deployer of token"); +// assert.equal(_data[2], tokenDetails, "Token details should matched with deployed ticker"); +// }); + +// it("Should alter the old storage", async() => { +// await I_STRProxied.changeTheDeployedAddress(symbol, account_temp, {from: account_polymath}); +// let _tokenAddress = await I_STRProxied.getSecurityTokenAddress.call(symbol); +// assert.equal(_tokenAddress, account_temp, "Should match with the changed address"); +// }); +// }) + +// describe("Transfer the ownership of the proxy contract", async() => { + +// it("Should change the ownership of the contract -- because of bad owner", async()=> { +// let errorThrown = false; +// try { +// await I_SecurityTokenRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_temp}); +// } catch(error) { +// console.log(` tx -> revert because of bad owner`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should change the ownership of the contract -- new address should not be 0x", async()=> { +// let errorThrown = false; +// try { +// await I_SecurityTokenRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert because new owner address should not be 0x`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should change the ownership of the contract", async()=> { +// await I_SecurityTokenRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_polymath}); +// let _currentOwner = await I_SecurityTokenRegistryProxy.proxyOwner.call({from: account_polymath_new}); +// assert.equal(_currentOwner, account_polymath_new, "Should equal to the new owner"); +// }); + +// it("Should change the implementation contract and version by the new owner", async() => { +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath}); +// await I_SecurityTokenRegistryProxy.upgradeTo("1.2.0", I_SecurityTokenRegistry.address, {from: account_polymath_new}); +// let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); +// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.2.0", "Version mis-match"); +// assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address, "Implemnted address is not matched"); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); +// }); +// }) + + +// }) diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index b6fcc5db5..61de1a2fa 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -1,339 +1,339 @@ -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { encodeProxyCall } from './helpers/encodeCall'; - -const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); -const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); -const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const MockModuleRegistry = artifacts.require("./MockModuleRegistry.sol"); -const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') -const STFactory = artifacts.require('./STFactory.sol'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract ("ModuleRegistryProxy", accounts => { - - - let I_SecurityTokenRegistry; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManagerfactory; - let I_MockModuleRegistry; - let I_STFactory; - let I_PolymathRegistry; - let I_ModuleRegistryProxy; - let I_PolyToken; - let I_STRProxied; - let I_MRProxied; - let I_SecurityToken; - let I_ModuleRegistry; - let I_FeatureRegistry; - - let account_polymath; - let account_temp; - let token_owner; - let account_polymath_new; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - const version = "1.0.0"; - const message = "Transaction Should Fail!"; - - // SecurityToken Details for funds raise Type ETH - const name = "Team"; - const symbol = "SAP"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - - const transferManagerKey = 2; - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - async function readStorage(contractAddress, slot) { - return await web3.eth.getStorageAt(contractAddress, slot); - } - - before(async() => { - account_polymath = accounts[0]; - account_temp = accounts[1]; - token_owner = accounts[2]; - account_polymath_new = accounts[3]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // Step 4: Deploy the SecurityTokenRegistry - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Attach the implementation address", async() => { - - // Storage - // __version -- index 11 - // __implementation -- index 12 - // __upgradeabilityOwner -- index 13 - - it("Should attach the MR implementation and version", async() => { - let bytesProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, {from: account_polymath}); - let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); - assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address); - assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.0.0"); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - }); - - it("Deploy the essential smart contracts", async() => { - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - - // Step 3: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - }) - - it("Verify the initialize data", async() => { - assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("owner"))), account_polymath, "Should equal to right address"); - assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry"))), I_PolymathRegistry.address); - }); - - }) - - describe("Feed some data in storage", async() => { - - it("Register and verify the new module", async() => { - - I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerfactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralPermissionManagerFactory contract was not deployed" - ); - - await I_MRProxied.registerModule(I_GeneralPermissionManagerfactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerfactory.address, true, { from: account_polymath }); - - }); - - }) - - describe("Upgrade the imlplementation address", async() => { - - it("Should upgrade the version and implementation address -- fail bad owner", async() => { - let errorThrown = false; - I_MockModuleRegistry = await MockModuleRegistry.new({from: account_polymath}); - try { - await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_MockModuleRegistry.address, {from: account_temp}); - } catch(error) { - console.log(` tx -> revert bad owner of the proxy contract`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- Implementaion address should be a contract address", async() => { - let errorThrown = false; - try { - await I_ModuleRegistryProxy.upgradeTo("1.1.0", account_temp, {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert Implementaion address should be a contract address`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async() => { - let errorThrown = false; - try { - await I_ModuleRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert Implemenation address should not be 0x`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- Implemenation address should not be the same address", async() => { - let errorThrown = false; - try { - await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_ModuleRegistry.address, {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert Implemenation address should not be the same address`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- same version as previous is not allowed", async() => { - let errorThrown = false; - try { - await I_ModuleRegistryProxy.upgradeTo("1.0.0", I_MockModuleRegistry.address, {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert same version as previous is not allowed`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and implementation address -- empty version string is not allowed", async() => { - let errorThrown = false; - try { - await I_ModuleRegistryProxy.upgradeTo("", I_MockModuleRegistry.address, {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert empty version string is not allowed`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should upgrade the version and the implementation address successfully", async() => { - await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_MockModuleRegistry.address, {from: account_polymath}); - let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); - assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.1.0", "Version mis-match"); - assert.equal(await readStorage(c.address, 12), I_MockModuleRegistry.address, "Implemnted address is not matched"); - I_MRProxied = await MockModuleRegistry.at(I_ModuleRegistryProxy.address); - }); - }); - - describe("Execute functionality of the implementation contract on the earlier storage", async() => { - - it("Should get the previous data", async() => { - let _data = await I_MRProxied.getReputationByFactory.call(I_GeneralTransferManagerFactory.address); - assert.equal(_data.length, 0, "Should give the original length"); - }); - - it("Should alter the old storage", async() => { - await I_MRProxied.addMoreReputation(I_GeneralTransferManagerFactory.address, [account_polymath, account_temp], {from: account_polymath}); - let _data = await I_MRProxied.getReputationByFactory.call(I_GeneralTransferManagerFactory.address); - assert.equal(_data.length, 2, "Should give the updated length"); - }); - }) - - describe("Transfer the ownership of the proxy contract", async() => { - - it("Should change the ownership of the contract -- because of bad owner", async()=> { - let errorThrown = false; - try { - await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_temp}); - } catch(error) { - console.log(` tx -> revert because of bad owner`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should change the ownership of the contract -- new address should not be 0x", async()=> { - let errorThrown = false; - try { - await I_ModuleRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", {from: account_polymath}); - } catch(error) { - console.log(` tx -> revert because new owner address should not be 0x`); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should change the ownership of the contract", async()=> { - await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_polymath}); - let _currentOwner = await I_ModuleRegistryProxy.proxyOwner.call({from: account_polymath_new}); - assert.equal(_currentOwner, account_polymath_new, "Should equal to the new owner"); - }); - - it("Should change the implementation contract and version by the new owner", async() => { - I_ModuleRegistry = await ModuleRegistry.new({from: account_polymath}); - await I_ModuleRegistryProxy.upgradeTo("1.2.0", I_ModuleRegistry.address, {from: account_polymath_new}); - let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); - assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.2.0", "Version mis-match"); - assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address, "Implemnted address is not matched"); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - }); - }) - - -}) +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import { encodeProxyCall } from './helpers/encodeCall'; + +// const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); +// const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); +// const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const MockModuleRegistry = artifacts.require("./MockModuleRegistry.sol"); +// const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') +// const STFactory = artifacts.require('./STFactory.sol'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract ("ModuleRegistryProxy", accounts => { + + +// let I_SecurityTokenRegistry; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let I_GeneralPermissionManagerfactory; +// let I_MockModuleRegistry; +// let I_STFactory; +// let I_PolymathRegistry; +// let I_ModuleRegistryProxy; +// let I_PolyToken; +// let I_STRProxied; +// let I_MRProxied; +// let I_SecurityToken; +// let I_ModuleRegistry; +// let I_FeatureRegistry; + +// let account_polymath; +// let account_temp; +// let token_owner; +// let account_polymath_new; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); +// const version = "1.0.0"; +// const message = "Transaction Should Fail!"; + +// // SecurityToken Details for funds raise Type ETH +// const name = "Team"; +// const symbol = "SAP"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; + +// const transferManagerKey = 2; +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// async function readStorage(contractAddress, slot) { +// return await web3.eth.getStorageAt(contractAddress, slot); +// } + +// before(async() => { +// account_polymath = accounts[0]; +// account_temp = accounts[1]; +// token_owner = accounts[2]; +// account_polymath_new = accounts[3]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // Step 4: Deploy the SecurityTokenRegistry +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + +// // Step 11: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Attach the implementation address", async() => { + +// // Storage +// // __version -- index 11 +// // __implementation -- index 12 +// // __upgradeabilityOwner -- index 13 + +// it("Should attach the MR implementation and version", async() => { +// let bytesProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, {from: account_polymath}); +// let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); +// assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address); +// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.0.0"); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); +// }); + +// it("Deploy the essential smart contracts", async() => { +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + +// // Step 3: Deploy the STFactory contract +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); +// }) + +// it("Verify the initialize data", async() => { +// assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("owner"))), account_polymath, "Should equal to right address"); +// assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry"))), I_PolymathRegistry.address); +// }); + +// }) + +// describe("Feed some data in storage", async() => { + +// it("Register and verify the new module", async() => { + +// I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerfactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralPermissionManagerFactory contract was not deployed" +// ); + +// await I_MRProxied.registerModule(I_GeneralPermissionManagerfactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerfactory.address, true, { from: account_polymath }); + +// }); + +// }) + +// describe("Upgrade the imlplementation address", async() => { + +// it("Should upgrade the version and implementation address -- fail bad owner", async() => { +// let errorThrown = false; +// I_MockModuleRegistry = await MockModuleRegistry.new({from: account_polymath}); +// try { +// await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_MockModuleRegistry.address, {from: account_temp}); +// } catch(error) { +// console.log(` tx -> revert bad owner of the proxy contract`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- Implementaion address should be a contract address", async() => { +// let errorThrown = false; +// try { +// await I_ModuleRegistryProxy.upgradeTo("1.1.0", account_temp, {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert Implementaion address should be a contract address`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async() => { +// let errorThrown = false; +// try { +// await I_ModuleRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert Implemenation address should not be 0x`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- Implemenation address should not be the same address", async() => { +// let errorThrown = false; +// try { +// await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_ModuleRegistry.address, {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert Implemenation address should not be the same address`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- same version as previous is not allowed", async() => { +// let errorThrown = false; +// try { +// await I_ModuleRegistryProxy.upgradeTo("1.0.0", I_MockModuleRegistry.address, {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert same version as previous is not allowed`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and implementation address -- empty version string is not allowed", async() => { +// let errorThrown = false; +// try { +// await I_ModuleRegistryProxy.upgradeTo("", I_MockModuleRegistry.address, {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert empty version string is not allowed`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should upgrade the version and the implementation address successfully", async() => { +// await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_MockModuleRegistry.address, {from: account_polymath}); +// let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); +// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.1.0", "Version mis-match"); +// assert.equal(await readStorage(c.address, 12), I_MockModuleRegistry.address, "Implemnted address is not matched"); +// I_MRProxied = await MockModuleRegistry.at(I_ModuleRegistryProxy.address); +// }); +// }); + +// describe("Execute functionality of the implementation contract on the earlier storage", async() => { + +// it("Should get the previous data", async() => { +// let _data = await I_MRProxied.getReputationByFactory.call(I_GeneralTransferManagerFactory.address); +// assert.equal(_data.length, 0, "Should give the original length"); +// }); + +// it("Should alter the old storage", async() => { +// await I_MRProxied.addMoreReputation(I_GeneralTransferManagerFactory.address, [account_polymath, account_temp], {from: account_polymath}); +// let _data = await I_MRProxied.getReputationByFactory.call(I_GeneralTransferManagerFactory.address); +// assert.equal(_data.length, 2, "Should give the updated length"); +// }); +// }) + +// describe("Transfer the ownership of the proxy contract", async() => { + +// it("Should change the ownership of the contract -- because of bad owner", async()=> { +// let errorThrown = false; +// try { +// await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_temp}); +// } catch(error) { +// console.log(` tx -> revert because of bad owner`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should change the ownership of the contract -- new address should not be 0x", async()=> { +// let errorThrown = false; +// try { +// await I_ModuleRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", {from: account_polymath}); +// } catch(error) { +// console.log(` tx -> revert because new owner address should not be 0x`); +// errorThrown = true; +// ensureException(error); +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should change the ownership of the contract", async()=> { +// await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_polymath}); +// let _currentOwner = await I_ModuleRegistryProxy.proxyOwner.call({from: account_polymath_new}); +// assert.equal(_currentOwner, account_polymath_new, "Should equal to the new owner"); +// }); + +// it("Should change the implementation contract and version by the new owner", async() => { +// I_ModuleRegistry = await ModuleRegistry.new({from: account_polymath}); +// await I_ModuleRegistryProxy.upgradeTo("1.2.0", I_ModuleRegistry.address, {from: account_polymath_new}); +// let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); +// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.2.0", "Version mis-match"); +// assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address, "Implemnted address is not matched"); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); +// }); +// }) + + +// }) diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 4330616ea..6bdea7f65 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -1,379 +1,379 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const TrackedRedemptionFactory = artifacts.require('./TrackedRedemptionFactory.sol'); -const TrackedRedemption = artifacts.require('./TrackedRedemption'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('TrackedRedemption', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_temp; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_TrackedRedemptionFactory; - let I_GeneralPermissionManager; - let I_TrackedRedemption; - let I_GeneralTransferManager; - let I_ExchangeTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_MRProxied; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - let snapId; - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - const checkpointKey = 4; - const burnKey = 5; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[6]; - account_investor2 = accounts[7]; - account_investor3 = accounts[8]; - account_investor4 = accounts[9]; - account_temp = accounts[2]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 4: Deploy the TrackedRedemption - I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_TrackedRedemptionFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "TrackedRedemptionFactory contract was not deployed" - ); - - - // Step 6: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 7: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 8: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 9: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 5: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the TrackedRedemptionFactory - await I_MRProxied.registerModule(I_TrackedRedemptionFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_TrackedRedemptionFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - TrackedRedemptionFactory: ${I_TrackedRedemptionFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - it("Should successfully attach the TrackedRedemption with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_TrackedRedemptionFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "TrackedRedemption", - "TrackedRedemption module was not added" - ); - I_TrackedRedemption = TrackedRedemption.at(tx.logs[2].args._module); - }); - }); - - describe("Make Redemptions", async() => { - - it("Buy some tokens for account_investor1 (1 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(30), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - - it("Buy some tokens for account_investor2 (2 ETH)", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(30), - true, - { - from: account_issuer, - gas: 500000 - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Redeem some tokens - fail insufficient allowance", async() => { - await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); - - let errorThrown = false; - try { - let tx = await I_TrackedRedemption.redeemTokens(web3.utils.toWei('1', 'ether'), {from: account_investor1}); - } catch(error) { - console.log(` tx -> failed insufficent allowance`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Redeem some tokens", async() => { - await I_SecurityToken.approve(I_TrackedRedemption.address, web3.utils.toWei('1', 'ether'), {from: account_investor1}); - let tx = await I_TrackedRedemption.redeemTokens(web3.utils.toWei('1', 'ether'), {from: account_investor1}); - console.log(JSON.stringify(tx.logs)); - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Mismatch address"); - assert.equal(tx.logs[0].args._value, web3.utils.toWei('1', 'ether'), "Wrong value"); - }); - - it("Get the init data", async() => { - let tx = await I_TrackedRedemption.getInitFunction.call(); - assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); - }); - - it("Should get the listed permissions", async() => { - let tx = await I_TrackedRedemption.getPermissions.call(); - assert.equal(tx.length,0); - }); - - describe("Test cases for the TrackedRedemptionFactory", async() => { - it("should get the exact details of the factory", async() => { - assert.equal((await I_TrackedRedemptionFactory.setupCost.call()).toNumber(), 0); - assert.equal((await I_TrackedRedemptionFactory.getTypes.call())[0], 5); - assert.equal(web3.utils.toAscii(await I_TrackedRedemptionFactory.getName.call()) - .replace(/\u0000/g, ''), - "TrackedRedemption", - "Wrong Module added"); - assert.equal(await I_TrackedRedemptionFactory.getDescription.call(), - "Track token redemptions", - "Wrong Module added"); - assert.equal(await I_TrackedRedemptionFactory.getTitle.call(), - "Tracked Redemption", - "Wrong Module added"); - assert.equal(await I_TrackedRedemptionFactory.getInstructions.call(), - "Allows an investor to redeem security tokens which are tracked by this module", - "Wrong Module added"); - let tags = await I_TrackedRedemptionFactory.getTags.call(); - assert.equal(tags.length, 2); - - }); - }); - - }); - -}); +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const TrackedRedemptionFactory = artifacts.require('./TrackedRedemptionFactory.sol'); +// const TrackedRedemption = artifacts.require('./TrackedRedemption'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('TrackedRedemption', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; +// let account_temp; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let I_GeneralTransferManagerFactory; +// let I_TrackedRedemptionFactory; +// let I_GeneralPermissionManager; +// let I_TrackedRedemption; +// let I_GeneralTransferManager; +// let I_ExchangeTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_STRProxied; +// let I_STFactory; +// let I_SecurityToken; +// let I_PolyToken; +// let I_MRProxied; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; +// let snapId; +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; +// const checkpointKey = 4; +// const burnKey = 5; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; + +// account_investor1 = accounts[6]; +// account_investor2 = accounts[7]; +// account_investor3 = accounts[8]; +// account_investor4 = accounts[9]; +// account_temp = accounts[2]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4: Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 5: Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the TrackedRedemption +// I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); +// assert.notEqual( +// I_TrackedRedemptionFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "TrackedRedemptionFactory contract was not deployed" +// ); + + +// // Step 6: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 7: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 8: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 9: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 5: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the TrackedRedemptionFactory +// await I_MRProxied.registerModule(I_TrackedRedemptionFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_TrackedRedemptionFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// TrackedRedemptionFactory: ${I_TrackedRedemptionFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + +// }); + +// it("Should successfully attach the TrackedRedemption with the security token", async () => { +// const tx = await I_SecurityToken.addModule(I_TrackedRedemptionFactory.address, "", 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "TrackedRedemption", +// "TrackedRedemption module was not added" +// ); +// I_TrackedRedemption = TrackedRedemption.at(tx.logs[2].args._module); +// }); +// }); + +// describe("Make Redemptions", async() => { + +// it("Buy some tokens for account_investor1 (1 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(30), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(5000); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); + +// it("Buy some tokens for account_investor2 (2 ETH)", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(30), +// true, +// { +// from: account_issuer, +// gas: 500000 +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('2', 'ether') +// ); +// }); + +// it("Redeem some tokens - fail insufficient allowance", async() => { +// await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); + +// let errorThrown = false; +// try { +// let tx = await I_TrackedRedemption.redeemTokens(web3.utils.toWei('1', 'ether'), {from: account_investor1}); +// } catch(error) { +// console.log(` tx -> failed insufficent allowance`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Redeem some tokens", async() => { +// await I_SecurityToken.approve(I_TrackedRedemption.address, web3.utils.toWei('1', 'ether'), {from: account_investor1}); +// let tx = await I_TrackedRedemption.redeemTokens(web3.utils.toWei('1', 'ether'), {from: account_investor1}); +// console.log(JSON.stringify(tx.logs)); +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Mismatch address"); +// assert.equal(tx.logs[0].args._value, web3.utils.toWei('1', 'ether'), "Wrong value"); +// }); + +// it("Get the init data", async() => { +// let tx = await I_TrackedRedemption.getInitFunction.call(); +// assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); +// }); + +// it("Should get the listed permissions", async() => { +// let tx = await I_TrackedRedemption.getPermissions.call(); +// assert.equal(tx.length,0); +// }); + +// describe("Test cases for the TrackedRedemptionFactory", async() => { +// it("should get the exact details of the factory", async() => { +// assert.equal((await I_TrackedRedemptionFactory.setupCost.call()).toNumber(), 0); +// assert.equal((await I_TrackedRedemptionFactory.getTypes.call())[0], 5); +// assert.equal(web3.utils.toAscii(await I_TrackedRedemptionFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "TrackedRedemption", +// "Wrong Module added"); +// assert.equal(await I_TrackedRedemptionFactory.getDescription.call(), +// "Track token redemptions", +// "Wrong Module added"); +// assert.equal(await I_TrackedRedemptionFactory.getTitle.call(), +// "Tracked Redemption", +// "Wrong Module added"); +// assert.equal(await I_TrackedRedemptionFactory.getInstructions.call(), +// "Allows an investor to redeem security tokens which are tracked by this module", +// "Wrong Module added"); +// let tags = await I_TrackedRedemptionFactory.getTags.call(); +// assert.equal(tags.length, 2); + +// }); +// }); + +// }); + +// }); diff --git a/test/w_volume_restriction_transfer_manager.js b/test/w_volume_restriction_transfer_manager.js index b117511c8..8165c15a4 100644 --- a/test/w_volume_restriction_transfer_manager.js +++ b/test/w_volume_restriction_transfer_manager.js @@ -1,1070 +1,1070 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const VolumeRestrictionTransferManagerFactory = artifacts.require('./VolumeRestrictionTransferManagerFactory.sol'); -const VolumeRestrictionTransferManager = artifacts.require('./VolumeRestrictionTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('VolumeRestrictionTransferManager', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let P_VolumeRestrictionTransferManagerFactory; - let I_SecurityTokenRegistryProxy; - let P_VolumeRestrictionTransferManager; - let I_GeneralTransferManagerFactory; - let I_VolumeRestrictionTransferManagerFactory; - let I_GeneralPermissionManager; - let I_VolumeRestrictionTransferManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STRProxied; - let I_MRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[7]; - account_investor2 = accounts[8]; - account_investor3 = accounts[9]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - // STEP 4(a): Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 4(b): Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 4(c): Deploy the VolumeRestrictionTransferManager - I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_VolumeRestrictionTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "VolumeRestrictionTransferManagerFactory contract was not deployed" - ); - - // STEP 4(d): Deploy the VolumeRestrictionTransferManager - P_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); - assert.notEqual( - P_VolumeRestrictionTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "VolumeRestrictionTransferManagerFactory contract was not deployed" - ); - - - // Step 6: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 7: Deploy the SecurityTokenRegistry contract +// import latestTime from './helpers/latestTime'; +// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +// import { encodeProxyCall } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const VolumeRestrictionTransferManagerFactory = artifacts.require('./VolumeRestrictionTransferManagerFactory.sol'); +// const VolumeRestrictionTransferManager = artifacts.require('./VolumeRestrictionTransferManager'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('VolumeRestrictionTransferManager', accounts => { + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; + +// // Contract Instance Declaration +// let I_GeneralPermissionManagerFactory; +// let P_VolumeRestrictionTransferManagerFactory; +// let I_SecurityTokenRegistryProxy; +// let P_VolumeRestrictionTransferManager; +// let I_GeneralTransferManagerFactory; +// let I_VolumeRestrictionTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_VolumeRestrictionTransferManager; +// let I_GeneralTransferManager; +// let I_ModuleRegistryProxy; +// let I_ModuleRegistry; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_STRProxied; +// let I_MRProxied; +// let I_STFactory; +// let I_SecurityToken; +// let I_PolyToken; +// let I_PolymathRegistry; + +// // SecurityToken Details +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; + +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// before(async() => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; + +// account_investor1 = accounts[7]; +// account_investor2 = accounts[8]; +// account_investor3 = accounts[9]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// // Step 2: Deploy the FeatureRegistry + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, +// { +// from: account_polymath +// }); + +// // STEP 3: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); +// // Step 3 (b): Deploy the proxy and attach the implementation contract to it +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + +// // STEP 4(a): Deploy the GeneralTransferManagerFactory + +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 4(b): Deploy the GeneralDelegateManagerFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 4(c): Deploy the VolumeRestrictionTransferManager +// I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); +// assert.notEqual( +// I_VolumeRestrictionTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "VolumeRestrictionTransferManagerFactory contract was not deployed" +// ); + +// // STEP 4(d): Deploy the VolumeRestrictionTransferManager +// P_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); +// assert.notEqual( +// P_VolumeRestrictionTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "VolumeRestrictionTransferManagerFactory contract was not deployed" +// ); + + +// // Step 6: Deploy the STFactory contract + +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 7: Deploy the SecurityTokenRegistry contract - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 8: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 9: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 5: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the VolumeRestrictionTransferManagerFactory - await I_MRProxied.registerModule(I_VolumeRestrictionTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_VolumeRestrictionTransferManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the Paid VolumeRestrictionTransferManagerFactory - await I_MRProxied.registerModule(P_VolumeRestrictionTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(P_VolumeRestrictionTransferManagerFactory.address, true, { from: account_polymath }); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - VolumeRestrictionTransferManagerFactory: ${I_VolumeRestrictionTransferManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - - }); - - describe("Buy tokens using on-chain whitelist and test locking them up and attempting to transfer", async() => { - - it("Should Buy the tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('10', 'ether') - ); - }); - - it("Should unsuccessfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { - let errorThrown = false; - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - try { - const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - } catch(error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should successfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { - let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManagerFactory doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "VolumeRestrictionTransferManager", - "VolumeRestrictionTransferManagerFactory module was not added" - ); - P_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[3].args._module); - await revertToSnapshot(snapId); - }); - - it("Should successfully attach the VolumeRestrictionTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_VolumeRestrictionTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "VolumeRestrictionTransferManager", - "VolumeRestrictionTransferManager module was not added" - ); - I_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[2].args._module); - }); - - it("Add a new token holder", async() => { - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('10', 'ether') - ); - }); - - it("Should pause the tranfers at transferManager level", async() => { - let tx = await I_VolumeRestrictionTransferManager.pause({from: token_owner}); - }); - - it("Should still be able to transfer between existing token holders up to limit", async() => { - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('3', 'ether') - ); - }); - - it("Should unpause the tranfers at transferManager level", async() => { - await I_VolumeRestrictionTransferManager.unpause({from: token_owner}); - }); - - it("Should prevent the creation of a lockup with bad parameters where the totalAmount is zero", async() => { - let errorThrown = false; - try { - // create a lockup - // this will generate an exception because the totalAmount is zero - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, 0, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> couldn't create lock up because totalAmount is zero`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should prevent the creation of a lockup with bad parameters where the releaseFrequencySeconds is zero", async() => { - let errorThrown = false; - try { - // create a lockup - // this will generate an exception because the releaseFrequencySeconds is zero - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 0, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> couldn't create lock up because releaseFrequencySeconds is zero`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is zero", async() => { - let errorThrown = false; - try { - // create a lockup - // this will generate an exception because the lockUpPeriodSeconds is zero - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 0, 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> couldn't create lock up because lockUpPeriodSeconds is zero`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - - it("Should prevent the creation of a lockup with bad parameters where the total amount to be released is more granular than allowed by the token", async() => { - let errorThrown = false; - try { - // create a lockup - // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, web3.utils.toWei('0.5', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> couldn't create lock up because the total amount to be released is more granular than allowed by the token`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - - it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is not evenly divisible by releaseFrequencySeconds", async() => { - - // balance should be 9000000000000000000 here (9 eth) - let balance = await I_SecurityToken.balanceOf(account_investor2) - - - let errorThrown = false; - try { - // create a lockup - // over 17 seconds total, with 4 periods. - // this will generate an exception because 17 is not evenly divisble by 4. - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 17, 4, 0, balance, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> couldn't create lock up because lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should prevent the creation of a lockup with bad parameters where the total amount being locked up isn't evenly divisible by the number of total periods", async() => { - - let errorThrown = false; - try { - // create a lockup for a balance of 1 eth - // over 16e18 seconds total, with 4e18 periods of 4 seconds each. - // this will generate an exception because 16e18 / 4e18 = 4e18 but the token granularity is 1e18 and 1e18 % 4e18 != 0 - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, web3.utils.toWei('16', 'ether'), 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); - } catch(error) { - console.log(` tx revert -> couldn't create lock up because the total amount being locked up must be evenly divisible by the number of total periods`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should prevent the creation of a lockup with bad parameters where the amount to be released per period is too granular for the token", async() => { - - // balance should be 9000000000000000000 here (9 eth) - let balance = await I_SecurityToken.balanceOf(account_investor2) - - - let errorThrown = false; - try { - // create a lockup for their entire balance - // over 16 seconds total, with 4 periods of 4 seconds each. - // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> couldn't create lock up because amount to be released per period is more granular than allowed by the token`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should prevent the transfer of tokens in a lockup", async() => { - - let balance = await I_SecurityToken.balanceOf(account_investor2) - - // create a lockup for their entire balance - // over 12 seconds total, with 3 periods of 4 seconds each. - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from: token_owner }); - - // read only - check if transfer will pass. it should return INVALID - let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('1', 'ether'), 0, false) - // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 - assert.equal(result.toString(), '0') - - - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { - - // wait 4 seconds - await new Promise(resolve => setTimeout(resolve, 4000)); - - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); - }); - - it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { - - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { - - // wait 4 more seconds - await new Promise(resolve => setTimeout(resolve, 4000)); - - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); - }); - - it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async() => { - - let balance = await I_SecurityToken.balanceOf(account_investor2) - - // wait 4 more seconds - await new Promise(resolve => setTimeout(resolve, 4000)); +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 8: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + +// // Step 9: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); +// await I_MRProxied.updateFromRegistry({from: account_polymath}); + +// // STEP 5: Register the Modules with the ModuleRegistry contract + +// // (A) : Register the GeneralTransferManagerFactory +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the VolumeRestrictionTransferManagerFactory +// await I_MRProxied.registerModule(I_VolumeRestrictionTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(I_VolumeRestrictionTransferManagerFactory.address, true, { from: account_polymath }); + +// // (C) : Register the Paid VolumeRestrictionTransferManagerFactory +// await I_MRProxied.registerModule(P_VolumeRestrictionTransferManagerFactory.address, { from: account_polymath }); +// await I_MRProxied.verifyModule(P_VolumeRestrictionTransferManagerFactory.address, true, { from: account_polymath }); + +// // Printing all the contract addresses +// console.log(` +// --------------------- Polymath Network Smart Contracts: --------------------- +// PolymathRegistry: ${PolymathRegistry.address} +// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} +// SecurityTokenRegistry: ${SecurityTokenRegistry.address} +// ModuleRegistry: ${ModuleRegistry.address} +// ModuleRegistryProxy: ${ModuleRegistryProxy.address} +// FeatureRegistry: ${FeatureRegistry.address} + +// STFactory: ${STFactory.address} +// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} +// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + +// VolumeRestrictionTransferManagerFactory: ${I_VolumeRestrictionTransferManagerFactory.address} +// ----------------------------------------------------------------------------- +// `); +// }); + +// describe("Generate the SecurityToken", async() => { + +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); +// }); + +// }); + +// describe("Buy tokens using on-chain whitelist and test locking them up and attempting to transfer", async() => { + +// it("Should Buy the tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(5000); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('2', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('2', 'ether') +// ); +// }); + +// it("Should Buy some more tokens", async() => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('10', 'ether') +// ); +// }); + +// it("Should unsuccessfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { +// let errorThrown = false; +// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); +// try { +// const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx -> failed because Token is not paid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should successfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { +// let snapId = await takeSnapshot(); +// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); +// const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); +// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManagerFactory doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[3].args._name) +// .replace(/\u0000/g, ''), +// "VolumeRestrictionTransferManager", +// "VolumeRestrictionTransferManagerFactory module was not added" +// ); +// P_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[3].args._module); +// await revertToSnapshot(snapId); +// }); + +// it("Should successfully attach the VolumeRestrictionTransferManager with the security token", async () => { +// const tx = await I_SecurityToken.addModule(I_VolumeRestrictionTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManager doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "VolumeRestrictionTransferManager", +// "VolumeRestrictionTransferManager module was not added" +// ); +// I_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[2].args._module); +// }); + +// it("Add a new token holder", async() => { + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, +// { +// from: account_issuer +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), +// web3.utils.toWei('10', 'ether') +// ); +// }); + +// it("Should pause the tranfers at transferManager level", async() => { +// let tx = await I_VolumeRestrictionTransferManager.pause({from: token_owner}); +// }); + +// it("Should still be able to transfer between existing token holders up to limit", async() => { +// // Add the Investor in to the whitelist +// // Mint some tokens +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('3', 'ether') +// ); +// }); + +// it("Should unpause the tranfers at transferManager level", async() => { +// await I_VolumeRestrictionTransferManager.unpause({from: token_owner}); +// }); + +// it("Should prevent the creation of a lockup with bad parameters where the totalAmount is zero", async() => { +// let errorThrown = false; +// try { +// // create a lockup +// // this will generate an exception because the totalAmount is zero +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, 0, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> couldn't create lock up because totalAmount is zero`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should prevent the creation of a lockup with bad parameters where the releaseFrequencySeconds is zero", async() => { +// let errorThrown = false; +// try { +// // create a lockup +// // this will generate an exception because the releaseFrequencySeconds is zero +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 0, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> couldn't create lock up because releaseFrequencySeconds is zero`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is zero", async() => { +// let errorThrown = false; +// try { +// // create a lockup +// // this will generate an exception because the lockUpPeriodSeconds is zero +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 0, 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> couldn't create lock up because lockUpPeriodSeconds is zero`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + + +// it("Should prevent the creation of a lockup with bad parameters where the total amount to be released is more granular than allowed by the token", async() => { +// let errorThrown = false; +// try { +// // create a lockup +// // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, web3.utils.toWei('0.5', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> couldn't create lock up because the total amount to be released is more granular than allowed by the token`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + + +// it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is not evenly divisible by releaseFrequencySeconds", async() => { + +// // balance should be 9000000000000000000 here (9 eth) +// let balance = await I_SecurityToken.balanceOf(account_investor2) + + +// let errorThrown = false; +// try { +// // create a lockup +// // over 17 seconds total, with 4 periods. +// // this will generate an exception because 17 is not evenly divisble by 4. +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 17, 4, 0, balance, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> couldn't create lock up because lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should prevent the creation of a lockup with bad parameters where the total amount being locked up isn't evenly divisible by the number of total periods", async() => { + +// let errorThrown = false; +// try { +// // create a lockup for a balance of 1 eth +// // over 16e18 seconds total, with 4e18 periods of 4 seconds each. +// // this will generate an exception because 16e18 / 4e18 = 4e18 but the token granularity is 1e18 and 1e18 % 4e18 != 0 +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, web3.utils.toWei('16', 'ether'), 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> couldn't create lock up because the total amount being locked up must be evenly divisible by the number of total periods`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should prevent the creation of a lockup with bad parameters where the amount to be released per period is too granular for the token", async() => { + +// // balance should be 9000000000000000000 here (9 eth) +// let balance = await I_SecurityToken.balanceOf(account_investor2) + + +// let errorThrown = false; +// try { +// // create a lockup for their entire balance +// // over 16 seconds total, with 4 periods of 4 seconds each. +// // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }); +// } catch(error) { +// console.log(` tx revert -> couldn't create lock up because amount to be released per period is more granular than allowed by the token`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should prevent the transfer of tokens in a lockup", async() => { + +// let balance = await I_SecurityToken.balanceOf(account_investor2) + +// // create a lockup for their entire balance +// // over 12 seconds total, with 3 periods of 4 seconds each. +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from: token_owner }); + +// // read only - check if transfer will pass. it should return INVALID +// let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('1', 'ether'), 0, false) +// // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 +// assert.equal(result.toString(), '0') + + +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { + +// // wait 4 seconds +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); +// }); + +// it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { + +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { + +// // wait 4 more seconds +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); +// }); + +// it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async() => { + +// let balance = await I_SecurityToken.balanceOf(account_investor2) + +// // wait 4 more seconds +// await new Promise(resolve => setTimeout(resolve, 4000)); - await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); - }); +// await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); +// }); - it("Should prevent the transfer of tokens in an edited lockup", async() => { +// it("Should prevent the transfer of tokens in an edited lockup", async() => { - // balance here should be 12000000000000000000 (12e18 or 12 eth) - let balance = await I_SecurityToken.balanceOf(account_investor1) +// // balance here should be 12000000000000000000 (12e18 or 12 eth) +// let balance = await I_SecurityToken.balanceOf(account_investor1) - // create a lockup for their entire balance - // over 16 seconds total, with 4 periods of 4 seconds each. - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, balance, { from: token_owner }); +// // create a lockup for their entire balance +// // over 16 seconds total, with 4 periods of 4 seconds each. +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, balance, { from: token_owner }); - // let blockNumber = await web3.eth.getBlockNumber(); - // console.log('blockNumber',blockNumber) - let now = (await web3.eth.getBlock('latest')).timestamp +// // let blockNumber = await web3.eth.getBlockNumber(); +// // console.log('blockNumber',blockNumber) +// let now = (await web3.eth.getBlock('latest')).timestamp - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); - // check and get the lockup - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 1) +// // check and get the lockup +// let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); +// assert.equal(lockUpCount, 1) - let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 0); - // console.log(lockUp); - // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount - assert.equal(lockUp[0].toString(), '16'); - assert.equal(lockUp[1].toString(), '4'); - assert.equal(lockUp[2].toNumber(), now); - assert.equal(lockUp[3].toString(), balance.toString()); +// let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 0); +// // console.log(lockUp); +// // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount +// assert.equal(lockUp[0].toString(), '16'); +// assert.equal(lockUp[1].toString(), '4'); +// assert.equal(lockUp[2].toNumber(), now); +// assert.equal(lockUp[3].toString(), balance.toString()); - // edit the lockup - await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 0, 8, 4, 0, balance, { from: token_owner }); +// // edit the lockup +// await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 0, 8, 4, 0, balance, { from: token_owner }); - // attempt a transfer - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); +// // attempt a transfer +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); - // wait 4 seconds - await new Promise(resolve => setTimeout(resolve, 4000)); +// // wait 4 seconds +// await new Promise(resolve => setTimeout(resolve, 4000)); - // transfer should succeed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); +// // transfer should succeed +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); - }); +// }); - it("Should be possible to remove a lockup", async() => { +// it("Should be possible to remove a lockup", async() => { - let acct1Balance = await I_SecurityToken.balanceOf(account_investor1) +// let acct1Balance = await I_SecurityToken.balanceOf(account_investor1) - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); - // check and get the lockup - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 1) +// // check and get the lockup +// let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); +// assert.equal(lockUpCount, 1) - // remove the lockup - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor1, 0, { from: token_owner }); +// // remove the lockup +// await I_VolumeRestrictionTransferManager.removeLockUp(account_investor1, 0, { from: token_owner }); - lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 0) +// lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); +// assert.equal(lockUpCount, 0) - let acct2BalanceBefore = await I_SecurityToken.balanceOf(account_investor2) - await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); - let acct2BalanceAfter = await I_SecurityToken.balanceOf(account_investor2) +// let acct2BalanceBefore = await I_SecurityToken.balanceOf(account_investor2) +// await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); +// let acct2BalanceAfter = await I_SecurityToken.balanceOf(account_investor2) - assert.equal(acct2BalanceAfter.sub(acct2BalanceBefore).toString(), acct1Balance.toString()) - }); +// assert.equal(acct2BalanceAfter.sub(acct2BalanceBefore).toString(), acct1Balance.toString()) +// }); - it("Should be possible to create multiple lockups at once", async() => { - - let balancesBefore = {} - - // should be 12000000000000000000 - balancesBefore[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - - - // should be 10000000000000000000 - balancesBefore[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - - - let lockUpCountsBefore = {} - - // get lockups for acct 2 - lockUpCountsBefore[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCountsBefore[account_investor2], 1) // there's one old, expired lockup on acct already - - // get lockups for acct 3 - lockUpCountsBefore[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); - assert.equal(lockUpCountsBefore[account_investor3], 0) - - // create lockups for their entire balances - await I_VolumeRestrictionTransferManager.addLockUpMulti( - [account_investor2, account_investor3], - [24, 8], - [4, 4], - [0, 0], - [balancesBefore[account_investor2], balancesBefore[account_investor3]], - { from: token_owner } - ); - - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - let balancesAfter = {} - balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - assert.equal(balancesBefore[account_investor2].toString(), balancesAfter[account_investor2].toString()) - - balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - assert.equal(balancesBefore[account_investor3].toString(), balancesAfter[account_investor3].toString()) +// it("Should be possible to create multiple lockups at once", async() => { + +// let balancesBefore = {} + +// // should be 12000000000000000000 +// balancesBefore[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) + + +// // should be 10000000000000000000 +// balancesBefore[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) + + +// let lockUpCountsBefore = {} + +// // get lockups for acct 2 +// lockUpCountsBefore[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); +// assert.equal(lockUpCountsBefore[account_investor2], 1) // there's one old, expired lockup on acct already + +// // get lockups for acct 3 +// lockUpCountsBefore[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); +// assert.equal(lockUpCountsBefore[account_investor3], 0) + +// // create lockups for their entire balances +// await I_VolumeRestrictionTransferManager.addLockUpMulti( +// [account_investor2, account_investor3], +// [24, 8], +// [4, 4], +// [0, 0], +// [balancesBefore[account_investor2], balancesBefore[account_investor3]], +// { from: token_owner } +// ); + +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// let balancesAfter = {} +// balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) +// assert.equal(balancesBefore[account_investor2].toString(), balancesAfter[account_investor2].toString()) + +// balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) +// assert.equal(balancesBefore[account_investor3].toString(), balancesAfter[account_investor3].toString()) - let lockUpCountsAfter = {} +// let lockUpCountsAfter = {} - // get lockups for acct 2 - lockUpCountsAfter[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCountsAfter[account_investor2], 2); - - // get lockups for acct 3 - lockUpCountsAfter[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); - assert.equal(lockUpCountsAfter[account_investor3], 1); - - // wait 4 seconds - await new Promise(resolve => setTimeout(resolve, 4000)); - - // try transfers again - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); - - - balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - assert.equal(balancesBefore[account_investor2].sub(web3.utils.toWei('2', 'ether')).toString(), balancesAfter[account_investor2].toString()) - - balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - assert.equal(balancesBefore[account_investor3].sub(web3.utils.toWei('5', 'ether')).toString(), balancesAfter[account_investor3].toString()) +// // get lockups for acct 2 +// lockUpCountsAfter[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); +// assert.equal(lockUpCountsAfter[account_investor2], 2); + +// // get lockups for acct 3 +// lockUpCountsAfter[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); +// assert.equal(lockUpCountsAfter[account_investor3], 1); + +// // wait 4 seconds +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// // try transfers again +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); + + +// balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) +// assert.equal(balancesBefore[account_investor2].sub(web3.utils.toWei('2', 'ether')).toString(), balancesAfter[account_investor2].toString()) + +// balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) +// assert.equal(balancesBefore[account_investor3].sub(web3.utils.toWei('5', 'ether')).toString(), balancesAfter[account_investor3].toString()) - }); - - it("Should revert if the parameters are bad when creating multiple lockups", async() => { - let errorThrown = false; - try { - // pass in the wrong number of params. txn should revert - await I_VolumeRestrictionTransferManager.addLockUpMulti( - [account_investor2, account_investor3], - [16, 8], - [2], // this array should have 2 elements but it has 1, which should cause a revert - [0, 0], - [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], - { from: token_owner } - ); - } catch(error) { - console.log(` tx revert -> passed in wrong number of array elements`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should be possible to create a lockup with a specific start time in the future", async() => { - - // remove all lockups for account 2 - let lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpsLength, 2); - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); - lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpsLength, 0); - - let now = (await web3.eth.getBlock('latest')).timestamp - - // balance here should be 10000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor2) - - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 100, 10, now + 4, balance, { from: token_owner }); - - // try a transfer. it should fail because the lockup hasn't started yet. - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - now = (await web3.eth.getBlock('latest')).timestamp - - // wait 4 seconds for the lockup to begin - await new Promise(resolve => setTimeout(resolve, 4000)); - - // try another transfer. it should also fail because the lockup has just begun - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - now = (await web3.eth.getBlock('latest')).timestamp - - assert.ok(errorThrown, message); - - }); - - it("Should be possible to edit a lockup with a specific start time in the future", async() => { - - // edit the lockup - let now = (await web3.eth.getBlock('latest')).timestamp - - // should be 10000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor2) - - // check and get the lockup - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCount, 1) - - let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - - // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount - assert.equal(lockUp[0].toString(), '100'); - assert.equal(lockUp[1].toString(), '10'); - assert.isAtMost(lockUp[2].toNumber(), now); - assert.equal(lockUp[3].toString(), balance.toString()); - - // edit the lockup - await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor2, 0, 8, 4, now + 4, balance, { from: token_owner }); - - // check and get the lockup again - lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCount, 1) - - lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - - // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount - assert.equal(lockUp[0].toString(), '8'); - assert.equal(lockUp[1].toString(), '4'); - assert.isAtMost(lockUp[2].toNumber(), now + 4); - assert.equal(lockUp[3].toString(), balance.toString()); - - // try a transfer. it should fail because again, the lockup hasn't started yet. - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - // wait 4 seconds for the lockup to begin - await new Promise(resolve => setTimeout(resolve, 4000)); - - // try another transfer. it should fail because the lockup has just begun - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - // wait 4 seconds for the lockup's first period to elapse - await new Promise(resolve => setTimeout(resolve, 4000)); - - // try another transfer. it should pass - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); - - - // try another transfer without waiting for another period to pass. it should fail - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - // wait 4 seconds for the lockup's first period to elapse - await new Promise(resolve => setTimeout(resolve, 4000)); - - let lockUpBeforeVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - // check if transfer will pass in read-only operation - let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('5', 'ether'), 0, false) - // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 - assert.equal(result.toString(), '2') - let lockUpAfterVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - - assert.equal(lockUpBeforeVerify[4].toString(), lockUpAfterVerify[4].toString()) - - // try another transfer. it should pass - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); - - // wait 4 seconds for the lockup's first period to elapse. but, we are all out of periods. - await new Promise(resolve => setTimeout(resolve, 4000)); - - // try one final transfer. this should fail because the user has already withdrawn their entire balance - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - it("Should be possible to stack lockups", async() => { - // should be 17000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor1) - - // check and make sure that acct1 has no lockups so far - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount.toString(), 0) - - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 12, 4, 0, web3.utils.toWei('6', 'ether'), { from: token_owner }); - - // try to transfer 11 tokens that aren't locked up yet be locked up. should succeed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('11', 'ether'), { from: account_investor1 }); - - // try a transfer. it should fail because it's locked up from the first lockups - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - // wait 4 seconds for the lockup's first period to elapse. - await new Promise(resolve => setTimeout(resolve, 4000)); - - - // should succeed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); - - // send 8 back to investor1 so that we can lock them up - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('8', 'ether'), { from: account_investor2 }); - - // let's add another lockup to stack them - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, web3.utils.toWei('8', 'ether'), { from: token_owner }); - - // try a transfer. it should fail because it's locked up from both lockups - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - // wait 4 seconds for the 1st lockup's second period to elapse, and the 2nd lockup's first period to elapse - await new Promise(resolve => setTimeout(resolve, 4000)); - - // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - - // try aother transfer. it should fail because it's locked up from both lockups again - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> couldn't transfer because of lock up`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - - // wait 4 seconds for the 1st lockup's final period to elapse, and the 2nd lockup's second period to elapse - await new Promise(resolve => setTimeout(resolve, 4000)); - - // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - - // // try aother transfer. it should fail because it's locked up from both lockups again - // errorThrown = false; - // try { - // await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - // } catch(error) { - // console.log(` tx revert -> couldn't transfer because of lock up`.grey); - // ensureException(error); - // errorThrown = true; - // } - // assert.ok(errorThrown, message); - - // wait 8 seconds for 2nd lockup's third and fourth periods to elapse - await new Promise(resolve => setTimeout(resolve, 8000)); - - // should now be able to transfer 4, because there are 2 allowed per period in the 2nd lockup, and 2 periods have elapsed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - - // send the 3 back from acct2 that we sent over in the beginning of this test - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); - - // try another transfer. it should pass because both lockups have been entirely used - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - - balance = await I_SecurityToken.balanceOf(account_investor1) - assert.equal(balance.toString(), web3.utils.toWei('2', 'ether')) - }); - - - it("Should get configuration function signature", async() => { - let sig = await I_VolumeRestrictionTransferManager.getInitFunction.call(); - assert.equal(web3.utils.hexToNumber(sig), 0); - }); - - - it("Should get the permission", async() => { - let perm = await I_VolumeRestrictionTransferManager.getPermissions.call(); - assert.equal(perm.length, 1); - // console.log(web3.utils.toAscii(perm[0]).replace(/\u0000/g, '')) - assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "ADMIN") - }); - - }); - - describe("VolumeRestriction Transfer Manager Factory test cases", async() => { - - it("Should get the exact details of the factory", async() => { - assert.equal(await I_VolumeRestrictionTransferManagerFactory.setupCost.call(),0); - assert.equal((await I_VolumeRestrictionTransferManagerFactory.getTypes.call())[0],2); - assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTransferManagerFactory.getName.call()) - .replace(/\u0000/g, ''), - "VolumeRestrictionTransferManager", - "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getDescription.call(), - "Manage transfers using lock ups over time", - "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getTitle.call(), - "Volume Restriction Transfer Manager", - "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getInstructions.call(), - "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", - "Wrong Module added"); - - }); - - it("Should get the tags of the factory", async() => { - let tags = await I_VolumeRestrictionTransferManagerFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Volume"); - }); - }); - -}); +// }); + +// it("Should revert if the parameters are bad when creating multiple lockups", async() => { +// let errorThrown = false; +// try { +// // pass in the wrong number of params. txn should revert +// await I_VolumeRestrictionTransferManager.addLockUpMulti( +// [account_investor2, account_investor3], +// [16, 8], +// [2], // this array should have 2 elements but it has 1, which should cause a revert +// [0, 0], +// [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], +// { from: token_owner } +// ); +// } catch(error) { +// console.log(` tx revert -> passed in wrong number of array elements`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should be possible to create a lockup with a specific start time in the future", async() => { + +// // remove all lockups for account 2 +// let lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); +// assert.equal(lockUpsLength, 2); +// await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); +// await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); +// lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); +// assert.equal(lockUpsLength, 0); + +// let now = (await web3.eth.getBlock('latest')).timestamp + +// // balance here should be 10000000000000000000 +// let balance = await I_SecurityToken.balanceOf(account_investor2) + +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 100, 10, now + 4, balance, { from: token_owner }); + +// // try a transfer. it should fail because the lockup hasn't started yet. +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// now = (await web3.eth.getBlock('latest')).timestamp + +// // wait 4 seconds for the lockup to begin +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// // try another transfer. it should also fail because the lockup has just begun +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// now = (await web3.eth.getBlock('latest')).timestamp + +// assert.ok(errorThrown, message); + +// }); + +// it("Should be possible to edit a lockup with a specific start time in the future", async() => { + +// // edit the lockup +// let now = (await web3.eth.getBlock('latest')).timestamp + +// // should be 10000000000000000000 +// let balance = await I_SecurityToken.balanceOf(account_investor2) + +// // check and get the lockup +// let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); +// assert.equal(lockUpCount, 1) + +// let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); + +// // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount +// assert.equal(lockUp[0].toString(), '100'); +// assert.equal(lockUp[1].toString(), '10'); +// assert.isAtMost(lockUp[2].toNumber(), now); +// assert.equal(lockUp[3].toString(), balance.toString()); + +// // edit the lockup +// await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor2, 0, 8, 4, now + 4, balance, { from: token_owner }); + +// // check and get the lockup again +// lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); +// assert.equal(lockUpCount, 1) + +// lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); + +// // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount +// assert.equal(lockUp[0].toString(), '8'); +// assert.equal(lockUp[1].toString(), '4'); +// assert.isAtMost(lockUp[2].toNumber(), now + 4); +// assert.equal(lockUp[3].toString(), balance.toString()); + +// // try a transfer. it should fail because again, the lockup hasn't started yet. +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// // wait 4 seconds for the lockup to begin +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// // try another transfer. it should fail because the lockup has just begun +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// // wait 4 seconds for the lockup's first period to elapse +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// // try another transfer. it should pass +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); + + +// // try another transfer without waiting for another period to pass. it should fail +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// // wait 4 seconds for the lockup's first period to elapse +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// let lockUpBeforeVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); +// // check if transfer will pass in read-only operation +// let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('5', 'ether'), 0, false) +// // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 +// assert.equal(result.toString(), '2') +// let lockUpAfterVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); + +// assert.equal(lockUpBeforeVerify[4].toString(), lockUpAfterVerify[4].toString()) + +// // try another transfer. it should pass +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); + +// // wait 4 seconds for the lockup's first period to elapse. but, we are all out of periods. +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// // try one final transfer. this should fail because the user has already withdrawn their entire balance +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + +// it("Should be possible to stack lockups", async() => { +// // should be 17000000000000000000 +// let balance = await I_SecurityToken.balanceOf(account_investor1) + +// // check and make sure that acct1 has no lockups so far +// let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); +// assert.equal(lockUpCount.toString(), 0) + +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 12, 4, 0, web3.utils.toWei('6', 'ether'), { from: token_owner }); + +// // try to transfer 11 tokens that aren't locked up yet be locked up. should succeed +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('11', 'ether'), { from: account_investor1 }); + +// // try a transfer. it should fail because it's locked up from the first lockups +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// // wait 4 seconds for the lockup's first period to elapse. +// await new Promise(resolve => setTimeout(resolve, 4000)); + + +// // should succeed +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); + +// // send 8 back to investor1 so that we can lock them up +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('8', 'ether'), { from: account_investor2 }); + +// // let's add another lockup to stack them +// await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, web3.utils.toWei('8', 'ether'), { from: token_owner }); + +// // try a transfer. it should fail because it's locked up from both lockups +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// // wait 4 seconds for the 1st lockup's second period to elapse, and the 2nd lockup's first period to elapse +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); + +// // try aother transfer. it should fail because it's locked up from both lockups again +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// } catch(error) { +// console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); + +// // wait 4 seconds for the 1st lockup's final period to elapse, and the 2nd lockup's second period to elapse +// await new Promise(resolve => setTimeout(resolve, 4000)); + +// // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); + +// // // try aother transfer. it should fail because it's locked up from both lockups again +// // errorThrown = false; +// // try { +// // await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); +// // } catch(error) { +// // console.log(` tx revert -> couldn't transfer because of lock up`.grey); +// // ensureException(error); +// // errorThrown = true; +// // } +// // assert.ok(errorThrown, message); + +// // wait 8 seconds for 2nd lockup's third and fourth periods to elapse +// await new Promise(resolve => setTimeout(resolve, 8000)); + +// // should now be able to transfer 4, because there are 2 allowed per period in the 2nd lockup, and 2 periods have elapsed +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); + +// // send the 3 back from acct2 that we sent over in the beginning of this test +// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); + +// // try another transfer. it should pass because both lockups have been entirely used +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + +// balance = await I_SecurityToken.balanceOf(account_investor1) +// assert.equal(balance.toString(), web3.utils.toWei('2', 'ether')) +// }); + + +// it("Should get configuration function signature", async() => { +// let sig = await I_VolumeRestrictionTransferManager.getInitFunction.call(); +// assert.equal(web3.utils.hexToNumber(sig), 0); +// }); + + +// it("Should get the permission", async() => { +// let perm = await I_VolumeRestrictionTransferManager.getPermissions.call(); +// assert.equal(perm.length, 1); +// // console.log(web3.utils.toAscii(perm[0]).replace(/\u0000/g, '')) +// assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "ADMIN") +// }); + +// }); + +// describe("VolumeRestriction Transfer Manager Factory test cases", async() => { + +// it("Should get the exact details of the factory", async() => { +// assert.equal(await I_VolumeRestrictionTransferManagerFactory.setupCost.call(),0); +// assert.equal((await I_VolumeRestrictionTransferManagerFactory.getTypes.call())[0],2); +// assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTransferManagerFactory.getName.call()) +// .replace(/\u0000/g, ''), +// "VolumeRestrictionTransferManager", +// "Wrong Module added"); +// assert.equal(await I_VolumeRestrictionTransferManagerFactory.getDescription.call(), +// "Manage transfers using lock ups over time", +// "Wrong Module added"); +// assert.equal(await I_VolumeRestrictionTransferManagerFactory.getTitle.call(), +// "Volume Restriction Transfer Manager", +// "Wrong Module added"); +// assert.equal(await I_VolumeRestrictionTransferManagerFactory.getInstructions.call(), +// "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", +// "Wrong Module added"); + +// }); + +// it("Should get the tags of the factory", async() => { +// let tags = await I_VolumeRestrictionTransferManagerFactory.getTags.call(); +// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Volume"); +// }); +// }); + +// }); diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index 64813eed1..afbcdb07f 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -1,1178 +1,1178 @@ -import latestTime from './helpers/latestTime'; -import { - duration, - ensureException, - promisifyLogWatch, - latestBlock -} from './helpers/utils'; -import takeSnapshot, { - increaseTime, - revertToSnapshot -} from './helpers/time'; -import { - encodeProxyCall -} from './helpers/encodeCall'; - -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const SingleTradeVolumeRestrictionManagerFactory = artifacts.require('./SingleTradeVolumeRestrictionManagerFactory.sol'); -const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionManager'); -const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('SingleTradeVolumeRestrictionManager', accounts => { - - - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_investor5; - let zero_address = '0x0000000000000000000000000000000000000000'; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_SecurityTokenRegistryProxy - let I_GeneralPermissionManagerFactory; - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_SingleTradeVolumeRestrictionManagerFactory; - let I_SingleTradeVolumeRestrictionManager; - let P_SingleTradeVolumeRestrictionManagerFactory; - let P_SingleTradeVolumeRestrictionManager; - let I_SingleTradeVolumeRestrictionPercentageManager; - let I_ModuleRegistry; - let I_MRProxied; - let I_ModuleRegistryProxy; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - - // SecurityToken Details - const swarmHash = "dagwrgwgvwergwrvwrg"; - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - before(async () => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[6]; - account_investor2 = accounts[7]; - account_investor3 = accounts[8]; - account_investor4 = accounts[9]; - account_investor5 = accounts[5]; - - // ----------- POLYMATH NETWORK Configuration ------------ - - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({ - from: account_polymath - }); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, { - from: account_polymath - }); - - // STEP 2: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({ - from: account_polymath - }); - // - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({ - from: account_polymath - }); - - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, { - from: account_polymath - }); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - - // - // - // // STEP 2: Deploy the GeneralTransferManagerFactory - // - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { - from: account_polymath - }); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 3: Deploy the GeneralDelegateManagerFactoryFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { - from: account_polymath - }); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory - I_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { - from: account_polymath - }); - - assert.notEqual( - I_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" - ); - - - P_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, { - from: account_polymath - }); - assert.notEqual( - P_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" - ); - // - // - // // Step 6: Deploy the STFactory contract - // - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, { - from: account_polymath - }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 7: Deploy the SecurityTokenRegistry contract - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({ - from: account_polymath - }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 8: Deploy the proxy and attach the implementation contract to it. - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({ - from: account_polymath - }); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { - from: account_polymath - }); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // - // // Step 9: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, { - from: account_polymath - }) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, { - from: account_polymath - }); - await I_MRProxied.updateFromRegistry({ - from: account_polymath - }); - - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { - from: account_polymath - }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { - from: account_polymath - }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { - from: account_polymath - }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { - from: account_polymath - }); - - // (C) : Register the SingleTradeVolumeRestrictionManagerFactory - await I_MRProxied.registerModule(I_SingleTradeVolumeRestrictionManagerFactory.address, { - from: account_polymath - }); - await I_MRProxied.verifyModule(I_SingleTradeVolumeRestrictionManagerFactory.address, true, { - from: account_polymath - }); - - // (C) : Register the Paid SingleTradeVolumeRestrictionManagerFactory - await I_MRProxied.registerModule(P_SingleTradeVolumeRestrictionManagerFactory.address, { - from: account_polymath - }); - await I_MRProxied.verifyModule(P_SingleTradeVolumeRestrictionManagerFactory.address, true, { - from: account_polymath - }); - }) - - describe("Generate the SecurityToken", async () => { - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { - from: token_owner - }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { - from: token_owner - }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { - from: token_owner - }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { - from: token_owner - }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ - from: _blockNo - }), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - }); - // - describe("Buy tokens using whitelist & manual approvals", async () => { - - it("Should Buy the tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('100', 'ether'), { - from: token_owner - }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('100', 'ether') - ); - }); - - it("Should Buy some more tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { - from: token_owner - }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - // - it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { - let managerArgs = web3.eth.abi.encodeFunctionCall({ - name: 'configure', - type: 'function', - inputs: [{ - type: 'bool', - name: '_isTransferLimitInPercentage' - }, - { - type: 'uint256', - name: '_globalTransferLimitInPercentageOrToken' - }, - { - type: 'bool', - name: '_allowPrimaryIssuance' - } - ] - }, [true, 90, false]) - let errorThrown = false; - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - try { - const tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { - from: token_owner - }); - } catch (error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); - }); - - - - it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { - let managerArgs = web3.eth.abi.encodeFunctionCall({ - name: 'configure', - type: 'function', - inputs: [{ - type: 'bool', - name: '_isTransferLimitInPercentage' - }, - { - type: 'uint256', - name: '_globalTransferLimitInPercentageOrToken' - }, - { - type: 'bool', - name: '_allowPrimaryIssuance' - } - ] - }, [false, 90, false]); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { - from: token_owner - }); - let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { - from: token_owner - }); - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "SingleTradeVolumeRestrictionManager did not get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestriction", - "SingleTradeVolumeRestrictionManagerFactory module was not added" - ); - P_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[3].args._module); - }); - - it("Should successfully attach the SingleTradeVolumeRestrictionManager with the security token", async () => { - let managerArgs = web3.eth.abi.encodeFunctionCall({ - name: 'configure', - type: 'function', - inputs: [{ - type: 'bool', - name: '_isTransferLimitInPercentage' - }, - { - type: 'uint256', - name: '_globalTransferLimitInPercentageOrToken' - }, - { - type: 'bool', - name: '_allowPrimaryIssuance' - } - ] - }, [false, 7 * 10 ** 16, false]) - const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { - from: token_owner - }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestriction", - "SingleTradeVolumeRestriction module was not added" - ); - I_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); - }); - - it("Should successfully attach the SingleTradeVolumeRestrictionManager (Percentage) with the security token", async () => { - let managerArgs = web3.eth.abi.encodeFunctionCall({ - name: 'configure', - type: 'function', - inputs: [{ - type: 'bool', - name: '_isTransferLimitInPercentage' - }, - { - type: 'uint256', - name: '_globalTransferLimitInPercentageOrToken' - }, - { - type: 'bool', - name: '_allowPrimaryIssuance' - } - ] - }, [true, 90, false]); - const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { - from: token_owner - }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestriction", - "SingleTradeVolumeRestriction module was not added" - ); - I_SingleTradeVolumeRestrictionPercentageManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); - }); - - it('should return get permissions', async () => { - let permissions = await I_SingleTradeVolumeRestrictionPercentageManager.getPermissions(); - assert.equal(permissions.length, 1, "Invalid Permissions"); - assert.equal( - web3.utils.toAscii(permissions[0]).replace(/\u0000/g, ''), - "ADMIN", - 'Wrong permissions' - ); - }); - - it('add exempt wallet', async () => { - let errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]); - } catch (e) { - errorThrown = true; - } - assert.ok(errorThrown, "Non Admins cannot add exempt wallets"); - - errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { - from: token_owner - }); - } catch (e) { - ensureException(e); - errorThrown = true; - } - - assert.ok(errorThrown, "Exempt wallet cannot be zero"); - - let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet added as exempt"); - }); - - it('should remove an exempt wallet', async () => { - let errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5]); - } catch (e) { - errorThrown = true; - } - assert.ok(errorThrown, "Non Admins cannot add exempt wallets"); - - errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(zero_address, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - - assert.ok(errorThrown, "Zero address cannot be added to exempt wallet"); - - let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet removed from exempt"); - }); - - it('should set transfer limit for a wallet', async () => { - let errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100); - } catch (e) { - errorThrown = true; - } - assert.ok(errorThrown, "Non Admins cannot set transfer limits"); - - errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 0, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Transfer limit cannot be set to 0") - errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInPercentage(accounts[4], 10, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Transfer limit cannot be set in percentage") - let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[4]); - assert.equal(tx.logs[0].args._amount, 100); - - errorThrown = false; - try { - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 0, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - errorThrown = false - try { - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Transfer limit can not be set to more 0") - errorThrown = false; - try { - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - - assert.ok(errorThrown, "Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage") - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 50, { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet added to transfer limits"); - assert.equal(tx.logs[0].args._percentage, 50, "Wrong percentage set"); - }); - - it('should remove transfer limit for wallet', async () => { - let errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4]); - } catch (e) { - errorThrown = true; - } - assert.ok(errorThrown, "Non Admins cannot set/remove transfer limits"); - - errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[0], { - from: token_owner - }); - } catch (e) { - errorThrown = true; - } - assert.ok(errorThrown, "Non Admins cannot set/remove transfer limits"); - - let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4], { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet removed"); - }); - - it("Should pause the tranfers at Manager level", async () => { - let tx = await I_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - }); - - it('should be able to set a global transfer limit', async () => { - let errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(100 * 10 ** 18); - } catch (e) { - errorThrown = true; - } - assert.ok(errorThrown, "only owner is allowed"); - - errorThrown = false; - - try { - let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(100 * 10 ** 18, { - from: token_owner - }); - } catch (e) { - ensureException(e); - errorThrown = true; - } - assert.ok(errorThrown, "Cannot change global limit in percentage when set to tokens"); - - errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(0, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Global limit cannot be set to 0"); - let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { - from: token_owner - }); - assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - - errorThrown = false; - - try { - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Global limit can be set by non-admins"); - - errorThrown = false; - - try { - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "cannot change global limit in tokens if transfer limit is set to percentage"); - - errorThrown = false; - try { - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(0, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Cannot set global limit in tokens to 0"); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(40, { - from: token_owner - }); - assert.equal(tx.logs[0].args._percentage, 40, "Global Limit not set"); - - errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(101 * 10 ** 16, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Global limit cannot be set to more than 100"); - - errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(10, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Global limit in percentage cannot be set when limit is in tokens"); - errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(10, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Global limit in tokens cannot be set when limit is in percentage"); - }); - - it('should perform batch updates', async () => { - let wallets = [accounts[0], accounts[1], accounts[2]]; - let tokenLimits = [1, 2, 3]; - let percentageLimits = [5, 6, 7]; - - let errorThrown = false; - try { - await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti([], { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Exempt wallet multi cannot be empty wallet"); - - // add exempt wallet multi - let tx = await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { - from: token_owner - }); - let logs = tx.logs.filter(log => log.event === 'ExemptWalletAdded'); - assert.equal(logs.length, wallets.length, "Batch Exempt wallets not added"); - for (let i = 0; i < logs.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); - } - - errorThrown = false; - try { - await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti([], { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Exempt wallet multi cannot be empty wallet"); - - // remove exempt wallet multi - tx = await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { - from: token_owner - }) - logs = tx.logs.filter(log => log.event === 'ExemptWalletRemoved'); - assert.equal(logs.length, wallets.length, "Batch Exempt wallets not removed"); - - for (let i = 0; i < logs.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); - } - - errorThrown = false; - try { - tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([], tokenLimits, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "wallets cannot be empty"); - - errorThrown = false; - try { - tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([accounts[0]], tokenLimits, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "wallet array length dont match"); - - tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInTokensSet'); - assert.equal(wallets.length, logs.length, "Transfer limit not set"); - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not set for wallet"); - assert.equal(logs[i].args._amount.toNumber(), tokenLimits[i]); - } - errorThrown = false - try { - await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti([], { - from: token_owner - }); - } catch (e) { - ensureException(e); - errorThrown = true; - } - assert.ok(errorThrown, "Wallets cannot be empty"); - tx = await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event === 'TransferLimitInTokensRemoved'); - assert.equal(logs.length, wallets.length, "Transfer limit not removed"); - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not removed for wallet"); - } - - errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti([], percentageLimits, { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "wallets cannot be empty"); - - errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, [], { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "wallets and amounts dont match be empty"); - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageSet'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - assert.equal(logs[i].args._percentage.toNumber(), percentageLimits[i]); - } - - errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti([], { - from: token_owner - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Wallets cannot be empty"); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageRemoved'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - } - - errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentage(wallets[0], { - from: token_owner - }); - } catch (e) { - ensureException(e) - errorThrown = true; - } - assert.ok(errorThrown, "Wallet should not be removed"); - }) - - it('should be able to transfer tokens SingleTradeVolumeRestriction', async () => { - await I_SingleTradeVolumeRestrictionManager.unpause({ - from: token_owner - }) - await I_SingleTradeVolumeRestrictionPercentageManager.pause({ - from: token_owner - }) - await P_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor4, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor5, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - - //setting a max of 5 tokens - await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(web3.utils.toWei('5', 'ether'), { - from: token_owner - }) - - let errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('6', 'ether'), { - from: account_investor1 - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Transfer should have not happened"); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('4', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('4', 'ether')); - - // exempt wallet - await I_SingleTradeVolumeRestrictionManager.addExemptWallet(account_investor1, { - from: token_owner - }); - await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('7', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toNumber(), web3.utils.toWei('7', 'ether')); - - //special limits wallet - await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(account_investor5, web3.utils.toWei('5', 'ether'), { - from: token_owner - }); - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('7', 'ether'), { - from: account_investor5 - }); - } catch (e) { - errorThrown = true; - ensureException(e); - } - assert.ok(errorThrown, "Transfer should have not happened"); - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('4', 'ether'), { - from: account_investor5 - }) - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei('4', 'ether')) - }) - - it('should be able to transfer tokens (percentage transfer limit)', async () => { - await I_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - let balance = (await I_SecurityToken.balanceOf(account_investor2)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor2 - }); - - - balance = (await I_SecurityToken.balanceOf(account_investor3)).toNumber(); - - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor3 - }); - - - balance = (await I_SecurityToken.balanceOf(account_investor4)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor4 - }); - - balance = (await I_SecurityToken.balanceOf(account_investor5)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor5 - }); - - await I_SingleTradeVolumeRestrictionPercentageManager.unpause({ - from: token_owner - }); - // // - await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(49 * 10 ** 16, { - from: token_owner - }); - - let errorThrown = false; - try { - // more than the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('90', 'ether'), { - from: account_investor1 - }); - } catch (e) { - ensureException(e); - errorThrown = true; - } - assert.ok(errorThrown, "Transfer above limit happened"); - - - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('20', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei('20', 'ether')) - - await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(account_investor1, 5 * 10 ** 16, { - from: token_owner - }); - errorThrown = false; - try { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('35', 'ether'), { - from: account_investor1 - }); - } catch (e) { - ensureException(e); - errorThrown = true; - } - assert.ok(errorThrown, "transfer happened above limit"); - - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('1', 'ether')); - }); - - it('should change transfer limits to tokens', async () => { - let errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { - from: token_owner - }); - } catch (e) { - - ensureException(e); - errorThrown = true; - } - assert.equal(errorThrown, true, "Should not change to percentage again"); - - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { - from: token_owner - }); - assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); - assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); - }) - - it('should change transfer limits to percentage', async () => { - let errorThrown = false; - try { - await I_SingleTradeVolumeRestrictionManager.changeTransferLimitToTokens(1, { - from: token_owner - }); - } catch (e) { - ensureException(e); - errorThrown = true; - } - assert.equal(errorThrown, true, "Should not change to tokens again"); - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { - from: token_owner - }); - assert.ok(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), "Error Changing"); - assert.equal(tx.logs[0].args._percentage.toNumber(), 1, "Transfer limit not changed"); - }) - - - - }); - - describe("SingleTradeVolumeRestrictionManager Factory test cases", async () => { - - it("Should get the exact details of the factory", async () => { - assert.equal(await I_SingleTradeVolumeRestrictionManagerFactory.setupCost.call(), 0); - assert.equal((await I_SingleTradeVolumeRestrictionManagerFactory.getTypes.call())[0], 2); - let name = web3.utils.toUtf8(await I_SingleTradeVolumeRestrictionManagerFactory.getName.call()); - assert.equal(name, "SingleTradeVolumeRestriction", "Wrong Module added"); - let desc = await I_SingleTradeVolumeRestrictionManagerFactory.getDescription.call(); - assert.equal(desc, "Imposes volume restriction on a single trade", "Wrong Module added"); - let title = await I_SingleTradeVolumeRestrictionManagerFactory.getTitle.call(); - assert.equal(title, "Single Trade Volume Restriction Manager", "Wrong Module added"); - let inst = await I_SingleTradeVolumeRestrictionManagerFactory.getInstructions.call(); - assert.equal(inst, "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens", "Wrong Module added"); - let version = await I_SingleTradeVolumeRestrictionManagerFactory.getVersion.call(); - assert.equal(version, "1.0.0", "Version not correct"); - }); - - it("Should get the tags of the factory", async () => { - let tags = await I_SingleTradeVolumeRestrictionManagerFactory.getTags.call(); - assert.equal(web3.utils.toUtf8(tags[0]), "Single Trade"); - assert.equal(web3.utils.toUtf8(tags[1]), "Transfer"); - assert.equal(web3.utils.toUtf8(tags[2]), "Volume"); - }); - - - }); -}); +// import latestTime from './helpers/latestTime'; +// import { +// duration, +// ensureException, +// promisifyLogWatch, +// latestBlock +// } from './helpers/utils'; +// import takeSnapshot, { +// increaseTime, +// revertToSnapshot +// } from './helpers/time'; +// import { +// encodeProxyCall +// } from './helpers/encodeCall'; + +// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +// const SecurityToken = artifacts.require('./SecurityToken.sol'); +// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +// const STFactory = artifacts.require('./STFactory.sol'); +// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +// const SingleTradeVolumeRestrictionManagerFactory = artifacts.require('./SingleTradeVolumeRestrictionManagerFactory.sol'); +// const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionManager'); +// const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); +// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +// const Web3 = require('web3'); +// const BigNumber = require('bignumber.js'); +// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +// contract('SingleTradeVolumeRestrictionManager', accounts => { + + + +// // Accounts Variable declaration +// let account_polymath; +// let account_issuer; +// let token_owner; +// let account_investor1; +// let account_investor2; +// let account_investor3; +// let account_investor4; +// let account_investor5; +// let zero_address = '0x0000000000000000000000000000000000000000'; + +// // investor Details +// let fromTime = latestTime(); +// let toTime = latestTime(); +// let expiryTime = toTime + duration.days(15); + +// let message = "Transaction Should Fail!"; + +// // Contract Instance Declaration +// let I_SecurityTokenRegistryProxy +// let I_GeneralPermissionManagerFactory; +// let I_GeneralTransferManagerFactory; +// let I_GeneralPermissionManager; +// let I_GeneralTransferManager; +// let I_SingleTradeVolumeRestrictionManagerFactory; +// let I_SingleTradeVolumeRestrictionManager; +// let P_SingleTradeVolumeRestrictionManagerFactory; +// let P_SingleTradeVolumeRestrictionManager; +// let I_SingleTradeVolumeRestrictionPercentageManager; +// let I_ModuleRegistry; +// let I_MRProxied; +// let I_ModuleRegistryProxy; +// let I_FeatureRegistry; +// let I_SecurityTokenRegistry; +// let I_STRProxied; +// let I_STFactory; +// let I_SecurityToken; +// let I_PolyToken; +// let I_PolymathRegistry; + +// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; +// const MRProxyParameters = ['address', 'address']; + +// // SecurityToken Details +// const swarmHash = "dagwrgwgvwergwrvwrg"; +// const name = "Team"; +// const symbol = "sap"; +// const tokenDetails = "This is equity type of issuance"; +// const decimals = 18; +// const contact = "team@polymath.network"; + +// // Module key +// const delegateManagerKey = 1; +// const transferManagerKey = 2; +// const stoKey = 3; + +// // Initial fee for ticker registry and security token registry +// const initRegFee = web3.utils.toWei("250"); + +// before(async () => { +// // Accounts setup +// account_polymath = accounts[0]; +// account_issuer = accounts[1]; + +// token_owner = account_issuer; + +// account_investor1 = accounts[6]; +// account_investor2 = accounts[7]; +// account_investor3 = accounts[8]; +// account_investor4 = accounts[9]; +// account_investor5 = accounts[5]; + +// // ----------- POLYMATH NETWORK Configuration ------------ + +// // Step 0: Deploy the PolymathRegistry +// I_PolymathRegistry = await PolymathRegistry.new({ +// from: account_polymath +// }); + +// // Step 1: Deploy the token Faucet and Mint tokens for token_owner +// I_PolyToken = await PolyTokenFaucet.new(); +// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + +// I_FeatureRegistry = await FeatureRegistry.new( +// I_PolymathRegistry.address, { +// from: account_polymath +// }); + +// // STEP 2: Deploy the ModuleRegistry + +// I_ModuleRegistry = await ModuleRegistry.new({ +// from: account_polymath +// }); +// // +// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({ +// from: account_polymath +// }); + +// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); +// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, { +// from: account_polymath +// }); +// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + +// // +// // +// // // STEP 2: Deploy the GeneralTransferManagerFactory +// // +// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { +// from: account_polymath +// }); + +// assert.notEqual( +// I_GeneralTransferManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralTransferManagerFactory contract was not deployed" +// ); + +// // STEP 3: Deploy the GeneralDelegateManagerFactoryFactory + +// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { +// from: account_polymath +// }); + +// assert.notEqual( +// I_GeneralPermissionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "GeneralDelegateManagerFactory contract was not deployed" +// ); + +// // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory +// I_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { +// from: account_polymath +// }); + +// assert.notEqual( +// I_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" +// ); + + +// P_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, { +// from: account_polymath +// }); +// assert.notEqual( +// P_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" +// ); +// // +// // +// // // Step 6: Deploy the STFactory contract +// // +// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, { +// from: account_polymath +// }); + +// assert.notEqual( +// I_STFactory.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "STFactory contract was not deployed", +// ); + +// // Step 7: Deploy the SecurityTokenRegistry contract + +// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({ +// from: account_polymath +// }); + +// assert.notEqual( +// I_SecurityTokenRegistry.address.valueOf(), +// "0x0000000000000000000000000000000000000000", +// "SecurityTokenRegistry contract was not deployed", +// ); + +// // Step 8: Deploy the proxy and attach the implementation contract to it. +// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({ +// from: account_polymath +// }); +// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); +// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { +// from: account_polymath +// }); +// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); +// // +// // // Step 9: update the registries addresses from the PolymathRegistry contract +// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, { +// from: account_polymath +// }) +// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, { +// from: account_polymath +// }); +// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, { +// from: account_polymath +// }); +// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, { +// from: account_polymath +// }); +// await I_MRProxied.updateFromRegistry({ +// from: account_polymath +// }); + +// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { +// from: account_polymath +// }); +// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { +// from: account_polymath +// }); + +// // (B) : Register the GeneralDelegateManagerFactory +// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { +// from: account_polymath +// }); +// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { +// from: account_polymath +// }); + +// // (C) : Register the SingleTradeVolumeRestrictionManagerFactory +// await I_MRProxied.registerModule(I_SingleTradeVolumeRestrictionManagerFactory.address, { +// from: account_polymath +// }); +// await I_MRProxied.verifyModule(I_SingleTradeVolumeRestrictionManagerFactory.address, true, { +// from: account_polymath +// }); + +// // (C) : Register the Paid SingleTradeVolumeRestrictionManagerFactory +// await I_MRProxied.registerModule(P_SingleTradeVolumeRestrictionManagerFactory.address, { +// from: account_polymath +// }); +// await I_MRProxied.verifyModule(P_SingleTradeVolumeRestrictionManagerFactory.address, true, { +// from: account_polymath +// }); +// }) + +// describe("Generate the SecurityToken", async () => { +// it("Should register the ticker before the generation of the security token", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { +// from: token_owner +// }); +// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { +// from: token_owner +// }); +// assert.equal(tx.logs[0].args._owner, token_owner); +// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); +// }); + +// it("Should generate the new security token with the same symbol as registered above", async () => { +// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { +// from: token_owner +// }); +// let _blockNo = latestBlock(); +// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { +// from: token_owner +// }); + +// // Verify the successful generation of the security token +// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + +// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + +// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ +// from: _blockNo +// }), 1); + +// // Verify that GeneralTransferManager module get added successfully or not +// assert.equal(log.args._types[0].toNumber(), 2); +// assert.equal( +// web3.utils.toAscii(log.args._name) +// .replace(/\u0000/g, ''), +// "GeneralTransferManager" +// ); +// }); + +// it("Should intialize the auto attached modules", async () => { +// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; +// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); +// }); +// }); +// // +// describe("Buy tokens using whitelist & manual approvals", async () => { + +// it("Should Buy the tokens", async () => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor1, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, { +// from: account_issuer +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Jump time +// await increaseTime(5000); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('100', 'ether'), { +// from: token_owner +// }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), +// web3.utils.toWei('100', 'ether') +// ); +// }); + +// it("Should Buy some more tokens", async () => { +// // Add the Investor in to the whitelist + +// let tx = await I_GeneralTransferManager.modifyWhitelist( +// account_investor2, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, { +// from: account_issuer +// }); + +// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + +// // Mint some tokens +// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { +// from: token_owner +// }); + +// assert.equal( +// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), +// web3.utils.toWei('1', 'ether') +// ); +// }); +// // +// it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { +// let managerArgs = web3.eth.abi.encodeFunctionCall({ +// name: 'configure', +// type: 'function', +// inputs: [{ +// type: 'bool', +// name: '_isTransferLimitInPercentage' +// }, +// { +// type: 'uint256', +// name: '_globalTransferLimitInPercentageOrToken' +// }, +// { +// type: 'bool', +// name: '_allowPrimaryIssuance' +// } +// ] +// }, [true, 90, false]) +// let errorThrown = false; +// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); +// try { +// const tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { +// from: token_owner +// }); +// } catch (error) { +// console.log(` tx -> failed because Token is not paid`.grey); +// ensureException(error); +// errorThrown = true; +// } +// assert.ok(errorThrown, message); +// }); + + + +// it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { +// let managerArgs = web3.eth.abi.encodeFunctionCall({ +// name: 'configure', +// type: 'function', +// inputs: [{ +// type: 'bool', +// name: '_isTransferLimitInPercentage' +// }, +// { +// type: 'uint256', +// name: '_globalTransferLimitInPercentageOrToken' +// }, +// { +// type: 'bool', +// name: '_allowPrimaryIssuance' +// } +// ] +// }, [false, 90, false]); +// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { +// from: token_owner +// }); +// let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { +// from: token_owner +// }); +// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "SingleTradeVolumeRestrictionManager did not get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[3].args._name) +// .replace(/\u0000/g, ''), +// "SingleTradeVolumeRestriction", +// "SingleTradeVolumeRestrictionManagerFactory module was not added" +// ); +// P_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[3].args._module); +// }); + +// it("Should successfully attach the SingleTradeVolumeRestrictionManager with the security token", async () => { +// let managerArgs = web3.eth.abi.encodeFunctionCall({ +// name: 'configure', +// type: 'function', +// inputs: [{ +// type: 'bool', +// name: '_isTransferLimitInPercentage' +// }, +// { +// type: 'uint256', +// name: '_globalTransferLimitInPercentageOrToken' +// }, +// { +// type: 'bool', +// name: '_allowPrimaryIssuance' +// } +// ] +// }, [false, 7 * 10 ** 16, false]) +// const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { +// from: token_owner +// }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "SingleTradeVolumeRestriction", +// "SingleTradeVolumeRestriction module was not added" +// ); +// I_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); +// }); + +// it("Should successfully attach the SingleTradeVolumeRestrictionManager (Percentage) with the security token", async () => { +// let managerArgs = web3.eth.abi.encodeFunctionCall({ +// name: 'configure', +// type: 'function', +// inputs: [{ +// type: 'bool', +// name: '_isTransferLimitInPercentage' +// }, +// { +// type: 'uint256', +// name: '_globalTransferLimitInPercentageOrToken' +// }, +// { +// type: 'bool', +// name: '_allowPrimaryIssuance' +// } +// ] +// }, [true, 90, false]); +// const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { +// from: token_owner +// }); +// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); +// assert.equal( +// web3.utils.toAscii(tx.logs[2].args._name) +// .replace(/\u0000/g, ''), +// "SingleTradeVolumeRestriction", +// "SingleTradeVolumeRestriction module was not added" +// ); +// I_SingleTradeVolumeRestrictionPercentageManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); +// }); + +// it('should return get permissions', async () => { +// let permissions = await I_SingleTradeVolumeRestrictionPercentageManager.getPermissions(); +// assert.equal(permissions.length, 1, "Invalid Permissions"); +// assert.equal( +// web3.utils.toAscii(permissions[0]).replace(/\u0000/g, ''), +// "ADMIN", +// 'Wrong permissions' +// ); +// }); + +// it('add exempt wallet', async () => { +// let errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]); +// } catch (e) { +// errorThrown = true; +// } +// assert.ok(errorThrown, "Non Admins cannot add exempt wallets"); + +// errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { +// from: token_owner +// }); +// } catch (e) { +// ensureException(e); +// errorThrown = true; +// } + +// assert.ok(errorThrown, "Exempt wallet cannot be zero"); + +// let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { +// from: token_owner +// }); +// assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet added as exempt"); +// }); + +// it('should remove an exempt wallet', async () => { +// let errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5]); +// } catch (e) { +// errorThrown = true; +// } +// assert.ok(errorThrown, "Non Admins cannot add exempt wallets"); + +// errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(zero_address, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } + +// assert.ok(errorThrown, "Zero address cannot be added to exempt wallet"); + +// let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { +// from: token_owner +// }); +// assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet removed from exempt"); +// }); + +// it('should set transfer limit for a wallet', async () => { +// let errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100); +// } catch (e) { +// errorThrown = true; +// } +// assert.ok(errorThrown, "Non Admins cannot set transfer limits"); + +// errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 0, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Transfer limit cannot be set to 0") +// errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInPercentage(accounts[4], 10, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Transfer limit cannot be set in percentage") +// let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { +// from: token_owner +// }); +// assert.equal(tx.logs[0].args._wallet, accounts[4]); +// assert.equal(tx.logs[0].args._amount, 100); + +// errorThrown = false; +// try { +// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 0, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// errorThrown = false +// try { +// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Transfer limit can not be set to more 0") +// errorThrown = false; +// try { +// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } + +// assert.ok(errorThrown, "Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage") +// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 50, { +// from: token_owner +// }); +// assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet added to transfer limits"); +// assert.equal(tx.logs[0].args._percentage, 50, "Wrong percentage set"); +// }); + +// it('should remove transfer limit for wallet', async () => { +// let errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4]); +// } catch (e) { +// errorThrown = true; +// } +// assert.ok(errorThrown, "Non Admins cannot set/remove transfer limits"); + +// errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[0], { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// } +// assert.ok(errorThrown, "Non Admins cannot set/remove transfer limits"); + +// let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4], { +// from: token_owner +// }); +// assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet removed"); +// }); + +// it("Should pause the tranfers at Manager level", async () => { +// let tx = await I_SingleTradeVolumeRestrictionManager.pause({ +// from: token_owner +// }); +// }); + +// it('should be able to set a global transfer limit', async () => { +// let errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(100 * 10 ** 18); +// } catch (e) { +// errorThrown = true; +// } +// assert.ok(errorThrown, "only owner is allowed"); + +// errorThrown = false; + +// try { +// let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(100 * 10 ** 18, { +// from: token_owner +// }); +// } catch (e) { +// ensureException(e); +// errorThrown = true; +// } +// assert.ok(errorThrown, "Cannot change global limit in percentage when set to tokens"); + +// errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(0, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Global limit cannot be set to 0"); +// let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { +// from: token_owner +// }); +// assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); + +// errorThrown = false; + +// try { +// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Global limit can be set by non-admins"); + +// errorThrown = false; + +// try { +// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "cannot change global limit in tokens if transfer limit is set to percentage"); + +// errorThrown = false; +// try { +// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(0, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Cannot set global limit in tokens to 0"); + +// tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(40, { +// from: token_owner +// }); +// assert.equal(tx.logs[0].args._percentage, 40, "Global Limit not set"); + +// errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(101 * 10 ** 16, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Global limit cannot be set to more than 100"); + +// errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(10, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Global limit in percentage cannot be set when limit is in tokens"); +// errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(10, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Global limit in tokens cannot be set when limit is in percentage"); +// }); + +// it('should perform batch updates', async () => { +// let wallets = [accounts[0], accounts[1], accounts[2]]; +// let tokenLimits = [1, 2, 3]; +// let percentageLimits = [5, 6, 7]; + +// let errorThrown = false; +// try { +// await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti([], { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Exempt wallet multi cannot be empty wallet"); + +// // add exempt wallet multi +// let tx = await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { +// from: token_owner +// }); +// let logs = tx.logs.filter(log => log.event === 'ExemptWalletAdded'); +// assert.equal(logs.length, wallets.length, "Batch Exempt wallets not added"); +// for (let i = 0; i < logs.length; i++) { +// assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); +// } + +// errorThrown = false; +// try { +// await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti([], { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Exempt wallet multi cannot be empty wallet"); + +// // remove exempt wallet multi +// tx = await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { +// from: token_owner +// }) +// logs = tx.logs.filter(log => log.event === 'ExemptWalletRemoved'); +// assert.equal(logs.length, wallets.length, "Batch Exempt wallets not removed"); + +// for (let i = 0; i < logs.length; i++) { +// assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); +// } + +// errorThrown = false; +// try { +// tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([], tokenLimits, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "wallets cannot be empty"); + +// errorThrown = false; +// try { +// tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([accounts[0]], tokenLimits, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "wallet array length dont match"); + +// tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { +// from: token_owner +// }); +// logs = tx.logs.filter(log => log.event == 'TransferLimitInTokensSet'); +// assert.equal(wallets.length, logs.length, "Transfer limit not set"); +// for (let i = 0; i < wallets.length; i++) { +// assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not set for wallet"); +// assert.equal(logs[i].args._amount.toNumber(), tokenLimits[i]); +// } +// errorThrown = false +// try { +// await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti([], { +// from: token_owner +// }); +// } catch (e) { +// ensureException(e); +// errorThrown = true; +// } +// assert.ok(errorThrown, "Wallets cannot be empty"); +// tx = await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, { +// from: token_owner +// }); +// logs = tx.logs.filter(log => log.event === 'TransferLimitInTokensRemoved'); +// assert.equal(logs.length, wallets.length, "Transfer limit not removed"); +// for (let i = 0; i < wallets.length; i++) { +// assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not removed for wallet"); +// } + +// errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti([], percentageLimits, { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "wallets cannot be empty"); + +// errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, [], { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "wallets and amounts dont match be empty"); +// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { +// from: token_owner +// }); +// logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageSet'); +// assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); + +// for (let i = 0; i < wallets.length; i++) { +// assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); +// assert.equal(logs[i].args._percentage.toNumber(), percentageLimits[i]); +// } + +// errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti([], { +// from: token_owner +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Wallets cannot be empty"); + +// tx = await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { +// from: token_owner +// }); +// logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageRemoved'); +// assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); + +// for (let i = 0; i < wallets.length; i++) { +// assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); +// } + +// errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentage(wallets[0], { +// from: token_owner +// }); +// } catch (e) { +// ensureException(e) +// errorThrown = true; +// } +// assert.ok(errorThrown, "Wallet should not be removed"); +// }) + +// it('should be able to transfer tokens SingleTradeVolumeRestriction', async () => { +// await I_SingleTradeVolumeRestrictionManager.unpause({ +// from: token_owner +// }) +// await I_SingleTradeVolumeRestrictionPercentageManager.pause({ +// from: token_owner +// }) +// await P_SingleTradeVolumeRestrictionManager.pause({ +// from: token_owner +// }); + +// await I_GeneralTransferManager.modifyWhitelist( +// account_investor3, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, { +// from: account_issuer +// } +// ); + +// await I_GeneralTransferManager.modifyWhitelist( +// account_investor4, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, { +// from: account_issuer +// } +// ); + +// await I_GeneralTransferManager.modifyWhitelist( +// account_investor5, +// latestTime(), +// latestTime(), +// latestTime() + duration.days(10), +// true, { +// from: account_issuer +// } +// ); + + +// //setting a max of 5 tokens +// await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(web3.utils.toWei('5', 'ether'), { +// from: token_owner +// }) + +// let errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('6', 'ether'), { +// from: account_investor1 +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Transfer should have not happened"); +// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('4', 'ether'), { +// from: account_investor1 +// }); +// assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('4', 'ether')); + +// // exempt wallet +// await I_SingleTradeVolumeRestrictionManager.addExemptWallet(account_investor1, { +// from: token_owner +// }); +// await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('7', 'ether'), { +// from: account_investor1 +// }); +// assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toNumber(), web3.utils.toWei('7', 'ether')); + +// //special limits wallet +// await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(account_investor5, web3.utils.toWei('5', 'ether'), { +// from: token_owner +// }); +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('7', 'ether'), { +// from: account_investor5 +// }); +// } catch (e) { +// errorThrown = true; +// ensureException(e); +// } +// assert.ok(errorThrown, "Transfer should have not happened"); +// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('4', 'ether'), { +// from: account_investor5 +// }) +// assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei('4', 'ether')) +// }) + +// it('should be able to transfer tokens (percentage transfer limit)', async () => { +// await I_SingleTradeVolumeRestrictionManager.pause({ +// from: token_owner +// }); +// let balance = (await I_SecurityToken.balanceOf(account_investor2)).toNumber(); +// await I_SecurityToken.transfer(account_investor1, balance, { +// from: account_investor2 +// }); + + +// balance = (await I_SecurityToken.balanceOf(account_investor3)).toNumber(); + +// await I_SecurityToken.transfer(account_investor1, balance, { +// from: account_investor3 +// }); + + +// balance = (await I_SecurityToken.balanceOf(account_investor4)).toNumber(); +// await I_SecurityToken.transfer(account_investor1, balance, { +// from: account_investor4 +// }); + +// balance = (await I_SecurityToken.balanceOf(account_investor5)).toNumber(); +// await I_SecurityToken.transfer(account_investor1, balance, { +// from: account_investor5 +// }); + +// await I_SingleTradeVolumeRestrictionPercentageManager.unpause({ +// from: token_owner +// }); +// // // +// await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(49 * 10 ** 16, { +// from: token_owner +// }); + +// let errorThrown = false; +// try { +// // more than the limit +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('90', 'ether'), { +// from: account_investor1 +// }); +// } catch (e) { +// ensureException(e); +// errorThrown = true; +// } +// assert.ok(errorThrown, "Transfer above limit happened"); + + +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('20', 'ether'), { +// from: account_investor1 +// }); +// assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei('20', 'ether')) + +// await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(account_investor1, 5 * 10 ** 16, { +// from: token_owner +// }); +// errorThrown = false; +// try { +// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('35', 'ether'), { +// from: account_investor1 +// }); +// } catch (e) { +// ensureException(e); +// errorThrown = true; +// } +// assert.ok(errorThrown, "transfer happened above limit"); + +// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { +// from: account_investor1 +// }); +// assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('1', 'ether')); +// }); + +// it('should change transfer limits to tokens', async () => { +// let errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { +// from: token_owner +// }); +// } catch (e) { + +// ensureException(e); +// errorThrown = true; +// } +// assert.equal(errorThrown, true, "Should not change to percentage again"); + + +// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { +// from: token_owner +// }); +// assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); +// assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); +// }) + +// it('should change transfer limits to percentage', async () => { +// let errorThrown = false; +// try { +// await I_SingleTradeVolumeRestrictionManager.changeTransferLimitToTokens(1, { +// from: token_owner +// }); +// } catch (e) { +// ensureException(e); +// errorThrown = true; +// } +// assert.equal(errorThrown, true, "Should not change to tokens again"); + +// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { +// from: token_owner +// }); +// assert.ok(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), "Error Changing"); +// assert.equal(tx.logs[0].args._percentage.toNumber(), 1, "Transfer limit not changed"); +// }) + + + +// }); + +// describe("SingleTradeVolumeRestrictionManager Factory test cases", async () => { + +// it("Should get the exact details of the factory", async () => { +// assert.equal(await I_SingleTradeVolumeRestrictionManagerFactory.setupCost.call(), 0); +// assert.equal((await I_SingleTradeVolumeRestrictionManagerFactory.getTypes.call())[0], 2); +// let name = web3.utils.toUtf8(await I_SingleTradeVolumeRestrictionManagerFactory.getName.call()); +// assert.equal(name, "SingleTradeVolumeRestriction", "Wrong Module added"); +// let desc = await I_SingleTradeVolumeRestrictionManagerFactory.getDescription.call(); +// assert.equal(desc, "Imposes volume restriction on a single trade", "Wrong Module added"); +// let title = await I_SingleTradeVolumeRestrictionManagerFactory.getTitle.call(); +// assert.equal(title, "Single Trade Volume Restriction Manager", "Wrong Module added"); +// let inst = await I_SingleTradeVolumeRestrictionManagerFactory.getInstructions.call(); +// assert.equal(inst, "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens", "Wrong Module added"); +// let version = await I_SingleTradeVolumeRestrictionManagerFactory.getVersion.call(); +// assert.equal(version, "1.0.0", "Version not correct"); +// }); + +// it("Should get the tags of the factory", async () => { +// let tags = await I_SingleTradeVolumeRestrictionManagerFactory.getTags.call(); +// assert.equal(web3.utils.toUtf8(tags[0]), "Single Trade"); +// assert.equal(web3.utils.toUtf8(tags[1]), "Transfer"); +// assert.equal(web3.utils.toUtf8(tags[2]), "Volume"); +// }); + + +// }); +// }); diff --git a/test/w_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js similarity index 98% rename from test/w_blacklist_transfer_manager.js rename to test/y_blacklist_transfer_manager.js index 375fbeb9f..adbce48e3 100644 --- a/test/w_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -164,7 +164,7 @@ contract('BlacklistTransferManager', accounts => { assert.notEqual( P_BlacklistTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", - "CountTransferManagerFactory contract was not deployed" + "BlacklistTransferManagerFactory contract was not deployed" ); // Step 9: Deploy the STFactory contract @@ -259,7 +259,7 @@ contract('BlacklistTransferManager', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -268,7 +268,7 @@ contract('BlacklistTransferManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -290,7 +290,7 @@ contract('BlacklistTransferManager', accounts => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); const tx = await I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type.toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); + assert.equal(tx.logs[3].args._type[0].toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), @@ -303,7 +303,7 @@ contract('BlacklistTransferManager', accounts => { it("Should successfully attach the BlacklistTransferManager with the security token", async () => { const tx = await I_SecurityToken.addModule(I_BlacklistTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); + assert.equal(tx.logs[2].args._type[0].toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), From 8fe926d0df17f5eec3171b8d44ccbe01630ab7c5 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Sun, 7 Oct 2018 14:38:40 +0530 Subject: [PATCH 012/582] minor changes in test cases --- .../BlacklistTransferManager.sol | 57 +- .../BlacklistTransferManagerFactory.sol | 6 +- test/a_poly_oracle.js | 698 +- test/b_capped_sto.js | 2698 +++---- test/c_checkpoints.js | 858 +- test/d_count_transfer_manager.js | 1010 +-- test/e_erc20_dividends.js | 1926 ++--- test/f_ether_dividends.js | 1966 ++--- test/g_general_permission_manager.js | 944 +-- test/h_general_transfer_manager.js | 1724 ++-- test/i_Issuance.js | 832 +- test/j_manual_approval_transfer_manager.js | 1420 ++-- test/k_module_registry.js | 1368 ++-- test/l_percentage_transfer_manager.js | 1010 +-- test/m_presale_sto.js | 954 +-- test/n_security_token_registry.js | 2486 +++--- test/o_security_token.js | 2810 +++---- test/p_usd_tiered_sto.js | 7034 ++++++++--------- test/q_usd_tiered_sto_sim.js | 1550 ++-- test/r_concurrent_STO.js | 726 +- test/s_v130_to_v140_upgrade.js | 1064 +-- test/t_security_token_registry_proxy.js | 696 +- test/u_module_registry_proxy.js | 678 +- test/v_tracked_redemptions.js | 758 +- test/w_volume_restriction_transfer_manager.js | 2082 ++--- test/x_single_trade_volume_restriction.js | 2356 +++--- test/y_blacklist_transfer_manager.js | 378 +- 27 files changed, 20052 insertions(+), 20037 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index e72127d0a..140a79131 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -27,10 +27,10 @@ contract BlacklistTransferManager is ITransferManager { mapping(bytes32 => address[]) blacklistToInvestor; //store the index of the investor to blacklist - mapping(address => mapping(bytes32 => uint256)) investorBlacklist; + mapping(address => mapping(bytes32 => uint256)) investorToIndex; //store the index of the blacklist to investor - mapping(bytes32 => mapping(address => uint256)) blacklistInvestor; + mapping(bytes32 => mapping(address => uint256)) blacklistToIndex; // Emit when new blacklist type is added event AddBlacklistType( @@ -65,6 +65,17 @@ contract BlacklistTransferManager is ITransferManager { bytes32 _blacklist ); + // Emit when investor is deleted from the blacklist type + event LogTransfer( + uint256 _endTime, + uint256 _startTime, + uint256 _repeat, + uint256 _blacklist, + uint256 _repeatar, + uint256 _now + + ); + /** * @notice Constructor * @param _securityToken Address of the security token @@ -84,7 +95,8 @@ contract BlacklistTransferManager is ITransferManager { } - /** @notice Used to verify the transfer transaction + /** + * @notice Used to verify the transfer transaction * @param _from Address of the sender * @dev Restrict the blacklist address to transfer token * if the current time is in the time frame define for the @@ -95,19 +107,21 @@ contract BlacklistTransferManager is ITransferManager { if(investorToBlacklist[_from].length != 0){ for(uint256 i = 0; i < investorToBlacklist[_from].length; i++){ if(investorToBlacklist[_from][i] != bytes32(0)){ - uint256 endTime = blacklists[investorToBlacklist[_from][i]].endTime; - uint256 startTime = blacklists[investorToBlacklist[_from][i]].startTime; - uint256 repeatPeriodTime = blacklists[investorToBlacklist[_from][i]].repeatPeriodTime * 1 days; + uint256 endTimeTemp = blacklists[investorToBlacklist[_from][i]].endTime; + uint256 startTimeTemp = blacklists[investorToBlacklist[_from][i]].startTime; + uint256 repeatPeriodTimeTemp = blacklists[investorToBlacklist[_from][i]].repeatPeriodTime * 1 days; // blacklistTime time is used to find the new startTime and endTime // suppose startTime=500,endTime=1500,repeatPeriodTime=500 then blacklistTime =1500 // if you add blacklistTime to startTime and endTime i.e startTime = 2000 and endTime = 3000 - uint256 blacklistTime = (endTime.sub(startTime)).add(repeatPeriodTime); + uint256 blacklistTime = (endTimeTemp.sub(startTimeTemp)).add(repeatPeriodTimeTemp); // Find the repeating parameter that will be used to calculate the new startTime and endTime - // based on the new now value - uint256 repeater = now.div(endTime.add(repeatPeriodTime)); - if (startTime.add(blacklistTime.mul(repeater)) <= now && endTime.add(blacklistTime.mul(repeater)) >= now) { + // based on the new current time value + uint256 repeater = now.div(endTimeTemp.add(repeatPeriodTimeTemp)); + if (startTimeTemp.add(blacklistTime.mul(repeater)) <= now && endTimeTemp.add(blacklistTime.mul(repeater)) >= now) { + emit LogTransfer(endTimeTemp,startTimeTemp,repeatPeriodTimeTemp,blacklistTime,repeater,now); return Result.INVALID; } + emit LogTransfer(endTimeTemp,startTimeTemp,repeatPeriodTimeTemp,blacklistTime,repeater,now); return Result.NA; } return Result.NA; @@ -163,6 +177,7 @@ contract BlacklistTransferManager is ITransferManager { function deleteBlacklistType(bytes32 _name) public withPerm(ADMIN){ require(blacklists[_name].endTime != 0, "Blacklist type doesn’t exist"); require(blacklistToInvestor[_name].length == 0, "Investors are associated with the blacklist"); + // delete blacklist type delete(blacklists[_name]); emit DeleteBlacklistType(_name); } @@ -176,15 +191,17 @@ contract BlacklistTransferManager is ITransferManager { require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); uint256 investorIndex = investorToBlacklist[_investor].length; - investorBlacklist[_investor][_blacklistName] = investorIndex; + // Add blacklist index to the investor + investorToIndex[_investor][_blacklistName] = investorIndex; uint256 blacklistIndex = blacklistToInvestor[_blacklistName].length; - blacklistInvestor[_blacklistName][_investor] = blacklistIndex; + // Add investor index to the blacklist + blacklistToIndex[_blacklistName][_investor] = blacklistIndex; investorToBlacklist[_investor].push(_blacklistName); blacklistToInvestor[_blacklistName].push(_investor); emit AddInvestorToBlacklist(_investor, _blacklistName); } - /** + /** * @notice Used to delete the investor from the all associated blacklists * @param _investor address of the investor */ @@ -196,7 +213,7 @@ contract BlacklistTransferManager is ITransferManager { } } - /** + /** * @notice Used to delete the investor from the blacklist * @param _investor address of the investor * @param _blacklistName name of the blacklist @@ -204,12 +221,12 @@ contract BlacklistTransferManager is ITransferManager { function deleteInvestorFromBlacklist(address _investor,bytes32 _blacklistName) public withPerm(ADMIN){ require(_investor != address(0), "Invalid investor address"); require(_blacklistName != bytes32(0),"Invalid blacklist name"); - require(investorToBlacklist[_investor][investorBlacklist[_investor][_blacklistName]] != bytes32(0), "Investor is not associated to blacklist type"); - delete(blacklistToInvestor[_blacklistName][blacklistInvestor[_blacklistName][_investor]]); - delete(blacklistInvestor[_blacklistName][_investor]); - delete(investorToBlacklist[_investor][investorBlacklist[_investor][_blacklistName]]); - delete(investorBlacklist[_investor][_blacklistName]); - emit DeleteInvestorFromBlacklist(_investor, investorToBlacklist[_investor][investorBlacklist[_investor][_blacklistName]]); + require(investorToBlacklist[_investor][investorToIndex[_investor][_blacklistName]] != bytes32(0), "Investor is not associated to blacklist type"); + delete(blacklistToInvestor[_blacklistName][blacklistToIndex[_blacklistName][_investor]]); + delete(blacklistToIndex[_blacklistName][_investor]); + delete(investorToBlacklist[_investor][investorToIndex[_investor][_blacklistName]]); + delete(investorToIndex[_investor][_blacklistName]); + emit DeleteInvestorFromBlacklist(_investor, investorToBlacklist[_investor][investorToIndex[_investor][_blacklistName]]); } /** diff --git a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol index 6a8f463a2..61bea2531 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol @@ -31,12 +31,10 @@ contract BlacklistTransferManagerFactory is ModuleFactory { * @notice used to launch the Module with the help of factory * @return address Contract address of the Module */ - function deploy(bytes _data) external returns(address) { + function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - BlacklistTransferManager blacklistTransferManager = new BlacklistTransferManager(msg.sender, address(polyToken)); - require(Util.getSig(_data) == blacklistTransferManager.getInitFunction(), "Provided data is not valid"); - require(address(blacklistTransferManager).call(_data), "Un-successfull call"); + address blacklistTransferManager = new BlacklistTransferManager(msg.sender, address(polyToken)); emit GenerateModuleFromFactory(address(blacklistTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(blacklistTransferManager); } diff --git a/test/a_poly_oracle.js b/test/a_poly_oracle.js index 3f84b814d..f727b4014 100644 --- a/test/a_poly_oracle.js +++ b/test/a_poly_oracle.js @@ -1,349 +1,349 @@ -// const PolyOracle = artifacts.require('./MockPolyOracle.sol'); -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import {increaseTime} from './helpers/time'; - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('PolyOracle', accounts=> { - -// let I_PolyOracle; -// let owner; -// const URL = '[URL] json(https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?id=2496&convert=USD&CMC_PRO_API_KEY=${[decrypt] BBObnGOy63qVI3OR2+MX88dzSMVjQboiZc7Wluuh2ngkSgiX1csxWgbAFtu22jbrry42zwCS4IUmer1Wk+1o1XhF7hyspoGCkbufQqYwuUYwcA2slX6RbEDai7NgdkgNGWSwd6DcuN8jD5ZMTkX68rJKkplr}).data."2496".quote.USD.price'; -// const alternateURL = "json(https://min-api.cryptocompare.com/data/price?fsym=POLY&tsyms=USD).USD"; -// const SanityBounds = 20*10**16; -// const GasLimit = 100000; -// const TimeTolerance = 5*60; -// const message = "Txn should fail"; -// let latestPrice; -// let requestIds = new Array(); - -// before(async()=> { -// owner = accounts[0]; -// I_PolyOracle = await PolyOracle.new({from : owner}); -// }); - - -// describe("state variables checks", async() => { - -// it("should set and check the api url", async() => { -// await I_PolyOracle.setOracleURL(URL, {from: owner}); -// let url = await I_PolyOracle.oracleURL.call(); -// assert.equal(URL, url); -// }); - -// it("should check the sanity bounds", async() => { -// let sanityBounds = await I_PolyOracle.sanityBounds.call(); -// assert.equal(SanityBounds, sanityBounds); -// }); - -// it("should check the gas limits", async() => { -// let gasLimit = await I_PolyOracle.gasLimit.call(); -// assert.equal(GasLimit, gasLimit); -// }); - -// it("should check the oraclize time tolerance", async() => { -// let timeTolerance = await I_PolyOracle.oraclizeTimeTolerance.call(); -// assert.equal(TimeTolerance, timeTolerance); -// }); - -// }) - -// describe("Scheduling test cases", async() => { - -// it("Should schedule the timing of the call - fails - non owner", async() => { -// let errorThrown = false; -// let timeScheduling = [latestTime()+duration.minutes(1), latestTime()+duration.minutes(2), latestTime()+duration.minutes(3)] -// try { -// await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: accounts[1], value: web3.utils.toWei("2")}); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// console.log(` tx -> revert msg.sender should be the owner of the contract`.grey); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should schedule the timing of the call - fails - no value", async() => { -// let errorThrown = false; -// let timeScheduling = [latestTime()+duration.minutes(1), latestTime()+duration.minutes(2), latestTime()+duration.minutes(3)] -// try { -// await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner}); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// console.log(` tx -> revert Because value for txn is not provided`.grey); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should schedule the timing of the call - single call", async() => { -// let blockNo = latestBlock(); -// let tx = await I_PolyOracle.schedulePriceUpdatesFixed([],{from: owner, value:web3.utils.toWei("1")}); -// assert.isAtMost(tx.logs[0].args._time.toNumber(), latestTime()); -// // await increaseTime(50); -// const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 1); -// // const log = await logNewPriceWatcher; -// assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') -// assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') -// assert.equal(logNewPriceWatcher.args._oldPrice.toNumber(), 0); -// console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY') - -// }); - -// it("Should schedule the timing of the call - multiple calls", async() => { -// let blockNo = latestBlock(); -// let timeScheduling = [latestTime()+duration.seconds(10), latestTime()+duration.seconds(20)] -// let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner, value:web3.utils.toWei("1.5")}); - -// let event_data = tx.logs; - -// for (var i = 0; i < event_data.length; i++) { -// let time = event_data[i].args._time; -// console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); -// assert.isAtMost(time.toNumber(), timeScheduling[i]); -// } - -// // Wait for the callback to be invoked by oraclize and the event to be emitted -// const logNewPriceWatcher = promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); -// const log = await logNewPriceWatcher; -// assert.equal(log.event, 'PriceUpdated', 'PriceUpdated not emitted.') -// assert.isNotNull(log.args._price, 'Price returned was null.'); -// console.log('Success! Current price is: ' + log.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY') -// }); - -// it("Should schedule to call using iters - fails", async() => { -// let errorThrown = false; -// try { -// await I_PolyOracle.schedulePriceUpdatesRolling(latestTime() + 10, 30, 2, {from: accounts[6]}); -// } catch(error) { -// errorThrown = true; -// console.log(` tx->revert msg.sender is not the owner`.grey); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should schedule to call using iters", async() => { -// let blockNo = latestBlock(); -// console.log(`Latest Block number of the local chain:${blockNo}`); -// let tx = await I_PolyOracle.schedulePriceUpdatesRolling(latestTime()+10, 10, 2, {from: owner}); -// let event_data = tx.logs; -// for (var i = 0; i < event_data.length; i++) { -// let time = event_data[i].args._time; -// requestIds.push(event_data[i].args._queryId); -// console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); -// assert.isAtMost(time.toNumber(), latestTime() + ((i + 1) * 30)); -// } -// // Wait for the callback to be invoked by oraclize and the event to be emitted -// const logNewPriceWatcher = promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); -// const log = await logNewPriceWatcher; -// assert.equal(log.event, 'PriceUpdated', 'PriceUpdated not emitted.') -// assert.isNotNull(log.args._price, 'Price returned was null.') -// console.log('Success! Current price is: ' + log.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); -// latestPrice = log.args._price; -// }); -// }) - -// describe("Ownable functions", async() => { - -// it("Should change the Poly USD price manually - fail - bad account", async() => { -// let errorThrown = false; -// try { -// await I_PolyOracle.setPOLYUSD(latestPrice.add(1), {from: accounts[5]}); -// } catch(error) { -// errorThrown = true; -// console.log(` tx->revert msg.sender is not the owner`.grey); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should change the Poly USD price manually", async() => { -// await I_PolyOracle.setPOLYUSD(latestPrice.add(1), {from: owner}); -// let price2 = await I_PolyOracle.getPriceAndTime.call(); -// assert.equal(price2[0].toNumber(), latestPrice.add(1).toNumber()); -// }) - -// it("Should freeze the Oracle manually", async() => { -// let errorThrown = false; -// try { -// await I_PolyOracle.setFreezeOracle(true, {from: accounts[5]}); -// } catch(error) { -// errorThrown = true; -// console.log(` tx->revert msg.sender is not the owner`.grey); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should change the URL manually", async() => { -// let freeze_ = await I_PolyOracle.freezeOracle.call(); -// await I_PolyOracle.setFreezeOracle(true, {from: owner}); -// let freeze = await I_PolyOracle.freezeOracle.call(); -// assert.isFalse(freeze_); -// assert.isTrue(freeze); -// await I_PolyOracle.setFreezeOracle(false, {from: owner}); -// }) - -// it("Should change the sanity bounds manually - fails - bad owner", async() => { -// let errorThrown = false; -// try { -// await I_PolyOracle.setSanityBounds(new BigNumber(25).times(new BigNumber(10).pow(16)), {from : accounts[6]}); -// } catch(error) { -// errorThrown = true; -// console.log(` tx->revert msg.sender is not the owner`.grey); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should change the sanity bounds manually", async() => { -// console.log(JSON.stringify(await I_PolyOracle.sanityBounds.call())); -// await I_PolyOracle.setSanityBounds(new BigNumber(25).times(new BigNumber(10).pow(16)), {from : owner}); -// let sanityBounds = await I_PolyOracle.sanityBounds.call(); -// console.log(JSON.stringify(await I_PolyOracle.sanityBounds.call())); -// assert.equal(sanityBounds.toNumber(), new BigNumber(25).times(new BigNumber(10).pow(16)).toNumber()) -// }); - -// it("Should change the gas price manually - fails - bad owner", async() => { -// let errorThrown = false; -// try{ -// await I_PolyOracle.setGasPrice(new BigNumber(60).times(new BigNumber(10).pow(9)),{from : accounts[6]}); -// } catch(error){ -// errorThrown = true; -// console.log(` tx->revert msg.sender is not the owner`.grey); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should change the gas price manually", async() => { -// await I_PolyOracle.setGasPrice(new BigNumber(60).times(new BigNumber(10).pow(9)),{from : owner}); -// let blockNo = latestBlock(); -// let timeScheduling = [latestTime()+duration.seconds(10), latestTime()+duration.seconds(20)]; -// let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner, value:web3.utils.toWei("2")}); - -// let event_data = tx.logs; - -// for (var i = 0; i < event_data.length; i++) { -// let time = event_data[i].args._time; -// console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); -// assert.isAtMost(time.toNumber(), timeScheduling[i]); -// } - -// const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); - -// assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') -// assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') -// console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); -// // assert.isTrue(false); - -// }); - -// it("Should change the gas limit manually - fails", async() => { -// let errorThrown = false; -// try{ -// await I_PolyOracle.setGasLimit(50000,{from : accounts[6]}); -// } catch(error){ -// errorThrown = true; -// console.log(` tx->revert msg.sender is not owner`.grey); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should change the gas limit manually", async() => { -// await I_PolyOracle.setGasLimit(50000,{from : owner}); -// let gasLimit = await I_PolyOracle.gasLimit.call(); -// assert.equal(gasLimit.toNumber(),50000); -// await I_PolyOracle.setGasLimit(100000,{from : owner}); -// }); - -// it("Should blacklist some IDS manually - fails - wrong size", async() => { -// let errorThrown = false; -// let ignore = [true]; -// try{ -// await I_PolyOracle.setIgnoreRequestIds(requestIds,ignore,{from : accounts[6]}); -// } catch(error){ -// errorThrown = true; -// console.log(` tx->revert msg.sender is not owner`.grey); -// } -// }); - -// it("Should blacklist some IDS manually", async() => { -// let ignore = [false, true]; -// console.log(requestIds); -// await I_PolyOracle.setIgnoreRequestIds(requestIds, ignore, {from : owner}); - -// // let ignoreRequestId0 = await I_PolyOracle.ignoreRequestIds.call(requestIds[1]); -// // assert.equal(ignoreRequestId0,true); - -// // let ignoreRequestId1 = await I_PolyOracle.ignoreRequestIds.call(requestIds[2]); -// // assert.equal(ignoreRequestId1,false); - -// }); - -// it("Should change the oraclize time tolerance manually - fails", async() => { -// let errorThrown = false; -// try{ -// await I_PolyOracle.setOraclizeTimeTolerance(3600,{from : accounts[6]}); -// } catch(error){ -// errorThrown = true; -// console.log(` tx->revert msg.sender is not the owner`.grey); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should change the oraclize time tolerance manually", async() => { -// await I_PolyOracle.setOraclizeTimeTolerance(3600,{from : owner}); -// let oraclizeTimeTolerance = await I_PolyOracle.oraclizeTimeTolerance.call(); -// assert.equal(oraclizeTimeTolerance.toNumber(),3600); -// }); - -// it("should change the api URL manually", async() => { -// let errorThrown = false; -// try { -// await I_PolyOracle.setOracleURL(alternateURL, {from: accounts[6]}); -// } catch(error){ -// errorThrown = true; -// console.log(` tx->revert msg.sender is not the owner`.grey); -// } -// assert.ok(errorThrown, message); -// }) - -// it("should change the api URL manually", async() => { -// await I_PolyOracle.setOracleURL(alternateURL, {from: owner}); -// await I_PolyOracle.setOracleQueryType("URL", {from: owner}); -// let url = await I_PolyOracle.oracleURL.call(); -// assert.equal(alternateURL, url); -// }); - -// it("Should schedule the timing of the call - after changes", async() => { -// let blockNo = latestBlock(); -// let tx = await I_PolyOracle.schedulePriceUpdatesFixed([],{from: owner, value:web3.utils.toWei("1")}); -// assert.isAtMost(tx.logs[0].args._time.toNumber(), latestTime()); -// const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 1); -// assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') -// assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') -// console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); -// // assert.isTrue(false); -// }); - -// }) - -// describe("Get Functions call", async() => { -// it("Should get the currency address", async() => { -// let polyTokenAddress = await I_PolyOracle.getCurrencyAddress.call(); -// assert.equal(polyTokenAddress, ("0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC").toLowerCase()); -// }); - -// it("Should get the currency symbol", async() => { -// let currency = await I_PolyOracle.getCurrencySymbol.call(); -// assert.equal(web3.utils.toAscii(currency).replace(/\u0000/g, ''), "POLY"); -// }); - -// it("Should get the currency denomination", async() => { -// let denomination = await I_PolyOracle.getCurrencyDenominated.call(); -// assert.equal(web3.utils.toAscii(denomination).replace(/\u0000/g, ''), "USD"); -// }) - -// }) - -// }) +const PolyOracle = artifacts.require('./MockPolyOracle.sol'); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import {increaseTime} from './helpers/time'; + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('PolyOracle', accounts=> { + +let I_PolyOracle; +let owner; +const URL = '[URL] json(https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?id=2496&convert=USD&CMC_PRO_API_KEY=${[decrypt] BBObnGOy63qVI3OR2+MX88dzSMVjQboiZc7Wluuh2ngkSgiX1csxWgbAFtu22jbrry42zwCS4IUmer1Wk+1o1XhF7hyspoGCkbufQqYwuUYwcA2slX6RbEDai7NgdkgNGWSwd6DcuN8jD5ZMTkX68rJKkplr}).data."2496".quote.USD.price'; +const alternateURL = "json(https://min-api.cryptocompare.com/data/price?fsym=POLY&tsyms=USD).USD"; +const SanityBounds = 20*10**16; +const GasLimit = 100000; +const TimeTolerance = 5*60; +const message = "Txn should fail"; +let latestPrice; +let requestIds = new Array(); + + before(async()=> { + owner = accounts[0]; + I_PolyOracle = await PolyOracle.new({from : owner}); + }); + + + describe("state variables checks", async() => { + + it("should set and check the api url", async() => { + await I_PolyOracle.setOracleURL(URL, {from: owner}); + let url = await I_PolyOracle.oracleURL.call(); + assert.equal(URL, url); + }); + + it("should check the sanity bounds", async() => { + let sanityBounds = await I_PolyOracle.sanityBounds.call(); + assert.equal(SanityBounds, sanityBounds); + }); + + it("should check the gas limits", async() => { + let gasLimit = await I_PolyOracle.gasLimit.call(); + assert.equal(GasLimit, gasLimit); + }); + + it("should check the oraclize time tolerance", async() => { + let timeTolerance = await I_PolyOracle.oraclizeTimeTolerance.call(); + assert.equal(TimeTolerance, timeTolerance); + }); + + }) + + describe("Scheduling test cases", async() => { + + it("Should schedule the timing of the call - fails - non owner", async() => { + let errorThrown = false; + let timeScheduling = [latestTime()+duration.minutes(1), latestTime()+duration.minutes(2), latestTime()+duration.minutes(3)] + try { + await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: accounts[1], value: web3.utils.toWei("2")}); + } catch(error) { + errorThrown = true; + ensureException(error); + console.log(` tx -> revert msg.sender should be the owner of the contract`.grey); + } + assert.ok(errorThrown, message); + }); + + it("Should schedule the timing of the call - fails - no value", async() => { + let errorThrown = false; + let timeScheduling = [latestTime()+duration.minutes(1), latestTime()+duration.minutes(2), latestTime()+duration.minutes(3)] + try { + await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner}); + } catch(error) { + errorThrown = true; + ensureException(error); + console.log(` tx -> revert Because value for txn is not provided`.grey); + } + assert.ok(errorThrown, message); + }) + + it("Should schedule the timing of the call - single call", async() => { + let blockNo = latestBlock(); + let tx = await I_PolyOracle.schedulePriceUpdatesFixed([],{from: owner, value:web3.utils.toWei("1")}); + assert.isAtMost(tx.logs[0].args._time.toNumber(), latestTime()); + // await increaseTime(50); + const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 1); + // const log = await logNewPriceWatcher; + assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') + assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') + assert.equal(logNewPriceWatcher.args._oldPrice.toNumber(), 0); + console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY') + + }); + + it("Should schedule the timing of the call - multiple calls", async() => { + let blockNo = latestBlock(); + let timeScheduling = [latestTime()+duration.seconds(10), latestTime()+duration.seconds(20)] + let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner, value:web3.utils.toWei("1.5")}); + + let event_data = tx.logs; + + for (var i = 0; i < event_data.length; i++) { + let time = event_data[i].args._time; + console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); + assert.isAtMost(time.toNumber(), timeScheduling[i]); + } + + // Wait for the callback to be invoked by oraclize and the event to be emitted + const logNewPriceWatcher = promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); + const log = await logNewPriceWatcher; + assert.equal(log.event, 'PriceUpdated', 'PriceUpdated not emitted.') + assert.isNotNull(log.args._price, 'Price returned was null.'); + console.log('Success! Current price is: ' + log.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY') + }); + + it("Should schedule to call using iters - fails", async() => { + let errorThrown = false; + try { + await I_PolyOracle.schedulePriceUpdatesRolling(latestTime() + 10, 30, 2, {from: accounts[6]}); + } catch(error) { + errorThrown = true; + console.log(` tx->revert msg.sender is not the owner`.grey); + } + assert.ok(errorThrown, message); + }) + + it("Should schedule to call using iters", async() => { + let blockNo = latestBlock(); + console.log(`Latest Block number of the local chain:${blockNo}`); + let tx = await I_PolyOracle.schedulePriceUpdatesRolling(latestTime()+10, 10, 2, {from: owner}); + let event_data = tx.logs; + for (var i = 0; i < event_data.length; i++) { + let time = event_data[i].args._time; + requestIds.push(event_data[i].args._queryId); + console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); + assert.isAtMost(time.toNumber(), latestTime() + ((i + 1) * 30)); + } + // Wait for the callback to be invoked by oraclize and the event to be emitted + const logNewPriceWatcher = promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); + const log = await logNewPriceWatcher; + assert.equal(log.event, 'PriceUpdated', 'PriceUpdated not emitted.') + assert.isNotNull(log.args._price, 'Price returned was null.') + console.log('Success! Current price is: ' + log.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); + latestPrice = log.args._price; + }); + }) + + describe("Ownable functions", async() => { + + it("Should change the Poly USD price manually - fail - bad account", async() => { + let errorThrown = false; + try { + await I_PolyOracle.setPOLYUSD(latestPrice.add(1), {from: accounts[5]}); + } catch(error) { + errorThrown = true; + console.log(` tx->revert msg.sender is not the owner`.grey); + } + assert.ok(errorThrown, message); + }); + + it("Should change the Poly USD price manually", async() => { + await I_PolyOracle.setPOLYUSD(latestPrice.add(1), {from: owner}); + let price2 = await I_PolyOracle.getPriceAndTime.call(); + assert.equal(price2[0].toNumber(), latestPrice.add(1).toNumber()); + }) + + it("Should freeze the Oracle manually", async() => { + let errorThrown = false; + try { + await I_PolyOracle.setFreezeOracle(true, {from: accounts[5]}); + } catch(error) { + errorThrown = true; + console.log(` tx->revert msg.sender is not the owner`.grey); + } + assert.ok(errorThrown, message); + }) + + it("Should change the URL manually", async() => { + let freeze_ = await I_PolyOracle.freezeOracle.call(); + await I_PolyOracle.setFreezeOracle(true, {from: owner}); + let freeze = await I_PolyOracle.freezeOracle.call(); + assert.isFalse(freeze_); + assert.isTrue(freeze); + await I_PolyOracle.setFreezeOracle(false, {from: owner}); + }) + + it("Should change the sanity bounds manually - fails - bad owner", async() => { + let errorThrown = false; + try { + await I_PolyOracle.setSanityBounds(new BigNumber(25).times(new BigNumber(10).pow(16)), {from : accounts[6]}); + } catch(error) { + errorThrown = true; + console.log(` tx->revert msg.sender is not the owner`.grey); + } + assert.ok(errorThrown, message); + }) + + it("Should change the sanity bounds manually", async() => { + console.log(JSON.stringify(await I_PolyOracle.sanityBounds.call())); + await I_PolyOracle.setSanityBounds(new BigNumber(25).times(new BigNumber(10).pow(16)), {from : owner}); + let sanityBounds = await I_PolyOracle.sanityBounds.call(); + console.log(JSON.stringify(await I_PolyOracle.sanityBounds.call())); + assert.equal(sanityBounds.toNumber(), new BigNumber(25).times(new BigNumber(10).pow(16)).toNumber()) + }); + + it("Should change the gas price manually - fails - bad owner", async() => { + let errorThrown = false; + try{ + await I_PolyOracle.setGasPrice(new BigNumber(60).times(new BigNumber(10).pow(9)),{from : accounts[6]}); + } catch(error){ + errorThrown = true; + console.log(` tx->revert msg.sender is not the owner`.grey); + } + assert.ok(errorThrown, message); + }); + + it("Should change the gas price manually", async() => { + await I_PolyOracle.setGasPrice(new BigNumber(60).times(new BigNumber(10).pow(9)),{from : owner}); + let blockNo = latestBlock(); + let timeScheduling = [latestTime()+duration.seconds(10), latestTime()+duration.seconds(20)]; + let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, {from: owner, value:web3.utils.toWei("2")}); + + let event_data = tx.logs; + + for (var i = 0; i < event_data.length; i++) { + let time = event_data[i].args._time; + console.log(` checking the time for the ${i} index and the scheduling time is ${time}`); + assert.isAtMost(time.toNumber(), timeScheduling[i]); + } + + const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 2); + + assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') + assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') + console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); + // assert.isTrue(false); + + }); + + it("Should change the gas limit manually - fails", async() => { + let errorThrown = false; + try{ + await I_PolyOracle.setGasLimit(50000,{from : accounts[6]}); + } catch(error){ + errorThrown = true; + console.log(` tx->revert msg.sender is not owner`.grey); + } + assert.ok(errorThrown, message); + }); + + it("Should change the gas limit manually", async() => { + await I_PolyOracle.setGasLimit(50000,{from : owner}); + let gasLimit = await I_PolyOracle.gasLimit.call(); + assert.equal(gasLimit.toNumber(),50000); + await I_PolyOracle.setGasLimit(100000,{from : owner}); + }); + + it("Should blacklist some IDS manually - fails - wrong size", async() => { + let errorThrown = false; + let ignore = [true]; + try{ + await I_PolyOracle.setIgnoreRequestIds(requestIds,ignore,{from : accounts[6]}); + } catch(error){ + errorThrown = true; + console.log(` tx->revert msg.sender is not owner`.grey); + } + }); + + it("Should blacklist some IDS manually", async() => { + let ignore = [false, true]; + console.log(requestIds); + await I_PolyOracle.setIgnoreRequestIds(requestIds, ignore, {from : owner}); + + // let ignoreRequestId0 = await I_PolyOracle.ignoreRequestIds.call(requestIds[1]); + // assert.equal(ignoreRequestId0,true); + + // let ignoreRequestId1 = await I_PolyOracle.ignoreRequestIds.call(requestIds[2]); + // assert.equal(ignoreRequestId1,false); + + }); + + it("Should change the oraclize time tolerance manually - fails", async() => { + let errorThrown = false; + try{ + await I_PolyOracle.setOraclizeTimeTolerance(3600,{from : accounts[6]}); + } catch(error){ + errorThrown = true; + console.log(` tx->revert msg.sender is not the owner`.grey); + } + assert.ok(errorThrown, message); + }) + + it("Should change the oraclize time tolerance manually", async() => { + await I_PolyOracle.setOraclizeTimeTolerance(3600,{from : owner}); + let oraclizeTimeTolerance = await I_PolyOracle.oraclizeTimeTolerance.call(); + assert.equal(oraclizeTimeTolerance.toNumber(),3600); + }); + + it("should change the api URL manually", async() => { + let errorThrown = false; + try { + await I_PolyOracle.setOracleURL(alternateURL, {from: accounts[6]}); + } catch(error){ + errorThrown = true; + console.log(` tx->revert msg.sender is not the owner`.grey); + } + assert.ok(errorThrown, message); + }) + + it("should change the api URL manually", async() => { + await I_PolyOracle.setOracleURL(alternateURL, {from: owner}); + await I_PolyOracle.setOracleQueryType("URL", {from: owner}); + let url = await I_PolyOracle.oracleURL.call(); + assert.equal(alternateURL, url); + }); + + it("Should schedule the timing of the call - after changes", async() => { + let blockNo = latestBlock(); + let tx = await I_PolyOracle.schedulePriceUpdatesFixed([],{from: owner, value:web3.utils.toWei("1")}); + assert.isAtMost(tx.logs[0].args._time.toNumber(), latestTime()); + const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 1); + assert.equal(logNewPriceWatcher.event, 'PriceUpdated', 'PriceUpdated not emitted.') + assert.isNotNull(logNewPriceWatcher.args._price, 'Price returned was null.') + console.log('Success! Current price is: ' + logNewPriceWatcher.args._price.dividedBy(new BigNumber(10).pow(18)).toNumber() + ' USD/POLY'); + // assert.isTrue(false); + }); + + }) + + describe("Get Functions call", async() => { + it("Should get the currency address", async() => { + let polyTokenAddress = await I_PolyOracle.getCurrencyAddress.call(); + assert.equal(polyTokenAddress, ("0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC").toLowerCase()); + }); + + it("Should get the currency symbol", async() => { + let currency = await I_PolyOracle.getCurrencySymbol.call(); + assert.equal(web3.utils.toAscii(currency).replace(/\u0000/g, ''), "POLY"); + }); + + it("Should get the currency denomination", async() => { + let denomination = await I_PolyOracle.getCurrencyDenominated.call(); + assert.equal(web3.utils.toAscii(denomination).replace(/\u0000/g, ''), "USD"); + }) + + }) + +}) diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 6d1845626..c753d22db 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -1,1349 +1,1349 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -// const CappedSTO = artifacts.require('./CappedSTO.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port -// let ETH = 0; -// let POLY = 1; -// let DAI = 2; - -// contract('CappedSTO', accounts => { -// // Accounts Variable declaration -// let account_polymath; -// let account_investor1; -// let account_issuer; -// let token_owner; -// let account_investor2; -// let account_investor3; -// let account_fundsReceiver; - -// let balanceOfReceiver; -// let message = "Transaction Should Fail!"; -// // investor Details -// let fromTime; -// let toTime; -// let expiryTime; -// let P_fromTime; -// let P_toTime; -// let P_expiryTime; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_GeneralTransferManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_SecurityTokenRegistry; -// let I_ModuleRegistry; -// let I_ModuleRegistryProxy; -// let I_FeatureRegistry; -// let I_CappedSTOFactory; -// let I_STFactory; -// let I_SecurityToken_ETH; -// let I_SecurityToken_POLY; -// let I_CappedSTO_Array_ETH = []; -// let I_CappedSTO_Array_POLY = []; -// let I_PolyToken; -// let I_PolymathRegistry; -// let I_STRProxied; -// let I_MRProxied; -// let pauseTime; - -// // SecurityToken Details for funds raise Type ETH -// const name = "Team"; -// const symbol = "SAP"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; - -// // SecurityToken Details for funds raise Type POLY -// const P_name = "Team Poly"; -// const P_symbol = "PAS"; -// const P_tokenDetails = "This is equity type of issuance"; -// const P_decimals = 18; - -// // Module key -// const transferManagerKey = 2; -// const stoKey = 3; -// const budget = 0; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// // Capped STO details -// let startTime_ETH1; -// let endTime_ETH1; -// let startTime_ETH2; -// let endTime_ETH2; -// const cap = web3.utils.toWei("10000"); -// const rate = 1000; -// const E_fundRaiseType = 0; - -// let startTime_POLY1; -// let endTime_POLY1; -// let startTime_POLY2; -// let endTime_POLY2; -// let blockNo; -// const P_cap = web3.utils.toWei("50000"); -// const P_fundRaiseType = 1; -// const P_rate = 5; -// const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); -// const maxCost = cappedSTOSetupCost; -// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; -// account_investor1 = accounts[4]; -// account_investor2 = accounts[3]; -// account_investor3 = accounts[5] -// account_fundsReceiver = accounts[2]; -// token_owner = account_issuer; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 6: Deploy the CappedSTOFactory - -// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); - -// assert.notEqual( -// I_CappedSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CappedSTOFactory contract was not deployed" -// ); - -// // Step 8: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 9: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 7: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// console.log(await I_MRProxied.owner()); -// console.log(account_polymath); -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// ModuleRegistry: ${ModuleRegistry.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// CappedSTOFactory: ${I_CappedSTOFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - -// I_SecurityToken_ETH = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - -// const log = await promisifyLogWatch(I_SecurityToken_ETH.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), transferManagerKey); -// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken_ETH.getModulesByType(transferManagerKey))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); -// }); - -// it("Should mint the tokens before attaching the STO", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken_ETH.mint("0x0000000000000000000000000000000000000000", web3.utils.toWei("1"), {from: token_owner}); -// } catch (error) { -// console.log(` tx -> revert 0x address is not allowed as investor`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to launch the STO due to security token doesn't have the sufficient POLY", async () => { -// let startTime = latestTime() + duration.days(1); -// let endTime = startTime + duration.days(30); -// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); - -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); -// let errorThrown = false; -// try { -// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Rate is ${0}. Test Passed Successfully`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to launch the STO due to rate is 0", async () => { -// let startTime = latestTime() + duration.days(1); -// let endTime = startTime + duration.days(30); -// await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); - -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); -// let errorThrown = false; -// try { -// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); -// } catch(error) { -// console.log(`Tx Failed because of rate is ${0}. Test Passed Successfully`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to launch the STO due to startTime > endTime", async () => { -// let bytesSTO = encodeModuleCall(STOParameters, [ Math.floor(Date.now()/1000 + 100000), Math.floor(Date.now()/1000 + 1000), cap, rate, [E_fundRaiseType], account_fundsReceiver]); -// let errorThrown = false; -// try { -// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); -// } catch(error) { -// errorThrown = true; -// console.log(` tx revert -> StartTime is greater than endTime. Test Passed Successfully`.grey); -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to launch the STO due to cap is of 0 securityToken", async () => { -// let startTime = latestTime() + duration.days(1); -// let endTime = startTime + duration.days(30); -// let bytesSTO = encodeModuleCall(STOParameters, [ startTime, endTime, 0, rate, [E_fundRaiseType], account_fundsReceiver]); -// let errorThrown = false; -// try { -// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); -// } catch(error) { -// console.log(`Tx Failed because the Cap is equal to ${0}. Test Passed Successfully`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the STO module to the security token", async () => { -// startTime_ETH1 = latestTime() + duration.days(1); -// endTime_ETH1 = startTime_ETH1 + duration.days(30); -// let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH1, endTime_ETH1, cap, rate, [E_fundRaiseType], account_fundsReceiver]); -// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - -// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); -// I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); -// }); -// }); - -// describe("verify the data of STO", async () => { - -// it("Should verify the configuration of the STO", async() => { -// assert.equal( -// await I_CappedSTO_Array_ETH[0].startTime.call(), -// startTime_ETH1, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_ETH[0].endTime.call(), -// endTime_ETH1, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// (await I_CappedSTO_Array_ETH[0].cap.call()).toNumber(), -// cap, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_ETH[0].rate.call(), -// rate, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_ETH[0].fundRaiseTypes.call(E_fundRaiseType), -// true, -// "STO Configuration doesn't set as expected" -// ); -// }); -// }); - -// describe("Buy tokens", async() => { - -// it("Should buy the tokens -- failed due to startTime is greater than Current time", async () => { -// let errorThrown = false; -// try { -// await web3.eth.sendTransaction({ -// from: account_investor1, -// to: I_CappedSTO_Array_ETH[0].address, -// value: web3.utils.toWei('1', 'ether') -// }); -// } catch(error) { -// console.log(` tx revert -> startTime is greater than Current time`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should buy the tokens -- failed due to invested amount is zero", async () => { -// let errorThrown = false; -// try { -// await web3.eth.sendTransaction({ -// from: account_investor1, -// to: I_CappedSTO_Array_ETH[0].address, -// value: web3.utils.toWei('0', 'ether') -// }); -// } catch(error) { -// console.log(` tx revert -> Invested amount is zero`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { -// let errorThrown = false; -// try { -// await web3.eth.sendTransaction({ -// from: account_investor1, -// to: I_CappedSTO_Array_ETH[0].address, -// value: web3.utils.toWei('1', 'ether') -// }); -// } catch(error) { -// console.log(` tx revert -> Investor doesn't present in the whitelist`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should buy the tokens -- Failed due to wrong granularity", async () => { -// let errorThrown = false; -// try { -// await web3.eth.sendTransaction({ -// from: account_investor1, -// to: I_CappedSTO_Array_ETH[0].address, -// value: web3.utils.toWei('0.1111', 'ether') -// }); -// } catch(error) { -// console.log(` tx revert -> Wrong purchase granularity`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should Buy the tokens", async() => { -// blockNo = latestBlock(); -// fromTime = latestTime(); -// toTime = latestTime() + duration.days(15); -// expiryTime = toTime + duration.days(100); -// P_fromTime = fromTime + duration.days(1); -// P_toTime = P_fromTime + duration.days(50); -// P_expiryTime = toTime + duration.days(100); - -// balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(duration.days(1)); -// // Fallback transaction -// await web3.eth.sendTransaction({ -// from: account_investor1, -// to: I_CappedSTO_Array_ETH[0].address, -// gas: 2100000, -// value: web3.utils.toWei('1', 'ether') -// }); - -// assert.equal( -// (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1 -// ); - -// assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 1); - -// assert.equal( -// (await I_SecurityToken_ETH.balanceOf(account_investor1)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000 -// ); -// }); - -// it("Verification of the event Token Purchase", async() => { -// const log = await promisifyLogWatch(I_CappedSTO_Array_ETH[0].TokenPurchase({from: blockNo}), 1); - -// assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); -// assert.equal( -// (log.args.amount) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000, -// "Wrong No. token get dilivered" -// ); -// }); - -// it("Should pause the STO -- Failed due to wrong msg.sender", async()=> { -// let errorThrown = false; -// try { -// let tx = await I_CappedSTO_Array_ETH[0].pause({from: account_investor1}); -// } catch(error) { -// console.log(` tx revert -> Wrong msg.sender`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should pause the STO", async()=> { -// pauseTime = latestTime(); -// let tx = await I_CappedSTO_Array_ETH[0].pause({from: account_issuer}); -// assert.isTrue(await I_CappedSTO_Array_ETH[0].paused.call()); -// }); - -// it("Should fail to buy the tokens after pausing the STO", async() => { -// let errorThrown = false; -// try { -// await web3.eth.sendTransaction({ -// from: account_investor1, -// to: I_CappedSTO_Array_ETH[0].address, -// gas: 2100000, -// value: web3.utils.toWei('1', 'ether') -// }); -// } catch(error) { -// console.log(` tx revert -> STO is paused`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should unpause the STO -- Failed due to wrong msg.sender", async()=> { -// let errorThrown = false; -// try { -// let tx = await I_CappedSTO_Array_ETH[0].unpause({from: account_investor1}); -// } catch(error) { -// console.log(` tx revert -> Wrong msg.sender`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should unpause the STO", async()=> { -// let tx = await I_CappedSTO_Array_ETH[0].unpause({from: account_issuer}); -// assert.isFalse(await I_CappedSTO_Array_ETH[0].paused.call()); -// }); - -// it("Should buy the tokens -- Failed due to wrong granularity", async () => { -// let errorThrown = false; -// try { -// await web3.eth.sendTransaction({ -// from: account_investor1, -// to: I_CappedSTO_Array_ETH[0].address, -// value: web3.utils.toWei('0.1111', 'ether') -// }); -// } catch(error) { -// console.log(` tx revert -> Wrong purchase granularity`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async() => { -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// fromTime, -// toTime + duration.days(20), -// expiryTime, -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - -// // Fallback transaction -// await web3.eth.sendTransaction({ -// from: account_investor2, -// to: I_CappedSTO_Array_ETH[0].address, -// gas: 2100000, -// value: web3.utils.toWei('9', 'ether') -// }); - -// assert.equal( -// (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 10 -// ); - -// assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 2); - -// assert.equal( -// (await I_SecurityToken_ETH.balanceOf(account_investor2)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 9000 -// ); -// try { -// // Fallback transaction -// await web3.eth.sendTransaction({ -// from: account_investor2, -// to: I_CappedSTO_Array_ETH[0].address, -// gas: 210000, -// value: web3.utils.toWei('1', 'ether') -// }); -// } catch(error) { -// console.log(` tx revert -> Cap reached`.grey); -// ensureException(error); -// } -// }); - -// it("Should failed at the time of buying the tokens -- Because STO get expired", async() => { -// await increaseTime(duration.days(17)); // increased beyond the end time of the STO -// let errorThrown = false; -// try { -// // Fallback transaction -// await web3.eth.sendTransaction({ -// from: account_investor2, -// to: I_CappedSTO_Array_ETH[0].address, -// gas: 2100000, -// value: web3.utils.toWei('1', 'ether') -// }); -// } catch(error) { -// console.log(` tx revert -> STO get expired reached`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fundRaised value equal to the raised value in the funds receiver wallet", async() => { -// const newBalance = await web3.eth.getBalance(account_fundsReceiver); -// //console.log("WWWW",newBalance,await I_CappedSTO.fundsRaised.call(),balanceOfReceiver); -// let op = (BigNumber(newBalance).minus(balanceOfReceiver)).toNumber(); -// assert.equal( -// (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).toNumber(), -// op, -// "Somewhere raised money get stolen or sent to wrong wallet" -// ); -// }); - -// it("Should get the raised amount of ether", async() => { -// assert.equal(await I_CappedSTO_Array_ETH[0].getRaised.call(ETH), web3.utils.toWei('10','ether')); -// }); - -// it("Should get the raised amount of poly", async() => { -// assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(POLY)).toNumber(), web3.utils.toWei('0','ether')); -// }); - -// }); - -// describe("Reclaim poly sent to STO by mistake", async() => { - -// it("Should fail to reclaim POLY because token contract address is 0 address", async() => { -// let value = web3.utils.toWei('100','ether'); -// await I_PolyToken.getTokens(value, account_investor1); -// await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); - -// let errorThrown = false; -// try { -// await I_CappedSTO_Array_ETH[0].reclaimERC20('0x0000000000000000000000000000000000000000', { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> token contract address is 0 address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully reclaim POLY", async() => { -// let initInvestorBalance = await I_PolyToken.balanceOf(account_investor1); -// let initOwnerBalance = await I_PolyToken.balanceOf(token_owner); -// let initContractBalance = await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address); -// let value = web3.utils.toWei('100','ether'); - -// await I_PolyToken.getTokens(value, account_investor1); -// await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); -// await I_CappedSTO_Array_ETH[0].reclaimERC20(I_PolyToken.address, { from: token_owner }); -// assert.equal((await I_PolyToken.balanceOf(account_investor3)).toNumber(), initInvestorBalance.toNumber(), "tokens are not transfered out from investor account"); -// assert.equal((await I_PolyToken.balanceOf(token_owner)).toNumber(), initOwnerBalance.add(value).add(initContractBalance).toNumber(), "tokens are not added to the owner account"); -// assert.equal((await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address)).toNumber(), 0, "tokens are not trandfered out from STO contract"); -// }); -// }); - -// describe("Attach second ETH STO module", async() => { - -// it("Should successfully attach the second STO module to the security token", async () => { -// startTime_ETH2 = latestTime() + duration.days(1); -// endTime_ETH2 = startTime_ETH2 + duration.days(30); - -// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); -// await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); -// let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH2, endTime_ETH2, cap, rate, [E_fundRaiseType], account_fundsReceiver]); -// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - -// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); -// I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); -// }); - -// it("Should verify the configuration of the STO", async() => { -// assert.equal( -// await I_CappedSTO_Array_ETH[1].startTime.call(), -// startTime_ETH2, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_ETH[1].endTime.call(), -// endTime_ETH2, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// (await I_CappedSTO_Array_ETH[1].cap.call()).toNumber(), -// cap, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_ETH[1].rate.call(), -// rate, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_ETH[1].fundRaiseTypes.call(E_fundRaiseType), -// true, -// "STO Configuration doesn't set as expected" -// ); -// }); - -// it("Should successfully whitelist investor 3", async() => { - -// balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); - -// // Jump time to beyond STO start -// await increaseTime(duration.days(2)); -// }); - -// it("Should invest in second STO - fails due to incorrect beneficiary", async() => { - -// // Buying on behalf of another user should fail -// let errorThrown = false; -// try { -// await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from : account_issuer, value: web3.utils.toWei('1', 'ether') }); -// } catch(error) { -// console.log(` tx revert -> incorrect beneficiary`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Should allow non-matching beneficiary", async() => { -// await I_CappedSTO_Array_ETH[1].changeAllowBeneficialInvestments(true, {from: account_issuer}); -// let allow = await I_CappedSTO_Array_ETH[1].allowBeneficialInvestments(); -// assert.equal(allow, true, "allowBeneficialInvestments should be true"); -// }); - -// it("Should invest in second STO", async() => { - -// await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from : account_issuer, value: web3.utils.toWei('1', 'ether') }); - -// assert.equal( -// (await I_CappedSTO_Array_ETH[1].getRaised.call(ETH)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1 -// ); - -// assert.equal(await I_CappedSTO_Array_ETH[1].investorCount.call(), 1); - -// assert.equal( -// (await I_SecurityToken_ETH.balanceOf(account_investor3)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000 -// ); -// }); -// }); - -// describe("Test cases for reaching limit number of STO modules", async() => { - -// it("Should successfully attach 10 STO modules", async () => { -// const MAX_MODULES = 10; -// let startTime = latestTime() + duration.days(1); -// let endTime = startTime + duration.days(30); - -// await I_PolyToken.getTokens(cappedSTOSetupCost*19, token_owner); -// await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost*19, { from: token_owner}); -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], account_fundsReceiver]); - -// for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { -// const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); -// assert.equal(tx.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); -// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); -// I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); -// } - -// }); - -// it("Should successfully invest in all STO modules attached", async () => { -// const MAX_MODULES = 10; -// await increaseTime(duration.days(2)); -// for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { -// await I_CappedSTO_Array_ETH[STOIndex].buyTokens(account_investor3, { from : account_investor3, value: web3.utils.toWei('1', 'ether') }); -// assert.equal( -// (await I_CappedSTO_Array_ETH[STOIndex].getRaised.call(ETH)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1 -// ); -// assert.equal(await I_CappedSTO_Array_ETH[STOIndex].investorCount.call(), 1); -// } -// }); -// }); - -// describe("Test Cases for an STO of fundraise type POLY", async() => { - -// describe("Launch a new SecurityToken", async() => { - -// it("POLY: Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, P_symbol, P_name, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, P_symbol); -// }); - -// it("POLY: Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(P_name, P_symbol, P_tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, P_symbol, "SecurityToken doesn't get deployed"); - -// I_SecurityToken_POLY = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken_POLY.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), transferManagerKey); -// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); -// }); - -// it("POLY: Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken_POLY.getModulesByType(transferManagerKey))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); -// }); - -// it("POLY: Should successfully attach the STO module to the security token", async () => { -// startTime_POLY1 = latestTime() + duration.days(2); -// endTime_POLY1 = startTime_POLY1 + duration.days(30); - -// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); -// await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); - -// let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY1, endTime_POLY1, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); - -// const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - -// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); -// I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); -// }); - -// }); - -// describe("verify the data of STO", async () => { - -// it("Should verify the configuration of the STO", async() => { -// assert.equal( -// (await I_CappedSTO_Array_POLY[0].startTime.call()).toNumber(), -// startTime_POLY1, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// (await I_CappedSTO_Array_POLY[0].endTime.call()).toNumber(), -// endTime_POLY1, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// (await I_CappedSTO_Array_POLY[0].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), -// BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_POLY[0].rate.call(), -// P_rate, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_POLY[0].fundRaiseTypes.call(P_fundRaiseType), -// true, -// "STO Configuration doesn't set as expected" -// ); -// }); -// }); - -// describe("Buy tokens", async() => { - -// it("Should Buy the tokens", async() => { -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_investor1); -// blockNo = latestBlock(); -// assert.equal( -// (await I_PolyToken.balanceOf(account_investor1)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 10000, -// "Tokens are not transfered properly" -// ); - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// P_fromTime, -// P_toTime, -// P_expiryTime, -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(duration.days(17)); - -// await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); - -// // buyTokensWithPoly transaction -// await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( -// (1000 * Math.pow(10, 18)), -// { -// from : account_investor1, -// gas: 6000000 -// } -// ); - -// assert.equal( -// (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000 -// ); - -// assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(), 1); - -// assert.equal( -// (await I_SecurityToken_POLY.balanceOf(account_investor1)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 5000 -// ); -// }); - -// it("Verification of the event Token Purchase", async() => { -// const log = await promisifyLogWatch(I_CappedSTO_Array_POLY[0].TokenPurchase({from: blockNo}), 1); - -// assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); -// assert.equal( -// (log.args.amount) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 5000, -// "Wrong No. token get dilivered" -// ); -// }); - -// it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async() => { -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// P_fromTime, -// P_toTime + duration.days(20), -// P_expiryTime, -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_investor2); - -// await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (9000 * Math.pow(10, 18)), { from: account_investor2}); - -// // buyTokensWithPoly transaction -// await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( -// (9000 * Math.pow(10, 18)), -// {from : account_investor2, gas: 6000000 } -// ); - -// assert.equal( -// (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 10000 -// ); - -// assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(), 2); - -// assert.equal( -// (await I_SecurityToken_POLY.balanceOf(account_investor2)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 45000 -// ); -// let errorThrown = false; -// try { - -// await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); -// // buyTokensWithPoly transaction -// await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( -// (1000 * Math.pow(10, 18)), -// {from : account_investor1, gas: 6000000 } -// ); -// } catch(error) { -// console.log(` tx revert -> Cap reached`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should failed at the time of buying the tokens -- Because STO get expired", async() => { -// await increaseTime(duration.days(31)); // increased beyond the end time of the STO -// let errorThrown = false; -// try { -// await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); -// // buyTokensWithPoly transaction -// await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( -// (1000 * Math.pow(10, 18)), -// {from : account_investor1, gas: 6000000 } -// ); -// } catch(error) { -// console.log(` tx revert -> STO expiry reached`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fundRaised value equal to the raised value in the funds receiver wallet", async() => { -// const balanceRaised = await I_PolyToken.balanceOf.call(account_fundsReceiver); -// assert.equal( -// (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toNumber(), -// balanceRaised, -// "Somewhere raised money get stolen or sent to wrong wallet" -// ); -// }); - -// }); - -// describe("Test cases for the CappedSTOFactory", async() => { -// it("should get the exact details of the factory", async() => { -// assert.equal((await I_CappedSTOFactory.setupCost.call()).toNumber(), cappedSTOSetupCost); -// assert.equal((await I_CappedSTOFactory.getTypes.call())[0],3); -// assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), -// "CappedSTO", -// "Wrong Module added"); -// assert.equal(await I_CappedSTOFactory.getDescription.call(), -// "Use to collects the funds and once the cap is reached then investment will be no longer entertained", -// "Wrong Module added"); -// assert.equal(await I_CappedSTOFactory.getTitle.call(), -// "Capped STO", -// "Wrong Module added"); -// assert.equal(await I_CappedSTOFactory.getInstructions.call(), -// "Initialises a capped STO. Init parameters are _startTime (time STO starts), _endTime (time STO ends), _cap (cap in tokens for STO), _rate (POLY/ETH to token rate), _fundRaiseType (whether you are raising in POLY or ETH), _polyToken (address of POLY token), _fundsReceiver (address which will receive funds)", -// "Wrong Module added"); -// let tags = await I_CappedSTOFactory.getTags.call(); -// assert.equal(web3.utils.hexToString(tags[0]),"Capped"); - -// }); - -// it("Should fail to change the title -- bad owner", async() => { -// let errorThrown = false; -// try { -// await I_CappedSTOFactory.changeTitle("STO Capped", {from:account_investor1}); -// } catch(error) { -// console.log(` tx revert -> bad owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to change the title -- zero length", async() => { -// let errorThrown = false; -// try { -// await I_CappedSTOFactory.changeTitle("", {from: token_owner}); -// } catch(error) { -// console.log(` tx revert -> bad owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully change the title", async() => { -// await I_CappedSTOFactory.changeTitle("STO Capped", {from: token_owner}); -// assert.equal(await I_CappedSTOFactory.getTitle.call(), -// "STO Capped", -// "Title doesn't get changed"); -// }); - -// it("Should fail to change the description -- bad owner", async() => { -// let errorThrown = false; -// try { -// await I_CappedSTOFactory.changeDescription("It is only a STO", {from:account_investor1}); -// } catch(error) { -// console.log(` tx revert -> bad owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to change the description -- zero length", async() => { -// let errorThrown = false; -// try { -// await I_CappedSTOFactory.changeDescription("", {from: token_owner}); -// } catch(error) { -// console.log(` tx revert -> length of string should not be zero`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully change the description", async() => { -// await I_CappedSTOFactory.changeDescription("It is only a STO", {from: token_owner}); -// assert.equal(await I_CappedSTOFactory.getDescription.call(), -// "It is only a STO", -// "Description doesn't get changed"); -// }); - -// it("Should fail to change the name -- bad owner", async() => { -// let errorThrown = false; -// try { -// await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), {from:account_investor1}); -// } catch(error) { -// console.log(` tx revert -> bad owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to change the name -- zero length", async() => { -// let errorThrown = false; -// try { -// await I_CappedSTOFactory.changeName(web3.utils.stringToHex(""), {from: token_owner}); -// } catch(error) { -// console.log(` tx revert -> length of string should not be zero`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully change the name", async() => { -// await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), {from: token_owner}); -// assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), -// "STOCapped", -// "Name doesn't get changed"); -// }); - -// it("Should successfully change the name", async() => { -// await I_CappedSTOFactory.changeName(web3.utils.stringToHex("CappedSTO"), {from: token_owner}); -// assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), -// "CappedSTO", -// "Name doesn't get changed"); -// }); - -// }); - -// describe("Test cases for the get functions of the capped sto", async() => { -// it("Should verify the cap reached or not", async() => { -// assert.isTrue(await I_CappedSTO_Array_POLY[0].capReached.call()); -// }); - -// it("Should get the raised amount of ether", async() => { -// assert.equal(await I_CappedSTO_Array_POLY[0].getRaised.call(ETH), web3.utils.toWei('0','ether')); -// }); - -// it("Should get the raised amount of poly", async() => { -// assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toNumber(), web3.utils.toWei('10000','ether')); -// }); - -// it("Should get the investors", async() => { -// assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(),2); -// }); - -// it("Should get the listed permissions", async() => { -// let tx = await I_CappedSTO_Array_POLY[0].getPermissions.call(); -// assert.equal(tx.length,0); -// }); - -// it("Should get the metrics of the STO", async() => { -// let metrics = await I_CappedSTO_Array_POLY[0].getSTODetails.call(); -// assert.isTrue(metrics[7]); -// }); - -// }); -// }); - -// describe("Attach second POLY STO module", async() => { -// it("Should successfully attach a second STO to the security token", async () => { -// startTime_POLY2 = latestTime() + duration.days(1); -// endTime_POLY2 = startTime_POLY2 + duration.days(30); - -// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); -// await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); - -// let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY2, endTime_POLY2, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); - -// const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - -// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); -// I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); -// }); - -// it("Should verify the configuration of the STO", async() => { -// assert.equal( -// (await I_CappedSTO_Array_POLY[1].startTime.call()).toNumber(), -// startTime_POLY2, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// (await I_CappedSTO_Array_POLY[1].endTime.call()).toNumber(), -// endTime_POLY2, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// (await I_CappedSTO_Array_POLY[1].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), -// BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_POLY[1].rate.call(), -// P_rate, -// "STO Configuration doesn't set as expected" -// ); -// assert.equal( -// await I_CappedSTO_Array_POLY[1].fundRaiseTypes.call(P_fundRaiseType), -// true, -// "STO Configuration doesn't set as expected" -// ); -// }); - -// it("Should successfully invest in second STO", async() => { - -// const polyToInvest = 1000; -// const stToReceive = polyToInvest * P_rate; - -// await I_PolyToken.getTokens((polyToInvest * Math.pow(10, 18)), account_investor3); - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// P_fromTime, -// P_toTime, -// P_expiryTime, -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// // Jump time to beyond STO start -// await increaseTime(duration.days(2)); - -// await I_PolyToken.approve(I_CappedSTO_Array_POLY[1].address, (polyToInvest * Math.pow(10, 18)), { from: account_investor3 }); - -// // buyTokensWithPoly transaction -// await I_CappedSTO_Array_POLY[1].buyTokensWithPoly( -// (polyToInvest * Math.pow(10, 18)), -// { -// from : account_investor3, -// gas: 6000000 -// } -// ); - -// assert.equal( -// (await I_CappedSTO_Array_POLY[1].getRaised.call(POLY)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// polyToInvest -// ); - -// assert.equal(await I_CappedSTO_Array_POLY[1].investorCount.call(), 1); - -// assert.equal( -// (await I_SecurityToken_POLY.balanceOf(account_investor3)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// stToReceive -// ); -// }); -// }); -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +const CappedSTO = artifacts.require('./CappedSTO.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port +let ETH = 0; +let POLY = 1; +let DAI = 2; + +contract('CappedSTO', accounts => { + // Accounts Variable declaration + let account_polymath; + let account_investor1; + let account_issuer; + let token_owner; + let account_investor2; + let account_investor3; + let account_fundsReceiver; + + let balanceOfReceiver; + let message = "Transaction Should Fail!"; + // investor Details + let fromTime; + let toTime; + let expiryTime; + let P_fromTime; + let P_toTime; + let P_expiryTime; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_SecurityTokenRegistry; + let I_ModuleRegistry; + let I_ModuleRegistryProxy; + let I_FeatureRegistry; + let I_CappedSTOFactory; + let I_STFactory; + let I_SecurityToken_ETH; + let I_SecurityToken_POLY; + let I_CappedSTO_Array_ETH = []; + let I_CappedSTO_Array_POLY = []; + let I_PolyToken; + let I_PolymathRegistry; + let I_STRProxied; + let I_MRProxied; + let pauseTime; + + // SecurityToken Details for funds raise Type ETH + const name = "Team"; + const symbol = "SAP"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + + // SecurityToken Details for funds raise Type POLY + const P_name = "Team Poly"; + const P_symbol = "PAS"; + const P_tokenDetails = "This is equity type of issuance"; + const P_decimals = 18; + + // Module key + const transferManagerKey = 2; + const stoKey = 3; + const budget = 0; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // Capped STO details + let startTime_ETH1; + let endTime_ETH1; + let startTime_ETH2; + let endTime_ETH2; + const cap = web3.utils.toWei("10000"); + const rate = 1000; + const E_fundRaiseType = 0; + + let startTime_POLY1; + let endTime_POLY1; + let startTime_POLY2; + let endTime_POLY2; + let blockNo; + const P_cap = web3.utils.toWei("50000"); + const P_fundRaiseType = 1; + const P_rate = 5; + const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); + const maxCost = cappedSTOSetupCost; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + account_investor1 = accounts[4]; + account_investor2 = accounts[3]; + account_investor3 = accounts[5] + account_fundsReceiver = accounts[2]; + token_owner = account_issuer; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 6: Deploy the CappedSTOFactory + + I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); + + assert.notEqual( + I_CappedSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CappedSTOFactory contract was not deployed" + ); + + // Step 8: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 9: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 7: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + console.log(await I_MRProxied.owner()); + console.log(account_polymath); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + ModuleRegistry: ${ModuleRegistry.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + CappedSTOFactory: ${I_CappedSTOFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + + I_SecurityToken_ETH = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + + const log = await promisifyLogWatch(I_SecurityToken_ETH.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), transferManagerKey); + assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken_ETH.getModulesByType(transferManagerKey))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + + it("Should mint the tokens before attaching the STO", async() => { + let errorThrown = false; + try { + await I_SecurityToken_ETH.mint("0x0000000000000000000000000000000000000000", web3.utils.toWei("1"), {from: token_owner}); + } catch (error) { + console.log(` tx -> revert 0x address is not allowed as investor`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to launch the STO due to security token doesn't have the sufficient POLY", async () => { + let startTime = latestTime() + duration.days(1); + let endTime = startTime + duration.days(30); + await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); + + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); + let errorThrown = false; + try { + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Rate is ${0}. Test Passed Successfully`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to launch the STO due to rate is 0", async () => { + let startTime = latestTime() + duration.days(1); + let endTime = startTime + duration.days(30); + await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); + + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); + let errorThrown = false; + try { + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + } catch(error) { + console.log(`Tx Failed because of rate is ${0}. Test Passed Successfully`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to launch the STO due to startTime > endTime", async () => { + let bytesSTO = encodeModuleCall(STOParameters, [ Math.floor(Date.now()/1000 + 100000), Math.floor(Date.now()/1000 + 1000), cap, rate, [E_fundRaiseType], account_fundsReceiver]); + let errorThrown = false; + try { + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> StartTime is greater than endTime. Test Passed Successfully`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to launch the STO due to cap is of 0 securityToken", async () => { + let startTime = latestTime() + duration.days(1); + let endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [ startTime, endTime, 0, rate, [E_fundRaiseType], account_fundsReceiver]); + let errorThrown = false; + try { + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + } catch(error) { + console.log(`Tx Failed because the Cap is equal to ${0}. Test Passed Successfully`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the STO module to the security token", async () => { + startTime_ETH1 = latestTime() + duration.days(1); + endTime_ETH1 = startTime_ETH1 + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH1, endTime_ETH1, cap, rate, [E_fundRaiseType], account_fundsReceiver]); + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); + I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); + }); + }); + + describe("verify the data of STO", async () => { + + it("Should verify the configuration of the STO", async() => { + assert.equal( + await I_CappedSTO_Array_ETH[0].startTime.call(), + startTime_ETH1, + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_ETH[0].endTime.call(), + endTime_ETH1, + "STO Configuration doesn't set as expected" + ); + assert.equal( + (await I_CappedSTO_Array_ETH[0].cap.call()).toNumber(), + cap, + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_ETH[0].rate.call(), + rate, + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_ETH[0].fundRaiseTypes.call(E_fundRaiseType), + true, + "STO Configuration doesn't set as expected" + ); + }); + }); + + describe("Buy tokens", async() => { + + it("Should buy the tokens -- failed due to startTime is greater than Current time", async () => { + let errorThrown = false; + try { + await web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO_Array_ETH[0].address, + value: web3.utils.toWei('1', 'ether') + }); + } catch(error) { + console.log(` tx revert -> startTime is greater than Current time`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should buy the tokens -- failed due to invested amount is zero", async () => { + let errorThrown = false; + try { + await web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO_Array_ETH[0].address, + value: web3.utils.toWei('0', 'ether') + }); + } catch(error) { + console.log(` tx revert -> Invested amount is zero`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { + let errorThrown = false; + try { + await web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO_Array_ETH[0].address, + value: web3.utils.toWei('1', 'ether') + }); + } catch(error) { + console.log(` tx revert -> Investor doesn't present in the whitelist`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should buy the tokens -- Failed due to wrong granularity", async () => { + let errorThrown = false; + try { + await web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO_Array_ETH[0].address, + value: web3.utils.toWei('0.1111', 'ether') + }); + } catch(error) { + console.log(` tx revert -> Wrong purchase granularity`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should Buy the tokens", async() => { + blockNo = latestBlock(); + fromTime = latestTime(); + toTime = latestTime() + duration.days(15); + expiryTime = toTime + duration.days(100); + P_fromTime = fromTime + duration.days(1); + P_toTime = P_fromTime + duration.days(50); + P_expiryTime = toTime + duration.days(100); + + balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + fromTime, + toTime, + expiryTime, + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(duration.days(1)); + // Fallback transaction + await web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO_Array_ETH[0].address, + gas: 2100000, + value: web3.utils.toWei('1', 'ether') + }); + + assert.equal( + (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1 + ); + + assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 1); + + assert.equal( + (await I_SecurityToken_ETH.balanceOf(account_investor1)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000 + ); + }); + + it("Verification of the event Token Purchase", async() => { + const log = await promisifyLogWatch(I_CappedSTO_Array_ETH[0].TokenPurchase({from: blockNo}), 1); + + assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); + assert.equal( + (log.args.amount) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000, + "Wrong No. token get dilivered" + ); + }); + + it("Should pause the STO -- Failed due to wrong msg.sender", async()=> { + let errorThrown = false; + try { + let tx = await I_CappedSTO_Array_ETH[0].pause({from: account_investor1}); + } catch(error) { + console.log(` tx revert -> Wrong msg.sender`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should pause the STO", async()=> { + pauseTime = latestTime(); + let tx = await I_CappedSTO_Array_ETH[0].pause({from: account_issuer}); + assert.isTrue(await I_CappedSTO_Array_ETH[0].paused.call()); + }); + + it("Should fail to buy the tokens after pausing the STO", async() => { + let errorThrown = false; + try { + await web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO_Array_ETH[0].address, + gas: 2100000, + value: web3.utils.toWei('1', 'ether') + }); + } catch(error) { + console.log(` tx revert -> STO is paused`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should unpause the STO -- Failed due to wrong msg.sender", async()=> { + let errorThrown = false; + try { + let tx = await I_CappedSTO_Array_ETH[0].unpause({from: account_investor1}); + } catch(error) { + console.log(` tx revert -> Wrong msg.sender`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should unpause the STO", async()=> { + let tx = await I_CappedSTO_Array_ETH[0].unpause({from: account_issuer}); + assert.isFalse(await I_CappedSTO_Array_ETH[0].paused.call()); + }); + + it("Should buy the tokens -- Failed due to wrong granularity", async () => { + let errorThrown = false; + try { + await web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO_Array_ETH[0].address, + value: web3.utils.toWei('0.1111', 'ether') + }); + } catch(error) { + console.log(` tx revert -> Wrong purchase granularity`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async() => { + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + fromTime, + toTime + duration.days(20), + expiryTime, + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + + // Fallback transaction + await web3.eth.sendTransaction({ + from: account_investor2, + to: I_CappedSTO_Array_ETH[0].address, + gas: 2100000, + value: web3.utils.toWei('9', 'ether') + }); + + assert.equal( + (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 10 + ); + + assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 2); + + assert.equal( + (await I_SecurityToken_ETH.balanceOf(account_investor2)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 9000 + ); + try { + // Fallback transaction + await web3.eth.sendTransaction({ + from: account_investor2, + to: I_CappedSTO_Array_ETH[0].address, + gas: 210000, + value: web3.utils.toWei('1', 'ether') + }); + } catch(error) { + console.log(` tx revert -> Cap reached`.grey); + ensureException(error); + } + }); + + it("Should failed at the time of buying the tokens -- Because STO get expired", async() => { + await increaseTime(duration.days(17)); // increased beyond the end time of the STO + let errorThrown = false; + try { + // Fallback transaction + await web3.eth.sendTransaction({ + from: account_investor2, + to: I_CappedSTO_Array_ETH[0].address, + gas: 2100000, + value: web3.utils.toWei('1', 'ether') + }); + } catch(error) { + console.log(` tx revert -> STO get expired reached`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fundRaised value equal to the raised value in the funds receiver wallet", async() => { + const newBalance = await web3.eth.getBalance(account_fundsReceiver); + //console.log("WWWW",newBalance,await I_CappedSTO.fundsRaised.call(),balanceOfReceiver); + let op = (BigNumber(newBalance).minus(balanceOfReceiver)).toNumber(); + assert.equal( + (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).toNumber(), + op, + "Somewhere raised money get stolen or sent to wrong wallet" + ); + }); + + it("Should get the raised amount of ether", async() => { + assert.equal(await I_CappedSTO_Array_ETH[0].getRaised.call(ETH), web3.utils.toWei('10','ether')); + }); + + it("Should get the raised amount of poly", async() => { + assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(POLY)).toNumber(), web3.utils.toWei('0','ether')); + }); + + }); + + describe("Reclaim poly sent to STO by mistake", async() => { + + it("Should fail to reclaim POLY because token contract address is 0 address", async() => { + let value = web3.utils.toWei('100','ether'); + await I_PolyToken.getTokens(value, account_investor1); + await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); + + let errorThrown = false; + try { + await I_CappedSTO_Array_ETH[0].reclaimERC20('0x0000000000000000000000000000000000000000', { from: token_owner }); + } catch(error) { + console.log(` tx revert -> token contract address is 0 address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully reclaim POLY", async() => { + let initInvestorBalance = await I_PolyToken.balanceOf(account_investor1); + let initOwnerBalance = await I_PolyToken.balanceOf(token_owner); + let initContractBalance = await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address); + let value = web3.utils.toWei('100','ether'); + + await I_PolyToken.getTokens(value, account_investor1); + await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); + await I_CappedSTO_Array_ETH[0].reclaimERC20(I_PolyToken.address, { from: token_owner }); + assert.equal((await I_PolyToken.balanceOf(account_investor3)).toNumber(), initInvestorBalance.toNumber(), "tokens are not transfered out from investor account"); + assert.equal((await I_PolyToken.balanceOf(token_owner)).toNumber(), initOwnerBalance.add(value).add(initContractBalance).toNumber(), "tokens are not added to the owner account"); + assert.equal((await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address)).toNumber(), 0, "tokens are not trandfered out from STO contract"); + }); + }); + + describe("Attach second ETH STO module", async() => { + + it("Should successfully attach the second STO module to the security token", async () => { + startTime_ETH2 = latestTime() + duration.days(1); + endTime_ETH2 = startTime_ETH2 + duration.days(30); + + await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); + await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); + let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH2, endTime_ETH2, cap, rate, [E_fundRaiseType], account_fundsReceiver]); + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); + I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); + }); + + it("Should verify the configuration of the STO", async() => { + assert.equal( + await I_CappedSTO_Array_ETH[1].startTime.call(), + startTime_ETH2, + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_ETH[1].endTime.call(), + endTime_ETH2, + "STO Configuration doesn't set as expected" + ); + assert.equal( + (await I_CappedSTO_Array_ETH[1].cap.call()).toNumber(), + cap, + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_ETH[1].rate.call(), + rate, + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_ETH[1].fundRaiseTypes.call(E_fundRaiseType), + true, + "STO Configuration doesn't set as expected" + ); + }); + + it("Should successfully whitelist investor 3", async() => { + + balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + fromTime, + toTime, + expiryTime, + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); + + // Jump time to beyond STO start + await increaseTime(duration.days(2)); + }); + + it("Should invest in second STO - fails due to incorrect beneficiary", async() => { + + // Buying on behalf of another user should fail + let errorThrown = false; + try { + await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from : account_issuer, value: web3.utils.toWei('1', 'ether') }); + } catch(error) { + console.log(` tx revert -> incorrect beneficiary`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + }); + + it("Should allow non-matching beneficiary", async() => { + await I_CappedSTO_Array_ETH[1].changeAllowBeneficialInvestments(true, {from: account_issuer}); + let allow = await I_CappedSTO_Array_ETH[1].allowBeneficialInvestments(); + assert.equal(allow, true, "allowBeneficialInvestments should be true"); + }); + + it("Should invest in second STO", async() => { + + await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from : account_issuer, value: web3.utils.toWei('1', 'ether') }); + + assert.equal( + (await I_CappedSTO_Array_ETH[1].getRaised.call(ETH)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1 + ); + + assert.equal(await I_CappedSTO_Array_ETH[1].investorCount.call(), 1); + + assert.equal( + (await I_SecurityToken_ETH.balanceOf(account_investor3)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000 + ); + }); + }); + + describe("Test cases for reaching limit number of STO modules", async() => { + + it("Should successfully attach 10 STO modules", async () => { + const MAX_MODULES = 10; + let startTime = latestTime() + duration.days(1); + let endTime = startTime + duration.days(30); + + await I_PolyToken.getTokens(cappedSTOSetupCost*19, token_owner); + await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost*19, { from: token_owner}); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], account_fundsReceiver]); + + for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); + assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); + I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); + } + + }); + + it("Should successfully invest in all STO modules attached", async () => { + const MAX_MODULES = 10; + await increaseTime(duration.days(2)); + for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { + await I_CappedSTO_Array_ETH[STOIndex].buyTokens(account_investor3, { from : account_investor3, value: web3.utils.toWei('1', 'ether') }); + assert.equal( + (await I_CappedSTO_Array_ETH[STOIndex].getRaised.call(ETH)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1 + ); + assert.equal(await I_CappedSTO_Array_ETH[STOIndex].investorCount.call(), 1); + } + }); + }); + + describe("Test Cases for an STO of fundraise type POLY", async() => { + + describe("Launch a new SecurityToken", async() => { + + it("POLY: Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, P_symbol, P_name, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, P_symbol); + }); + + it("POLY: Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(P_name, P_symbol, P_tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, P_symbol, "SecurityToken doesn't get deployed"); + + I_SecurityToken_POLY = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken_POLY.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), transferManagerKey); + assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); + }); + + it("POLY: Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken_POLY.getModulesByType(transferManagerKey))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + + it("POLY: Should successfully attach the STO module to the security token", async () => { + startTime_POLY1 = latestTime() + duration.days(2); + endTime_POLY1 = startTime_POLY1 + duration.days(30); + + await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); + await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); + + let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY1, endTime_POLY1, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); + + const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); + I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); + }); + + }); + + describe("verify the data of STO", async () => { + + it("Should verify the configuration of the STO", async() => { + assert.equal( + (await I_CappedSTO_Array_POLY[0].startTime.call()).toNumber(), + startTime_POLY1, + "STO Configuration doesn't set as expected" + ); + assert.equal( + (await I_CappedSTO_Array_POLY[0].endTime.call()).toNumber(), + endTime_POLY1, + "STO Configuration doesn't set as expected" + ); + assert.equal( + (await I_CappedSTO_Array_POLY[0].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), + BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_POLY[0].rate.call(), + P_rate, + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_POLY[0].fundRaiseTypes.call(P_fundRaiseType), + true, + "STO Configuration doesn't set as expected" + ); + }); + }); + + describe("Buy tokens", async() => { + + it("Should Buy the tokens", async() => { + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_investor1); + blockNo = latestBlock(); + assert.equal( + (await I_PolyToken.balanceOf(account_investor1)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 10000, + "Tokens are not transfered properly" + ); + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + P_fromTime, + P_toTime, + P_expiryTime, + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(duration.days(17)); + + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); + + // buyTokensWithPoly transaction + await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( + (1000 * Math.pow(10, 18)), + { + from : account_investor1, + gas: 6000000 + } + ); + + assert.equal( + (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000 + ); + + assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(), 1); + + assert.equal( + (await I_SecurityToken_POLY.balanceOf(account_investor1)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 5000 + ); + }); + + it("Verification of the event Token Purchase", async() => { + const log = await promisifyLogWatch(I_CappedSTO_Array_POLY[0].TokenPurchase({from: blockNo}), 1); + + assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); + assert.equal( + (log.args.amount) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 5000, + "Wrong No. token get dilivered" + ); + }); + + it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async() => { + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + P_fromTime, + P_toTime + duration.days(20), + P_expiryTime, + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_investor2); + + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (9000 * Math.pow(10, 18)), { from: account_investor2}); + + // buyTokensWithPoly transaction + await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( + (9000 * Math.pow(10, 18)), + {from : account_investor2, gas: 6000000 } + ); + + assert.equal( + (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 10000 + ); + + assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(), 2); + + assert.equal( + (await I_SecurityToken_POLY.balanceOf(account_investor2)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 45000 + ); + let errorThrown = false; + try { + + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); + // buyTokensWithPoly transaction + await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( + (1000 * Math.pow(10, 18)), + {from : account_investor1, gas: 6000000 } + ); + } catch(error) { + console.log(` tx revert -> Cap reached`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should failed at the time of buying the tokens -- Because STO get expired", async() => { + await increaseTime(duration.days(31)); // increased beyond the end time of the STO + let errorThrown = false; + try { + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, (1000 * Math.pow(10, 18)), { from: account_investor1}); + // buyTokensWithPoly transaction + await I_CappedSTO_Array_POLY[0].buyTokensWithPoly( + (1000 * Math.pow(10, 18)), + {from : account_investor1, gas: 6000000 } + ); + } catch(error) { + console.log(` tx revert -> STO expiry reached`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fundRaised value equal to the raised value in the funds receiver wallet", async() => { + const balanceRaised = await I_PolyToken.balanceOf.call(account_fundsReceiver); + assert.equal( + (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toNumber(), + balanceRaised, + "Somewhere raised money get stolen or sent to wrong wallet" + ); + }); + + }); + + describe("Test cases for the CappedSTOFactory", async() => { + it("should get the exact details of the factory", async() => { + assert.equal((await I_CappedSTOFactory.setupCost.call()).toNumber(), cappedSTOSetupCost); + assert.equal((await I_CappedSTOFactory.getTypes.call())[0],3); + assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), + "CappedSTO", + "Wrong Module added"); + assert.equal(await I_CappedSTOFactory.getDescription.call(), + "Use to collects the funds and once the cap is reached then investment will be no longer entertained", + "Wrong Module added"); + assert.equal(await I_CappedSTOFactory.getTitle.call(), + "Capped STO", + "Wrong Module added"); + assert.equal(await I_CappedSTOFactory.getInstructions.call(), + "Initialises a capped STO. Init parameters are _startTime (time STO starts), _endTime (time STO ends), _cap (cap in tokens for STO), _rate (POLY/ETH to token rate), _fundRaiseType (whether you are raising in POLY or ETH), _polyToken (address of POLY token), _fundsReceiver (address which will receive funds)", + "Wrong Module added"); + let tags = await I_CappedSTOFactory.getTags.call(); + assert.equal(web3.utils.hexToString(tags[0]),"Capped"); + + }); + + it("Should fail to change the title -- bad owner", async() => { + let errorThrown = false; + try { + await I_CappedSTOFactory.changeTitle("STO Capped", {from:account_investor1}); + } catch(error) { + console.log(` tx revert -> bad owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to change the title -- zero length", async() => { + let errorThrown = false; + try { + await I_CappedSTOFactory.changeTitle("", {from: token_owner}); + } catch(error) { + console.log(` tx revert -> bad owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully change the title", async() => { + await I_CappedSTOFactory.changeTitle("STO Capped", {from: token_owner}); + assert.equal(await I_CappedSTOFactory.getTitle.call(), + "STO Capped", + "Title doesn't get changed"); + }); + + it("Should fail to change the description -- bad owner", async() => { + let errorThrown = false; + try { + await I_CappedSTOFactory.changeDescription("It is only a STO", {from:account_investor1}); + } catch(error) { + console.log(` tx revert -> bad owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to change the description -- zero length", async() => { + let errorThrown = false; + try { + await I_CappedSTOFactory.changeDescription("", {from: token_owner}); + } catch(error) { + console.log(` tx revert -> length of string should not be zero`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully change the description", async() => { + await I_CappedSTOFactory.changeDescription("It is only a STO", {from: token_owner}); + assert.equal(await I_CappedSTOFactory.getDescription.call(), + "It is only a STO", + "Description doesn't get changed"); + }); + + it("Should fail to change the name -- bad owner", async() => { + let errorThrown = false; + try { + await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), {from:account_investor1}); + } catch(error) { + console.log(` tx revert -> bad owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to change the name -- zero length", async() => { + let errorThrown = false; + try { + await I_CappedSTOFactory.changeName(web3.utils.stringToHex(""), {from: token_owner}); + } catch(error) { + console.log(` tx revert -> length of string should not be zero`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully change the name", async() => { + await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), {from: token_owner}); + assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), + "STOCapped", + "Name doesn't get changed"); + }); + + it("Should successfully change the name", async() => { + await I_CappedSTOFactory.changeName(web3.utils.stringToHex("CappedSTO"), {from: token_owner}); + assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), + "CappedSTO", + "Name doesn't get changed"); + }); + + }); + + describe("Test cases for the get functions of the capped sto", async() => { + it("Should verify the cap reached or not", async() => { + assert.isTrue(await I_CappedSTO_Array_POLY[0].capReached.call()); + }); + + it("Should get the raised amount of ether", async() => { + assert.equal(await I_CappedSTO_Array_POLY[0].getRaised.call(ETH), web3.utils.toWei('0','ether')); + }); + + it("Should get the raised amount of poly", async() => { + assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toNumber(), web3.utils.toWei('10000','ether')); + }); + + it("Should get the investors", async() => { + assert.equal(await I_CappedSTO_Array_POLY[0].investorCount.call(),2); + }); + + it("Should get the listed permissions", async() => { + let tx = await I_CappedSTO_Array_POLY[0].getPermissions.call(); + assert.equal(tx.length,0); + }); + + it("Should get the metrics of the STO", async() => { + let metrics = await I_CappedSTO_Array_POLY[0].getSTODetails.call(); + assert.isTrue(metrics[7]); + }); + + }); + }); + + describe("Attach second POLY STO module", async() => { + it("Should successfully attach a second STO to the security token", async () => { + startTime_POLY2 = latestTime() + duration.days(1); + endTime_POLY2 = startTime_POLY2 + duration.days(30); + + await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); + await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); + + let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY2, endTime_POLY2, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); + + const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); + I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); + }); + + it("Should verify the configuration of the STO", async() => { + assert.equal( + (await I_CappedSTO_Array_POLY[1].startTime.call()).toNumber(), + startTime_POLY2, + "STO Configuration doesn't set as expected" + ); + assert.equal( + (await I_CappedSTO_Array_POLY[1].endTime.call()).toNumber(), + endTime_POLY2, + "STO Configuration doesn't set as expected" + ); + assert.equal( + (await I_CappedSTO_Array_POLY[1].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), + BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_POLY[1].rate.call(), + P_rate, + "STO Configuration doesn't set as expected" + ); + assert.equal( + await I_CappedSTO_Array_POLY[1].fundRaiseTypes.call(P_fundRaiseType), + true, + "STO Configuration doesn't set as expected" + ); + }); + + it("Should successfully invest in second STO", async() => { + + const polyToInvest = 1000; + const stToReceive = polyToInvest * P_rate; + + await I_PolyToken.getTokens((polyToInvest * Math.pow(10, 18)), account_investor3); + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + P_fromTime, + P_toTime, + P_expiryTime, + true, + { + from: account_issuer, + gas: 500000 + }); + + // Jump time to beyond STO start + await increaseTime(duration.days(2)); + + await I_PolyToken.approve(I_CappedSTO_Array_POLY[1].address, (polyToInvest * Math.pow(10, 18)), { from: account_investor3 }); + + // buyTokensWithPoly transaction + await I_CappedSTO_Array_POLY[1].buyTokensWithPoly( + (polyToInvest * Math.pow(10, 18)), + { + from : account_investor3, + gas: 6000000 + } + ); + + assert.equal( + (await I_CappedSTO_Array_POLY[1].getRaised.call(POLY)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + polyToInvest + ); + + assert.equal(await I_CappedSTO_Array_POLY[1].investorCount.call(), 1); + + assert.equal( + (await I_SecurityToken_POLY.balanceOf(account_investor3)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + stToReceive + ); + }); + }); +}); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 25196ce1b..f4ad15ee1 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -1,429 +1,429 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('Checkpoints', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ExchangeTransferManager; -// let I_STRProxied; -// let I_MRProxied; -// let I_ModuleRegistry; -// let I_ModuleRegistryProxy; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_STFactory; -// let I_SecurityToken; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; - -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; - -// account_investor1 = accounts[6]; -// account_investor2 = accounts[7]; -// account_investor3 = accounts[8]; -// account_investor4 = accounts[9]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // Step 7: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 8: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 9: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 10: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 6: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// ModuleRegistry: ${ModuleRegistry.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should set controller to token owner", async () => { -// await I_SecurityToken.setController(token_owner, {from: token_owner}); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); -// }); - -// }); - -// describe("Buy tokens using on-chain whitelist", async() => { - -// it("Should Buy the tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// false, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('10', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('10', 'ether') -// ); -// }); - -// it("Should Buy some more tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// false, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('10', 'ether') -// ); -// }); - -// it("Add a new token holder", async() => { - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// false, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), -// web3.utils.toWei('10', 'ether') -// ); -// }); - -// it("Fuzz test balance checkpoints", async() => { -// await I_SecurityToken.changeGranularity(1, {from: token_owner}); -// let cps = []; -// let ts = []; -// for (let j = 0; j < 10; j++) { -// let balance1 = BigNumber(await I_SecurityToken.balanceOf(account_investor1)); -// let balance2 = BigNumber(await I_SecurityToken.balanceOf(account_investor2)); -// let balance3 = BigNumber(await I_SecurityToken.balanceOf(account_investor3)); -// let totalSupply = BigNumber(await I_SecurityToken.totalSupply()); -// cps.push([balance1, balance2, balance3]); -// ts.push(totalSupply); -// console.log("Checkpoint: " + (j + 1) + " Balances: " + JSON.stringify(cps[cps.length - 1]) + " TotalSupply: " + JSON.stringify(totalSupply)); -// await I_SecurityToken.createCheckpoint({ from: token_owner }); -// let checkpointTimes = (await I_SecurityToken.getCheckpointTimes()); -// assert.equal(checkpointTimes.length, (j + 1)); -// console.log("Checkpoint Times: " + checkpointTimes); -// let txs = Math.floor(Math.random() * 3); -// for (let i = 0; i < txs; i++) { -// let sender; -// let receiver; -// let s = Math.random() * 3; -// if (s < 1) { -// sender = account_investor1; -// } else if (s < 2) { -// sender = account_investor2; -// } else { -// sender = account_investor3; -// } -// let r = Math.random() * 3; -// if (r < 1) { -// receiver = account_investor1; -// } else if (r < 2) { -// receiver = account_investor2; -// } else { -// receiver = account_investor3; -// } -// let m = Math.random(); -// let amount = BigNumber(await I_SecurityToken.balanceOf(sender)).mul(Math.random().toFixed(10)).toFixed(0); -// if (m > 0.8) { -// console.log("Sending full balance"); -// amount = BigNumber(await I_SecurityToken.balanceOf(sender)); -// } -// console.log("Sender: " + sender + " Receiver: " + receiver + " Amount: " + JSON.stringify(amount)); -// await I_SecurityToken.transfer(receiver, amount, { from: sender }); -// } -// if (Math.random() > 0.5) { -// let n = BigNumber(Math.random().toFixed(10)).mul(10**17).toFixed(0); -// let p = Math.random() * 3; -// let r = Math.random() * 3; -// let minter; -// if (r < 1) { -// minter = account_investor1; -// } else if (r < 2) { -// minter = account_investor2; -// } else { -// minter = account_investor3; -// } -// console.log("Minting: " + n.toString() + " to: " + minter); -// await I_SecurityToken.mint(minter, n, { from: token_owner }); -// } -// if (Math.random() > 0.5) { -// let n = BigNumber(Math.random().toFixed(10)).mul(10**17); -// let p = Math.random() * 3; -// let r = Math.random() * 3; -// let burner; -// if (r < 1) { -// burner = account_investor1; -// } else if (r < 2) { -// burner = account_investor2; -// } else { -// burner = account_investor3; -// } -// let burnerBalance = BigNumber(await I_SecurityToken.balanceOf(burner)); -// if (n.gt(burnerBalance.div(2))) { -// n = burnerBalance.div(2); -// } -// n = n.toFixed(0); -// console.log("Burning: " + n.toString() + " from: " + burner); -// await I_SecurityToken.forceBurn(burner, n, "", "", { from: token_owner }); -// } -// console.log("Checking Interim..."); -// for (let k = 0; k < cps.length; k++) { -// let balance1 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); -// let balance2 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); -// let balance3 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); -// let totalSupply = BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); -// let balances = [balance1, balance2, balance3]; -// console.log("Checking TotalSupply: " + totalSupply + " is " + ts[k] + " at checkpoint: " + (k + 1)); -// assert.isTrue(totalSupply.eq(ts[k])); -// console.log("Checking Balances: " + balances + " is " + cps[k] + " at checkpoint: " + (k + 1)); -// for (let l = 0; l < cps[k].length; l++) { -// // console.log(balances[l].toString(), cps[k][l].toString()); -// assert.isTrue(balances[l].eq(cps[k][l])); -// } -// } -// } -// console.log("Checking..."); -// for (let k = 0; k < cps.length; k++) { -// let balance1 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); -// let balance2 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); -// let balance3 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); -// let totalSupply = BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); -// let balances = [balance1, balance2, balance3]; -// console.log("Checking TotalSupply: " + totalSupply + " is " + ts[k] + " at checkpoint: " + (k + 1)); -// assert.isTrue(totalSupply.eq(ts[k])); -// console.log("Checking Balances: " + balances + " is " + cps[k] + " at checkpoint: " + (k + 1)); -// for (let l = 0; l < cps[k].length; l++) { -// // console.log(balances[l].toString(), cps[k][l].toString()); -// assert.isTrue(balances[l].eq(cps[k][l])); -// } -// } - -// }); -// }); - -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('Checkpoints', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ExchangeTransferManager; + let I_STRProxied; + let I_MRProxied; + let I_ModuleRegistry; + let I_ModuleRegistryProxy; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[6]; + account_investor2 = accounts[7]; + account_investor3 = accounts[8]; + account_investor4 = accounts[9]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // Step 7: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 8: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 9: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 10: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 6: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + ModuleRegistry: ${ModuleRegistry.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should set controller to token owner", async () => { + await I_SecurityToken.setController(token_owner, {from: token_owner}); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + + }); + + describe("Buy tokens using on-chain whitelist", async() => { + + it("Should Buy the tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + false, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('10', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('10', 'ether') + ); + }); + + it("Should Buy some more tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + false, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('10', 'ether') + ); + }); + + it("Add a new token holder", async() => { + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + false, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('10', 'ether') + ); + }); + + it("Fuzz test balance checkpoints", async() => { + await I_SecurityToken.changeGranularity(1, {from: token_owner}); + let cps = []; + let ts = []; + for (let j = 0; j < 10; j++) { + let balance1 = BigNumber(await I_SecurityToken.balanceOf(account_investor1)); + let balance2 = BigNumber(await I_SecurityToken.balanceOf(account_investor2)); + let balance3 = BigNumber(await I_SecurityToken.balanceOf(account_investor3)); + let totalSupply = BigNumber(await I_SecurityToken.totalSupply()); + cps.push([balance1, balance2, balance3]); + ts.push(totalSupply); + console.log("Checkpoint: " + (j + 1) + " Balances: " + JSON.stringify(cps[cps.length - 1]) + " TotalSupply: " + JSON.stringify(totalSupply)); + await I_SecurityToken.createCheckpoint({ from: token_owner }); + let checkpointTimes = (await I_SecurityToken.getCheckpointTimes()); + assert.equal(checkpointTimes.length, (j + 1)); + console.log("Checkpoint Times: " + checkpointTimes); + let txs = Math.floor(Math.random() * 3); + for (let i = 0; i < txs; i++) { + let sender; + let receiver; + let s = Math.random() * 3; + if (s < 1) { + sender = account_investor1; + } else if (s < 2) { + sender = account_investor2; + } else { + sender = account_investor3; + } + let r = Math.random() * 3; + if (r < 1) { + receiver = account_investor1; + } else if (r < 2) { + receiver = account_investor2; + } else { + receiver = account_investor3; + } + let m = Math.random(); + let amount = BigNumber(await I_SecurityToken.balanceOf(sender)).mul(Math.random().toFixed(10)).toFixed(0); + if (m > 0.8) { + console.log("Sending full balance"); + amount = BigNumber(await I_SecurityToken.balanceOf(sender)); + } + console.log("Sender: " + sender + " Receiver: " + receiver + " Amount: " + JSON.stringify(amount)); + await I_SecurityToken.transfer(receiver, amount, { from: sender }); + } + if (Math.random() > 0.5) { + let n = BigNumber(Math.random().toFixed(10)).mul(10**17).toFixed(0); + let p = Math.random() * 3; + let r = Math.random() * 3; + let minter; + if (r < 1) { + minter = account_investor1; + } else if (r < 2) { + minter = account_investor2; + } else { + minter = account_investor3; + } + console.log("Minting: " + n.toString() + " to: " + minter); + await I_SecurityToken.mint(minter, n, { from: token_owner }); + } + if (Math.random() > 0.5) { + let n = BigNumber(Math.random().toFixed(10)).mul(10**17); + let p = Math.random() * 3; + let r = Math.random() * 3; + let burner; + if (r < 1) { + burner = account_investor1; + } else if (r < 2) { + burner = account_investor2; + } else { + burner = account_investor3; + } + let burnerBalance = BigNumber(await I_SecurityToken.balanceOf(burner)); + if (n.gt(burnerBalance.div(2))) { + n = burnerBalance.div(2); + } + n = n.toFixed(0); + console.log("Burning: " + n.toString() + " from: " + burner); + await I_SecurityToken.forceBurn(burner, n, "", "", { from: token_owner }); + } + console.log("Checking Interim..."); + for (let k = 0; k < cps.length; k++) { + let balance1 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); + let balance2 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); + let balance3 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); + let totalSupply = BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); + let balances = [balance1, balance2, balance3]; + console.log("Checking TotalSupply: " + totalSupply + " is " + ts[k] + " at checkpoint: " + (k + 1)); + assert.isTrue(totalSupply.eq(ts[k])); + console.log("Checking Balances: " + balances + " is " + cps[k] + " at checkpoint: " + (k + 1)); + for (let l = 0; l < cps[k].length; l++) { + // console.log(balances[l].toString(), cps[k][l].toString()); + assert.isTrue(balances[l].eq(cps[k][l])); + } + } + } + console.log("Checking..."); + for (let k = 0; k < cps.length; k++) { + let balance1 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); + let balance2 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); + let balance3 = BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); + let totalSupply = BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); + let balances = [balance1, balance2, balance3]; + console.log("Checking TotalSupply: " + totalSupply + " is " + ts[k] + " at checkpoint: " + (k + 1)); + assert.isTrue(totalSupply.eq(ts[k])); + console.log("Checking Balances: " + balances + " is " + cps[k] + " at checkpoint: " + (k + 1)); + for (let l = 0; l < cps[k].length; l++) { + // console.log(balances[l].toString(), cps[k][l].toString()); + assert.isTrue(balances[l].eq(cps[k][l])); + } + } + + }); + }); + +}); diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 2b762825c..164538f50 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -1,505 +1,505 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); -// const CountTransferManager = artifacts.require('./CountTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('CountTransferManager', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let P_CountTransferManagerFactory; -// let P_CountTransferManager; -// let I_GeneralTransferManagerFactory; -// let I_CountTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_CountTransferManager; -// let I_GeneralTransferManager; -// let I_ExchangeTransferManager; -// let I_ModuleRegistry; -// let I_ModuleRegistryProxy; -// let I_MRProxied; -// let I_STRProxied; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_STFactory; -// let I_SecurityToken; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; - -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// // CountTransferManager details -// const holderCount = 2; // Maximum number of token holders -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; -// let bytesSTO = encodeModuleCall(['uint256'], [holderCount]); - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; - -// account_investor1 = accounts[7]; -// account_investor2 = accounts[8]; -// account_investor3 = accounts[9]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// assert.notEqual( -// I_FeatureRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "FeatureRegistry contract was not deployed", -// ); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 6: Deploy the CountTransferManager -// I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); -// assert.notEqual( -// I_CountTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CountTransferManagerFactory contract was not deployed" -// ); - -// // STEP 7: Deploy Paid the CountTransferManager -// P_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); -// assert.notEqual( -// P_CountTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CountTransferManagerFactory contract was not deployed" -// ); - -// // Step 9: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 10: Deploy the SecurityTokenRegistry - -// // Deploy the SecurityTokenregistry -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 11: Deploy the proxy and attach the implementation contract -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 12: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 8: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the CountTransferManagerFactory -// await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the Paid CountTransferManagerFactory -// await I_MRProxied.registerModule(P_CountTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(P_CountTransferManagerFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// CountTransferManagerFactory: ${I_CountTransferManagerFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); - -// it("Should successfully attach the CountTransferManager factory with the security token", async () => { -// let errorThrown = false; -// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); -// try { -// const tx = await I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx -> failed because Token is not paid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the CountTransferManager factory with the security token", async () => { -// let snapId = await takeSnapshot(); -// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); -// const tx = await I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "CountTransferManagerFactory doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[3].args._name) -// .replace(/\u0000/g, ''), -// "CountTransferManager", -// "CountTransferManagerFactory module was not added" -// ); -// P_CountTransferManager = CountTransferManager.at(tx.logs[3].args._module); -// await revertToSnapshot(snapId); -// }); - -// it("Should successfully attach the CountTransferManager with the security token", async () => { -// const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "CountTransferManager", -// "CountTransferManager module was not added" -// ); -// I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); -// }); -// }); - -// describe("Buy tokens using on-chain whitelist", async() => { - -// it("Should Buy the tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(5000); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Should Buy some more tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('2', 'ether') -// ); -// }); - -// it("Should fail to buy some more tokens (more than 2 holders)", async() => { -// // Add the Investor in to the whitelist -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - -// let errorThrown = false; -// try { -// // Mint some tokens -// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('3', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Too many holders`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - - -// it("Should still be able to add to original token holders", async() => { -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('4', 'ether') -// ); -// }); - -// it("Should still be able to transfer between existing token holders before count change", async() => { -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('2', 'ether') -// ); -// }); - -// it("Should fail in modifying the holder count", async() => { -// let errorThrown = false; -// try { -// await I_CountTransferManager.changeHolderCount(1, { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> Only owner have the permission to change the holder count`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Modify holder count to 1", async() => { -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_CountTransferManager.changeHolderCount(1, { from: token_owner }); - -// assert.equal( -// (await I_CountTransferManager.maxHolderCount()).toNumber(), -// 1 -// ); -// }); - -// it("Should still be able to transfer between existing token holders after count change", async() => { -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('4', 'ether') -// ); -// }); - -// it("Should not be able to transfer to a new token holder", async() => { -// let errorThrown = false; -// // await I_CountTransferManager.unpause({from: token_owner}); -// try { -// // Mint some tokens -// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> Too many holders`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Should be able to consolidate balances", async() => { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// }); - -// it("Should get the permission list", async() => { -// let perm = await I_CountTransferManager.getPermissions.call(); -// assert.equal(perm.length, 1); -// }); - -// describe("Test cases for the factory", async() => { -// it("should get the exact details of the factory", async() => { -// assert.equal(await I_CountTransferManagerFactory.setupCost.call(),0); -// assert.equal((await I_CountTransferManagerFactory.getTypes.call())[0],2); -// assert.equal(web3.utils.toAscii(await I_CountTransferManagerFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "CountTransferManager", -// "Wrong Module added"); -// assert.equal(await I_CountTransferManagerFactory.getDescription.call(), -// "Restrict the number of investors", -// "Wrong Module added"); -// assert.equal(await I_CountTransferManagerFactory.getTitle.call(), -// "Count Transfer Manager", -// "Wrong Module added"); -// assert.equal(await I_CountTransferManagerFactory.getInstructions.call(), -// "Allows an issuer to restrict the total number of non-zero token holders", -// "Wrong Module added"); - -// }); - -// it("Should get the tags of the factory", async() => { -// let tags = await I_CountTransferManagerFactory.getTags.call(); -// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Count"); -// }); -// }); - -// }); - -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); +const CountTransferManager = artifacts.require('./CountTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('CountTransferManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let P_CountTransferManagerFactory; + let P_CountTransferManager; + let I_GeneralTransferManagerFactory; + let I_CountTransferManagerFactory; + let I_GeneralPermissionManager; + let I_CountTransferManager; + let I_GeneralTransferManager; + let I_ExchangeTransferManager; + let I_ModuleRegistry; + let I_ModuleRegistryProxy; + let I_MRProxied; + let I_STRProxied; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // CountTransferManager details + const holderCount = 2; // Maximum number of token holders + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + let bytesSTO = encodeModuleCall(['uint256'], [holderCount]); + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[7]; + account_investor2 = accounts[8]; + account_investor3 = accounts[9]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + assert.notEqual( + I_FeatureRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "FeatureRegistry contract was not deployed", + ); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 6: Deploy the CountTransferManager + I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + assert.notEqual( + I_CountTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CountTransferManagerFactory contract was not deployed" + ); + + // STEP 7: Deploy Paid the CountTransferManager + P_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); + assert.notEqual( + P_CountTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CountTransferManagerFactory contract was not deployed" + ); + + // Step 9: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 10: Deploy the SecurityTokenRegistry + + // Deploy the SecurityTokenregistry + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 11: Deploy the proxy and attach the implementation contract + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 12: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 8: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the CountTransferManagerFactory + await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the Paid CountTransferManagerFactory + await I_MRProxied.registerModule(P_CountTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_CountTransferManagerFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + CountTransferManagerFactory: ${I_CountTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + it("Should successfully attach the CountTransferManager factory with the security token", async () => { + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + try { + const tx = await I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + } catch(error) { + console.log(` tx -> failed because Token is not paid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the CountTransferManager factory with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "CountTransferManagerFactory doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "CountTransferManager", + "CountTransferManagerFactory module was not added" + ); + P_CountTransferManager = CountTransferManager.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the CountTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "CountTransferManager", + "CountTransferManager module was not added" + ); + I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); + }); + }); + + describe("Buy tokens using on-chain whitelist", async() => { + + it("Should Buy the tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should Buy some more tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should fail to buy some more tokens (more than 2 holders)", async() => { + // Add the Investor in to the whitelist + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + let errorThrown = false; + try { + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('3', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Too many holders`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + + it("Should still be able to add to original token holders", async() => { + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('4', 'ether') + ); + }); + + it("Should still be able to transfer between existing token holders before count change", async() => { + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should fail in modifying the holder count", async() => { + let errorThrown = false; + try { + await I_CountTransferManager.changeHolderCount(1, { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to change the holder count`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Modify holder count to 1", async() => { + // Add the Investor in to the whitelist + // Mint some tokens + await I_CountTransferManager.changeHolderCount(1, { from: token_owner }); + + assert.equal( + (await I_CountTransferManager.maxHolderCount()).toNumber(), + 1 + ); + }); + + it("Should still be able to transfer between existing token holders after count change", async() => { + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('4', 'ether') + ); + }); + + it("Should not be able to transfer to a new token holder", async() => { + let errorThrown = false; + // await I_CountTransferManager.unpause({from: token_owner}); + try { + // Mint some tokens + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> Too many holders`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + }); + + it("Should be able to consolidate balances", async() => { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + }); + + it("Should get the permission list", async() => { + let perm = await I_CountTransferManager.getPermissions.call(); + assert.equal(perm.length, 1); + }); + + describe("Test cases for the factory", async() => { + it("should get the exact details of the factory", async() => { + assert.equal(await I_CountTransferManagerFactory.setupCost.call(),0); + assert.equal((await I_CountTransferManagerFactory.getTypes.call())[0],2); + assert.equal(web3.utils.toAscii(await I_CountTransferManagerFactory.getName.call()) + .replace(/\u0000/g, ''), + "CountTransferManager", + "Wrong Module added"); + assert.equal(await I_CountTransferManagerFactory.getDescription.call(), + "Restrict the number of investors", + "Wrong Module added"); + assert.equal(await I_CountTransferManagerFactory.getTitle.call(), + "Count Transfer Manager", + "Wrong Module added"); + assert.equal(await I_CountTransferManagerFactory.getInstructions.call(), + "Allows an issuer to restrict the total number of non-zero token holders", + "Wrong Module added"); + + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_CountTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Count"); + }); + }); + + }); + +}); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 5e918d99f..9f8f71984 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -1,963 +1,963 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol'); -// const ERC20DividendCheckpoint = artifacts.require('./ERC20DividendCheckpoint'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('ERC20DividendCheckpoint', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; -// let account_temp; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; -// let dividendName = "0x546573744469766964656e640000000000000000000000000000000000000000"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_GeneralTransferManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_ERC20DividendCheckpointFactory; -// let P_ERC20DividendCheckpointFactory; -// let P_ERC20DividendCheckpoint; -// let I_GeneralPermissionManager; -// let I_ERC20DividendCheckpoint; -// let I_GeneralTransferManager; -// let I_ExchangeTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_STRProxied; -// let I_MRProxied; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_STFactory; -// let I_SecurityToken; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; -// let snapId; -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; -// const checkpointKey = 4; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; - -// account_investor1 = accounts[6]; -// account_investor2 = accounts[7]; -// account_investor3 = accounts[8]; -// account_investor4 = accounts[9]; -// account_temp = accounts[2]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 6: Deploy the ERC20DividendCheckpoint -// P_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); -// assert.notEqual( -// P_ERC20DividendCheckpointFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "ERC20DividendCheckpointFactory contract was not deployed" -// ); - -// // STEP 7: Deploy the ERC20DividendCheckpoint -// I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); -// assert.notEqual( -// I_ERC20DividendCheckpointFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "ERC20DividendCheckpointFactory contract was not deployed" -// ); - -// // Step 9: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 10: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 11: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 12: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 8: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the ERC20DividendCheckpointFactory -// await I_MRProxied.registerModule(I_ERC20DividendCheckpointFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); - -// // (C) : Register the Paid ERC20DividendCheckpointFactory -// await I_MRProxied.registerModule(P_ERC20DividendCheckpointFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(P_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// ERC20DividendCheckpointFactory: ${I_ERC20DividendCheckpointFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); - -// it("Should successfully attach the ERC20DividendCheckpoint with the security token - fail insufficient payment", async () => { -// let errorThrown = false; -// try { -// const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx -> failed because Token is not paid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the ERC20DividendCheckpoint with the security token with budget", async () => { -// let snapId = await takeSnapshot() -// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); -// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); -// const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[3].args._name) -// .replace(/\u0000/g, ''), -// "ERC20DividendCheckpoint", -// "ERC20DividendCheckpoint module was not added" -// ); -// P_ERC20DividendCheckpoint = ERC20DividendCheckpoint.at(tx.logs[3].args._module); -// await revertToSnapshot(snapId); -// }); - -// it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { -// const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "ERC20DividendCheckpoint", -// "ERC20DividendCheckpoint module was not added" -// ); -// I_ERC20DividendCheckpoint = ERC20DividendCheckpoint.at(tx.logs[2].args._module); -// }); -// }); - -// describe("Check Dividend payouts", async() => { - -// it("Buy some tokens for account_investor1 (1 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(30), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(5000); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Buy some tokens for account_investor2 (2 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(30), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('2', 'ether') -// ); -// }); - -// it("Should fail in creating the dividend - incorrect allowance", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(10); -// await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); -// try { -// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because allowance = 0`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in creating the dividend - maturity > expiry", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() - duration.days(10); -// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('1.5', 'ether'), {from: token_owner}); -// try { -// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because maturity > expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in creating the dividend - now > expiry", async() => { -// let errorThrown = false; -// let maturity = latestTime() - duration.days(2); -// let expiry = latestTime() - duration.days(1); -// try { -// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because now > expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in creating the dividend - bad token", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(10); -// try { -// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, 0, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because token address is 0x`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in creating the dividend - amount is 0", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(10); -// try { -// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, 0, dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because amount < 0`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create new dividend of POLY tokens", async() => { -// let maturity = latestTime() + duration.days(1); -// let expiry = latestTime() + duration.days(10); - -// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); -// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 1, "Dividend should be created at checkpoint 1"); -// assert.equal(tx.logs[0].args._name.toString(), dividendName, "Dividend name incorrect in event"); -// }); - -// it("Investor 1 transfers his token balance to investor 2", async() => { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), {from: account_investor1}); -// assert.equal(await I_SecurityToken.balanceOf(account_investor1), 0); -// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('3', 'ether')); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails maturity in the future", async() => { -// let errorThrown = false; -// try { -// await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because dividend index has maturity in future`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails not owner", async() => { -// let errorThrown = false; -// // Increase time by 2 day -// await increaseTime(duration.days(2)); -// try { -// await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: account_temp}); -// } catch(error) { -// console.log(` tx -> failed because msg.sender is not the owner`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails wrong index", async() => { -// let errorThrown = false; -// try { -// await I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because dividend index is greator than the dividend array length`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { -// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner, gas: 5000000}); -// let investor1BalanceAfter = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2BalanceAfter = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// assert.equal(investor1BalanceAfter.sub(investor1Balance).toNumber(), web3.utils.toWei('0.5', 'ether')); -// assert.equal(investor2BalanceAfter.sub(investor2Balance).toNumber(), web3.utils.toWei('1', 'ether')); -// //Check fully claimed -// assert.equal((await I_ERC20DividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei('1.5', 'ether')); -// }); - -// it("Buy some tokens for account_temp (1 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_temp, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(20), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_temp.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_temp, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_temp)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Should not allow to create dividend without name", async() => { -// let maturity = latestTime() + duration.days(1); -// let expiry = latestTime() + duration.days(10); -// await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); -// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('1.5', 'ether'), {from: token_owner}); -// let errorThrown = false; -// try { -// await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), '', {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because dividend name is empty`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create new dividend", async() => { -// let maturity = latestTime() + duration.days(1); -// let expiry = latestTime() + duration.days(10); -// await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); -// // approved in above test -// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); -// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 1"); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails past expiry", async() => { -// let errorThrown = false; -// await increaseTime(duration.days(12)); -// try { -// await I_ERC20DividendCheckpoint.pushDividendPayment(1, 0, 10, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because dividend index has passed its expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoin - fails already reclaimed", async() => { -// let errorThrown = false; -// let tx = await I_ERC20DividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); -// assert.equal((tx.logs[0].args._claimedAmount).toNumber(), web3.utils.toWei("1.5", "ether")); -// try { -// await I_ERC20DividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); -// } catch(error) { -// console.log(` tx -> failed because dividend index has already reclaimed`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Buy some tokens for account_investor3 (7 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('7', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), -// web3.utils.toWei('7', 'ether') -// ); -// }); - -// it("Exclude account_temp using global exclusion list", async() => { -// await I_ERC20DividendCheckpoint.setDefaultExcluded([account_temp], {from: token_owner}); -// }); - -// it("Create another new dividend", async() => { -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(10); -// await I_PolyToken.getTokens(web3.utils.toWei('11', 'ether'), token_owner); -// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('11', 'ether'), {from: token_owner}); -// let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('10', 'ether'), dividendName, {from: token_owner}); -// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 2"); -// }); - -// it("should investor 3 claims dividend - fail bad index", async() => { -// let errorThrown = false; -// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// try { -// await I_ERC20DividendCheckpoint.pullDividendPayment(5, {from: account_investor3, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because dividend index is not valid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("should investor 3 claims dividend", async() => { -// console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); -// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// await I_ERC20DividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); -// let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); -// assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); -// assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei('7', 'ether')); -// }); - -// it("should investor 3 claims dividend - fails already claimed", async() => { -// let errorThrown = false; -// try { -// await I_ERC20DividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because investor already claimed the dividend`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("should issuer pushes remain", async() => { -// console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); -// let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// let investorTempBalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_temp)); -// await I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); -// let investor1BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// let investorTempBalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_temp)); -// assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); -// assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), web3.utils.toWei('3', 'ether')); -// assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); -// assert.equal(investorTempBalanceAfter2.sub(investorTempBalanceAfter1).toNumber(), 0); -// //Check fully claimed -// assert.equal((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei('10', 'ether')); -// }); - - -// it("Delete global exclusion list", async() => { -// await I_ERC20DividendCheckpoint.setDefaultExcluded([], {from: token_owner}); -// }); - - -// it("Investor 2 transfers 1 ETH of his token balance to investor 1", async() => { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_investor2}); -// assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); -// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); -// assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); -// assert.equal(await I_SecurityToken.balanceOf(account_temp), web3.utils.toWei('1', 'ether')); -// }); - -// it("Create another new dividend with explicit checkpoint - fails bad allowance", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(2); -// let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); -// console.log(JSON.stringify(tx.logs[0].args)); -// console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); -// await I_PolyToken.getTokens(web3.utils.toWei('20', 'ether'), token_owner); -// try { -// tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because allowance is not provided`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create another new dividend with explicit - fails maturity > expiry", async() => { -// console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); - -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() - duration.days(10); -// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('20', 'ether'), {from: token_owner}); -// try { -// tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because maturity > expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create another new dividend with explicit - fails now > expiry", async() => { -// console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); - -// let errorThrown = false; -// let maturity = latestTime() - duration.days(5); -// let expiry = latestTime() - duration.days(2); -// try { -// tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because now > expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create another new dividend with explicit - fails bad checkpoint", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(2); -// try { -// tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 5, dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because checkpoint id > current checkpoint`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Set withholding tax of 20% on account_temp and 10% on investor2", async() => { -// await I_ERC20DividendCheckpoint.setWithholding([account_temp, account_investor2], [BigNumber(20*10**16), BigNumber(10*10**16)], {from: token_owner}); -// }); - -// it("Create another new dividend with explicit checkpoint and exclusion", async() => { -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(10); -// await I_PolyToken.getTokens(web3.utils.toWei('11', 'ether'), token_owner); -// await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('11', 'ether'), {from: token_owner}); -// let tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, I_PolyToken.address, web3.utils.toWei('10', 'ether'), 4, [account_investor1], dividendName, {from: token_owner}); -// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 3"); -// }); - -// it("Investor 2 claims dividend, issuer pushes investor 1 - fails not owner", async() => { -// let errorThrown = false; -// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// try { -// await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(2, [account_investor2, account_investor1],{from: account_investor2, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because not called by the owner`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Investor 2 claims dividend, issuer pushes investor 1 - fails bad index", async() => { -// let errorThrown = false; -// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// try { -// await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(5, [account_investor2, account_investor1],{from: token_owner, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because dividend index is not valid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("should calculate dividend before the push dividend payment", async() => { -// let dividendAmount1 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor1); -// let dividendAmount2 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor2); -// let dividendAmount3 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor3); -// let dividendAmount_temp = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_temp); -// assert.equal(dividendAmount1[0].toNumber(), web3.utils.toWei("0", "ether")); -// assert.equal(dividendAmount2[0].toNumber(), web3.utils.toWei("2", "ether")); -// assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); -// assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); -// assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); -// assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.2", "ether")); -// assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); -// assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0.2", "ether")); -// }); - -// it("Investor 2 claims dividend", async() => { -// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// let tempBalance = BigNumber(await web3.eth.getBalance(account_temp)); -// await I_ERC20DividendCheckpoint.pullDividendPayment(3, {from: account_investor2, gasPrice: 0}); -// let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); -// assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); -// assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei('1.8', 'ether')); -// assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); -// assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); -// }); - -// it("Should issuer pushes temp investor - investor1 excluded", async() => { -// let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// let tempBalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_temp)); -// await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(3, [account_temp, account_investor1], {from: token_owner}); -// let investor1BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// let tempBalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_temp)); -// assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); -// assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), 0); -// assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); -// assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toNumber(), web3.utils.toWei('0.8', 'ether')); -// //Check fully claimed -// assert.equal((await I_ERC20DividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei('3', 'ether')); -// }); - -// it("should calculate dividend after the push dividend payment", async() => { -// let dividendAmount1 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor1); -// let dividendAmount2 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor2); -// assert.equal(dividendAmount1[0].toNumber(), 0); -// assert.equal(dividendAmount2[0].toNumber(), 0); -// }); - -// it("Issuer reclaims withholding tax", async() => { -// let issuerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); -// await I_ERC20DividendCheckpoint.withdrawWithholding(3, {from: token_owner, gasPrice: 0}); -// let issuerBalanceAfter = BigNumber(await I_PolyToken.balanceOf(token_owner)); -// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.4', 'ether')) -// }); - -// it("Issuer unable to reclaim dividend (expiry not passed)", async() => { -// let errorThrown = false; -// try { -// await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner}); -// } catch(error) { -// console.log(`Tx Failed because expiry is in the future ${0}. Test Passed Successfully`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer is able to reclaim dividend after expiry", async() => { -// let errorThrown = false; -// await increaseTime(11 * 24 * 60 * 60); -// try { -// await I_ERC20DividendCheckpoint.reclaimDividend(8, {from: token_owner, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because dividend index is not valid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer is able to reclaim dividend after expiry", async() => { -// let tokenOwnerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); -// await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); -// let tokenOwnerAfter = BigNumber(await I_PolyToken.balanceOf(token_owner)); -// assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei('7', 'ether')); -// }); - - -// it("Issuer is able to reclaim dividend after expiry", async() => { -// let errorThrown = false; -// let tokenOwnerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); -// try { -// await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because dividend are already reclaimed`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Investor 3 unable to pull dividend after expiry", async() => { -// let errorThrown = false; -// try { -// await I_ERC20DividendCheckpoint.pullDividendPayment(3, {from: account_investor3, gasPrice: 0}); -// } catch(error) { -// console.log(`Tx Failed because expiry is in the past ${0}. Test Passed Successfully`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Should give the right dividend index", async() => { -// let index = await I_ERC20DividendCheckpoint.getDividendIndex.call(3); -// assert.equal(index[0], 2); -// }); - -// it("Should give the right dividend index", async() => { -// let index = await I_ERC20DividendCheckpoint.getDividendIndex.call(8); -// assert.equal(index.length, 0); -// }); - -// it("Get the init data", async() => { -// let tx = await I_ERC20DividendCheckpoint.getInitFunction.call(); -// assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); -// }); - -// it("Should get the listed permissions", async() => { -// let tx = await I_ERC20DividendCheckpoint.getPermissions.call(); -// assert.equal(tx.length,1); -// }); - -// describe("Test cases for the ERC20DividendCheckpointFactory", async() => { -// it("should get the exact details of the factory", async() => { -// assert.equal((await I_ERC20DividendCheckpointFactory.setupCost.call()).toNumber(), 0); -// assert.equal((await I_ERC20DividendCheckpointFactory.getTypes.call())[0], 4); -// assert.equal(web3.utils.toAscii(await I_ERC20DividendCheckpointFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "ERC20DividendCheckpoint", -// "Wrong Module added"); -// assert.equal(await I_ERC20DividendCheckpointFactory.getDescription.call(), -// "Create ERC20 dividends for token holders at a specific checkpoint", -// "Wrong Module added"); -// assert.equal(await I_ERC20DividendCheckpointFactory.getTitle.call(), -// "ERC20 Dividend Checkpoint", -// "Wrong Module added"); -// assert.equal(await I_ERC20DividendCheckpointFactory.getInstructions.call(), -// "Create a ERC20 dividend which will be paid out to token holders proportional to their balances at the point the dividend is created", -// "Wrong Module added"); -// let tags = await I_ERC20DividendCheckpointFactory.getTags.call(); -// assert.equal(tags.length, 3); - -// }); -// }); - -// }); - -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol'); +const ERC20DividendCheckpoint = artifacts.require('./ERC20DividendCheckpoint'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('ERC20DividendCheckpoint', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_temp; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + let dividendName = "0x546573744469766964656e640000000000000000000000000000000000000000"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_ERC20DividendCheckpointFactory; + let P_ERC20DividendCheckpointFactory; + let P_ERC20DividendCheckpoint; + let I_GeneralPermissionManager; + let I_ERC20DividendCheckpoint; + let I_GeneralTransferManager; + let I_ExchangeTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_STRProxied; + let I_MRProxied; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + let snapId; + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + const checkpointKey = 4; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[6]; + account_investor2 = accounts[7]; + account_investor3 = accounts[8]; + account_investor4 = accounts[9]; + account_temp = accounts[2]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 6: Deploy the ERC20DividendCheckpoint + P_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); + assert.notEqual( + P_ERC20DividendCheckpointFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "ERC20DividendCheckpointFactory contract was not deployed" + ); + + // STEP 7: Deploy the ERC20DividendCheckpoint + I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + assert.notEqual( + I_ERC20DividendCheckpointFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "ERC20DividendCheckpointFactory contract was not deployed" + ); + + // Step 9: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 10: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 11: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 12: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 8: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the ERC20DividendCheckpointFactory + await I_MRProxied.registerModule(I_ERC20DividendCheckpointFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); + + // (C) : Register the Paid ERC20DividendCheckpointFactory + await I_MRProxied.registerModule(P_ERC20DividendCheckpointFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + ERC20DividendCheckpointFactory: ${I_ERC20DividendCheckpointFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + it("Should successfully attach the ERC20DividendCheckpoint with the security token - fail insufficient payment", async () => { + let errorThrown = false; + try { + const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + } catch(error) { + console.log(` tx -> failed because Token is not paid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the ERC20DividendCheckpoint with the security token with budget", async () => { + let snapId = await takeSnapshot() + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "ERC20DividendCheckpoint", + "ERC20DividendCheckpoint module was not added" + ); + P_ERC20DividendCheckpoint = ERC20DividendCheckpoint.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "ERC20DividendCheckpoint", + "ERC20DividendCheckpoint module was not added" + ); + I_ERC20DividendCheckpoint = ERC20DividendCheckpoint.at(tx.logs[2].args._module); + }); + }); + + describe("Check Dividend payouts", async() => { + + it("Buy some tokens for account_investor1 (1 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(30), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Buy some tokens for account_investor2 (2 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(30), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should fail in creating the dividend - incorrect allowance", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() + duration.days(10); + await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); + try { + let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because allowance = 0`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail in creating the dividend - maturity > expiry", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() - duration.days(10); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('1.5', 'ether'), {from: token_owner}); + try { + let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because maturity > expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail in creating the dividend - now > expiry", async() => { + let errorThrown = false; + let maturity = latestTime() - duration.days(2); + let expiry = latestTime() - duration.days(1); + try { + let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because now > expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail in creating the dividend - bad token", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() + duration.days(10); + try { + let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, 0, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because token address is 0x`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail in creating the dividend - amount is 0", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() + duration.days(10); + try { + let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, 0, dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because amount < 0`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create new dividend of POLY tokens", async() => { + let maturity = latestTime() + duration.days(1); + let expiry = latestTime() + duration.days(10); + + let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 1, "Dividend should be created at checkpoint 1"); + assert.equal(tx.logs[0].args._name.toString(), dividendName, "Dividend name incorrect in event"); + }); + + it("Investor 1 transfers his token balance to investor 2", async() => { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), {from: account_investor1}); + assert.equal(await I_SecurityToken.balanceOf(account_investor1), 0); + assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('3', 'ether')); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails maturity in the future", async() => { + let errorThrown = false; + try { + await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because dividend index has maturity in future`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails not owner", async() => { + let errorThrown = false; + // Increase time by 2 day + await increaseTime(duration.days(2)); + try { + await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: account_temp}); + } catch(error) { + console.log(` tx -> failed because msg.sender is not the owner`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails wrong index", async() => { + let errorThrown = false; + try { + await I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because dividend index is greator than the dividend array length`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { + let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner, gas: 5000000}); + let investor1BalanceAfter = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + assert.equal(investor1BalanceAfter.sub(investor1Balance).toNumber(), web3.utils.toWei('0.5', 'ether')); + assert.equal(investor2BalanceAfter.sub(investor2Balance).toNumber(), web3.utils.toWei('1', 'ether')); + //Check fully claimed + assert.equal((await I_ERC20DividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei('1.5', 'ether')); + }); + + it("Buy some tokens for account_temp (1 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_temp, + latestTime(), + latestTime(), + latestTime() + duration.days(20), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_temp.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_temp, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_temp)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should not allow to create dividend without name", async() => { + let maturity = latestTime() + duration.days(1); + let expiry = latestTime() + duration.days(10); + await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('1.5', 'ether'), {from: token_owner}); + let errorThrown = false; + try { + await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), '', {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because dividend name is empty`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create new dividend", async() => { + let maturity = latestTime() + duration.days(1); + let expiry = latestTime() + duration.days(10); + await I_PolyToken.getTokens(web3.utils.toWei('1.5', 'ether'), token_owner); + // approved in above test + let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('1.5', 'ether'), dividendName, {from: token_owner}); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 1"); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails past expiry", async() => { + let errorThrown = false; + await increaseTime(duration.days(12)); + try { + await I_ERC20DividendCheckpoint.pushDividendPayment(1, 0, 10, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because dividend index has passed its expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoin - fails already reclaimed", async() => { + let errorThrown = false; + let tx = await I_ERC20DividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); + assert.equal((tx.logs[0].args._claimedAmount).toNumber(), web3.utils.toWei("1.5", "ether")); + try { + await I_ERC20DividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); + } catch(error) { + console.log(` tx -> failed because dividend index has already reclaimed`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Buy some tokens for account_investor3 (7 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('7', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('7', 'ether') + ); + }); + + it("Exclude account_temp using global exclusion list", async() => { + await I_ERC20DividendCheckpoint.setDefaultExcluded([account_temp], {from: token_owner}); + }); + + it("Create another new dividend", async() => { + let maturity = latestTime(); + let expiry = latestTime() + duration.days(10); + await I_PolyToken.getTokens(web3.utils.toWei('11', 'ether'), token_owner); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('11', 'ether'), {from: token_owner}); + let tx = await I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei('10', 'ether'), dividendName, {from: token_owner}); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 2"); + }); + + it("should investor 3 claims dividend - fail bad index", async() => { + let errorThrown = false; + let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + try { + await I_ERC20DividendCheckpoint.pullDividendPayment(5, {from: account_investor3, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because dividend index is not valid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("should investor 3 claims dividend", async() => { + console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); + let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + await I_ERC20DividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); + let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); + assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); + assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei('7', 'ether')); + }); + + it("should investor 3 claims dividend - fails already claimed", async() => { + let errorThrown = false; + try { + await I_ERC20DividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because investor already claimed the dividend`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("should issuer pushes remain", async() => { + console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); + let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let investorTempBalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_temp)); + await I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); + let investor1BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let investorTempBalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_temp)); + assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); + assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), web3.utils.toWei('3', 'ether')); + assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); + assert.equal(investorTempBalanceAfter2.sub(investorTempBalanceAfter1).toNumber(), 0); + //Check fully claimed + assert.equal((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei('10', 'ether')); + }); + + + it("Delete global exclusion list", async() => { + await I_ERC20DividendCheckpoint.setDefaultExcluded([], {from: token_owner}); + }); + + + it("Investor 2 transfers 1 ETH of his token balance to investor 1", async() => { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_investor2}); + assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); + assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); + assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); + assert.equal(await I_SecurityToken.balanceOf(account_temp), web3.utils.toWei('1', 'ether')); + }); + + it("Create another new dividend with explicit checkpoint - fails bad allowance", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() + duration.days(2); + let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); + console.log(JSON.stringify(tx.logs[0].args)); + console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); + await I_PolyToken.getTokens(web3.utils.toWei('20', 'ether'), token_owner); + try { + tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because allowance is not provided`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create another new dividend with explicit - fails maturity > expiry", async() => { + console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); + + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() - duration.days(10); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('20', 'ether'), {from: token_owner}); + try { + tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because maturity > expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create another new dividend with explicit - fails now > expiry", async() => { + console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); + + let errorThrown = false; + let maturity = latestTime() - duration.days(5); + let expiry = latestTime() - duration.days(2); + try { + tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 4, dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because now > expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create another new dividend with explicit - fails bad checkpoint", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() + duration.days(2); + try { + tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, I_PolyToken.address, web3.utils.toWei('20', 'ether'), 5, dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because checkpoint id > current checkpoint`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Set withholding tax of 20% on account_temp and 10% on investor2", async() => { + await I_ERC20DividendCheckpoint.setWithholding([account_temp, account_investor2], [BigNumber(20*10**16), BigNumber(10*10**16)], {from: token_owner}); + }); + + it("Create another new dividend with explicit checkpoint and exclusion", async() => { + let maturity = latestTime(); + let expiry = latestTime() + duration.days(10); + await I_PolyToken.getTokens(web3.utils.toWei('11', 'ether'), token_owner); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei('11', 'ether'), {from: token_owner}); + let tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, I_PolyToken.address, web3.utils.toWei('10', 'ether'), 4, [account_investor1], dividendName, {from: token_owner}); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 3"); + }); + + it("Investor 2 claims dividend, issuer pushes investor 1 - fails not owner", async() => { + let errorThrown = false; + let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + try { + await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(2, [account_investor2, account_investor1],{from: account_investor2, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because not called by the owner`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Investor 2 claims dividend, issuer pushes investor 1 - fails bad index", async() => { + let errorThrown = false; + let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + try { + await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(5, [account_investor2, account_investor1],{from: token_owner, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because dividend index is not valid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("should calculate dividend before the push dividend payment", async() => { + let dividendAmount1 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor1); + let dividendAmount2 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor2); + let dividendAmount3 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor3); + let dividendAmount_temp = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_temp); + assert.equal(dividendAmount1[0].toNumber(), web3.utils.toWei("0", "ether")); + assert.equal(dividendAmount2[0].toNumber(), web3.utils.toWei("2", "ether")); + assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); + assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); + assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); + assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.2", "ether")); + assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); + assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0.2", "ether")); + }); + + it("Investor 2 claims dividend", async() => { + let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let tempBalance = BigNumber(await web3.eth.getBalance(account_temp)); + await I_ERC20DividendCheckpoint.pullDividendPayment(3, {from: account_investor2, gasPrice: 0}); + let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); + assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); + assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei('1.8', 'ether')); + assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); + assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); + }); + + it("Should issuer pushes temp investor - investor1 excluded", async() => { + let investor1BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let tempBalanceAfter1 = BigNumber(await I_PolyToken.balanceOf(account_temp)); + await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(3, [account_temp, account_investor1], {from: token_owner}); + let investor1BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let tempBalanceAfter2 = BigNumber(await I_PolyToken.balanceOf(account_temp)); + assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); + assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), 0); + assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); + assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toNumber(), web3.utils.toWei('0.8', 'ether')); + //Check fully claimed + assert.equal((await I_ERC20DividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei('3', 'ether')); + }); + + it("should calculate dividend after the push dividend payment", async() => { + let dividendAmount1 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor1); + let dividendAmount2 = await I_ERC20DividendCheckpoint.calculateDividend.call(3, account_investor2); + assert.equal(dividendAmount1[0].toNumber(), 0); + assert.equal(dividendAmount2[0].toNumber(), 0); + }); + + it("Issuer reclaims withholding tax", async() => { + let issuerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); + await I_ERC20DividendCheckpoint.withdrawWithholding(3, {from: token_owner, gasPrice: 0}); + let issuerBalanceAfter = BigNumber(await I_PolyToken.balanceOf(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.4', 'ether')) + }); + + it("Issuer unable to reclaim dividend (expiry not passed)", async() => { + let errorThrown = false; + try { + await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner}); + } catch(error) { + console.log(`Tx Failed because expiry is in the future ${0}. Test Passed Successfully`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Issuer is able to reclaim dividend after expiry", async() => { + let errorThrown = false; + await increaseTime(11 * 24 * 60 * 60); + try { + await I_ERC20DividendCheckpoint.reclaimDividend(8, {from: token_owner, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because dividend index is not valid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer is able to reclaim dividend after expiry", async() => { + let tokenOwnerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); + await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); + let tokenOwnerAfter = BigNumber(await I_PolyToken.balanceOf(token_owner)); + assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei('7', 'ether')); + }); + + + it("Issuer is able to reclaim dividend after expiry", async() => { + let errorThrown = false; + let tokenOwnerBalance = BigNumber(await I_PolyToken.balanceOf(token_owner)); + try { + await I_ERC20DividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because dividend are already reclaimed`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Investor 3 unable to pull dividend after expiry", async() => { + let errorThrown = false; + try { + await I_ERC20DividendCheckpoint.pullDividendPayment(3, {from: account_investor3, gasPrice: 0}); + } catch(error) { + console.log(`Tx Failed because expiry is in the past ${0}. Test Passed Successfully`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + + }); + + it("Should give the right dividend index", async() => { + let index = await I_ERC20DividendCheckpoint.getDividendIndex.call(3); + assert.equal(index[0], 2); + }); + + it("Should give the right dividend index", async() => { + let index = await I_ERC20DividendCheckpoint.getDividendIndex.call(8); + assert.equal(index.length, 0); + }); + + it("Get the init data", async() => { + let tx = await I_ERC20DividendCheckpoint.getInitFunction.call(); + assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); + }); + + it("Should get the listed permissions", async() => { + let tx = await I_ERC20DividendCheckpoint.getPermissions.call(); + assert.equal(tx.length,1); + }); + + describe("Test cases for the ERC20DividendCheckpointFactory", async() => { + it("should get the exact details of the factory", async() => { + assert.equal((await I_ERC20DividendCheckpointFactory.setupCost.call()).toNumber(), 0); + assert.equal((await I_ERC20DividendCheckpointFactory.getTypes.call())[0], 4); + assert.equal(web3.utils.toAscii(await I_ERC20DividendCheckpointFactory.getName.call()) + .replace(/\u0000/g, ''), + "ERC20DividendCheckpoint", + "Wrong Module added"); + assert.equal(await I_ERC20DividendCheckpointFactory.getDescription.call(), + "Create ERC20 dividends for token holders at a specific checkpoint", + "Wrong Module added"); + assert.equal(await I_ERC20DividendCheckpointFactory.getTitle.call(), + "ERC20 Dividend Checkpoint", + "Wrong Module added"); + assert.equal(await I_ERC20DividendCheckpointFactory.getInstructions.call(), + "Create a ERC20 dividend which will be paid out to token holders proportional to their balances at the point the dividend is created", + "Wrong Module added"); + let tags = await I_ERC20DividendCheckpointFactory.getTags.call(); + assert.equal(tags.length, 3); + + }); + }); + + }); + +}); diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 18cd0b39e..b65a8f7c1 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -1,983 +1,983 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol'); -// const EtherDividendCheckpoint = artifacts.require('./EtherDividendCheckpoint'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('EtherDividendCheckpoint', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; -// let account_temp; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; -// let dividendName = "0x546573744469766964656e640000000000000000000000000000000000000000"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let P_EtherDividendCheckpointFactory; -// let P_EtherDividendCheckpoint; -// let I_EtherDividendCheckpointFactory; -// let I_GeneralPermissionManager; -// let I_EtherDividendCheckpoint; -// let I_GeneralTransferManager; -// let I_ExchangeTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_STRProxied; -// let I_STFactory; -// let I_SecurityToken; -// let I_PolyToken; -// let I_MRProxied; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; -// let snapId; -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; -// const checkpointKey = 4; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; - -// account_investor1 = accounts[6]; -// account_investor2 = accounts[7]; -// account_investor3 = accounts[8]; -// account_investor4 = accounts[9]; -// account_temp = accounts[2]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the ERC20DividendCheckpoint -// P_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); -// assert.notEqual( -// P_EtherDividendCheckpointFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "ERC20DividendCheckpointFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the EtherDividendCheckpoint -// I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); -// assert.notEqual( -// I_EtherDividendCheckpointFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "EtherDividendCheckpointFactory contract was not deployed" -// ); - -// // Step 6: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 7: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 8: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 9: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 5: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the EtherDividendCheckpointFactory -// await I_MRProxied.registerModule(I_EtherDividendCheckpointFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); - -// // (C) : Register the Paid EtherDividendCheckpointFactory -// await I_MRProxied.registerModule(P_EtherDividendCheckpointFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(P_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// EtherDividendCheckpointFactory: ${I_EtherDividendCheckpointFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); - -// it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { -// let errorThrown = false; -// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); -// try { -// const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx -> failed because Token is not paid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { -// let snapId = await takeSnapshot(); -// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); -// const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[3].args._name) -// .replace(/\u0000/g, ''), -// "EtherDividendCheckpoint", -// "EtherDividendCheckpoint module was not added" -// ); -// P_EtherDividendCheckpoint = EtherDividendCheckpoint.at(tx.logs[3].args._module); -// await revertToSnapshot(snapId); -// }); - -// it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { -// const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "EtherDividendCheckpoint", -// "EtherDividendCheckpoint module was not added" -// ); -// I_EtherDividendCheckpoint = EtherDividendCheckpoint.at(tx.logs[2].args._module); -// }); -// }); - -// describe("Check Dividend payouts", async() => { - -// it("Buy some tokens for account_investor1 (1 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(30), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(5000); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Buy some tokens for account_investor2 (2 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(30), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('2', 'ether') -// ); -// }); - -// it("Should fail in creating the dividend", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(10); -// try { -// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because msg.value = 0`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in creating the dividend", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() - duration.days(10); -// try { -// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); -// } catch(error) { -// console.log(` tx -> failed because maturity > expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in creating the dividend", async() => { -// let errorThrown = false; -// let maturity = latestTime() - duration.days(2); -// let expiry = latestTime() - duration.days(1); -// try { -// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); -// } catch(error) { -// console.log(` tx -> failed because now > expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Set withholding tax of 20% on investor 2", async() => { -// await I_EtherDividendCheckpoint.setWithholdingFixed([account_investor2], BigNumber(20*10**16), {from: token_owner}); -// }); - -// it("Should fail in creating the dividend", async() => { -// let errorThrown = false; -// let maturity = latestTime() + duration.days(1); -// let expiry = latestTime() + duration.days(10); -// try { -// await I_EtherDividendCheckpoint.createDividend(maturity, expiry, '', {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); -// } catch(error) { -// console.log(` tx -> failed because dividend name is empty`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create new dividend", async() => { -// let maturity = latestTime() + duration.days(1); -// let expiry = latestTime() + duration.days(10); -// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); -// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 1, "Dividend should be created at checkpoint 1"); -// assert.equal(tx.logs[0].args._name.toString(), dividendName, "Dividend name incorrect in event"); -// }); - -// it("Investor 1 transfers his token balance to investor 2", async() => { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), {from: account_investor1}); -// assert.equal(await I_SecurityToken.balanceOf(account_investor1), 0); -// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('3', 'ether')); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { -// let errorThrown = false; -// try { -// await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because dividend index has maturity in future`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { -// let errorThrown = false; -// // Increase time by 2 day -// await increaseTime(duration.days(2)); -// try { -// await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: account_temp}); -// } catch(error) { -// console.log(` tx -> failed because msg.sender is not the owner`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { -// let errorThrown = false; -// try { -// await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because dividend index is greator than the dividend array length`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { -// let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); -// await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); -// let investor1BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor2)); -// assert.equal(investor1BalanceAfter.sub(investor1Balance).toNumber(), web3.utils.toWei('0.5', 'ether')); -// assert.equal(investor2BalanceAfter.sub(investor2Balance).toNumber(), web3.utils.toWei('0.8', 'ether')); -// //Check fully claimed -// assert.equal((await I_EtherDividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei('1.5', 'ether')); -// }); - -// it("Issuer reclaims withholding tax", async() => { -// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); -// await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); -// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); -// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.2', 'ether')) -// }); - -// it("No more withholding tax to withdraw", async() => { -// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); -// await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); -// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); -// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) -// }); - -// it("Buy some tokens for account_temp (1 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_temp, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(20), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_temp.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_temp, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_temp)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Create new dividend", async() => { -// let maturity = latestTime() + duration.days(1); -// let expiry = latestTime() + duration.days(10); -// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); -// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 2"); -// }); - -// it("Issuer pushes dividends fails due to passed expiry", async() => { -// let errorThrown = false; -// await increaseTime(duration.days(12)); -// try { -// await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); -// } catch(error) { -// console.log(` tx -> failed because dividend index has passed its expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer reclaims dividend", async() => { -// let errorThrown = false; -// let tx = await I_EtherDividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); -// assert.equal((tx.logs[0].args._claimedAmount).toNumber(), web3.utils.toWei("1.5", "ether")); -// try { -// await I_EtherDividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); -// } catch(error) { -// console.log(` tx -> failed because dividend index has already reclaimed`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Still no more withholding tax to withdraw", async() => { -// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); -// await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); -// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); -// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) -// }); - -// it("Buy some tokens for account_investor3 (7 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('7', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), -// web3.utils.toWei('7', 'ether') -// ); -// }); - -// it("Create another new dividend", async() => { -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(10); -// let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); -// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 3"); -// }); - -// it("should investor 3 claims dividend - fails bad index", async() => { -// let errorThrown = false; -// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// try { -// await I_EtherDividendCheckpoint.pullDividendPayment(5, {from: account_investor3, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because dividend index is not valid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should investor 3 claims dividend", async() => { -// let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3Balance = BigNumber(await web3.eth.getBalance(account_investor3)); -// await I_EtherDividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); -// let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); -// assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); -// assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); -// assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei('7', 'ether')); -// }); - -// it("Still no more withholding tax to withdraw", async() => { -// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); -// await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); -// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); -// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) -// }); - -// it("should investor 3 claims dividend", async() => { -// let errorThrown = false; -// try { -// await I_EtherDividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because investor already claimed the dividend`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer pushes remainder", async() => { -// let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); -// await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); -// let investor1BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor3)); -// assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); -// assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), web3.utils.toWei('2.4', 'ether')); -// assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); -// //Check fully claimed -// assert.equal((await I_EtherDividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei('11', 'ether')); -// }); - -// it("Issuer withdraws new withholding tax", async() => { -// let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); -// await I_EtherDividendCheckpoint.withdrawWithholding(2, {from: token_owner, gasPrice: 0}); -// let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); -// assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.6', 'ether')) -// }); - -// it("Investor 2 transfers 1 ETH of his token balance to investor 1", async() => { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_investor2}); -// assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); -// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); -// assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); -// }); - -// it("Create another new dividend with no value - fails", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(2); -// let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); -// try { -// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: 0}); -// } catch(error) { -// console.log(` tx -> failed because msg.value is 0`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create another new dividend with explicit", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() - duration.days(10); -// try { -// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); -// } catch(error) { -// console.log(` tx -> failed because maturity > expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create another new dividend with bad expirty - fails", async() => { -// let errorThrown = false; -// let maturity = latestTime() - duration.days(5); -// let expiry = latestTime() - duration.days(2); -// try { -// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); -// } catch(error) { -// console.log(` tx -> failed because now > expiry`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create another new dividend with bad checkpoint in the future - fails", async() => { -// let errorThrown = false; -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(2); -// try { -// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 5, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); -// } catch(error) { -// console.log(` tx -> failed because checkpoint id > current checkpoint`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Create another new dividend with explicit checkpoint and excluding account_investor1", async() => { -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(10); -// let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); -// tx = await I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, 4, [account_investor1], dividendName, {from: token_owner, value: web3.utils.toWei('10', 'ether')}); -// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 4"); -// }); - -// it("Non-owner pushes investor 1 - fails", async() => { -// let errorThrown = false; -// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// try { -// await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor2, account_investor1],{from: account_investor2, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because not called by the owner`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("issuer pushes investor 1 with bad dividend index - fails", async() => { -// let errorThrown = false; -// let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); -// let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); -// let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); -// try { -// await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(6, [account_investor2, account_investor1],{from: token_owner, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because dividend index is not valid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("should calculate dividend before the push dividend payment", async() => { -// let dividendAmount1 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor1); -// let dividendAmount2 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor2); -// let dividendAmount3 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor3); -// let dividendAmount_temp = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_temp); -// //1 has 1/11th, 2 has 2/11th, 3 has 7/11th, temp has 1/11th, but 1 is excluded -// assert.equal(dividendAmount1[0].toNumber(), web3.utils.toWei("0", "ether")); -// assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); -// assert.equal(dividendAmount2[0].toNumber(), web3.utils.toWei("2", "ether")); -// assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.4", "ether")); -// assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); -// assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); -// assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); -// assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0", "ether")); -// }); - -// it("Investor 2 claims dividend", async() => { -// let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3Balance = BigNumber(await web3.eth.getBalance(account_investor3)); -// let tempBalance = BigNumber(await web3.eth.getBalance(account_temp)); -// await I_EtherDividendCheckpoint.pullDividendPayment(3, {from: account_investor2, gasPrice: 0}); -// let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); -// let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); -// assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); -// assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei('1.6', 'ether')); -// assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); -// assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); -// }); - -// it("Should issuer pushes investor 1 and temp investor", async() => { -// let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); -// let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); -// await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor1, account_temp], {from: token_owner}); -// let investor1BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor3)); -// let tempBalanceAfter2 = BigNumber(await web3.eth.getBalance(account_temp)); -// assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); -// assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), 0); -// assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); -// assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toNumber(), web3.utils.toWei('1', 'ether')); -// //Check fully claimed -// assert.equal((await I_EtherDividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei('3', 'ether')); -// }); - -// it("should calculate dividend after the push dividend payment", async() => { -// let dividendAmount1 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor1); -// let dividendAmount2 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor2); -// assert.equal(dividendAmount1[0].toNumber(), 0); -// assert.equal(dividendAmount2[0].toNumber(), 0); -// }); - -// it("Issuer unable to reclaim dividend (expiry not passed)", async() => { -// let errorThrown = false; -// try { -// await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner}); -// } catch(error) { -// console.log(`Tx Failed because expiry is in the future ${0}. Test Passed Successfully`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer is able to reclaim dividend after expiry", async() => { -// let errorThrown = false; -// await increaseTime(11 * 24 * 60 * 60); -// try { -// await I_EtherDividendCheckpoint.reclaimDividend(8, {from: token_owner, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because dividend index is not valid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Issuer is able to reclaim dividend after expiry", async() => { -// let tokenOwnerBalance = BigNumber(await web3.eth.getBalance(token_owner)); -// await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); -// let tokenOwnerAfter = BigNumber(await web3.eth.getBalance(token_owner)); -// assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei('7', 'ether')); -// }); - -// it("Issuer is able to reclaim dividend after expiry", async() => { -// let errorThrown = false; -// try { -// await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); -// } catch(error) { -// console.log(` tx -> failed because dividend are already reclaimed`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Investor 3 unable to pull dividend after expiry", async() => { -// let errorThrown = false; -// try { -// await I_EtherDividendCheckpoint.pullDividendPayment(3, {from: account_investor3, gasPrice: 0}); -// } catch(error) { -// console.log(`Tx Failed because expiry is in the past ${0}. Test Passed Successfully`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Assign token balance to an address that can't receive funds", async() => { - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// I_PolyToken.address, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); -// // Jump time -// await increaseTime(5000); -// // Mint some tokens -// await I_SecurityToken.mint(I_PolyToken.address, web3.utils.toWei('1', 'ether'), { from: token_owner }); -// assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); -// assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); -// assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); -// assert.equal(await I_SecurityToken.balanceOf(account_temp), web3.utils.toWei('1', 'ether')); -// assert.equal(await I_SecurityToken.balanceOf(I_PolyToken.address), web3.utils.toWei('1', 'ether')); -// }); - -// it("Create another new dividend", async() => { -// let maturity = latestTime(); -// let expiry = latestTime() + duration.days(10); -// let tx = await I_EtherDividendCheckpoint.createDividendWithExclusions(maturity, expiry, [], dividendName, {from: token_owner, value: web3.utils.toWei('12', 'ether')}); -// assert.equal(tx.logs[0].args._checkpointId.toNumber(), 6, "Dividend should be created at checkpoint 6"); -// }); - -// it("Should issuer pushes all dividends", async() => { -// let investor1BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor3)); -// let tempBalanceBefore = BigNumber(await web3.eth.getBalance(account_temp)); -// let tokenBalanceBefore = BigNumber(await web3.eth.getBalance(I_PolyToken.address)); - -// await I_EtherDividendCheckpoint.pushDividendPayment(4, 0, 10, {from: token_owner}); - -// let investor1BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor1)); -// let investor2BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor2)); -// let investor3BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor3)); -// let tempBalanceAfter = BigNumber(await web3.eth.getBalance(account_temp)); -// let tokenBalanceAfter = BigNumber(await web3.eth.getBalance(I_PolyToken.address)); - -// assert.equal(investor1BalanceAfter.sub(investor1BalanceBefore).toNumber(), web3.utils.toWei('1', 'ether')); -// assert.equal(investor2BalanceAfter.sub(investor2BalanceBefore).toNumber(), web3.utils.toWei('1.6', 'ether')); -// assert.equal(investor3BalanceAfter.sub(investor3BalanceBefore).toNumber(), web3.utils.toWei('7', 'ether')); -// assert.equal(tempBalanceAfter.sub(tempBalanceBefore).toNumber(), web3.utils.toWei('1', 'ether')); -// assert.equal(tokenBalanceAfter.sub(tokenBalanceBefore).toNumber(), web3.utils.toWei('0', 'ether')); - -// //Check partially claimed -// assert.equal((await I_EtherDividendCheckpoint.dividends(4))[5].toNumber(), web3.utils.toWei('11', 'ether')); -// }); - -// it("Should give the right dividend index", async() => { -// let index = await I_EtherDividendCheckpoint.getDividendIndex.call(3); -// assert.equal(index[0], 2); -// }); - -// it("Should give the right dividend index", async() => { -// let index = await I_EtherDividendCheckpoint.getDividendIndex.call(8); -// assert.equal(index.length, 0); -// }); - -// it("Get the init data", async() => { -// let tx = await I_EtherDividendCheckpoint.getInitFunction.call(); -// assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); -// }); - -// it("Should get the listed permissions", async() => { -// let tx = await I_EtherDividendCheckpoint.getPermissions.call(); -// assert.equal(tx.length,1); -// }); - -// describe("Test cases for the EtherDividendCheckpointFactory", async() => { -// it("should get the exact details of the factory", async() => { -// assert.equal((await I_EtherDividendCheckpointFactory.setupCost.call()).toNumber(), 0); -// assert.equal((await I_EtherDividendCheckpointFactory.getTypes.call())[0], 4); -// assert.equal(web3.utils.toAscii(await I_EtherDividendCheckpointFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "EtherDividendCheckpoint", -// "Wrong Module added"); -// assert.equal(await I_EtherDividendCheckpointFactory.getDescription.call(), -// "Create ETH dividends for token holders at a specific checkpoint", -// "Wrong Module added"); -// assert.equal(await I_EtherDividendCheckpointFactory.getTitle.call(), -// "Ether Dividend Checkpoint", -// "Wrong Module added"); -// assert.equal(await I_EtherDividendCheckpointFactory.getInstructions.call(), -// "Create a dividend which will be paid out to token holders proportional to their balances at the point the dividend is created", -// "Wrong Module added"); -// let tags = await I_EtherDividendCheckpointFactory.getTags.call(); -// assert.equal(tags.length, 3); - -// }); -// }); - -// }); - -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol'); +const EtherDividendCheckpoint = artifacts.require('./EtherDividendCheckpoint'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('EtherDividendCheckpoint', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_temp; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + let dividendName = "0x546573744469766964656e640000000000000000000000000000000000000000"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let P_EtherDividendCheckpointFactory; + let P_EtherDividendCheckpoint; + let I_EtherDividendCheckpointFactory; + let I_GeneralPermissionManager; + let I_EtherDividendCheckpoint; + let I_GeneralTransferManager; + let I_ExchangeTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_MRProxied; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + let snapId; + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + const checkpointKey = 4; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[6]; + account_investor2 = accounts[7]; + account_investor3 = accounts[8]; + account_investor4 = accounts[9]; + account_temp = accounts[2]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 4: Deploy the ERC20DividendCheckpoint + P_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); + assert.notEqual( + P_EtherDividendCheckpointFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "ERC20DividendCheckpointFactory contract was not deployed" + ); + + // STEP 4: Deploy the EtherDividendCheckpoint + I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + assert.notEqual( + I_EtherDividendCheckpointFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "EtherDividendCheckpointFactory contract was not deployed" + ); + + // Step 6: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 7: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 8: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 9: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 5: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the EtherDividendCheckpointFactory + await I_MRProxied.registerModule(I_EtherDividendCheckpointFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); + + // (C) : Register the Paid EtherDividendCheckpointFactory + await I_MRProxied.registerModule(P_EtherDividendCheckpointFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + EtherDividendCheckpointFactory: ${I_EtherDividendCheckpointFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + try { + const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + } catch(error) { + console.log(` tx -> failed because Token is not paid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "EtherDividendCheckpoint", + "EtherDividendCheckpoint module was not added" + ); + P_EtherDividendCheckpoint = EtherDividendCheckpoint.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "EtherDividendCheckpoint", + "EtherDividendCheckpoint module was not added" + ); + I_EtherDividendCheckpoint = EtherDividendCheckpoint.at(tx.logs[2].args._module); + }); + }); + + describe("Check Dividend payouts", async() => { + + it("Buy some tokens for account_investor1 (1 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(30), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Buy some tokens for account_investor2 (2 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(30), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should fail in creating the dividend", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() + duration.days(10); + try { + let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because msg.value = 0`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail in creating the dividend", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() - duration.days(10); + try { + let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); + } catch(error) { + console.log(` tx -> failed because maturity > expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail in creating the dividend", async() => { + let errorThrown = false; + let maturity = latestTime() - duration.days(2); + let expiry = latestTime() - duration.days(1); + try { + let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); + } catch(error) { + console.log(` tx -> failed because now > expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Set withholding tax of 20% on investor 2", async() => { + await I_EtherDividendCheckpoint.setWithholdingFixed([account_investor2], BigNumber(20*10**16), {from: token_owner}); + }); + + it("Should fail in creating the dividend", async() => { + let errorThrown = false; + let maturity = latestTime() + duration.days(1); + let expiry = latestTime() + duration.days(10); + try { + await I_EtherDividendCheckpoint.createDividend(maturity, expiry, '', {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); + } catch(error) { + console.log(` tx -> failed because dividend name is empty`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create new dividend", async() => { + let maturity = latestTime() + duration.days(1); + let expiry = latestTime() + duration.days(10); + let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 1, "Dividend should be created at checkpoint 1"); + assert.equal(tx.logs[0].args._name.toString(), dividendName, "Dividend name incorrect in event"); + }); + + it("Investor 1 transfers his token balance to investor 2", async() => { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), {from: account_investor1}); + assert.equal(await I_SecurityToken.balanceOf(account_investor1), 0); + assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('3', 'ether')); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { + let errorThrown = false; + try { + await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because dividend index has maturity in future`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { + let errorThrown = false; + // Increase time by 2 day + await increaseTime(duration.days(2)); + try { + await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: account_temp}); + } catch(error) { + console.log(` tx -> failed because msg.sender is not the owner`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { + let errorThrown = false; + try { + await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because dividend index is greator than the dividend array length`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async() => { + let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); + await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); + let investor1BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor2)); + assert.equal(investor1BalanceAfter.sub(investor1Balance).toNumber(), web3.utils.toWei('0.5', 'ether')); + assert.equal(investor2BalanceAfter.sub(investor2Balance).toNumber(), web3.utils.toWei('0.8', 'ether')); + //Check fully claimed + assert.equal((await I_EtherDividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei('1.5', 'ether')); + }); + + it("Issuer reclaims withholding tax", async() => { + let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); + await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); + let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.2', 'ether')) + }); + + it("No more withholding tax to withdraw", async() => { + let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); + await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); + let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) + }); + + it("Buy some tokens for account_temp (1 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_temp, + latestTime(), + latestTime(), + latestTime() + duration.days(20), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_temp.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_temp, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_temp)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Create new dividend", async() => { + let maturity = latestTime() + duration.days(1); + let expiry = latestTime() + duration.days(10); + let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('1.5', 'ether')}); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 2"); + }); + + it("Issuer pushes dividends fails due to passed expiry", async() => { + let errorThrown = false; + await increaseTime(duration.days(12)); + try { + await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, {from: token_owner}); + } catch(error) { + console.log(` tx -> failed because dividend index has passed its expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer reclaims dividend", async() => { + let errorThrown = false; + let tx = await I_EtherDividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); + assert.equal((tx.logs[0].args._claimedAmount).toNumber(), web3.utils.toWei("1.5", "ether")); + try { + await I_EtherDividendCheckpoint.reclaimDividend(1, {from: token_owner, gas: 500000}); + } catch(error) { + console.log(` tx -> failed because dividend index has already reclaimed`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Still no more withholding tax to withdraw", async() => { + let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); + await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); + let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) + }); + + it("Buy some tokens for account_investor3 (7 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('7', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('7', 'ether') + ); + }); + + it("Create another new dividend", async() => { + let maturity = latestTime(); + let expiry = latestTime() + duration.days(10); + let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 3"); + }); + + it("should investor 3 claims dividend - fails bad index", async() => { + let errorThrown = false; + let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + try { + await I_EtherDividendCheckpoint.pullDividendPayment(5, {from: account_investor3, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because dividend index is not valid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should investor 3 claims dividend", async() => { + let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3Balance = BigNumber(await web3.eth.getBalance(account_investor3)); + await I_EtherDividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); + let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); + assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); + assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); + assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei('7', 'ether')); + }); + + it("Still no more withholding tax to withdraw", async() => { + let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); + await I_EtherDividendCheckpoint.withdrawWithholding(0, {from: token_owner, gasPrice: 0}); + let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0', 'ether')) + }); + + it("should investor 3 claims dividend", async() => { + let errorThrown = false; + try { + await I_EtherDividendCheckpoint.pullDividendPayment(2, {from: account_investor3, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because investor already claimed the dividend`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer pushes remainder", async() => { + let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); + await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, {from: token_owner}); + let investor1BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor3)); + assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); + assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), web3.utils.toWei('2.4', 'ether')); + assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); + //Check fully claimed + assert.equal((await I_EtherDividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei('11', 'ether')); + }); + + it("Issuer withdraws new withholding tax", async() => { + let issuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); + await I_EtherDividendCheckpoint.withdrawWithholding(2, {from: token_owner, gasPrice: 0}); + let issuerBalanceAfter = BigNumber(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei('0.6', 'ether')) + }); + + it("Investor 2 transfers 1 ETH of his token balance to investor 1", async() => { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_investor2}); + assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); + assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); + assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); + }); + + it("Create another new dividend with no value - fails", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() + duration.days(2); + let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); + try { + tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: 0}); + } catch(error) { + console.log(` tx -> failed because msg.value is 0`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create another new dividend with explicit", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() - duration.days(10); + try { + tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); + } catch(error) { + console.log(` tx -> failed because maturity > expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create another new dividend with bad expirty - fails", async() => { + let errorThrown = false; + let maturity = latestTime() - duration.days(5); + let expiry = latestTime() - duration.days(2); + try { + tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); + } catch(error) { + console.log(` tx -> failed because now > expiry`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create another new dividend with bad checkpoint in the future - fails", async() => { + let errorThrown = false; + let maturity = latestTime(); + let expiry = latestTime() + duration.days(2); + try { + tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 5, dividendName, {from: token_owner, value: web3.utils.toWei('11', 'ether')}); + } catch(error) { + console.log(` tx -> failed because checkpoint id > current checkpoint`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Create another new dividend with explicit checkpoint and excluding account_investor1", async() => { + let maturity = latestTime(); + let expiry = latestTime() + duration.days(10); + let tx = await I_SecurityToken.createCheckpoint({from: token_owner}); + tx = await I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, 4, [account_investor1], dividendName, {from: token_owner, value: web3.utils.toWei('10', 'ether')}); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 4"); + }); + + it("Non-owner pushes investor 1 - fails", async() => { + let errorThrown = false; + let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + try { + await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor2, account_investor1],{from: account_investor2, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because not called by the owner`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("issuer pushes investor 1 with bad dividend index - fails", async() => { + let errorThrown = false; + let investor1Balance = BigNumber(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = BigNumber(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = BigNumber(await I_PolyToken.balanceOf(account_investor3)); + try { + await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(6, [account_investor2, account_investor1],{from: token_owner, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because dividend index is not valid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("should calculate dividend before the push dividend payment", async() => { + let dividendAmount1 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor1); + let dividendAmount2 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor2); + let dividendAmount3 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor3); + let dividendAmount_temp = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_temp); + //1 has 1/11th, 2 has 2/11th, 3 has 7/11th, temp has 1/11th, but 1 is excluded + assert.equal(dividendAmount1[0].toNumber(), web3.utils.toWei("0", "ether")); + assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); + assert.equal(dividendAmount2[0].toNumber(), web3.utils.toWei("2", "ether")); + assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.4", "ether")); + assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); + assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); + assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); + assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0", "ether")); + }); + + it("Investor 2 claims dividend", async() => { + let investor1Balance = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2Balance = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3Balance = BigNumber(await web3.eth.getBalance(account_investor3)); + let tempBalance = BigNumber(await web3.eth.getBalance(account_temp)); + await I_EtherDividendCheckpoint.pullDividendPayment(3, {from: account_investor2, gasPrice: 0}); + let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); + let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); + assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); + assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei('1.6', 'ether')); + assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); + assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); + }); + + it("Should issuer pushes investor 1 and temp investor", async() => { + let investor1BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter1 = BigNumber(await web3.eth.getBalance(account_investor3)); + let tempBalanceAfter1 = BigNumber(await web3.eth.getBalance(account_temp)); + await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor1, account_temp], {from: token_owner}); + let investor1BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter2 = BigNumber(await web3.eth.getBalance(account_investor3)); + let tempBalanceAfter2 = BigNumber(await web3.eth.getBalance(account_temp)); + assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); + assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), 0); + assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); + assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toNumber(), web3.utils.toWei('1', 'ether')); + //Check fully claimed + assert.equal((await I_EtherDividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei('3', 'ether')); + }); + + it("should calculate dividend after the push dividend payment", async() => { + let dividendAmount1 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor1); + let dividendAmount2 = await I_EtherDividendCheckpoint.calculateDividend.call(3, account_investor2); + assert.equal(dividendAmount1[0].toNumber(), 0); + assert.equal(dividendAmount2[0].toNumber(), 0); + }); + + it("Issuer unable to reclaim dividend (expiry not passed)", async() => { + let errorThrown = false; + try { + await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner}); + } catch(error) { + console.log(`Tx Failed because expiry is in the future ${0}. Test Passed Successfully`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Issuer is able to reclaim dividend after expiry", async() => { + let errorThrown = false; + await increaseTime(11 * 24 * 60 * 60); + try { + await I_EtherDividendCheckpoint.reclaimDividend(8, {from: token_owner, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because dividend index is not valid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Issuer is able to reclaim dividend after expiry", async() => { + let tokenOwnerBalance = BigNumber(await web3.eth.getBalance(token_owner)); + await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); + let tokenOwnerAfter = BigNumber(await web3.eth.getBalance(token_owner)); + assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei('7', 'ether')); + }); + + it("Issuer is able to reclaim dividend after expiry", async() => { + let errorThrown = false; + try { + await I_EtherDividendCheckpoint.reclaimDividend(3, {from: token_owner, gasPrice: 0}); + } catch(error) { + console.log(` tx -> failed because dividend are already reclaimed`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Investor 3 unable to pull dividend after expiry", async() => { + let errorThrown = false; + try { + await I_EtherDividendCheckpoint.pullDividendPayment(3, {from: account_investor3, gasPrice: 0}); + } catch(error) { + console.log(`Tx Failed because expiry is in the past ${0}. Test Passed Successfully`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Assign token balance to an address that can't receive funds", async() => { + + let tx = await I_GeneralTransferManager.modifyWhitelist( + I_PolyToken.address, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + }); + // Jump time + await increaseTime(5000); + // Mint some tokens + await I_SecurityToken.mint(I_PolyToken.address, web3.utils.toWei('1', 'ether'), { from: token_owner }); + assert.equal(await I_SecurityToken.balanceOf(account_investor1), web3.utils.toWei('1', 'ether')); + assert.equal(await I_SecurityToken.balanceOf(account_investor2), web3.utils.toWei('2', 'ether')); + assert.equal(await I_SecurityToken.balanceOf(account_investor3), web3.utils.toWei('7', 'ether')); + assert.equal(await I_SecurityToken.balanceOf(account_temp), web3.utils.toWei('1', 'ether')); + assert.equal(await I_SecurityToken.balanceOf(I_PolyToken.address), web3.utils.toWei('1', 'ether')); + }); + + it("Create another new dividend", async() => { + let maturity = latestTime(); + let expiry = latestTime() + duration.days(10); + let tx = await I_EtherDividendCheckpoint.createDividendWithExclusions(maturity, expiry, [], dividendName, {from: token_owner, value: web3.utils.toWei('12', 'ether')}); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 6, "Dividend should be created at checkpoint 6"); + }); + + it("Should issuer pushes all dividends", async() => { + let investor1BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3BalanceBefore = BigNumber(await web3.eth.getBalance(account_investor3)); + let tempBalanceBefore = BigNumber(await web3.eth.getBalance(account_temp)); + let tokenBalanceBefore = BigNumber(await web3.eth.getBalance(I_PolyToken.address)); + + await I_EtherDividendCheckpoint.pushDividendPayment(4, 0, 10, {from: token_owner}); + + let investor1BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter = BigNumber(await web3.eth.getBalance(account_investor3)); + let tempBalanceAfter = BigNumber(await web3.eth.getBalance(account_temp)); + let tokenBalanceAfter = BigNumber(await web3.eth.getBalance(I_PolyToken.address)); + + assert.equal(investor1BalanceAfter.sub(investor1BalanceBefore).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal(investor2BalanceAfter.sub(investor2BalanceBefore).toNumber(), web3.utils.toWei('1.6', 'ether')); + assert.equal(investor3BalanceAfter.sub(investor3BalanceBefore).toNumber(), web3.utils.toWei('7', 'ether')); + assert.equal(tempBalanceAfter.sub(tempBalanceBefore).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal(tokenBalanceAfter.sub(tokenBalanceBefore).toNumber(), web3.utils.toWei('0', 'ether')); + + //Check partially claimed + assert.equal((await I_EtherDividendCheckpoint.dividends(4))[5].toNumber(), web3.utils.toWei('11', 'ether')); + }); + + it("Should give the right dividend index", async() => { + let index = await I_EtherDividendCheckpoint.getDividendIndex.call(3); + assert.equal(index[0], 2); + }); + + it("Should give the right dividend index", async() => { + let index = await I_EtherDividendCheckpoint.getDividendIndex.call(8); + assert.equal(index.length, 0); + }); + + it("Get the init data", async() => { + let tx = await I_EtherDividendCheckpoint.getInitFunction.call(); + assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); + }); + + it("Should get the listed permissions", async() => { + let tx = await I_EtherDividendCheckpoint.getPermissions.call(); + assert.equal(tx.length,1); + }); + + describe("Test cases for the EtherDividendCheckpointFactory", async() => { + it("should get the exact details of the factory", async() => { + assert.equal((await I_EtherDividendCheckpointFactory.setupCost.call()).toNumber(), 0); + assert.equal((await I_EtherDividendCheckpointFactory.getTypes.call())[0], 4); + assert.equal(web3.utils.toAscii(await I_EtherDividendCheckpointFactory.getName.call()) + .replace(/\u0000/g, ''), + "EtherDividendCheckpoint", + "Wrong Module added"); + assert.equal(await I_EtherDividendCheckpointFactory.getDescription.call(), + "Create ETH dividends for token holders at a specific checkpoint", + "Wrong Module added"); + assert.equal(await I_EtherDividendCheckpointFactory.getTitle.call(), + "Ether Dividend Checkpoint", + "Wrong Module added"); + assert.equal(await I_EtherDividendCheckpointFactory.getInstructions.call(), + "Create a dividend which will be paid out to token holders proportional to their balances at the point the dividend is created", + "Wrong Module added"); + let tags = await I_EtherDividendCheckpointFactory.getTags.call(); + assert.equal(tags.length, 3); + + }); + }); + + }); + +}); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index e6d5cde6c..b04f8a18d 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -1,493 +1,493 @@ -// import latestTime from './helpers/latestTime'; -// import {signData} from './helpers/signData'; -// import { pk } from './helpers/testprivateKey'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -// const DummySTO = artifacts.require('./DummySTO.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('GeneralPermissionManager', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let token_owner_pk; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; -// let account_delegate; -// let account_delegate2; -// let account_delegate3; -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let P_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let P_GeneralPermissionManager; -// let I_GeneralTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_DummySTOFactory; -// let I_STFactory; -// let I_SecurityToken; -// let I_MRProxied; -// let I_STRProxied; -// let I_DummySTO; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; -// const delegateDetails = "Hello I am legit delegate"; - -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// // Dummy STO details -// const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time -// const endTime = startTime + duration.days(80); // Add 80 days more -// const cap = web3.utils.toWei('10', 'ether'); -// const someString = "A string which is not used"; -// const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, someString]); - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; -// token_owner_pk = pk.account_1; - -// account_investor1 = accounts[8]; -// account_investor2 = accounts[9]; -// account_delegate = accounts[7]; -// account_delegate2 = accounts[6]; -// account_delegate3 = accounts[5]; - - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 6: Deploy the GeneralDelegateManagerFactory - -// P_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); - -// assert.notEqual( -// P_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); +import latestTime from './helpers/latestTime'; +import {signData} from './helpers/signData'; +import { pk } from './helpers/testprivateKey'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +const DummySTO = artifacts.require('./DummySTO.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('GeneralPermissionManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let token_owner_pk; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_delegate; + let account_delegate2; + let account_delegate3; + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let P_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let P_GeneralPermissionManager; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_DummySTOFactory; + let I_STFactory; + let I_SecurityToken; + let I_MRProxied; + let I_STRProxied; + let I_DummySTO; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + const delegateDetails = "Hello I am legit delegate"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // Dummy STO details + const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time + const endTime = startTime + duration.days(80); // Add 80 days more + const cap = web3.utils.toWei('10', 'ether'); + const someString = "A string which is not used"; + const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, someString]); + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + token_owner_pk = pk.account_1; + + account_investor1 = accounts[8]; + account_investor2 = accounts[9]; + account_delegate = accounts[7]; + account_delegate2 = accounts[6]; + account_delegate3 = accounts[5]; + + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 6: Deploy the GeneralDelegateManagerFactory + + P_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); + + assert.notEqual( + P_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); -// // STEP 7: Deploy the DummySTOFactory + // STEP 7: Deploy the DummySTOFactory -// I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); -// assert.notEqual( -// I_DummySTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "DummySTOFactory contract was not deployed" -// ); + assert.notEqual( + I_DummySTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "DummySTOFactory contract was not deployed" + ); -// // Step 8: Deploy the STFactory contract + // Step 8: Deploy the STFactory contract -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); -// // Step 9: Deploy the SecurityTokenRegistry contract + // Step 9: Deploy the SecurityTokenRegistry contract -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 8: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the Paid GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(P_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(P_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistryProxy ${ModuleRegistryProxy.address} -// ModuleRegistry: ${ModuleRegistry.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// DummySTOFactory: ${I_DummySTOFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); -// }); - -// it("Should successfully attach the General permission manager factory with the security token", async () => { -// let errorThrown = false; -// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); -// try { -// const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx -> failed because Token is not paid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the General permission manager factory with the security token", async () => { -// let snapId = await takeSnapshot(); -// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); -// const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// assert.equal(tx.logs[3].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[3].args._name) -// .replace(/\u0000/g, ''), -// "GeneralPermissionManager", -// "GeneralPermissionManagerFactory module was not added" -// ); -// P_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[3].args._module); -// await revertToSnapshot(snapId); -// }); - -// it("Should successfully attach the General permission manager factory with the security token", async () => { -// const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "GeneralPermissionManager", -// "GeneralPermissionManagerFactory module was not added" -// ); -// I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); -// }); - -// }); - -// describe("General Permission Manager test cases", async() => { - -// it("Get the init data", async() => { -// let tx = await I_GeneralPermissionManager.getInitFunction.call(); -// assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); -// }); - -// it("Should fail in adding the delegate -- msg.sender doesn't have permission", async() => { -// let errorThrown = false; -// try { -// let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_investor1}); -// } catch(error) { -// console.log(` tx revert -> msg.sender doesn't have permission`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in adding the delegate -- no delegate details provided", async() => { -// let errorThrown = false; -// try { -// let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, '', { from: account_investor1}); -// } catch(error) { -// console.log(` tx revert -> delegate details were not provided`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to provide the permission -- because delegate is not yet added", async() => { -// let errorThrown = false; -// try { -// let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); -// } catch(error) { -// console.log(` tx revert -> Delegate is not yet added`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfuly add the delegate", async() => { -// let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); -// assert.equal(tx.logs[0].args._delegate, account_delegate); -// }); - -// it("Should fail to provide the permission", async() => { -// let errorThrown = false; -// try { -// let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: account_investor1}); -// } catch(error) { -// console.log(` tx revert -> msg.sender doesn't have permission`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should check the permission", async() => { -// assert.isFalse(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST")); -// }); - -// it("Should provide the permission", async() => { -// let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); -// assert.equal(tx.logs[0].args._delegate, account_delegate); -// }); - -// it("Should check the permission", async() => { -// assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST")); -// }); - -// it("Should check the delegate details", async() => { -// assert.equal(web3.utils.toAscii(await I_GeneralPermissionManager.delegateDetails.call(account_delegate)) -// .replace(/\u0000/g, ''), -// delegateDetails, -// "Wrong delegate address get checked"); -// }); - -// it("Should get the permission of the general permission manager contract", async() => { -// let tx = await I_GeneralPermissionManager.getPermissions.call(); -// assert.equal(web3.utils.toAscii(tx[0]) -// .replace(/\u0000/g, ''), -// "CHANGE_PERMISSION", -// "Wrong permissions"); -// }); - -// it("Should return all delegates", async() => { -// await I_GeneralPermissionManager.addDelegate(account_delegate2, delegateDetails, { from: token_owner}); -// let tx = await I_GeneralPermissionManager.getAllDelegates.call(); -// console.log(tx); -// assert.equal(tx.length, 2); -// assert.equal(tx[0], account_delegate); -// assert.equal(tx[1], account_delegate2); -// }); - -// it("Should return false when check is delegate - because user is not a delegate", async() => { -// assert.equal(await I_GeneralPermissionManager.checkDelegate.call(account_investor1), false); -// }); - -// it("Should return true when check is delegate - because user is a delegate", async() => { -// assert.equal(await I_GeneralPermissionManager.checkDelegate.call(account_delegate), true); -// }); + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 8: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the Paid GeneralDelegateManagerFactory + await I_MRProxied.registerModule(P_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy ${ModuleRegistryProxy.address} + ModuleRegistry: ${ModuleRegistry.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + DummySTOFactory: ${I_DummySTOFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + + it("Should successfully attach the General permission manager factory with the security token", async () => { + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + try { + const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + } catch(error) { + console.log(` tx -> failed because Token is not paid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the General permission manager factory with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "GeneralPermissionManager", + "GeneralPermissionManagerFactory module was not added" + ); + P_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the General permission manager factory with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "GeneralPermissionManager", + "GeneralPermissionManagerFactory module was not added" + ); + I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); + }); + + }); + + describe("General Permission Manager test cases", async() => { + + it("Get the init data", async() => { + let tx = await I_GeneralPermissionManager.getInitFunction.call(); + assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); + }); + + it("Should fail in adding the delegate -- msg.sender doesn't have permission", async() => { + let errorThrown = false; + try { + let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_investor1}); + } catch(error) { + console.log(` tx revert -> msg.sender doesn't have permission`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the delegate -- no delegate details provided", async() => { + let errorThrown = false; + try { + let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, '', { from: account_investor1}); + } catch(error) { + console.log(` tx revert -> delegate details were not provided`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to provide the permission -- because delegate is not yet added", async() => { + let errorThrown = false; + try { + let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); + } catch(error) { + console.log(` tx revert -> Delegate is not yet added`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfuly add the delegate", async() => { + let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); + assert.equal(tx.logs[0].args._delegate, account_delegate); + }); + + it("Should fail to provide the permission", async() => { + let errorThrown = false; + try { + let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: account_investor1}); + } catch(error) { + console.log(` tx revert -> msg.sender doesn't have permission`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should check the permission", async() => { + assert.isFalse(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST")); + }); + + it("Should provide the permission", async() => { + let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); + assert.equal(tx.logs[0].args._delegate, account_delegate); + }); + + it("Should check the permission", async() => { + assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST")); + }); + + it("Should check the delegate details", async() => { + assert.equal(web3.utils.toAscii(await I_GeneralPermissionManager.delegateDetails.call(account_delegate)) + .replace(/\u0000/g, ''), + delegateDetails, + "Wrong delegate address get checked"); + }); + + it("Should get the permission of the general permission manager contract", async() => { + let tx = await I_GeneralPermissionManager.getPermissions.call(); + assert.equal(web3.utils.toAscii(tx[0]) + .replace(/\u0000/g, ''), + "CHANGE_PERMISSION", + "Wrong permissions"); + }); + + it("Should return all delegates", async() => { + await I_GeneralPermissionManager.addDelegate(account_delegate2, delegateDetails, { from: token_owner}); + let tx = await I_GeneralPermissionManager.getAllDelegates.call(); + console.log(tx); + assert.equal(tx.length, 2); + assert.equal(tx[0], account_delegate); + assert.equal(tx[1], account_delegate2); + }); + + it("Should return false when check is delegate - because user is not a delegate", async() => { + assert.equal(await I_GeneralPermissionManager.checkDelegate.call(account_investor1), false); + }); + + it("Should return true when check is delegate - because user is a delegate", async() => { + assert.equal(await I_GeneralPermissionManager.checkDelegate.call(account_delegate), true); + }); -// it("Should provide the permission in bulk", async() => { -// await I_GeneralPermissionManager.addDelegate(account_delegate3, delegateDetails, { from: token_owner}); + it("Should provide the permission in bulk", async() => { + await I_GeneralPermissionManager.addDelegate(account_delegate3, delegateDetails, { from: token_owner}); -// let tx = await I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}); -// assert.equal(tx.logs[0].args._delegate, account_delegate3); + let tx = await I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}); + assert.equal(tx.logs[0].args._delegate, account_delegate3); -// assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate3, I_GeneralTransferManager.address, "WHITELIST")); -// assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate3, I_GeneralPermissionManager.address, "CHANGE_PERMISSION")); -// }); + assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate3, I_GeneralTransferManager.address, "WHITELIST")); + assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate3, I_GeneralPermissionManager.address, "CHANGE_PERMISSION")); + }); -// it("Should provide all delegates with specified permission", async() => { + it("Should provide all delegates with specified permission", async() => { -// await I_GeneralPermissionManager.changePermission(account_delegate2, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); + await I_GeneralPermissionManager.changePermission(account_delegate2, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); -// let tx = await I_GeneralPermissionManager.getAllDelegatesWithPerm.call(I_GeneralTransferManager.address, "WHITELIST"); -// // console.log(tx); -// assert.equal(tx.length, 3); -// assert.equal(tx[0], account_delegate); -// assert.equal(tx[1], account_delegate2); -// }); + let tx = await I_GeneralPermissionManager.getAllDelegatesWithPerm.call(I_GeneralTransferManager.address, "WHITELIST"); + // console.log(tx); + assert.equal(tx.length, 3); + assert.equal(tx[0], account_delegate); + assert.equal(tx[1], account_delegate2); + }); -// it("Should return all modules and all permission", async() => { + it("Should return all modules and all permission", async() => { -// let tx = await I_GeneralPermissionManager.getAllModulesAndPermsFromTypes.call(account_delegate3, [2,1], I_SecurityToken.address); -// console.log (tx); -// assert.equal(tx[0][0], I_GeneralTransferManager.address); -// assert.equal(tx[1][0], "0x57484954454c4953540000000000000000000000000000000000000000000000"); -// assert.equal(tx[0][1], I_GeneralPermissionManager.address); -// assert.equal(tx[1][1], "0x4348414e47455f5045524d495353494f4e000000000000000000000000000000"); + let tx = await I_GeneralPermissionManager.getAllModulesAndPermsFromTypes.call(account_delegate3, [2,1], I_SecurityToken.address); + console.log (tx); + assert.equal(tx[0][0], I_GeneralTransferManager.address); + assert.equal(tx[1][0], "0x57484954454c4953540000000000000000000000000000000000000000000000"); + assert.equal(tx[0][1], I_GeneralPermissionManager.address); + assert.equal(tx[1][1], "0x4348414e47455f5045524d495353494f4e000000000000000000000000000000"); -// }); - -// }); - -// describe("General Permission Manager Factory test cases", async() => { -// it("should get the exact details of the factory", async() => { -// assert.equal(await I_GeneralPermissionManagerFactory.setupCost.call(),0); -// assert.equal((await I_GeneralPermissionManagerFactory.getTypes.call())[0],1); -// assert.equal(web3.utils.toAscii(await I_GeneralPermissionManagerFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "GeneralPermissionManager", -// "Wrong Module added"); -// assert.equal(await I_GeneralPermissionManagerFactory.getDescription.call(), -// "Manage permissions within the Security Token and attached modules", -// "Wrong Module added"); -// assert.equal(await I_GeneralPermissionManagerFactory.getTitle.call(), -// "General Permission Manager", -// "Wrong Module added"); -// assert.equal(await I_GeneralPermissionManagerFactory.getInstructions.call(), -// "Add and remove permissions for the SecurityToken and associated modules. Permission types should be encoded as bytes32 values, and attached using the withPerm modifier to relevant functions.No initFunction required.", -// "Wrong Module added"); - -// }); - -// it("Should get the tags of the factory", async() => { -// let tags = await I_GeneralPermissionManagerFactory.getTags.call(); -// assert.equal(tags.length,0); -// }); -// }); - -// }); + }); + + }); + + describe("General Permission Manager Factory test cases", async() => { + it("should get the exact details of the factory", async() => { + assert.equal(await I_GeneralPermissionManagerFactory.setupCost.call(),0); + assert.equal((await I_GeneralPermissionManagerFactory.getTypes.call())[0],1); + assert.equal(web3.utils.toAscii(await I_GeneralPermissionManagerFactory.getName.call()) + .replace(/\u0000/g, ''), + "GeneralPermissionManager", + "Wrong Module added"); + assert.equal(await I_GeneralPermissionManagerFactory.getDescription.call(), + "Manage permissions within the Security Token and attached modules", + "Wrong Module added"); + assert.equal(await I_GeneralPermissionManagerFactory.getTitle.call(), + "General Permission Manager", + "Wrong Module added"); + assert.equal(await I_GeneralPermissionManagerFactory.getInstructions.call(), + "Add and remove permissions for the SecurityToken and associated modules. Permission types should be encoded as bytes32 values, and attached using the withPerm modifier to relevant functions.No initFunction required.", + "Wrong Module added"); + + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_GeneralPermissionManagerFactory.getTags.call(); + assert.equal(tags.length,0); + }); + }); + +}); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 8b230297c..883834f30 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -1,863 +1,863 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import {signData} from './helpers/signData'; -// import { pk } from './helpers/testprivateKey'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -// const DummySTO = artifacts.require('./DummySTO.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('GeneralTransferManager', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let token_owner_pk; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; -// let account_delegate; -// let account_affiliates1; -// let account_affiliates2; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_GeneralTransferManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_DummySTOFactory; -// let I_STFactory; -// let I_SecurityToken; -// let I_STRProxied; -// let I_MRProxied; -// let I_DummySTO; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; - -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// // Dummy STO details -// const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time -// const endTime = startTime + duration.days(80); // Add 80 days more -// const cap = web3.utils.toWei('10', 'ether'); -// const someString = "A string which is not used"; -// const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; -// token_owner_pk = pk.account_1; - -// account_investor1 = accounts[8]; -// account_investor2 = accounts[9]; -// account_delegate = accounts[7]; -// account_investor4 = accounts[6]; - -// account_affiliates1 = accounts[3]; -// account_affiliates2 = accounts[4]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - -// // STEP 2: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 3: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the DummySTOFactory - -// I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_DummySTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "DummySTOFactory contract was not deployed" -// ); - -// // Step 8: Deploy the STFactory contract +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import {signData} from './helpers/signData'; +import { pk } from './helpers/testprivateKey'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +const DummySTO = artifacts.require('./DummySTO.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('GeneralTransferManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let token_owner_pk; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_delegate; + let account_affiliates1; + let account_affiliates2; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_DummySTOFactory; + let I_STFactory; + let I_SecurityToken; + let I_STRProxied; + let I_MRProxied; + let I_DummySTO; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // Dummy STO details + const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time + const endTime = startTime + duration.days(80); // Add 80 days more + const cap = web3.utils.toWei('10', 'ether'); + const someString = "A string which is not used"; + const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + token_owner_pk = pk.account_1; + + account_investor1 = accounts[8]; + account_investor2 = accounts[9]; + account_delegate = accounts[7]; + account_investor4 = accounts[6]; + + account_affiliates1 = accounts[3]; + account_affiliates2 = accounts[4]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + + // STEP 2: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 3: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 4: Deploy the DummySTOFactory + + I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_DummySTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "DummySTOFactory contract was not deployed" + ); + + // Step 8: Deploy the STFactory contract -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 9: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 5: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// ModuleRegistry: ${ModuleRegistry.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// DummySTOFactory: ${I_DummySTOFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); - -// it("Should whitelist the affiliates before the STO attached", async() => { -// let tx = await I_GeneralTransferManager.modifyWhitelistMulti( -// [account_affiliates1, account_affiliates2], -// [(latestTime() + duration.days(30)),(latestTime() + duration.days(30))], -// [(latestTime() + duration.days(90)),(latestTime() + duration.days(90))], -// [(latestTime() + duration.years(1)),(latestTime() + duration.years(1))], -// [false, false], -// { -// from: account_issuer, -// gas: 6000000 -// }); -// assert.equal(tx.logs[0].args._investor, account_affiliates1); -// assert.equal(tx.logs[1].args._investor, account_affiliates2); -// }); - -// it("Should mint the tokens to the affiliates", async () => { -// await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [(100 * Math.pow(10, 18)), (100 * Math.pow(10, 18))], { from: account_issuer, gas:6000000 }); -// assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates1)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); -// assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); -// }); - -// it("Should successfully attach the STO factory with the security token", async () => { -// let bytesSTO = encodeModuleCall(STOParameters, [latestTime() + duration.seconds(1000), latestTime() + duration.days(40), cap, someString]); -// const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "DummySTO", -// "DummySTOFactory module was not added" -// ); -// I_DummySTO = DummySTO.at(tx.logs[2].args._module); -// }); - -// it("Should successfully attach the permission manager factory with the security token", async () => { -// const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, 0, 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "GeneralPermissionManager doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "GeneralPermissionManager", -// "GeneralPermissionManager module was not added" -// ); -// I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); -// }); - -// }); - -// describe("Buy tokens using on-chain whitelist", async() => { - -// it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { -// let errorThrown = false; -// try { -// await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Investor isn't present in the whitelist`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should Buy the tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(5000); - -// // Mint some tokens -// await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Should fail in buying the token from the STO", async() => { -// let errorThrown = false; -// try { -// await I_DummySTO.generateTokens(account_affiliates1, web3.utils.toWei('1', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Investor is restricted investor`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in investing the money in STO -- expiry limit reached", async() => { -// let errorThrown = false; -// await increaseTime(duration.days(10)); - -// try { -// await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Investor isn't present in the whitelist`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// }); - -// describe("Buy tokens using off-chain whitelist", async() => { - -// it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { -// let errorThrown = false; -// try { -// await I_DummySTO.generateTokens(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Investor isn't present in the whitelist`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should buy the tokens -- Failed due to incorrect signature input", async() => { -// // Add the Investor in to the whitelist -// //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk -// let validFrom = latestTime(); -// let validTo = latestTime() + duration.days(5); -// const sig = signData(account_investor2, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, token_owner_pk); - -// const r = `0x${sig.r.toString('hex')}`; -// const s = `0x${sig.s.toString('hex')}`; -// const v = sig.v; -// let errorThrown = false; - -// try { -// let tx = await I_GeneralTransferManager.modifyWhitelistSigned( -// account_investor2, -// fromTime, -// toTime, -// expiryTime, -// true, -// validFrom, -// validTo, -// v, -// r, -// s, -// { -// from: account_investor2, -// gas: 6000000 -// }); -// } catch(error) { -// console.log(` tx revert -> Incorrect sig data`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Should buy the tokens -- Failed due to incorrect signature timing", async() => { -// // Add the Investor in to the whitelist -// //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk -// let validFrom = latestTime() - 100; -// let validTo = latestTime() - 1; -// const sig = signData(I_GeneralTransferManager.address, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, token_owner_pk); - -// const r = `0x${sig.r.toString('hex')}`; -// const s = `0x${sig.s.toString('hex')}`; -// const v = sig.v; - -// let errorThrown = false; -// try { -// let tx = await I_GeneralTransferManager.modifyWhitelistSigned( -// account_investor2, -// fromTime, -// toTime, -// expiryTime, -// true, -// validFrom, -// validTo, -// v, -// r, -// s, -// { -// from: account_investor2, -// gas: 6000000 -// }); -// } catch(error) { -// console.log(` tx revert -> Incorrect sig data`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Should buy the tokens -- Failed due to incorrect signature signer", async() => { -// // Add the Investor in to the whitelist -// //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk -// let validFrom = latestTime(); -// let validTo = latestTime() + (60 * 60); - -// const sig = signData(account_investor2, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, '2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200'); - -// const r = `0x${sig.r.toString('hex')}`; -// const s = `0x${sig.s.toString('hex')}`; -// const v = sig.v; -// let errorThrown = false; - -// try { -// let tx = await I_GeneralTransferManager.modifyWhitelistSigned( -// account_investor2, -// fromTime, -// toTime, -// expiryTime, -// true, -// validFrom, -// validTo, -// v, -// r, -// s, -// { -// from: account_investor2, -// gas: 6000000 -// }); -// } catch(error) { -// console.log(` tx revert -> Incorrect sig data`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Should Buy the tokens", async() => { -// // Add the Investor in to the whitelist -// //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk -// let validFrom = latestTime(); -// let validTo = latestTime() + duration.days(5); -// const sig = signData(I_GeneralTransferManager.address, account_investor2, latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), true, validFrom, validTo, token_owner_pk); - -// const r = `0x${sig.r.toString('hex')}`; -// const s = `0x${sig.s.toString('hex')}`; -// const v = sig.v; -// let tx = await I_GeneralTransferManager.modifyWhitelistSigned( -// account_investor2, -// latestTime(), -// latestTime() + duration.days(80), -// expiryTime + duration.days(200), -// true, -// validFrom, -// validTo, -// v, -// r, -// s, -// { -// from: account_investor2, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(10000); -// // Mint some tokens - -// await I_DummySTO.generateTokens(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); - -// }); - -// it("Should fail in changing the signing address", async() => { -// let errorThrown = false; -// try { -// await I_GeneralTransferManager.changeSigningAddress(account_polymath, {from: account_investor4}); -// } catch(error) { -// console.log(` tx revert -> msg.sender is not token_owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should get the permission", async() => { -// let perm = await I_GeneralTransferManager.getPermissions.call(); -// assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "WHITELIST"); -// assert.equal(web3.utils.toAscii(perm[1]).replace(/\u0000/g, ''), "FLAGS"); -// }); - -// it("Should provide the permission and change the signing address", async() => { -// let log = await I_GeneralPermissionManager.addDelegate(account_delegate, "My details", {from: token_owner}); -// assert.equal(log.logs[0].args._delegate, account_delegate); - -// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "FLAGS", true, {from: token_owner}); - -// assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "FLAGS")); - -// let tx = await I_GeneralTransferManager.changeSigningAddress(account_polymath, {from: account_delegate}); -// assert.equal(tx.logs[0].args._signingAddress, account_polymath); -// }); - -// it("Should fail to pull fees as no budget set", async() => { - -// let errorThrown = false; -// try { -// await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> No budget set`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should set a budget for the GeneralTransferManager", async() => { -// await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, 10 * Math.pow(10, 18), {from: token_owner}); -// let errorThrown = false; -// try { -// await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> No balance on token`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// await I_PolyToken.getTokens(10 * Math.pow(10, 18), token_owner); -// await I_PolyToken.transfer(I_SecurityToken.address, 10 * Math.pow(10, 18), {from: token_owner}); -// }); - - -// it("Factory owner should pull fees - fails as not permissioned by issuer", async() => { -// let errorThrown = false; -// try { -// await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_delegate}); -// } catch(error) { -// console.log(` tx revert -> Incorrect permissions`.grey); -// errorThrown = true; -// ensureException(error); -// } -// }); - -// it("Factory owner should pull fees", async() => { -// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "FEE_ADMIN", true, {from: token_owner}); -// let balanceBefore = await I_PolyToken.balanceOf(account_polymath); -// await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_delegate}); -// let balanceAfter = await I_PolyToken.balanceOf(account_polymath); -// assert.equal(balanceBefore.add(web3.utils.toWei('1','ether')).toNumber(), balanceAfter.toNumber(), "Fee is transferred"); -// }); - -// it("Should change the white list transfer variable", async() => { -// let tx = await I_GeneralTransferManager.changeAllowAllWhitelistIssuances(true, {from : token_owner}); -// assert.isTrue(tx.logs[0].args._allowAllWhitelistIssuances); -// }); - -// it("should failed in trasfering the tokens", async() => { -// let tx = await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); -// await I_GeneralTransferManager.pause({from: token_owner}); -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2','ether'), {from: account_investor2}); -// } catch(error) { -// console.log(` tx revert -> Transfer is paused`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should change the Issuance address", async() => { -// let tx = await I_GeneralTransferManager.changeIssuanceAddress(account_investor2, {from: account_delegate}); -// assert.equal(tx.logs[0].args._issuanceAddress, account_investor2); -// }); - -// it("Should unpause the transfers", async() => { -// await I_GeneralTransferManager.unpause({from: token_owner}); - -// assert.isFalse(await I_GeneralTransferManager.paused.call()); -// }); - -// it("Should get the init function", async() => { -// let byte = await I_GeneralTransferManager.getInitFunction.call(); -// assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); -// }); - -// }); - -// describe("WhiteList that addresses", async () => { - -// it("Should fail in adding the investors in whitelist", async() => { -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(20); -// let expiryTime = toTime + duration.days(10); -// let errorThrown = false; -// try { -// await I_GeneralTransferManager.modifyWhitelistMulti( -// [account_investor3, account_investor4], -// [fromTime, fromTime], -// [toTime, toTime], -// [expiryTime, expiryTime], -// [true, true], -// { -// from: account_delegate, -// gas: 6000000 -// } -// ); -// } catch(error) { -// console.log(` tx revert -> msg.sender is not allowed to modify the whitelist`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(20); -// let expiryTime = toTime + duration.days(10); -// let errorThrown = false; -// try { -// await I_GeneralTransferManager.modifyWhitelistMulti( -// [account_investor3, account_investor4], -// [fromTime], -// [toTime, toTime], -// [expiryTime, expiryTime], -// [true, true], -// { -// from: account_delegate, -// gas: 6000000 -// } -// ); -// } catch(error) { -// console.log(` tx revert -> Array length mismatch`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(20); -// let expiryTime = toTime + duration.days(10); -// let errorThrown = false; -// try { -// await I_GeneralTransferManager.modifyWhitelistMulti( -// [account_investor3, account_investor4], -// [fromTime, fromTime], -// [toTime], -// [expiryTime, expiryTime], -// [true, true], -// { -// from: account_delegate, -// gas: 6000000 -// } -// ); -// } catch(error) { -// console.log(` tx revert -> Array length mismatch`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(20); -// let expiryTime = toTime + duration.days(10); -// let errorThrown = false; -// try { -// await I_GeneralTransferManager.modifyWhitelistMulti( -// [account_investor3, account_investor4], -// [fromTime, fromTime], -// [toTime, toTime], -// [expiryTime], -// [true, true], -// { -// from: account_delegate, -// gas: 6000000 -// } -// ); -// } catch(error) { -// console.log(` tx revert -> Array length mismatch`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully add the investors in whitelist", async() => { -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(20); -// let expiryTime = toTime + duration.days(10); -// let errorThrown = false; -// let tx = await I_GeneralTransferManager.modifyWhitelistMulti( -// [account_investor3, account_investor4], -// [fromTime, fromTime], -// [toTime, toTime], -// [expiryTime, expiryTime], -// [true, true], -// { -// from: token_owner, -// gas: 6000000 -// } -// ); -// assert.equal(tx.logs[1].args._investor, account_investor4); -// }); -// }); - -// describe("General Transfer Manager Factory test cases", async() => { - -// it("Should get the exact details of the factory", async() => { -// assert.equal(await I_GeneralTransferManagerFactory.setupCost.call(),0); -// assert.equal((await I_GeneralTransferManagerFactory.getTypes.call())[0],2); -// assert.equal(web3.utils.toAscii(await I_GeneralTransferManagerFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager", -// "Wrong Module added"); -// assert.equal(await I_GeneralTransferManagerFactory.getDescription.call(), -// "Manage transfers using a time based whitelist", -// "Wrong Module added"); -// assert.equal(await I_GeneralTransferManagerFactory.getTitle.call(), -// "General Transfer Manager", -// "Wrong Module added"); -// assert.equal(await I_GeneralTransferManagerFactory.getInstructions.call(), -// "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist, and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters.", -// "Wrong Module added"); - -// }); - -// it("Should get the tags of the factory", async() => { -// let tags = await I_GeneralTransferManagerFactory.getTags.call(); -// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "General"); -// }); -// }); - -// describe("Dummy STO Factory test cases", async() => { -// it("should get the exact details of the factory", async() => { -// assert.equal(await I_DummySTOFactory.setupCost.call(),0); -// assert.equal((await I_DummySTOFactory.getTypes.call())[0],3); -// assert.equal(web3.utils.toAscii(await I_DummySTOFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "DummySTO", -// "Wrong Module added"); -// assert.equal(await I_DummySTOFactory.getDescription.call(), -// "Dummy STO", -// "Wrong Module added"); -// assert.equal(await I_DummySTOFactory.getTitle.call(), -// "Dummy STO", -// "Wrong Module added"); -// assert.equal(await I_DummySTOFactory.getInstructions.call(), -// "Dummy STO - you can mint tokens at will", -// "Wrong Module added"); - -// }); - -// it("Should get the tags of the factory", async() => { -// let tags = await I_DummySTOFactory.getTags.call(); -// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Dummy"); -// }); -// }); - -// describe("Test cases for the get functions of the dummy sto", async() => { - -// it("Should get the raised amount of ether", async() => { -// assert.equal(await I_DummySTO.getRaised.call(0), web3.utils.toWei('0','ether')); -// }); - -// it("Should get the raised amount of poly", async() => { -// assert.equal((await I_DummySTO.getRaised.call(1)).toNumber(), web3.utils.toWei('0','ether')); -// }); - -// it("Should get the investors", async() => { -// assert.equal((await I_DummySTO.investorCount.call()).toNumber(), 2); -// }); - -// it("Should get the listed permissions", async() => { -// let tx = await I_DummySTO.getPermissions.call(); -// assert.equal(web3.utils.toAscii(tx[0]).replace(/\u0000/g, ''), "ADMIN"); -// }); -// }); - -// }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 9: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 5: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + ModuleRegistry: ${ModuleRegistry.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + DummySTOFactory: ${I_DummySTOFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + it("Should whitelist the affiliates before the STO attached", async() => { + let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + [account_affiliates1, account_affiliates2], + [(latestTime() + duration.days(30)),(latestTime() + duration.days(30))], + [(latestTime() + duration.days(90)),(latestTime() + duration.days(90))], + [(latestTime() + duration.years(1)),(latestTime() + duration.years(1))], + [false, false], + { + from: account_issuer, + gas: 6000000 + }); + assert.equal(tx.logs[0].args._investor, account_affiliates1); + assert.equal(tx.logs[1].args._investor, account_affiliates2); + }); + + it("Should mint the tokens to the affiliates", async () => { + await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [(100 * Math.pow(10, 18)), (100 * Math.pow(10, 18))], { from: account_issuer, gas:6000000 }); + assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates1)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); + assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); + }); + + it("Should successfully attach the STO factory with the security token", async () => { + let bytesSTO = encodeModuleCall(STOParameters, [latestTime() + duration.seconds(1000), latestTime() + duration.days(40), cap, someString]); + const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "DummySTO", + "DummySTOFactory module was not added" + ); + I_DummySTO = DummySTO.at(tx.logs[2].args._module); + }); + + it("Should successfully attach the permission manager factory with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, 0, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "GeneralPermissionManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "GeneralPermissionManager", + "GeneralPermissionManager module was not added" + ); + I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); + }); + + }); + + describe("Buy tokens using on-chain whitelist", async() => { + + it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { + let errorThrown = false; + try { + await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Investor isn't present in the whitelist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should Buy the tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should fail in buying the token from the STO", async() => { + let errorThrown = false; + try { + await I_DummySTO.generateTokens(account_affiliates1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Investor is restricted investor`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in investing the money in STO -- expiry limit reached", async() => { + let errorThrown = false; + await increaseTime(duration.days(10)); + + try { + await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Investor isn't present in the whitelist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + }); + + describe("Buy tokens using off-chain whitelist", async() => { + + it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { + let errorThrown = false; + try { + await I_DummySTO.generateTokens(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Investor isn't present in the whitelist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should buy the tokens -- Failed due to incorrect signature input", async() => { + // Add the Investor in to the whitelist + //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + let validFrom = latestTime(); + let validTo = latestTime() + duration.days(5); + const sig = signData(account_investor2, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, token_owner_pk); + + const r = `0x${sig.r.toString('hex')}`; + const s = `0x${sig.s.toString('hex')}`; + const v = sig.v; + let errorThrown = false; + + try { + let tx = await I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + fromTime, + toTime, + expiryTime, + true, + validFrom, + validTo, + v, + r, + s, + { + from: account_investor2, + gas: 6000000 + }); + } catch(error) { + console.log(` tx revert -> Incorrect sig data`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + + }); + + it("Should buy the tokens -- Failed due to incorrect signature timing", async() => { + // Add the Investor in to the whitelist + //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + let validFrom = latestTime() - 100; + let validTo = latestTime() - 1; + const sig = signData(I_GeneralTransferManager.address, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, token_owner_pk); + + const r = `0x${sig.r.toString('hex')}`; + const s = `0x${sig.s.toString('hex')}`; + const v = sig.v; + + let errorThrown = false; + try { + let tx = await I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + fromTime, + toTime, + expiryTime, + true, + validFrom, + validTo, + v, + r, + s, + { + from: account_investor2, + gas: 6000000 + }); + } catch(error) { + console.log(` tx revert -> Incorrect sig data`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + + }); + + it("Should buy the tokens -- Failed due to incorrect signature signer", async() => { + // Add the Investor in to the whitelist + //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + let validFrom = latestTime(); + let validTo = latestTime() + (60 * 60); + + const sig = signData(account_investor2, account_investor2, fromTime, toTime, expiryTime, true, validFrom, validTo, '2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200'); + + const r = `0x${sig.r.toString('hex')}`; + const s = `0x${sig.s.toString('hex')}`; + const v = sig.v; + let errorThrown = false; + + try { + let tx = await I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + fromTime, + toTime, + expiryTime, + true, + validFrom, + validTo, + v, + r, + s, + { + from: account_investor2, + gas: 6000000 + }); + } catch(error) { + console.log(` tx revert -> Incorrect sig data`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + + }); + + it("Should Buy the tokens", async() => { + // Add the Investor in to the whitelist + //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + let validFrom = latestTime(); + let validTo = latestTime() + duration.days(5); + const sig = signData(I_GeneralTransferManager.address, account_investor2, latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), true, validFrom, validTo, token_owner_pk); + + const r = `0x${sig.r.toString('hex')}`; + const s = `0x${sig.s.toString('hex')}`; + const v = sig.v; + let tx = await I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + latestTime(), + latestTime() + duration.days(80), + expiryTime + duration.days(200), + true, + validFrom, + validTo, + v, + r, + s, + { + from: account_investor2, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(10000); + // Mint some tokens + + await I_DummySTO.generateTokens(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + + }); + + it("Should fail in changing the signing address", async() => { + let errorThrown = false; + try { + await I_GeneralTransferManager.changeSigningAddress(account_polymath, {from: account_investor4}); + } catch(error) { + console.log(` tx revert -> msg.sender is not token_owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should get the permission", async() => { + let perm = await I_GeneralTransferManager.getPermissions.call(); + assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "WHITELIST"); + assert.equal(web3.utils.toAscii(perm[1]).replace(/\u0000/g, ''), "FLAGS"); + }); + + it("Should provide the permission and change the signing address", async() => { + let log = await I_GeneralPermissionManager.addDelegate(account_delegate, "My details", {from: token_owner}); + assert.equal(log.logs[0].args._delegate, account_delegate); + + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "FLAGS", true, {from: token_owner}); + + assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "FLAGS")); + + let tx = await I_GeneralTransferManager.changeSigningAddress(account_polymath, {from: account_delegate}); + assert.equal(tx.logs[0].args._signingAddress, account_polymath); + }); + + it("Should fail to pull fees as no budget set", async() => { + + let errorThrown = false; + try { + await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> No budget set`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should set a budget for the GeneralTransferManager", async() => { + await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, 10 * Math.pow(10, 18), {from: token_owner}); + let errorThrown = false; + try { + await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> No balance on token`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + await I_PolyToken.getTokens(10 * Math.pow(10, 18), token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, 10 * Math.pow(10, 18), {from: token_owner}); + }); + + + it("Factory owner should pull fees - fails as not permissioned by issuer", async() => { + let errorThrown = false; + try { + await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_delegate}); + } catch(error) { + console.log(` tx revert -> Incorrect permissions`.grey); + errorThrown = true; + ensureException(error); + } + }); + + it("Factory owner should pull fees", async() => { + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "FEE_ADMIN", true, {from: token_owner}); + let balanceBefore = await I_PolyToken.balanceOf(account_polymath); + await I_GeneralTransferManager.takeFee(web3.utils.toWei('1','ether'), {from: account_delegate}); + let balanceAfter = await I_PolyToken.balanceOf(account_polymath); + assert.equal(balanceBefore.add(web3.utils.toWei('1','ether')).toNumber(), balanceAfter.toNumber(), "Fee is transferred"); + }); + + it("Should change the white list transfer variable", async() => { + let tx = await I_GeneralTransferManager.changeAllowAllWhitelistIssuances(true, {from : token_owner}); + assert.isTrue(tx.logs[0].args._allowAllWhitelistIssuances); + }); + + it("should failed in trasfering the tokens", async() => { + let tx = await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); + await I_GeneralTransferManager.pause({from: token_owner}); + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2','ether'), {from: account_investor2}); + } catch(error) { + console.log(` tx revert -> Transfer is paused`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should change the Issuance address", async() => { + let tx = await I_GeneralTransferManager.changeIssuanceAddress(account_investor2, {from: account_delegate}); + assert.equal(tx.logs[0].args._issuanceAddress, account_investor2); + }); + + it("Should unpause the transfers", async() => { + await I_GeneralTransferManager.unpause({from: token_owner}); + + assert.isFalse(await I_GeneralTransferManager.paused.call()); + }); + + it("Should get the init function", async() => { + let byte = await I_GeneralTransferManager.getInitFunction.call(); + assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); + }); + + }); + + describe("WhiteList that addresses", async () => { + + it("Should fail in adding the investors in whitelist", async() => { + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + let errorThrown = false; + try { + await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime, fromTime], + [toTime, toTime], + [expiryTime, expiryTime], + [true, true], + { + from: account_delegate, + gas: 6000000 + } + ); + } catch(error) { + console.log(` tx revert -> msg.sender is not allowed to modify the whitelist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + let errorThrown = false; + try { + await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime], + [toTime, toTime], + [expiryTime, expiryTime], + [true, true], + { + from: account_delegate, + gas: 6000000 + } + ); + } catch(error) { + console.log(` tx revert -> Array length mismatch`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + let errorThrown = false; + try { + await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime, fromTime], + [toTime], + [expiryTime, expiryTime], + [true, true], + { + from: account_delegate, + gas: 6000000 + } + ); + } catch(error) { + console.log(` tx revert -> Array length mismatch`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in adding the investors in whitelist -- array length mismatch", async() => { + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + let errorThrown = false; + try { + await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime, fromTime], + [toTime, toTime], + [expiryTime], + [true, true], + { + from: account_delegate, + gas: 6000000 + } + ); + } catch(error) { + console.log(` tx revert -> Array length mismatch`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully add the investors in whitelist", async() => { + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + let errorThrown = false; + let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime, fromTime], + [toTime, toTime], + [expiryTime, expiryTime], + [true, true], + { + from: token_owner, + gas: 6000000 + } + ); + assert.equal(tx.logs[1].args._investor, account_investor4); + }); + }); + + describe("General Transfer Manager Factory test cases", async() => { + + it("Should get the exact details of the factory", async() => { + assert.equal(await I_GeneralTransferManagerFactory.setupCost.call(),0); + assert.equal((await I_GeneralTransferManagerFactory.getTypes.call())[0],2); + assert.equal(web3.utils.toAscii(await I_GeneralTransferManagerFactory.getName.call()) + .replace(/\u0000/g, ''), + "GeneralTransferManager", + "Wrong Module added"); + assert.equal(await I_GeneralTransferManagerFactory.getDescription.call(), + "Manage transfers using a time based whitelist", + "Wrong Module added"); + assert.equal(await I_GeneralTransferManagerFactory.getTitle.call(), + "General Transfer Manager", + "Wrong Module added"); + assert.equal(await I_GeneralTransferManagerFactory.getInstructions.call(), + "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist, and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters.", + "Wrong Module added"); + + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_GeneralTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "General"); + }); + }); + + describe("Dummy STO Factory test cases", async() => { + it("should get the exact details of the factory", async() => { + assert.equal(await I_DummySTOFactory.setupCost.call(),0); + assert.equal((await I_DummySTOFactory.getTypes.call())[0],3); + assert.equal(web3.utils.toAscii(await I_DummySTOFactory.getName.call()) + .replace(/\u0000/g, ''), + "DummySTO", + "Wrong Module added"); + assert.equal(await I_DummySTOFactory.getDescription.call(), + "Dummy STO", + "Wrong Module added"); + assert.equal(await I_DummySTOFactory.getTitle.call(), + "Dummy STO", + "Wrong Module added"); + assert.equal(await I_DummySTOFactory.getInstructions.call(), + "Dummy STO - you can mint tokens at will", + "Wrong Module added"); + + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_DummySTOFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Dummy"); + }); + }); + + describe("Test cases for the get functions of the dummy sto", async() => { + + it("Should get the raised amount of ether", async() => { + assert.equal(await I_DummySTO.getRaised.call(0), web3.utils.toWei('0','ether')); + }); + + it("Should get the raised amount of poly", async() => { + assert.equal((await I_DummySTO.getRaised.call(1)).toNumber(), web3.utils.toWei('0','ether')); + }); + + it("Should get the investors", async() => { + assert.equal((await I_DummySTO.investorCount.call()).toNumber(), 2); + }); + + it("Should get the listed permissions", async() => { + let tx = await I_DummySTO.getPermissions.call(); + assert.equal(web3.utils.toAscii(tx[0]).replace(/\u0000/g, ''), "ADMIN"); + }); + }); + +}); diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 012029b87..8cf353dfc 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -1,423 +1,423 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -// const CappedSTO = artifacts.require('./CappedSTO.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - - -// contract('Issuance', accounts => { - - -// // Accounts Variable declaration -// let account_polymath; -// let account_investor1; -// let account_issuer; -// let token_owner; -// let account_investor2; -// let account_fundsReceiver; -// let account_delegate; -// let blockNo; -// let balanceOfReceiver; -// let message = "Transaction Should Fail!"; -// const TM_Perm = "WHITELIST"; -// const delegateDetails = "I am delegate" -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(15); -// let expiryTime = toTime + duration.days(100); - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_CappedSTOFactory; -// let I_MRProxied; -// let I_STRProxied; -// let I_STFactory; -// let I_SecurityToken; -// let I_CappedSTO; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details (Launched ST on the behalf of the issuer) -// const name = "Demo Token"; -// const symbol = "DET"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; - -// // Module key -// const permissionManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; -// const budget = 0; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// // Capped STO details -// //let startTime; // Start time will be 5000 seconds more than the latest time -// //let endTime; // Add 30 days more -// const cap = web3.utils.toWei("10000"); -// const rate = 1000; -// const fundRaiseType = [0]; -// const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); -// const maxCost = cappedSTOSetupCost; -// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; -// account_investor1 = accounts[3]; -// account_investor2 = accounts[2]; -// account_fundsReceiver = accounts[4]; -// account_delegate = accounts[5]; -// token_owner = account_issuer; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 6: Deploy the CappedSTOFactory - -// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); - -// assert.notEqual( -// I_CappedSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CappedSTOFactory contract was not deployed" -// ); - -// // Step 8: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 9: Deploy the SecurityTokenRegistry contract +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +const CappedSTO = artifacts.require('./CappedSTO.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + + +contract('Issuance', accounts => { + + + // Accounts Variable declaration + let account_polymath; + let account_investor1; + let account_issuer; + let token_owner; + let account_investor2; + let account_fundsReceiver; + let account_delegate; + let blockNo; + let balanceOfReceiver; + let message = "Transaction Should Fail!"; + const TM_Perm = "WHITELIST"; + const delegateDetails = "I am delegate" + // investor Details + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(15); + let expiryTime = toTime + duration.days(100); + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_CappedSTOFactory; + let I_MRProxied; + let I_STRProxied; + let I_STFactory; + let I_SecurityToken; + let I_CappedSTO; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details (Launched ST on the behalf of the issuer) + const name = "Demo Token"; + const symbol = "DET"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + + // Module key + const permissionManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + const budget = 0; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // Capped STO details + //let startTime; // Start time will be 5000 seconds more than the latest time + //let endTime; // Add 30 days more + const cap = web3.utils.toWei("10000"); + const rate = 1000; + const fundRaiseType = [0]; + const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); + const maxCost = cappedSTOSetupCost; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + account_investor1 = accounts[3]; + account_investor2 = accounts[2]; + account_fundsReceiver = accounts[4]; + account_delegate = accounts[5]; + token_owner = account_issuer; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 6: Deploy the CappedSTOFactory + + I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); + + assert.notEqual( + I_CappedSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CappedSTOFactory contract was not deployed" + ); + + // Step 8: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 9: Deploy the SecurityTokenRegistry contract -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); -// // STEP 7: Register the Modules with the ModuleRegistry contract + // STEP 7: Register the Modules with the ModuleRegistry contract -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// CappedSTOFactory: ${I_CappedSTOFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Launch SecurityToken & STO on the behalf of the issuer", async() => { - -// describe("Create securityToken for the issuer by the polymath", async() => { - -// it("POLYMATH: Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_polymath); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_polymath }); -// let tx = await I_STRProxied.registerTicker(account_polymath, symbol, name, { from : account_polymath }); -// assert.equal(tx.logs[0].args._owner, account_polymath); -// assert.equal(tx.logs[0].args._ticker, symbol); -// }); - -// it("POLYMATH: Should generate the new security token with the same symbol as registered above", async () => { -// console.log(name, symbol, tokenDetails, false); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_polymath }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_polymath }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), transferManagerKey); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("POLYMATH: Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - -// }); - -// it("POLYMATH: Should successfully attach the STO factory with the security token", async () => { -// // STEP 4: Deploy the CappedSTOFactory - -// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: account_polymath }); - -// assert.notEqual( -// I_CappedSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CappedSTOFactory contract was not deployed" -// ); - -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - -// let bytesSTO = encodeModuleCall(STOParameters, [(latestTime() + duration.seconds(5000)), (latestTime() + duration.days(30)), cap, rate, fundRaiseType, account_fundsReceiver]); - -// await I_PolyToken.getTokens(cappedSTOSetupCost, account_polymath); -// await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: account_polymath}); - -// const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: account_polymath }); - -// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[3].args._name) -// .replace(/\u0000/g, ''), -// "CappedSTO", -// "CappedSTOFactory module was not added" -// ); -// I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); -// }); -// }); - -// describe("Transfer Manager operations by the polymath_account", async() => { -// it("Should modify the whitelist", async () => { - -// fromTime = latestTime(); -// toTime = latestTime() + duration.days(15); -// expiryTime = toTime + duration.days(100); - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// fromTime + duration.days(70), -// toTime + duration.days(90), -// expiryTime + duration.days(50), -// true, -// { -// from: account_polymath -// }); -// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); -// }); - -// it("Should add the delegate with permission", async() => { -// //First attach a permission manager to the token -// await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: account_polymath}); -// let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; -// I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); -// // Add permission to the deletgate (A regesteration process) -// await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_polymath}); -// // Providing the permission to the delegate -// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm, true, { from: account_polymath }); - -// assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm)); -// }); - -// it("POLYMATH: Should change the ownership of the SecurityToken", async() => { -// await I_SecurityToken.transferOwnership(token_owner, { from : account_polymath }); - -// assert.equal(await I_SecurityToken.owner.call(), token_owner); -// }); -// }) - -// describe("Operations on the STO", async() => { -// it("Should Buy the tokens", async() => { -// balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); -// blockNo = latestBlock(); -// // Jump time -// await increaseTime(5000); -// // Fallback transaction -// await web3.eth.sendTransaction({ -// from: account_investor1, -// to: I_CappedSTO.address, -// gas: 6100000, -// value: web3.utils.toWei('1', 'ether') -// }); - -// assert.equal( -// (await I_CappedSTO.getRaised.call(0)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1 -// ); - -// assert.equal(await I_CappedSTO.investorCount.call(), 1); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000 -// ); -// }); - -// it("Verification of the event Token Purchase", async() => { -// const log = await promisifyLogWatch(I_CappedSTO.TokenPurchase({from: blockNo}), 1); -// assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); -// assert.equal( -// (log.args.amount) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000, -// "Wrong No. token get dilivered" -// ); -// }); - -// it("should add the investor into the whitelist by the delegate", async () => { -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: account_delegate, -// gas: 7000000 -// }); -// assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); -// }); - -// it("Should buy the token", async () => { -// await web3.eth.sendTransaction({ -// from: account_investor2, -// to: I_CappedSTO.address, -// gas: 2100000, -// value: web3.utils.toWei('1', 'ether') -// }); - -// assert.equal( -// (await I_CappedSTO.getRaised.call(0)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 2 -// ); - -// assert.equal(await I_CappedSTO.investorCount.call(), 2); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000 -// ); -// }) -// }); -// }); -// }); + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + CappedSTOFactory: ${I_CappedSTOFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Launch SecurityToken & STO on the behalf of the issuer", async() => { + + describe("Create securityToken for the issuer by the polymath", async() => { + + it("POLYMATH: Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_polymath); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_polymath }); + let tx = await I_STRProxied.registerTicker(account_polymath, symbol, name, { from : account_polymath }); + assert.equal(tx.logs[0].args._owner, account_polymath); + assert.equal(tx.logs[0].args._ticker, symbol); + }); + + it("POLYMATH: Should generate the new security token with the same symbol as registered above", async () => { + console.log(name, symbol, tokenDetails, false); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_polymath }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_polymath }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), transferManagerKey); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("POLYMATH: Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + + }); + + it("POLYMATH: Should successfully attach the STO factory with the security token", async () => { + // STEP 4: Deploy the CappedSTOFactory + + I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: account_polymath }); + + assert.notEqual( + I_CappedSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CappedSTOFactory contract was not deployed" + ); + + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + + let bytesSTO = encodeModuleCall(STOParameters, [(latestTime() + duration.seconds(5000)), (latestTime() + duration.days(30)), cap, rate, fundRaiseType, account_fundsReceiver]); + + await I_PolyToken.getTokens(cappedSTOSetupCost, account_polymath); + await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: account_polymath}); + + const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: account_polymath }); + + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "CappedSTO", + "CappedSTOFactory module was not added" + ); + I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); + }); + }); + + describe("Transfer Manager operations by the polymath_account", async() => { + it("Should modify the whitelist", async () => { + + fromTime = latestTime(); + toTime = latestTime() + duration.days(15); + expiryTime = toTime + duration.days(100); + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + fromTime + duration.days(70), + toTime + duration.days(90), + expiryTime + duration.days(50), + true, + { + from: account_polymath + }); + assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); + }); + + it("Should add the delegate with permission", async() => { + //First attach a permission manager to the token + await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: account_polymath}); + let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; + I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); + // Add permission to the deletgate (A regesteration process) + await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_polymath}); + // Providing the permission to the delegate + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm, true, { from: account_polymath }); + + assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm)); + }); + + it("POLYMATH: Should change the ownership of the SecurityToken", async() => { + await I_SecurityToken.transferOwnership(token_owner, { from : account_polymath }); + + assert.equal(await I_SecurityToken.owner.call(), token_owner); + }); + }) + + describe("Operations on the STO", async() => { + it("Should Buy the tokens", async() => { + balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); + blockNo = latestBlock(); + // Jump time + await increaseTime(5000); + // Fallback transaction + await web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO.address, + gas: 6100000, + value: web3.utils.toWei('1', 'ether') + }); + + assert.equal( + (await I_CappedSTO.getRaised.call(0)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1 + ); + + assert.equal(await I_CappedSTO.investorCount.call(), 1); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000 + ); + }); + + it("Verification of the event Token Purchase", async() => { + const log = await promisifyLogWatch(I_CappedSTO.TokenPurchase({from: blockNo}), 1); + assert.equal(log.args.purchaser, account_investor1, "Wrong address of the investor"); + assert.equal( + (log.args.amount) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000, + "Wrong No. token get dilivered" + ); + }); + + it("should add the investor into the whitelist by the delegate", async () => { + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + fromTime, + toTime, + expiryTime, + true, + { + from: account_delegate, + gas: 7000000 + }); + assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + }); + + it("Should buy the token", async () => { + await web3.eth.sendTransaction({ + from: account_investor2, + to: I_CappedSTO.address, + gas: 2100000, + value: web3.utils.toWei('1', 'ether') + }); + + assert.equal( + (await I_CappedSTO.getRaised.call(0)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 2 + ); + + assert.equal(await I_CappedSTO.investorCount.call(), 2); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000 + ); + }) + }); + }); +}); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 0515b7e9c..064027246 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -1,711 +1,711 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol'); -// const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); -// const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); -// const CountTransferManager = artifacts.require('./CountTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('ManualApprovalTransferManager', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; -// let account_investor5; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_GeneralTransferManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_ManualApprovalTransferManagerFactory; -// let P_ManualApprovalTransferManagerFactory; -// let P_ManualApprovalTransferManager; -// let I_CountTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_ManualApprovalTransferManager; -// let I_CountTransferManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_MRProxied; -// let I_STRProxied; -// let I_STFactory; -// let I_SecurityToken; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; - -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; - -// account_investor1 = accounts[6]; -// account_investor2 = accounts[7]; -// account_investor3 = accounts[8]; -// account_investor4 = accounts[9]; -// account_investor5 = accounts[5]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the GeneralDelegateManagerFactoryFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 6: Deploy the ManualApprovalTransferManagerFactory -// I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); -// assert.notEqual( -// I_ManualApprovalTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "ManualApprovalTransferManagerFactory contract was not deployed" -// ); - -// // STEP 7: Deploy the Paid ManualApprovalTransferManagerFactory -// P_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); -// assert.notEqual( -// P_ManualApprovalTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "ManualApprovalTransferManagerFactory contract was not deployed" -// ); - -// // STEP 8: Deploy the CountTransferManagerFactory -// I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); -// assert.notEqual( -// I_CountTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CountTransferManagerFactory contract was not deployed" -// ); - -// // Step 10: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol'); +const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); +const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); +const CountTransferManager = artifacts.require('./CountTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('ManualApprovalTransferManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_investor5; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_ManualApprovalTransferManagerFactory; + let P_ManualApprovalTransferManagerFactory; + let P_ManualApprovalTransferManager; + let I_CountTransferManagerFactory; + let I_GeneralPermissionManager; + let I_ManualApprovalTransferManager; + let I_CountTransferManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_MRProxied; + let I_STRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[6]; + account_investor2 = accounts[7]; + account_investor3 = accounts[8]; + account_investor4 = accounts[9]; + account_investor5 = accounts[5]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactoryFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 6: Deploy the ManualApprovalTransferManagerFactory + I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + assert.notEqual( + I_ManualApprovalTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "ManualApprovalTransferManagerFactory contract was not deployed" + ); + + // STEP 7: Deploy the Paid ManualApprovalTransferManagerFactory + P_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); + assert.notEqual( + P_ManualApprovalTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "ManualApprovalTransferManagerFactory contract was not deployed" + ); + + // STEP 8: Deploy the CountTransferManagerFactory + I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + assert.notEqual( + I_CountTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CountTransferManagerFactory contract was not deployed" + ); + + // Step 10: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); -// // Step 11: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 12: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 13: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 9: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the ManualApprovalTransferManagerFactory -// await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the ManualApprovalTransferManagerFactory -// await I_MRProxied.registerModule(P_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(P_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); - -// // (D) : Register the CountTransferManagerFactory -// await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// ManualApprovalTransferManagerFactory: ${I_ManualApprovalTransferManagerFactory.address} -// CountTransferManagerFactory: ${I_CountTransferManagerFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal(web3.utils.toUtf8(log.args._name), "GeneralTransferManager"); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); - -// }); - -// describe("Buy tokens using whitelist & manual approvals", async() => { - -// it("Should Buy the tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(5000); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('4', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('4', 'ether') -// ); -// }); - -// it("Should Buy some more tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { -// let errorThrown = false; -// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); -// try { -// const tx = await I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx -> failed because Token is not paid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the General permission manager factory with the security token", async () => { -// let snapId = await takeSnapshot(); -// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); -// const tx = await I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "Manual Approval Transfer Manager doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[3].args._name) -// .replace(/\u0000/g, ''), -// "ManualApprovalTransferManager", -// "ManualApprovalTransferManagerFactory module was not added" -// ); -// P_ManualApprovalTransferManagerFactory = ManualApprovalTransferManager.at(tx.logs[3].args._module); -// await revertToSnapshot(snapId); -// }); - - -// it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { -// const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); -// assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManager module was not added"); -// I_ManualApprovalTransferManager = ManualApprovalTransferManager.at(tx.logs[2].args._module); -// }); -// //function verifyTransfer(address _from, address _to, uint256 _amount, bool _isTransfer) public returns(Result) { -// it("Cannot call verifyTransfer on the TM directly if _isTransfer == true", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.verifyTransfer(account_investor4, account_investor4, web3.utils.toWei('2', 'ether'), "", true, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid not from SecurityToken`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Can call verifyTransfer on the TM directly if _isTransfer == false", async() => { -// await I_ManualApprovalTransferManager.verifyTransfer(account_investor4, account_investor4, web3.utils.toWei('2', 'ether'), "", false, { from: token_owner }); -// }); - -// it("Add a new token holder", async() => { - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Should still be able to transfer between existing token holders", async() => { -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('5', 'ether') -// ); -// }); - -// it("Should fail to add a manual approval because invalid _from address", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.addManualApproval("", account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid _from address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to add a manual approval because invalid _to address", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.addManualApproval(account_investor1, "", web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid _to address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to add a manual approval because invalid expiry time", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), 99999, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid expiry time`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Add a manual approval for a 4th investor", async() => { -// await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); -// }); - -// it("Should fail to revoke manual approval because invalid _from address", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.revokeManualApproval("", account_investor4, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid _from address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to revoke manual approval because invalid _to address", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, "", { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid _to address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should revoke manual approval", async() => { -// let tx = await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { from: token_owner }); -// assert.equal(tx.logs[0].args._from, account_investor1); -// assert.equal(tx.logs[0].args._to, account_investor4); -// assert.equal(tx.logs[0].args._addedBy, token_owner); -// await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); -// }); - -// it("Use 50% of manual approval for transfer", async() => { -// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Check verifyTransfer without actually transferring", async() => { -// let verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('1', 'ether'), ""); -// console.log(JSON.stringify(verified)); -// assert.equal(verified, true); - -// verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), ""); -// assert.equal(verified, false); - -// verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('1', 'ether'), ""); -// assert.equal(verified, true); - -// }); - -// it("Use remaining 50% of manual approval for transfer", async() => { -// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), -// web3.utils.toWei('2', 'ether') -// ); -// }); - -// it("Check further transfers fail", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> No remaining allowance`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// //Check that other transfers are still valid -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - -// }); - -// it("Should fail to add a manual block because invalid _from address", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.addManualBlocking("", account_investor2, latestTime() + duration.days(1), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid _from address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to add a manual block because invalid _to address", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, "", latestTime() + duration.days(1), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid _to address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to add a manual block because invalid expiry time", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, 99999, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid expiry time`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Add a manual block for a 2nd investor", async() => { -// await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { from: token_owner }); -// }); - -// it("Check manual block causes failure", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> Manual block`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Should fail to revoke manual block because invalid _from address", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.revokeManualBlocking("0x0", account_investor2, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid _from address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to revoke manual block because invalid _to address", async() => { -// let errorThrown = false; -// try { -// await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, "0x0", { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> invalid _to address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Revoke manual block and check transfer works", async() => { -// await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: token_owner }); -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('2', 'ether') -// ); -// }); - -// it("Check manual block ignored after expiry", async() => { -// await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { from: token_owner }); -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> Manual block`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// await increaseTime(1 + (24 * 60 * 60)); -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// }); - -// it("Should successfully attach the CountTransferManager with the security token (count of 1)", async () => { -// let bytesCountTM = web3.eth.abi.encodeFunctionCall({ -// name: 'configure', -// type: 'function', -// inputs: [{ -// type: 'uint256', -// name: '_maxHolderCount' -// } -// ] -// }, [1]); - -// const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); -// let name = web3.utils.toUtf8(tx.logs[2].args._name); -// assert.equal(name, "CountTransferManager", "CountTransferManager module was not added"); -// I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); - -// }); - -// it("Should get the permission list", async() => { -// let perm = await I_ManualApprovalTransferManager.getPermissions.call(); -// assert.equal(perm.length, 1); -// }); - -// // it("Check manual approval has a higher priority than an INVALID result from another TM", async() => { -// // //Should fail initial transfer -// // let errorThrown = false; -// // try { -// // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); -// // } catch(error) { -// // console.log(`Failed due to to count block`); -// // ensureException(error); -// // errorThrown = true; -// // } -// // //Add a manual approval - transfer should now work -// // await I_ManualApprovalTransferManager.addManualApproval(account_investor2, account_investor5, web3.utils.toWei('1', 'ether'), latestTime() + duration.days(1), { from: token_owner }); -// // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); -// // }); - -// it("Should get the init function", async() => { -// let byte = await I_ManualApprovalTransferManager.getInitFunction.call(); -// assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); -// }); - -// }); - -// describe("ManualApproval Transfer Manager Factory test cases", async() => { - -// it("Should get the exact details of the factory", async() => { -// assert.equal(await I_ManualApprovalTransferManagerFactory.setupCost.call(),0); -// assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0],2); -// let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); -// assert.equal(name,"ManualApprovalTransferManager","Wrong Module added"); -// let desc = await I_ManualApprovalTransferManagerFactory.getDescription.call(); -// assert.equal(desc,"Manage transfers using single approvals / blocking","Wrong Module added"); -// let title = await I_ManualApprovalTransferManagerFactory.getTitle.call(); -// assert.equal(title,"Manual Approval Transfer Manager","Wrong Module added"); -// let inst = await I_ManualApprovalTransferManagerFactory.getInstructions.call(); -// assert.equal(inst,"Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.","Wrong Module added"); -// }); - -// it("Should get the tags of the factory", async() => { -// let tags = await I_ManualApprovalTransferManagerFactory.getTags.call(); -// assert.equal(web3.utils.toUtf8(tags[0]), "ManualApproval"); -// }); -// }); - -// }); + // Step 11: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 12: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 13: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 9: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the ManualApprovalTransferManagerFactory + await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the ManualApprovalTransferManagerFactory + await I_MRProxied.registerModule(P_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); + + // (D) : Register the CountTransferManagerFactory + await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + ManualApprovalTransferManagerFactory: ${I_ManualApprovalTransferManagerFactory.address} + CountTransferManagerFactory: ${I_CountTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner}); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal(web3.utils.toUtf8(log.args._name), "GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + }); + + describe("Buy tokens using whitelist & manual approvals", async() => { + + it("Should Buy the tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('4', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('4', 'ether') + ); + }); + + it("Should Buy some more tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + try { + const tx = await I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + } catch(error) { + console.log(` tx -> failed because Token is not paid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the General permission manager factory with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "Manual Approval Transfer Manager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "ManualApprovalTransferManager", + "ManualApprovalTransferManagerFactory module was not added" + ); + P_ManualApprovalTransferManagerFactory = ManualApprovalTransferManager.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + + it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); + assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManager module was not added"); + I_ManualApprovalTransferManager = ManualApprovalTransferManager.at(tx.logs[2].args._module); + }); +//function verifyTransfer(address _from, address _to, uint256 _amount, bool _isTransfer) public returns(Result) { + it("Cannot call verifyTransfer on the TM directly if _isTransfer == true", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.verifyTransfer(account_investor4, account_investor4, web3.utils.toWei('2', 'ether'), "", true, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid not from SecurityToken`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + }); + + it("Can call verifyTransfer on the TM directly if _isTransfer == false", async() => { + await I_ManualApprovalTransferManager.verifyTransfer(account_investor4, account_investor4, web3.utils.toWei('2', 'ether'), "", false, { from: token_owner }); + }); + + it("Add a new token holder", async() => { + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should still be able to transfer between existing token holders", async() => { + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('5', 'ether') + ); + }); + + it("Should fail to add a manual approval because invalid _from address", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.addManualApproval("", account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid _from address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail to add a manual approval because invalid _to address", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.addManualApproval(account_investor1, "", web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid _to address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail to add a manual approval because invalid expiry time", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), 99999, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid expiry time`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Add a manual approval for a 4th investor", async() => { + await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); + }); + + it("Should fail to revoke manual approval because invalid _from address", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.revokeManualApproval("", account_investor4, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid _from address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail to revoke manual approval because invalid _to address", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, "", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid _to address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should revoke manual approval", async() => { + let tx = await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { from: token_owner }); + assert.equal(tx.logs[0].args._from, account_investor1); + assert.equal(tx.logs[0].args._to, account_investor4); + assert.equal(tx.logs[0].args._addedBy, token_owner); + await I_ManualApprovalTransferManager.addManualApproval(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), latestTime() + duration.days(1), { from: token_owner }); + }); + + it("Use 50% of manual approval for transfer", async() => { + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Check verifyTransfer without actually transferring", async() => { + let verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('1', 'ether'), ""); + console.log(JSON.stringify(verified)); + assert.equal(verified, true); + + verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('2', 'ether'), ""); + assert.equal(verified, false); + + verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei('1', 'ether'), ""); + assert.equal(verified, true); + + }); + + it("Use remaining 50% of manual approval for transfer", async() => { + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Check further transfers fail", async() => { + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> No remaining allowance`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + //Check that other transfers are still valid + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + + }); + + it("Should fail to add a manual block because invalid _from address", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.addManualBlocking("", account_investor2, latestTime() + duration.days(1), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid _from address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail to add a manual block because invalid _to address", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, "", latestTime() + duration.days(1), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid _to address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail to add a manual block because invalid expiry time", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, 99999, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid expiry time`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Add a manual block for a 2nd investor", async() => { + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { from: token_owner }); + }); + + it("Check manual block causes failure", async() => { + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> Manual block`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + }); + + it("Should fail to revoke manual block because invalid _from address", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.revokeManualBlocking("0x0", account_investor2, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid _from address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should fail to revoke manual block because invalid _to address", async() => { + let errorThrown = false; + try { + await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, "0x0", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> invalid _to address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Revoke manual block and check transfer works", async() => { + await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: token_owner }); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Check manual block ignored after expiry", async() => { + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { from: token_owner }); + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> Manual block`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + await increaseTime(1 + (24 * 60 * 60)); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + }); + + it("Should successfully attach the CountTransferManager with the security token (count of 1)", async () => { + let bytesCountTM = web3.eth.abi.encodeFunctionCall({ + name: 'configure', + type: 'function', + inputs: [{ + type: 'uint256', + name: '_maxHolderCount' + } + ] + }, [1]); + + const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + let name = web3.utils.toUtf8(tx.logs[2].args._name); + assert.equal(name, "CountTransferManager", "CountTransferManager module was not added"); + I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); + + }); + + it("Should get the permission list", async() => { + let perm = await I_ManualApprovalTransferManager.getPermissions.call(); + assert.equal(perm.length, 1); + }); + + // it("Check manual approval has a higher priority than an INVALID result from another TM", async() => { + // //Should fail initial transfer + // let errorThrown = false; + // try { + // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + // } catch(error) { + // console.log(`Failed due to to count block`); + // ensureException(error); + // errorThrown = true; + // } + // //Add a manual approval - transfer should now work + // await I_ManualApprovalTransferManager.addManualApproval(account_investor2, account_investor5, web3.utils.toWei('1', 'ether'), latestTime() + duration.days(1), { from: token_owner }); + // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + // }); + + it("Should get the init function", async() => { + let byte = await I_ManualApprovalTransferManager.getInitFunction.call(); + assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); + }); + + }); + + describe("ManualApproval Transfer Manager Factory test cases", async() => { + + it("Should get the exact details of the factory", async() => { + assert.equal(await I_ManualApprovalTransferManagerFactory.setupCost.call(),0); + assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0],2); + let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); + assert.equal(name,"ManualApprovalTransferManager","Wrong Module added"); + let desc = await I_ManualApprovalTransferManagerFactory.getDescription.call(); + assert.equal(desc,"Manage transfers using single approvals / blocking","Wrong Module added"); + let title = await I_ManualApprovalTransferManagerFactory.getTitle.call(); + assert.equal(title,"Manual Approval Transfer Manager","Wrong Module added"); + let inst = await I_ManualApprovalTransferManagerFactory.getInstructions.call(); + assert.equal(inst,"Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.","Wrong Module added"); + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_ManualApprovalTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toUtf8(tags[0]), "ManualApproval"); + }); + }); + +}); diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 9266b014c..ae5bfb434 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -1,684 +1,684 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -// const CappedSTO = artifacts.require('./CappedSTO.sol'); -// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); -// const MockFactory = artifacts.require('./MockFactory.sol'); -// const TestSTOFactory = artifacts.require('./TestSTOFactory.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - - -// contract('ModuleRegistry', accounts => { - - -// // Accounts Variable declaration -// let account_polymath; -// let account_investor1; -// let account_issuer; -// let token_owner; -// let account_investor2; -// let account_fundsReceiver; -// let account_delegate; -// let account_temp; - -// let balanceOfReceiver; -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(15); - -// let ID_snap; -// let message = "Transaction Should fail!"; -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_GeneralTransferManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_CappedSTOFactory1; -// let I_CappedSTOFactory2; -// let I_STFactory; -// let I_MRProxied; -// let I_SecurityToken; -// let I_STRProxied; -// let I_CappedSTO; -// let I_PolyToken; -// let I_MockFactory; -// let I_TestSTOFactory; -// let I_DummySTOFactory; -// let I_PolymathRegistry; -// let I_SecurityToken2; - -// // SecurityToken Details (Launched ST on the behalf of the issuer) -// const name = "Demo Token"; -// const symbol = "det"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; - -// // Module key -// const permissionManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; -// const budget = 0; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// // delagate details -// const delegateDetails = "I am delegate .."; -// const TM_Perm = 'FLAGS'; - -// // Capped STO details -// let startTime; -// let endTime; -// const cap = web3.utils.toWei("10000"); -// const rate = 1000; -// const fundRaiseType = [0]; -// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256','uint8[]', 'address']; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; -// account_investor1 = accounts[9]; -// account_investor2 = accounts[6]; -// account_fundsReceiver = accounts[4]; -// account_delegate = accounts[5]; -// account_temp = accounts[8]; -// token_owner = account_issuer; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - -// assert.notEqual( -// I_ModuleRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "ModuleRegistry contract was not deployed", -// ); - -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// let tx = await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - -// // STEP 2: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 9: Deploy the SecurityTokenRegistry - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: update the registries addresses from the PolymathRegistry contract -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - - -// assert.notEqual( -// I_FeatureRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "FeatureRegistry contract was not deployed", -// ); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Test cases for the ModuleRegistry", async() => { - -// describe("Test case for the upgradeFromregistry", async() => { - -// it("Should successfully update the registry contract address -- failed because of bad owner", async() => { -// let errorThrown = false; -// try { -// await I_MRProxied.updateFromRegistry({from: account_temp}); -// } catch(error) { -// console.log(` tx -> revert because of bad owner`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully update the registry contract addresses", async() => { -// await I_MRProxied.updateFromRegistry({from: account_polymath}); -// assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("securityTokenRegistry")), I_SecurityTokenRegistryProxy.address); -// assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("featureRegistry")), I_FeatureRegistry.address); -// assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), I_PolyToken.address); -// }); - -// }); - -// describe("Test the state variables", async() => { - -// it("Should be the right owner", async() => { -// let _owner = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3('owner')); -// assert.equal(_owner, account_polymath, "Owner should be the correct"); -// }) - -// it("Should be the expected value of the paused and intialised variable", async() => { -// let _paused = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); -// assert.isFalse(_paused, "Should be the false"); - -// let _intialised = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); -// assert.isTrue(_intialised, "Values should be the true"); -// }) - -// it("Should be the expected value of the polymath registry", async() => { -// let _polymathRegistry = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); -// assert.equal(_polymathRegistry, I_PolymathRegistry.address, "Should be the right value of the address of the polymath registry"); -// }); -// }); - -// describe("Test cases for the registering the module", async() => { - -// it("Should fail to register the module -- when registerModule is paused", async() => { -// await I_MRProxied.pause({from: account_polymath}); -// let errorThrown = false; -// try { -// let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_delegate}); -// } catch(error) { -// console.log(` tx -> revert because already registered modules are not allowed`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// await I_MRProxied.unpause({from: account_polymath}); -// }) - -// it("Should register the module with the Module Registry", async() => { -// let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); -// assert.equal(tx.logs[0].args._moduleFactory, I_GeneralTransferManagerFactory.address, "Should be the same address"); -// assert.equal(tx.logs[0].args._owner, account_polymath, "Should be the right owner"); - -// let _list = await I_MRProxied.getModulesByType(transferManagerKey); -// assert.equal(_list.length, 1, "Length should be 1"); -// assert.equal(_list[0], I_GeneralTransferManagerFactory.address); - -// let _reputation = await I_MRProxied.getReputationByFactory(I_GeneralTransferManagerFactory.address); -// assert.equal(_reputation.length, 0); -// }); - -// it("Should fail the register the module -- Already registered module", async() => { -// let errorThrown = false; -// try { -// let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert because already registered modules are not allowed`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should fail in registering the module-- type = 0", async() => { -// I_MockFactory = await MockFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); -// let errorThrown = false; -// try { -// await I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath }); -// } catch(error) { -// console.log(` tx revert -> Module factory of 0 type`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); -// }); - -// describe("Test case for verifyModule", async() => { - -// it("Should fail in calling the verify module. Because msg.sender should be account_polymath", async () => { -// let errorThrown = false; -// try { -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> msg.sender should be account_polymath`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully verify the module -- true", async() => { -// let tx = await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); -// assert.equal( -// tx.logs[0].args._moduleFactory, -// I_GeneralTransferManagerFactory.address, -// "Failed in verifying the module" -// ); -// assert.equal( -// tx.logs[0].args._verified, -// true, -// "Failed in verifying the module" -// ); -// }); - -// it("Should successfully verify the module -- false", async() => { -// I_CappedSTOFactory1 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); -// await I_MRProxied.registerModule(I_CappedSTOFactory1.address, {from: account_polymath}); -// let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory1.address, false, { from: account_polymath }); -// assert.equal( -// tx.logs[0].args._moduleFactory, -// I_CappedSTOFactory1.address, -// "Failed in verifying the module" -// ); -// assert.equal( -// tx.logs[0].args._verified, -// false, -// "Failed in verifying the module" -// ); -// }); - -// it("Should fail in verifying the module. Because the module is not registered", async() => { -// let errorThrown = false; -// try { -// await I_MRProxied.verifyModule(I_MockFactory.address, true, { from: account_polymath }); -// } catch(error) { -// console.log(` tx revert -> Module is not registered`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); -// }) - -// describe("Test cases for the useModule function of the module registry", async() => { - -// it("Deploy the securityToken", async() => { -// await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); -// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); -// await I_STRProxied.registerTicker(account_issuer, symbol, name, {from: account_issuer}); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, true, {from: account_issuer}); -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase()); -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); -// }); - -// it("Should fail in adding module. Because module is un-verified", async() => { -// startTime = latestTime() + duration.seconds(5000); -// endTime = startTime + duration.days(30); -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); -// let errorThrown = false; -// try { -// const tx = await I_SecurityToken.addModule(I_CappedSTOFactory1.address, bytesSTO, 0, 0, { from: token_owner}); -// } catch(error) { -// errorThrown = true; -// console.log(` tx revert -> Module is un-verified`.grey); -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to register module because custom modules not allowed", async() => { -// I_CappedSTOFactory2 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); - -// assert.notEqual( -// I_CappedSTOFactory2.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CappedSTOFactory contract was not deployed" -// ); - - -// let errorThrown = false; -// try { -// let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); -// } catch(error) { -// errorThrown = true; -// console.log(` tx revert -> Module is un-verified`.grey); -// ensureException(error); -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Should switch customModulesAllowed to true", async() => { -// assert.equal(false, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be dissabled by default."); -// let tx = await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", true, { from: account_polymath }); -// assert.equal(true, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be switched to true."); -// }); - -// it("Should successfully add module because custom modules switched on", async() => { -// startTime = latestTime() + duration.seconds(5000); -// endTime = startTime + duration.days(30); -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); -// let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); -// tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, 0, 0, { from: token_owner}); - -// assert.equal(tx.logs[2].args._types[0], stoKey, "CappedSTO doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "CappedSTO", -// "CappedSTOFactory module was not added" -// ); -// let _reputation = await I_MRProxied.getReputationByFactory.call(I_CappedSTOFactory2.address); -// assert.equal(_reputation.length, 1); -// }); - -// it("Should successfully add verified module", async() => { -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, {from: account_polymath}); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, {from: account_polymath}); -// let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0], permissionManagerKey, "module doesn't get deployed"); -// }); - -// it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --lower", async() => { -// I_TestSTOFactory = await TestSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); -// await I_MRProxied.registerModule(I_TestSTOFactory.address, {from: account_polymath}); -// await I_MRProxied.verifyModule(I_TestSTOFactory.address, true, {from: account_polymath}); -// // Taking the snapshot the revert the changes from here -// let id = await takeSnapshot(); -// await I_TestSTOFactory.changeSTVersionBounds("lowerBound", [0,1,0], {from: account_polymath}); -// let _lstVersion = await I_TestSTOFactory.getLowerSTVersionBounds.call() -// assert.equal(_lstVersion[2],0); -// assert.equal(_lstVersion[1],1); -// let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); -// let errorThrown = false; -// try { -// let tx = await I_SecurityToken.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); -// } catch(error) { -// errorThrown = true; -// console.log(` tx revert -> Incompatible with the lower bound of the Module factory`.grey); -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// await revertToSnapshot(id); -// }) - -// it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --upper", async() => { -// await I_TestSTOFactory.changeSTVersionBounds("upperBound", [0,0,1], {from: account_polymath}); -// let _ustVersion = await I_TestSTOFactory.getUpperSTVersionBounds.call() -// assert.equal(_ustVersion[0],0); -// assert.equal(_ustVersion[2],1); -// await I_STRProxied.setProtocolVersion(I_STFactory.address, 1, 0, 1); - -// // Generate the new securityToken -// let newSymbol = "toro"; -// await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); -// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); -// await I_STRProxied.registerTicker(account_issuer, newSymbol, name, {from: account_issuer}); -// let tx = await I_STRProxied.generateSecurityToken(name, newSymbol, tokenDetails, true, {from: account_issuer}); -// assert.equal(tx.logs[1].args._ticker, newSymbol.toUpperCase()); -// I_SecurityToken2 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - -// let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); -// let errorThrown = false; -// try { -// let tx = await I_SecurityToken2.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); -// } catch(error) { -// errorThrown = true; -// console.log(` tx revert -> Incompatible with the upper bound of the Module factory`.grey); -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// }); - -// describe("Test case for the getModulesByTypeAndToken()", async() => { - -// it("Should get the list of available modules when the customModulesAllowed", async() => { -// let _list = await I_MRProxied.getModulesByTypeAndToken.call(3, I_SecurityToken.address); -// assert.equal(_list[0], I_CappedSTOFactory2.address); -// }) - -// it("Should get the list of available modules when the customModulesAllowed is not allowed", async() => { -// await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", false, { from: account_polymath }); -// let _list = await I_MRProxied.getModulesByTypeAndToken.call(3, I_SecurityToken.address); -// assert.equal(_list.length, 0); -// }) -// }) - -// describe("Test cases for getters", async() => { - -// it("Check getter - ", async() => { -// console.log("getModulesByType:") -// for (let i = 0; i < 5; i++) { -// let _list = await I_MRProxied.getModulesByType.call(i); -// console.log("Type: " + i + ":" + _list); -// } -// console.log("getModulesByTypeAndToken:") -// for (let i = 0; i < 5; i++) { -// let _list = await I_MRProxied.getModulesByTypeAndToken.call(i, I_SecurityToken.address); -// console.log("Type: " + i + ":" + _list); -// } -// console.log("getTagsByType:") -// for (let i = 0; i < 5; i++) { -// let _list = await I_MRProxied.getTagsByType.call(i); -// console.log("Type: " + i + ":" + _list[1]); -// console.log("Type: " + i + ":" + _list[0].map(x => web3.utils.toAscii(x))); -// } -// console.log("getTagsByTypeAndToken:") -// for (let i = 0; i < 5; i++) { -// let _list = await I_MRProxied.getTagsByTypeAndToken.call(i, I_SecurityToken.address); -// console.log("Type: " + i + ":" + _list[1]); -// console.log("Type: " + i + ":" + _list[0].map(x => web3.utils.toAscii(x))); -// } -// }) - -// }); - -// describe("Test cases for removeModule()", async() => { - -// it("Should fail if msg.sender not curator or owner", async() => { -// let errorThrown = false; -// try { -// await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_temp }); -// } catch(error) { -// errorThrown = true; -// console.log(` tx revert -> Module is un-verified`.grey); -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully remove module and delete data if msg.sender is curator", async() => { -// let snap = await takeSnapshot(); - -// let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; -// let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; - -// assert.equal(sto1,I_CappedSTOFactory1.address); -// assert.equal(sto2,I_CappedSTOFactory2.address); -// assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); - -// let tx = await I_MRProxied.removeModule(sto1, { from: account_polymath }); - -// assert.equal(tx.logs[0].args._moduleFactory, sto1, "Event is not properly emitted for _moduleFactory"); -// assert.equal(tx.logs[0].args._decisionMaker, account_polymath, "Event is not properly emitted for _decisionMaker"); - -// let sto2_end = (await I_MRProxied.getModulesByType.call(3))[1]; - -// // re-ordering -// assert.equal(sto2_end,sto2); -// // delete related data -// assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto1)), 0); -// assert.equal(await I_MRProxied.getReputationByFactory.call(sto1), 0); -// assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); -// assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto1)), false); - -// await revertToSnapshot(snap); -// }); - -// it("Should successfully remove module and delete data if msg.sender is owner", async() => { -// let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; -// let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; - -// assert.equal(sto1,I_CappedSTOFactory1.address); -// assert.equal(sto2,I_CappedSTOFactory2.address); -// assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); - -// let tx = await I_MRProxied.removeModule(sto2, { from: token_owner }); - -// assert.equal(tx.logs[0].args._moduleFactory, sto2, "Event is not properly emitted for _moduleFactory"); -// assert.equal(tx.logs[0].args._decisionMaker, token_owner, "Event is not properly emitted for _decisionMaker"); - -// let sto1_end = (await I_MRProxied.getModulesByType.call(3))[0]; - -// // re-ordering -// assert.equal(sto1_end,sto1); -// // delete related data -// assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto2)), 0); -// assert.equal(await I_MRProxied.getReputationByFactory.call(sto2), 0); -// assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); -// assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto2)), false); -// }); - -// it("Should fail if module already removed", async() => { -// let errorThrown = false; -// try { -// await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_polymath }); -// } catch(error) { -// errorThrown = true; -// console.log(` tx revert -> Module is un-verified`.grey); -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// }); - -// describe("Test cases for IRegistry functionality", async() => { - -// describe("Test cases for reclaiming funds", async() => { - -// it("Should successfully reclaim POLY tokens", async() => { -// await I_PolyToken.getTokens(web3.utils.toWei("1"), I_MRProxied.address); -// let bal1 = await I_PolyToken.balanceOf.call(account_polymath); -// await I_MRProxied.reclaimERC20(I_PolyToken.address); -// let bal2 = await I_PolyToken.balanceOf.call(account_polymath); -// assert.isAtLeast(bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), bal2.dividedBy(new BigNumber(10).pow(18)).toNumber()); -// }); - -// }); - -// describe("Test cases for pausing the contract", async() => { - -// it("Should fail to pause if msg.sender is not owner", async() => { -// let errorThrown = false; -// try { -// await I_MRProxied.pause({ from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> msg.sender should be account_polymath`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully pause the contract", async() => { -// await I_MRProxied.pause({ from: account_polymath }); -// let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); -// assert.isOk(status); -// }); - -// it("Should fail to unpause if msg.sender is not owner", async() => { -// let errorThrown = false; -// try { -// await I_MRProxied.unpause({ from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> msg.sender should be account_polymath`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully unpause the contract", async() => { -// await I_MRProxied.unpause({ from: account_polymath }); -// let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); -// assert.isNotOk(status); -// }); - -// }); - -// }); -// }); - -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +const CappedSTO = artifacts.require('./CappedSTO.sol'); +const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); +const MockFactory = artifacts.require('./MockFactory.sol'); +const TestSTOFactory = artifacts.require('./TestSTOFactory.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + + +contract('ModuleRegistry', accounts => { + + + // Accounts Variable declaration + let account_polymath; + let account_investor1; + let account_issuer; + let token_owner; + let account_investor2; + let account_fundsReceiver; + let account_delegate; + let account_temp; + + let balanceOfReceiver; + // investor Details + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(15); + + let ID_snap; + let message = "Transaction Should fail!"; + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_CappedSTOFactory1; + let I_CappedSTOFactory2; + let I_STFactory; + let I_MRProxied; + let I_SecurityToken; + let I_STRProxied; + let I_CappedSTO; + let I_PolyToken; + let I_MockFactory; + let I_TestSTOFactory; + let I_DummySTOFactory; + let I_PolymathRegistry; + let I_SecurityToken2; + + // SecurityToken Details (Launched ST on the behalf of the issuer) + const name = "Demo Token"; + const symbol = "det"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + + // Module key + const permissionManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + const budget = 0; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // delagate details + const delegateDetails = "I am delegate .."; + const TM_Perm = 'FLAGS'; + + // Capped STO details + let startTime; + let endTime; + const cap = web3.utils.toWei("10000"); + const rate = 1000; + const fundRaiseType = [0]; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256','uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + account_investor1 = accounts[9]; + account_investor2 = accounts[6]; + account_fundsReceiver = accounts[4]; + account_delegate = accounts[5]; + account_temp = accounts[8]; + token_owner = account_issuer; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + + assert.notEqual( + I_ModuleRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "ModuleRegistry contract was not deployed", + ); + + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + let tx = await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + + // STEP 2: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 9: Deploy the SecurityTokenRegistry + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: update the registries addresses from the PolymathRegistry contract + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + + + assert.notEqual( + I_FeatureRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "FeatureRegistry contract was not deployed", + ); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Test cases for the ModuleRegistry", async() => { + + describe("Test case for the upgradeFromregistry", async() => { + + it("Should successfully update the registry contract address -- failed because of bad owner", async() => { + let errorThrown = false; + try { + await I_MRProxied.updateFromRegistry({from: account_temp}); + } catch(error) { + console.log(` tx -> revert because of bad owner`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully update the registry contract addresses", async() => { + await I_MRProxied.updateFromRegistry({from: account_polymath}); + assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("securityTokenRegistry")), I_SecurityTokenRegistryProxy.address); + assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("featureRegistry")), I_FeatureRegistry.address); + assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), I_PolyToken.address); + }); + + }); + + describe("Test the state variables", async() => { + + it("Should be the right owner", async() => { + let _owner = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3('owner')); + assert.equal(_owner, account_polymath, "Owner should be the correct"); + }) + + it("Should be the expected value of the paused and intialised variable", async() => { + let _paused = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + assert.isFalse(_paused, "Should be the false"); + + let _intialised = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); + assert.isTrue(_intialised, "Values should be the true"); + }) + + it("Should be the expected value of the polymath registry", async() => { + let _polymathRegistry = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); + assert.equal(_polymathRegistry, I_PolymathRegistry.address, "Should be the right value of the address of the polymath registry"); + }); + }); + + describe("Test cases for the registering the module", async() => { + + it("Should fail to register the module -- when registerModule is paused", async() => { + await I_MRProxied.pause({from: account_polymath}); + let errorThrown = false; + try { + let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_delegate}); + } catch(error) { + console.log(` tx -> revert because already registered modules are not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + await I_MRProxied.unpause({from: account_polymath}); + }) + + it("Should register the module with the Module Registry", async() => { + let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); + assert.equal(tx.logs[0].args._moduleFactory, I_GeneralTransferManagerFactory.address, "Should be the same address"); + assert.equal(tx.logs[0].args._owner, account_polymath, "Should be the right owner"); + + let _list = await I_MRProxied.getModulesByType(transferManagerKey); + assert.equal(_list.length, 1, "Length should be 1"); + assert.equal(_list[0], I_GeneralTransferManagerFactory.address); + + let _reputation = await I_MRProxied.getReputationByFactory(I_GeneralTransferManagerFactory.address); + assert.equal(_reputation.length, 0); + }); + + it("Should fail the register the module -- Already registered module", async() => { + let errorThrown = false; + try { + let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert because already registered modules are not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should fail in registering the module-- type = 0", async() => { + I_MockFactory = await MockFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); + let errorThrown = false; + try { + await I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath }); + } catch(error) { + console.log(` tx revert -> Module factory of 0 type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + }); + + describe("Test case for verifyModule", async() => { + + it("Should fail in calling the verify module. Because msg.sender should be account_polymath", async () => { + let errorThrown = false; + try { + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_temp }); + } catch(error) { + console.log(` tx revert -> msg.sender should be account_polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully verify the module -- true", async() => { + let tx = await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + assert.equal( + tx.logs[0].args._moduleFactory, + I_GeneralTransferManagerFactory.address, + "Failed in verifying the module" + ); + assert.equal( + tx.logs[0].args._verified, + true, + "Failed in verifying the module" + ); + }); + + it("Should successfully verify the module -- false", async() => { + I_CappedSTOFactory1 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); + await I_MRProxied.registerModule(I_CappedSTOFactory1.address, {from: account_polymath}); + let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory1.address, false, { from: account_polymath }); + assert.equal( + tx.logs[0].args._moduleFactory, + I_CappedSTOFactory1.address, + "Failed in verifying the module" + ); + assert.equal( + tx.logs[0].args._verified, + false, + "Failed in verifying the module" + ); + }); + + it("Should fail in verifying the module. Because the module is not registered", async() => { + let errorThrown = false; + try { + await I_MRProxied.verifyModule(I_MockFactory.address, true, { from: account_polymath }); + } catch(error) { + console.log(` tx revert -> Module is not registered`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + }) + + describe("Test cases for the useModule function of the module registry", async() => { + + it("Deploy the securityToken", async() => { + await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); + await I_STRProxied.registerTicker(account_issuer, symbol, name, {from: account_issuer}); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, true, {from: account_issuer}); + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase()); + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + }); + + it("Should fail in adding module. Because module is un-verified", async() => { + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + let errorThrown = false; + try { + const tx = await I_SecurityToken.addModule(I_CappedSTOFactory1.address, bytesSTO, 0, 0, { from: token_owner}); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Module is un-verified`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to register module because custom modules not allowed", async() => { + I_CappedSTOFactory2 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); + + assert.notEqual( + I_CappedSTOFactory2.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CappedSTOFactory contract was not deployed" + ); + + + let errorThrown = false; + try { + let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Module is un-verified`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + + }); + + it("Should switch customModulesAllowed to true", async() => { + assert.equal(false, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be dissabled by default."); + let tx = await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", true, { from: account_polymath }); + assert.equal(true, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be switched to true."); + }); + + it("Should successfully add module because custom modules switched on", async() => { + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); + tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, 0, 0, { from: token_owner}); + + assert.equal(tx.logs[2].args._types[0], stoKey, "CappedSTO doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "CappedSTO", + "CappedSTOFactory module was not added" + ); + let _reputation = await I_MRProxied.getReputationByFactory.call(I_CappedSTOFactory2.address); + assert.equal(_reputation.length, 1); + }); + + it("Should successfully add verified module", async() => { + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, {from: account_polymath}); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, {from: account_polymath}); + let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0], permissionManagerKey, "module doesn't get deployed"); + }); + + it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --lower", async() => { + I_TestSTOFactory = await TestSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); + await I_MRProxied.registerModule(I_TestSTOFactory.address, {from: account_polymath}); + await I_MRProxied.verifyModule(I_TestSTOFactory.address, true, {from: account_polymath}); + // Taking the snapshot the revert the changes from here + let id = await takeSnapshot(); + await I_TestSTOFactory.changeSTVersionBounds("lowerBound", [0,1,0], {from: account_polymath}); + let _lstVersion = await I_TestSTOFactory.getLowerSTVersionBounds.call() + assert.equal(_lstVersion[2],0); + assert.equal(_lstVersion[1],1); + let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); + let errorThrown = false; + try { + let tx = await I_SecurityToken.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Incompatible with the lower bound of the Module factory`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + await revertToSnapshot(id); + }) + + it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --upper", async() => { + await I_TestSTOFactory.changeSTVersionBounds("upperBound", [0,0,1], {from: account_polymath}); + let _ustVersion = await I_TestSTOFactory.getUpperSTVersionBounds.call() + assert.equal(_ustVersion[0],0); + assert.equal(_ustVersion[2],1); + await I_STRProxied.setProtocolVersion(I_STFactory.address, 1, 0, 1); + + // Generate the new securityToken + let newSymbol = "toro"; + await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); + await I_STRProxied.registerTicker(account_issuer, newSymbol, name, {from: account_issuer}); + let tx = await I_STRProxied.generateSecurityToken(name, newSymbol, tokenDetails, true, {from: account_issuer}); + assert.equal(tx.logs[1].args._ticker, newSymbol.toUpperCase()); + I_SecurityToken2 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + + let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); + let errorThrown = false; + try { + let tx = await I_SecurityToken2.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Incompatible with the upper bound of the Module factory`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + }); + + describe("Test case for the getModulesByTypeAndToken()", async() => { + + it("Should get the list of available modules when the customModulesAllowed", async() => { + let _list = await I_MRProxied.getModulesByTypeAndToken.call(3, I_SecurityToken.address); + assert.equal(_list[0], I_CappedSTOFactory2.address); + }) + + it("Should get the list of available modules when the customModulesAllowed is not allowed", async() => { + await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", false, { from: account_polymath }); + let _list = await I_MRProxied.getModulesByTypeAndToken.call(3, I_SecurityToken.address); + assert.equal(_list.length, 0); + }) + }) + + describe("Test cases for getters", async() => { + + it("Check getter - ", async() => { + console.log("getModulesByType:") + for (let i = 0; i < 5; i++) { + let _list = await I_MRProxied.getModulesByType.call(i); + console.log("Type: " + i + ":" + _list); + } + console.log("getModulesByTypeAndToken:") + for (let i = 0; i < 5; i++) { + let _list = await I_MRProxied.getModulesByTypeAndToken.call(i, I_SecurityToken.address); + console.log("Type: " + i + ":" + _list); + } + console.log("getTagsByType:") + for (let i = 0; i < 5; i++) { + let _list = await I_MRProxied.getTagsByType.call(i); + console.log("Type: " + i + ":" + _list[1]); + console.log("Type: " + i + ":" + _list[0].map(x => web3.utils.toAscii(x))); + } + console.log("getTagsByTypeAndToken:") + for (let i = 0; i < 5; i++) { + let _list = await I_MRProxied.getTagsByTypeAndToken.call(i, I_SecurityToken.address); + console.log("Type: " + i + ":" + _list[1]); + console.log("Type: " + i + ":" + _list[0].map(x => web3.utils.toAscii(x))); + } + }) + + }); + + describe("Test cases for removeModule()", async() => { + + it("Should fail if msg.sender not curator or owner", async() => { + let errorThrown = false; + try { + await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_temp }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Module is un-verified`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully remove module and delete data if msg.sender is curator", async() => { + let snap = await takeSnapshot(); + + let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; + let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; + + assert.equal(sto1,I_CappedSTOFactory1.address); + assert.equal(sto2,I_CappedSTOFactory2.address); + assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); + + let tx = await I_MRProxied.removeModule(sto1, { from: account_polymath }); + + assert.equal(tx.logs[0].args._moduleFactory, sto1, "Event is not properly emitted for _moduleFactory"); + assert.equal(tx.logs[0].args._decisionMaker, account_polymath, "Event is not properly emitted for _decisionMaker"); + + let sto2_end = (await I_MRProxied.getModulesByType.call(3))[1]; + + // re-ordering + assert.equal(sto2_end,sto2); + // delete related data + assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto1)), 0); + assert.equal(await I_MRProxied.getReputationByFactory.call(sto1), 0); + assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); + assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto1)), false); + + await revertToSnapshot(snap); + }); + + it("Should successfully remove module and delete data if msg.sender is owner", async() => { + let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; + let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; + + assert.equal(sto1,I_CappedSTOFactory1.address); + assert.equal(sto2,I_CappedSTOFactory2.address); + assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); + + let tx = await I_MRProxied.removeModule(sto2, { from: token_owner }); + + assert.equal(tx.logs[0].args._moduleFactory, sto2, "Event is not properly emitted for _moduleFactory"); + assert.equal(tx.logs[0].args._decisionMaker, token_owner, "Event is not properly emitted for _decisionMaker"); + + let sto1_end = (await I_MRProxied.getModulesByType.call(3))[0]; + + // re-ordering + assert.equal(sto1_end,sto1); + // delete related data + assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto2)), 0); + assert.equal(await I_MRProxied.getReputationByFactory.call(sto2), 0); + assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); + assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto2)), false); + }); + + it("Should fail if module already removed", async() => { + let errorThrown = false; + try { + await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_polymath }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Module is un-verified`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + }); + + describe("Test cases for IRegistry functionality", async() => { + + describe("Test cases for reclaiming funds", async() => { + + it("Should successfully reclaim POLY tokens", async() => { + await I_PolyToken.getTokens(web3.utils.toWei("1"), I_MRProxied.address); + let bal1 = await I_PolyToken.balanceOf.call(account_polymath); + await I_MRProxied.reclaimERC20(I_PolyToken.address); + let bal2 = await I_PolyToken.balanceOf.call(account_polymath); + assert.isAtLeast(bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), bal2.dividedBy(new BigNumber(10).pow(18)).toNumber()); + }); + + }); + + describe("Test cases for pausing the contract", async() => { + + it("Should fail to pause if msg.sender is not owner", async() => { + let errorThrown = false; + try { + await I_MRProxied.pause({ from: account_temp }); + } catch(error) { + console.log(` tx revert -> msg.sender should be account_polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully pause the contract", async() => { + await I_MRProxied.pause({ from: account_polymath }); + let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + assert.isOk(status); + }); + + it("Should fail to unpause if msg.sender is not owner", async() => { + let errorThrown = false; + try { + await I_MRProxied.unpause({ from: account_temp }); + } catch(error) { + console.log(` tx revert -> msg.sender should be account_polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully unpause the contract", async() => { + await I_MRProxied.unpause({ from: account_polymath }); + let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + assert.isNotOk(status); + }); + + }); + + }); + }); + +}); diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index 0bd37009b..95b56bc68 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -1,507 +1,507 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol'); -// const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('PercentageTransferManager', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let P_PercentageTransferManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let P_PercentageTransferManager; -// let I_GeneralTransferManagerFactory; -// let I_PercentageTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_PercentageTransferManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_STRProxied; -// let I_MRProxied; -// let I_STFactory; -// let I_SecurityToken; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; - -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// // PercentageTransferManager details -// const holderPercentage = 70 * 10**16; // Maximum number of token holders - -// let bytesSTO = web3.eth.abi.encodeFunctionCall({ -// name: 'configure', -// type: 'function', -// inputs: [{ -// type: 'uint256', -// name: '_maxHolderPercentage' -// },{ -// type: 'bool', -// name: '_allowPrimaryIssuance' -// } -// ] -// }, [holderPercentage, false]); - -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; - -// account_investor1 = accounts[7]; -// account_investor2 = accounts[8]; -// account_investor3 = accounts[9]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4(a): Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 4(b): Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 4(c): Deploy the PercentageTransferManager -// I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); -// assert.notEqual( -// I_PercentageTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "PercentageTransferManagerFactory contract was not deployed" -// ); - -// // STEP 4(d): Deploy the PercentageTransferManager -// P_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); -// assert.notEqual( -// P_PercentageTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "PercentageTransferManagerFactory contract was not deployed" -// ); - - -// // Step 6: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 7: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 8: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol'); +const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('PercentageTransferManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let P_PercentageTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let P_PercentageTransferManager; + let I_GeneralTransferManagerFactory; + let I_PercentageTransferManagerFactory; + let I_GeneralPermissionManager; + let I_PercentageTransferManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_MRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // PercentageTransferManager details + const holderPercentage = 70 * 10**16; // Maximum number of token holders + + let bytesSTO = web3.eth.abi.encodeFunctionCall({ + name: 'configure', + type: 'function', + inputs: [{ + type: 'uint256', + name: '_maxHolderPercentage' + },{ + type: 'bool', + name: '_allowPrimaryIssuance' + } + ] + }, [holderPercentage, false]); + + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[7]; + account_investor2 = accounts[8]; + account_investor3 = accounts[9]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4(a): Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 4(b): Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 4(c): Deploy the PercentageTransferManager + I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + assert.notEqual( + I_PercentageTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "PercentageTransferManagerFactory contract was not deployed" + ); + + // STEP 4(d): Deploy the PercentageTransferManager + P_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); + assert.notEqual( + P_PercentageTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "PercentageTransferManagerFactory contract was not deployed" + ); + + + // Step 6: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 7: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 8: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); -// // Step 9: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); + // Step 9: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); -// // STEP 5: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the PercentageTransferManagerFactory -// await I_MRProxied.registerModule(I_PercentageTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_PercentageTransferManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the Paid PercentageTransferManagerFactory -// await I_MRProxied.registerModule(P_PercentageTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(P_PercentageTransferManagerFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// PercentageTransferManagerFactory: ${I_PercentageTransferManagerFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); - -// }); - -// describe("Buy tokens using on-chain whitelist", async() => { - -// it("Should Buy the tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(5000); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Should Buy some more tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Should successfully attach the PercentageTransferManager factory with the security token - failed payment", async () => { -// let errorThrown = false; -// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); -// try { -// const tx = await I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx -> failed because Token is not paid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the PercentageTransferManager factory with the security token", async () => { -// let snapId = await takeSnapshot(); -// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); -// const tx = await I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManagerFactory doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[3].args._name) -// .replace(/\u0000/g, ''), -// "PercentageTransferManager", -// "PercentageTransferManagerFactory module was not added" -// ); -// P_PercentageTransferManager = PercentageTransferManager.at(tx.logs[3].args._module); -// await revertToSnapshot(snapId); -// }); - -// it("Should successfully attach the PercentageTransferManager with the security token", async () => { -// const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "PercentageTransferManager", -// "PercentageTransferManager module was not added" -// ); -// I_PercentageTransferManager = PercentageTransferManager.at(tx.logs[2].args._module); -// }); - -// it("Add a new token holder", async() => { - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Should pause the tranfers at transferManager level", async() => { -// let tx = await I_PercentageTransferManager.pause({from: token_owner}); -// }); - -// it("Should still be able to transfer between existing token holders up to limit", async() => { -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('2', 'ether') -// ); -// }); - -// it("Should unpause the tranfers at transferManager level", async() => { -// await I_PercentageTransferManager.unpause({from: token_owner}); -// }) - -// it("Should not be able to mint token amount over limit", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Too high minting`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Allow unlimited primary issuance and remint", async() => { -// let snapId = await takeSnapshot(); -// await I_PercentageTransferManager.setAllowPrimaryIssuance(true, { from: token_owner }); -// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner }); -// await revertToSnapshot(snapId); -// }); - -// it("Should not be able to transfer between existing token holders over limit", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> Too many holders`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Modify holder percentage to 100", async() => { -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_PercentageTransferManager.changeHolderPercentage(100 * 10**16, { from: token_owner }); - -// assert.equal( -// (await I_PercentageTransferManager.maxHolderPercentage()).toNumber(), -// 100 * 10**16 -// ); -// }); - -// it("Should be able to transfer between existing token holders up to limit", async() => { -// await I_PercentageTransferManager.modifyWhitelist(account_investor3, false, { from: token_owner }); -// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); -// }); - -// it("Should be able to whitelist address and then transfer regardless of holders", async() => { -// await I_PercentageTransferManager.changeHolderPercentage(30 * 10**16, { from: token_owner }); -// await I_PercentageTransferManager.modifyWhitelist(account_investor1, true, { from: token_owner }); -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor3 }); -// }); - -// it("Should get the permission", async() => { -// let perm = await I_PercentageTransferManager.getPermissions.call(); -// assert.equal(perm.length, 2); -// }); - -// }); - -// describe("Percentage Transfer Manager Factory test cases", async() => { - -// it("Should get the exact details of the factory", async() => { -// assert.equal(await I_PercentageTransferManagerFactory.setupCost.call(),0); -// assert.equal((await I_PercentageTransferManagerFactory.getTypes.call())[0],2); -// assert.equal(web3.utils.toAscii(await I_PercentageTransferManagerFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "PercentageTransferManager", -// "Wrong Module added"); -// assert.equal(await I_PercentageTransferManagerFactory.getDescription.call(), -// "Restrict the number of investors", -// "Wrong Module added"); -// assert.equal(await I_PercentageTransferManagerFactory.getTitle.call(), -// "Percentage Transfer Manager", -// "Wrong Module added"); -// assert.equal(await I_PercentageTransferManagerFactory.getInstructions.call(), -// "Allows an issuer to restrict the total number of non-zero token holders", -// "Wrong Module added"); - -// }); - -// it("Should get the tags of the factory", async() => { -// let tags = await I_PercentageTransferManagerFactory.getTags.call(); -// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Percentage"); -// }); -// }); - -// }); + // STEP 5: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the PercentageTransferManagerFactory + await I_MRProxied.registerModule(I_PercentageTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_PercentageTransferManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the Paid PercentageTransferManagerFactory + await I_MRProxied.registerModule(P_PercentageTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_PercentageTransferManagerFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + PercentageTransferManagerFactory: ${I_PercentageTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + }); + + describe("Buy tokens using on-chain whitelist", async() => { + + it("Should Buy the tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should Buy some more tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should successfully attach the PercentageTransferManager factory with the security token - failed payment", async () => { + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + try { + const tx = await I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + } catch(error) { + console.log(` tx -> failed because Token is not paid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the PercentageTransferManager factory with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManagerFactory doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "PercentageTransferManager", + "PercentageTransferManagerFactory module was not added" + ); + P_PercentageTransferManager = PercentageTransferManager.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the PercentageTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "PercentageTransferManager", + "PercentageTransferManager module was not added" + ); + I_PercentageTransferManager = PercentageTransferManager.at(tx.logs[2].args._module); + }); + + it("Add a new token holder", async() => { + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should pause the tranfers at transferManager level", async() => { + let tx = await I_PercentageTransferManager.pause({from: token_owner}); + }); + + it("Should still be able to transfer between existing token holders up to limit", async() => { + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should unpause the tranfers at transferManager level", async() => { + await I_PercentageTransferManager.unpause({from: token_owner}); + }) + + it("Should not be able to mint token amount over limit", async() => { + let errorThrown = false; + try { + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Too high minting`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Allow unlimited primary issuance and remint", async() => { + let snapId = await takeSnapshot(); + await I_PercentageTransferManager.setAllowPrimaryIssuance(true, { from: token_owner }); + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner }); + await revertToSnapshot(snapId); + }); + + it("Should not be able to transfer between existing token holders over limit", async() => { + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> Too many holders`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Modify holder percentage to 100", async() => { + // Add the Investor in to the whitelist + // Mint some tokens + await I_PercentageTransferManager.changeHolderPercentage(100 * 10**16, { from: token_owner }); + + assert.equal( + (await I_PercentageTransferManager.maxHolderPercentage()).toNumber(), + 100 * 10**16 + ); + }); + + it("Should be able to transfer between existing token holders up to limit", async() => { + await I_PercentageTransferManager.modifyWhitelist(account_investor3, false, { from: token_owner }); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); + }); + + it("Should be able to whitelist address and then transfer regardless of holders", async() => { + await I_PercentageTransferManager.changeHolderPercentage(30 * 10**16, { from: token_owner }); + await I_PercentageTransferManager.modifyWhitelist(account_investor1, true, { from: token_owner }); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor3 }); + }); + + it("Should get the permission", async() => { + let perm = await I_PercentageTransferManager.getPermissions.call(); + assert.equal(perm.length, 2); + }); + + }); + + describe("Percentage Transfer Manager Factory test cases", async() => { + + it("Should get the exact details of the factory", async() => { + assert.equal(await I_PercentageTransferManagerFactory.setupCost.call(),0); + assert.equal((await I_PercentageTransferManagerFactory.getTypes.call())[0],2); + assert.equal(web3.utils.toAscii(await I_PercentageTransferManagerFactory.getName.call()) + .replace(/\u0000/g, ''), + "PercentageTransferManager", + "Wrong Module added"); + assert.equal(await I_PercentageTransferManagerFactory.getDescription.call(), + "Restrict the number of investors", + "Wrong Module added"); + assert.equal(await I_PercentageTransferManagerFactory.getTitle.call(), + "Percentage Transfer Manager", + "Wrong Module added"); + assert.equal(await I_PercentageTransferManagerFactory.getInstructions.call(), + "Allows an issuer to restrict the total number of non-zero token holders", + "Wrong Module added"); + + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_PercentageTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Percentage"); + }); + }); + +}); diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index 2ee41f30f..81ed48fd7 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -1,477 +1,477 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); -// const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('PreSaleSTO', accounts => { -// // Accounts Variable declaration -// let account_polymath; -// let account_investor1; -// let account_issuer; -// let token_owner; -// let account_investor2; -// let account_investor3; -// let account_fundsReceiver; - -// let balanceOfReceiver; -// let message = "Transaction Should Fail!"; -// // investor Details -// let fromTime; -// let toTime; -// let expiryTime; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_PreSaleSTOFactory; -// let I_STFactory; -// let I_SecurityToken; -// let I_MRProxied; -// let I_STRProxied; -// let I_PreSaleSTO; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details for funds raise Type ETH -// const name = "Team"; -// const symbol = "SAP"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; - -// // SecurityToken Details for funds raise Type POLY -// const P_name = "Team Poly"; -// const P_symbol = "PAS"; -// const P_tokenDetails = "This is equity type of issuance"; -// const P_decimals = 18; - -// // Module key -// const transferManagerKey = 2; -// const stoKey = 3; -// const budget = 0; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); -// let endTime; -// const STOParameters = ['uint256']; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { - -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; -// account_investor1 = accounts[4]; -// account_investor2 = accounts[3]; -// account_investor3 = accounts[5]; -// account_fundsReceiver = accounts[2]; -// token_owner = account_issuer; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 2: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 3: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the PreSaleSTOFactory - -// I_PreSaleSTOFactory = await PreSaleSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); - -// assert.notEqual( -// I_PreSaleSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "PreSaleSTOFactory contract was not deployed" -// ); - -// // Step 8: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 9: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 5: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// PreSaleSTOFactory: ${I_PreSaleSTOFactory.address} -// LatestTime: ${latestTime()}\n -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), transferManagerKey); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); -// }); - -// it("Should fail to launch the STO due to endTime is 0", async () => { -// let bytesSTO = encodeModuleCall(STOParameters, [0]); -// let errorThrown = false; -// try { -// const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Rate is ${0}. Test Passed Successfully`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the STO factory with the security token", async () => { -// endTime = latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time -// let bytesSTO = encodeModuleCall(STOParameters, [endTime]); - -// const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); - -// assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "PreSaleSTO", -// "PreSaleSTOFactory module was not added" -// ); -// I_PreSaleSTO = PreSaleSTO.at(tx.logs[2].args._module); -// }); -// }); - -// describe("verify the data of STO", async () => { - -// it("Should verify the configuration of the STO", async() => { -// assert.equal( -// (await I_PreSaleSTO.endTime.call()).toNumber(), -// endTime, -// "STO Configuration doesn't set as expected" -// ); -// }); - -// it("Should get the permissions", async() => { -// let perm = await I_PreSaleSTO.getPermissions.call(); -// assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "PRE_SALE_ADMIN"); -// }); -// }); - -// describe("Buy tokens", async() => { - -// it("Should allocate the tokens -- failed due to investor not on whitelist", async () => { -// let errorThrown = false; -// try { -// await I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei('1', 'ether'), 0); -// } catch(error) { -// console.log(` tx revert -> Investor is not on whitelist`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should Buy the tokens", async() => { -// fromTime = latestTime(); -// toTime = fromTime + duration.days(100); -// expiryTime = toTime + duration.days(100); - -// // Add the Investor in to the whitelist -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(duration.days(1)); -// await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether'), 0, {from: account_issuer }); - -// assert.equal( -// (await I_PreSaleSTO.getRaised.call(0)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1 -// ); -// console.log(await I_PreSaleSTO.getNumberInvestors.call()); -// assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 1); -// // assert.isTrue(false); - -// }); - -// it("Should allocate the tokens -- failed due to msg.sender is not pre sale admin", async () => { -// let errorThrown = false; -// try { -// await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether'), 0, {from: account_fundsReceiver }); -// } catch(error) { -// console.log(` tx revert -> msg.sender is not pre sale admin`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should allocate tokens to multiple investors", async() => { -// fromTime = latestTime(); -// toTime = fromTime + duration.days(100); -// expiryTime = toTime + duration.days(100); - -// // Add the Investor in to the whitelist -// let tx1 = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx1.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - -// // Add the Investor in to the whitelist -// let tx2 = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: account_issuer, -// gas: 6000000 -// }); - -// assert.equal(tx2.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); - -// await I_PreSaleSTO.allocateTokensMulti([account_investor2, account_investor3], [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], [0,0], [web3.utils.toWei('1000', 'ether'), web3.utils.toWei('1000', 'ether')], {from: account_issuer }); - -// assert.equal( -// (await I_PreSaleSTO.getRaised.call(1)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 2000 -// ); -// assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 3); -// }); - -// it("Should failed at the time of buying the tokens -- Because STO has started", async() => { -// await increaseTime(duration.days(100)); // increased beyond the end time of the STO -// let errorThrown = false; -// try { -// // Fallback transaction -// await I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei('1', 'ether'), 0, {from: account_issuer}); -// } catch(error) { -// console.log(` tx revert -> STO has started`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// }); - -// describe("Reclaim poly sent to STO by mistake", async() => { - -// it("Should fail to reclaim POLY because token contract address is 0 address", async() => { -// let value = web3.utils.toWei('100','ether'); -// await I_PolyToken.getTokens(value, account_investor1); -// await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); - -// let errorThrown = false; -// try { -// await I_PreSaleSTO.reclaimERC20('0x0000000000000000000000000000000000000000', { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> token contract address is 0 address`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully reclaim POLY", async() => { -// let value = web3.utils.toWei('100','ether'); -// await I_PolyToken.getTokens(value, account_investor1); -// let initInvestorBalance = await I_PolyToken.balanceOf(account_investor1); -// let initOwnerBalance = await I_PolyToken.balanceOf(token_owner); -// let initContractBalance = await I_PolyToken.balanceOf(I_PreSaleSTO.address); - -// await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); -// await I_PreSaleSTO.reclaimERC20(I_PolyToken.address, { from: token_owner }); -// assert.equal((await I_PolyToken.balanceOf(account_investor1)).toNumber(), initInvestorBalance.sub(value).toNumber(), "tokens are not transfered out from investor account"); -// assert.equal((await I_PolyToken.balanceOf(token_owner)).toNumber(), initOwnerBalance.add(value).add(initContractBalance).toNumber(), "tokens are not added to the owner account"); -// assert.equal((await I_PolyToken.balanceOf(I_PreSaleSTO.address)).toNumber(), 0, "tokens are not trandfered out from STO contract"); -// }); -// }); - -// describe("Test cases for the PresaleSTOFactory", async() => { -// it("should get the exact details of the factory", async() => { -// assert.equal(await I_PreSaleSTOFactory.setupCost.call(),0); -// assert.equal((await I_PreSaleSTOFactory.getTypes.call())[0],3); -// assert.equal(web3.utils.toAscii(await I_PreSaleSTOFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "PreSaleSTO", -// "Wrong Module added"); -// assert.equal(await I_PreSaleSTOFactory.getDescription.call(), -// "Allows Issuer to configure pre-sale token allocations", -// "Wrong Module added"); -// assert.equal(await I_PreSaleSTOFactory.getTitle.call(), -// "PreSale STO", -// "Wrong Module added"); -// assert.equal(await I_PreSaleSTOFactory.getInstructions.call(), -// "Configure and track pre-sale token allocations", -// "Wrong Module added"); -// let tags = await I_PreSaleSTOFactory.getTags.call(); -// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Presale"); -// }); -// }); - -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); +const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('PreSaleSTO', accounts => { + // Accounts Variable declaration + let account_polymath; + let account_investor1; + let account_issuer; + let token_owner; + let account_investor2; + let account_investor3; + let account_fundsReceiver; + + let balanceOfReceiver; + let message = "Transaction Should Fail!"; + // investor Details + let fromTime; + let toTime; + let expiryTime; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_PreSaleSTOFactory; + let I_STFactory; + let I_SecurityToken; + let I_MRProxied; + let I_STRProxied; + let I_PreSaleSTO; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details for funds raise Type ETH + const name = "Team"; + const symbol = "SAP"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + + // SecurityToken Details for funds raise Type POLY + const P_name = "Team Poly"; + const P_symbol = "PAS"; + const P_tokenDetails = "This is equity type of issuance"; + const P_decimals = 18; + + // Module key + const transferManagerKey = 2; + const stoKey = 3; + const budget = 0; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + let endTime; + const STOParameters = ['uint256']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + account_investor1 = accounts[4]; + account_investor2 = accounts[3]; + account_investor3 = accounts[5]; + account_fundsReceiver = accounts[2]; + token_owner = account_issuer; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 2: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 3: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 4: Deploy the PreSaleSTOFactory + + I_PreSaleSTOFactory = await PreSaleSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); + + assert.notEqual( + I_PreSaleSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "PreSaleSTOFactory contract was not deployed" + ); + + // Step 8: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 9: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 5: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + PreSaleSTOFactory: ${I_PreSaleSTOFactory.address} + LatestTime: ${latestTime()}\n + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), transferManagerKey); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + + it("Should fail to launch the STO due to endTime is 0", async () => { + let bytesSTO = encodeModuleCall(STOParameters, [0]); + let errorThrown = false; + try { + const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Rate is ${0}. Test Passed Successfully`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the STO factory with the security token", async () => { + endTime = latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time + let bytesSTO = encodeModuleCall(STOParameters, [endTime]); + + const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); + + assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "PreSaleSTO", + "PreSaleSTOFactory module was not added" + ); + I_PreSaleSTO = PreSaleSTO.at(tx.logs[2].args._module); + }); + }); + + describe("verify the data of STO", async () => { + + it("Should verify the configuration of the STO", async() => { + assert.equal( + (await I_PreSaleSTO.endTime.call()).toNumber(), + endTime, + "STO Configuration doesn't set as expected" + ); + }); + + it("Should get the permissions", async() => { + let perm = await I_PreSaleSTO.getPermissions.call(); + assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "PRE_SALE_ADMIN"); + }); + }); + + describe("Buy tokens", async() => { + + it("Should allocate the tokens -- failed due to investor not on whitelist", async () => { + let errorThrown = false; + try { + await I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei('1', 'ether'), 0); + } catch(error) { + console.log(` tx revert -> Investor is not on whitelist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should Buy the tokens", async() => { + fromTime = latestTime(); + toTime = fromTime + duration.days(100); + expiryTime = toTime + duration.days(100); + + // Add the Investor in to the whitelist + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + fromTime, + toTime, + expiryTime, + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(duration.days(1)); + await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether'), 0, {from: account_issuer }); + + assert.equal( + (await I_PreSaleSTO.getRaised.call(0)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1 + ); + console.log(await I_PreSaleSTO.getNumberInvestors.call()); + assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 1); + // assert.isTrue(false); + + }); + + it("Should allocate the tokens -- failed due to msg.sender is not pre sale admin", async () => { + let errorThrown = false; + try { + await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether'), 0, {from: account_fundsReceiver }); + } catch(error) { + console.log(` tx revert -> msg.sender is not pre sale admin`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should allocate tokens to multiple investors", async() => { + fromTime = latestTime(); + toTime = fromTime + duration.days(100); + expiryTime = toTime + duration.days(100); + + // Add the Investor in to the whitelist + let tx1 = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + fromTime, + toTime, + expiryTime, + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx1.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + + // Add the Investor in to the whitelist + let tx2 = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + fromTime, + toTime, + expiryTime, + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx2.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); + + await I_PreSaleSTO.allocateTokensMulti([account_investor2, account_investor3], [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], [0,0], [web3.utils.toWei('1000', 'ether'), web3.utils.toWei('1000', 'ether')], {from: account_issuer }); + + assert.equal( + (await I_PreSaleSTO.getRaised.call(1)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 2000 + ); + assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 3); + }); + + it("Should failed at the time of buying the tokens -- Because STO has started", async() => { + await increaseTime(duration.days(100)); // increased beyond the end time of the STO + let errorThrown = false; + try { + // Fallback transaction + await I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei('1', 'ether'), 0, {from: account_issuer}); + } catch(error) { + console.log(` tx revert -> STO has started`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + }); + + describe("Reclaim poly sent to STO by mistake", async() => { + + it("Should fail to reclaim POLY because token contract address is 0 address", async() => { + let value = web3.utils.toWei('100','ether'); + await I_PolyToken.getTokens(value, account_investor1); + await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); + + let errorThrown = false; + try { + await I_PreSaleSTO.reclaimERC20('0x0000000000000000000000000000000000000000', { from: token_owner }); + } catch(error) { + console.log(` tx revert -> token contract address is 0 address`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully reclaim POLY", async() => { + let value = web3.utils.toWei('100','ether'); + await I_PolyToken.getTokens(value, account_investor1); + let initInvestorBalance = await I_PolyToken.balanceOf(account_investor1); + let initOwnerBalance = await I_PolyToken.balanceOf(token_owner); + let initContractBalance = await I_PolyToken.balanceOf(I_PreSaleSTO.address); + + await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); + await I_PreSaleSTO.reclaimERC20(I_PolyToken.address, { from: token_owner }); + assert.equal((await I_PolyToken.balanceOf(account_investor1)).toNumber(), initInvestorBalance.sub(value).toNumber(), "tokens are not transfered out from investor account"); + assert.equal((await I_PolyToken.balanceOf(token_owner)).toNumber(), initOwnerBalance.add(value).add(initContractBalance).toNumber(), "tokens are not added to the owner account"); + assert.equal((await I_PolyToken.balanceOf(I_PreSaleSTO.address)).toNumber(), 0, "tokens are not trandfered out from STO contract"); + }); + }); + + describe("Test cases for the PresaleSTOFactory", async() => { + it("should get the exact details of the factory", async() => { + assert.equal(await I_PreSaleSTOFactory.setupCost.call(),0); + assert.equal((await I_PreSaleSTOFactory.getTypes.call())[0],3); + assert.equal(web3.utils.toAscii(await I_PreSaleSTOFactory.getName.call()) + .replace(/\u0000/g, ''), + "PreSaleSTO", + "Wrong Module added"); + assert.equal(await I_PreSaleSTOFactory.getDescription.call(), + "Allows Issuer to configure pre-sale token allocations", + "Wrong Module added"); + assert.equal(await I_PreSaleSTOFactory.getTitle.call(), + "PreSale STO", + "Wrong Module added"); + assert.equal(await I_PreSaleSTOFactory.getInstructions.call(), + "Configure and track pre-sale token allocations", + "Wrong Module added"); + let tags = await I_PreSaleSTOFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Presale"); + }); + }); + +}); diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index 3ab004e66..7c47e12a9 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -1,1248 +1,1248 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -// const DummySTO = artifacts.require('./DummySTO.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryMock = artifacts.require('./SecurityTokenRegistryMock.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyToken = artifacts.require('./PolyToken.sol'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - - -// contract('SecurityTokenRegistry', accounts => { - - -// // Accounts Variable declaration -// let account_polymath; -// let account_investor1; -// let account_issuer; -// let token_owner; -// let account_investor2; -// let account_fundsReceiver; -// let account_delegate; -// let account_temp; -// let dummy_token; - -// let balanceOfReceiver; -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(100); - -// let ID_snap; -// const message = "Transaction Should Fail!!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_GeneralTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_SecurityTokenRegistryV2; -// let I_DummySTOFactory; -// let I_STVersion; -// let I_SecurityToken; -// let I_DummySTO; -// let I_PolyToken; -// let I_STFactory; -// let I_STFactory002; -// let I_SecurityToken002; -// let I_STFactory003; -// let I_PolymathRegistry; -// let I_SecurityTokenRegistryProxy; -// let I_STRProxied; -// let I_MRProxied; - -// // SecurityToken Details (Launched ST on the behalf of the issuer) -// const name = "Demo Token"; -// const symbol = "DET"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; - -// //Security Token Detials (Version 2) -// const name2 = "Demo2 Token"; -// const symbol2 = "DET2"; -// const tokenDetails2 = "This is equity type of issuance"; - -// // Module key -// const permissionManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; -// const budget = 0; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); -// const newRegFee = web3.utils.toWei("300"); - -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; -// const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; - -// // Capped STO details -// const cap = web3.utils.toWei("10000"); -// const someString = "Hello string"; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; -// account_investor1 = accounts[9]; -// account_investor2 = accounts[6]; -// account_fundsReceiver = accounts[4]; -// account_delegate = accounts[5]; -// account_temp = accounts[8]; -// token_owner = account_issuer; -// dummy_token = accounts[3]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 2: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 3: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - - -// // Step 6: Deploy the STversionProxy contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +const DummySTO = artifacts.require('./DummySTO.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryMock = artifacts.require('./SecurityTokenRegistryMock.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyToken = artifacts.require('./PolyToken.sol'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + + +contract('SecurityTokenRegistry', accounts => { + + + // Accounts Variable declaration + let account_polymath; + let account_investor1; + let account_issuer; + let token_owner; + let account_investor2; + let account_fundsReceiver; + let account_delegate; + let account_temp; + let dummy_token; + + let balanceOfReceiver; + // investor Details + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(100); + + let ID_snap; + const message = "Transaction Should Fail!!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_SecurityTokenRegistryV2; + let I_DummySTOFactory; + let I_STVersion; + let I_SecurityToken; + let I_DummySTO; + let I_PolyToken; + let I_STFactory; + let I_STFactory002; + let I_SecurityToken002; + let I_STFactory003; + let I_PolymathRegistry; + let I_SecurityTokenRegistryProxy; + let I_STRProxied; + let I_MRProxied; + + // SecurityToken Details (Launched ST on the behalf of the issuer) + const name = "Demo Token"; + const symbol = "DET"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + + //Security Token Detials (Version 2) + const name2 = "Demo2 Token"; + const symbol2 = "DET2"; + const tokenDetails2 = "This is equity type of issuance"; + + // Module key + const permissionManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + const budget = 0; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + const newRegFee = web3.utils.toWei("300"); + + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; + + // Capped STO details + const cap = web3.utils.toWei("10000"); + const someString = "Hello string"; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + account_investor1 = accounts[9]; + account_investor2 = accounts[6]; + account_fundsReceiver = accounts[4]; + account_delegate = accounts[5]; + account_temp = accounts[8]; + token_owner = account_issuer; + dummy_token = accounts[3]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 2: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 3: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + + // Step 6: Deploy the STversionProxy contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); -// // STEP 8: Deploy the CappedSTOFactory + // STEP 8: Deploy the CappedSTOFactory -// I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 1000 * Math.pow(10, 18), 0, 0,{ from: token_owner }); + I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 1000 * Math.pow(10, 18), 0, 0,{ from: token_owner }); -// assert.notEqual( -// I_DummySTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "TestSTOFactory contract was not deployed" -// ); + assert.notEqual( + I_DummySTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "TestSTOFactory contract was not deployed" + ); -// // Step 9: Deploy the SecurityTokenRegistry + // Step 9: Deploy the SecurityTokenRegistry -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 9 (a): Deploy the proxy -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 10: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// assert.notEqual( -// I_FeatureRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "FeatureRegistry contract was not deployed", -// ); - -// //Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 4: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); - -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// DummySTOFactory: ${I_DummySTOFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - - -// describe(" Test cases of the registerTicker", async() => { - -// it("verify the intial parameters", async() => { -// let intialised = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); -// assert.isTrue(intialised, "Should be true"); - -// let expiry = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit")); -// assert.equal(expiry.toNumber(), 5184000, "Expiry limit should be equal to 60 days"); - -// let polytoken = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")); -// assert.equal(polytoken, I_PolyToken.address, "Should be the polytoken address"); - -// let stlaunchFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("stLaunchFee")); -// assert.equal(stlaunchFee.toNumber(), initRegFee, "Should be provided reg fee"); - -// let tickerRegFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee")); -// assert.equal(tickerRegFee.toNumber(), tickerRegFee, "Should be provided reg fee"); - -// let polymathRegistry = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); -// assert.equal(polymathRegistry, I_PolymathRegistry.address, "Should be the address of the polymath registry"); - -// let owner = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("owner")); -// assert.equal(owner, account_polymath, "Should be the address of the registry owner"); -// }); - -// it("Can't call the intialize function again", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.initialize(I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath); -// } catch(error) { -// console.log(` tx revert -> Can't call the intialize function again`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should fail to register ticker if tickerRegFee not approved", async() => { -// let errorThrown = false; -// try { -// let tx = await I_STRProxied.registerTicker(account_temp, symbol, name, { from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> POLY allowance not provided for registration fee`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to register ticker if owner is 0x", async() => { -// let errorThrown = false; -// try { -// await I_PolyToken.getTokens(initRegFee, account_temp); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); -// let tx = await I_STRProxied.registerTicker("0x0000000000000000000000000000000000000000", symbol, name, { from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> owner should not be 0x`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to register ticker due to the symbol length is 0", async() => { -// let errorThrown = false; -// try { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); -// let tx = await I_STRProxied.registerTicker(account_temp, "", name, { from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> Symbol Length is 0`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to register ticker due to the symbol length is greater than 10", async() => { -// let errorThrown = false; -// try { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); -// let tx = await I_STRProxied.registerTicker(account_temp, "POLYMATHNET", name, { from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> Symbol Length is greater than 10`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should register the ticker before the generation of the security token", async () => { -// let tx = await I_STRProxied.registerTicker(account_temp, symbol, name, { from: account_temp }); -// assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); -// assert.equal(tx.logs[0].args._ticker, symbol, `Symbol should be ${symbol}`); -// }); - -// it("Should fail to register same symbol again", async() => { -// // Give POLY to token issuer -// await I_PolyToken.getTokens(initRegFee, token_owner); - -// // Call registration function -// let errorThrown = false; -// try { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Symbol is already alloted to someone else`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully register pre registerd ticker if expiry is reached", async() => { -// await increaseTime(5184000 + 100); // 60(5184000) days of expiry + 100 sec for buffer -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner, `Owner should be the ${token_owner}`); -// assert.equal(tx.logs[0].args._ticker, symbol, `Symbol should be ${symbol}`); -// }); - -// it("Should fail to register ticker if registration is paused", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.pause({ from: account_polymath}); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Registration is paused`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to pause if already paused", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.pause({ from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> Registration is already paused`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully register ticker if registration is unpaused", async() => { -// await I_STRProxied.unpause({ from: account_polymath}); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner, `Owner should be the ${token_owner}`); -// assert.equal(tx.logs[0].args._ticker, "AAA", `Symbol should be AAA`); -// }); - -// it("Should fail to unpause if already unpaused", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.unpause({ from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> Registration is already unpaused`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); -// }); - -// describe("Test cases for the expiry limit", async() => { - -// it("Should fail to set the expiry limit because msg.sender is not owner", async() => { -// let errorThrown = false; -// try { -// let tx = await I_STRProxied.changeExpiryLimit(duration.days(10), {from: account_temp}); -// } catch(error) { -// console.log(` tx revert -> msg.sender is not owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully set the expiry limit", async() => { -// await I_STRProxied.changeExpiryLimit(duration.days(10), {from: account_polymath}); -// assert.equal( -// (await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))) -// .toNumber(), -// duration.days(10), -// "Failed to change the expiry limit"); -// }); - -// it("Should fail to set the expiry limit because new expiry limit is lesser than one day", async() => { -// let errorThrown = false; -// try { -// let tx = await I_STRProxied.changeExpiryLimit(duration.seconds(5000), {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> New expiry limit is lesser than one day`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); -// }); - -// describe("Test cases for the getTickerDetails", async() => { - -// it("Should get the details of the symbol", async() => { -// let tx = await I_STRProxied.getTickerDetails.call(symbol); -// assert.equal(tx[0], token_owner, "Should equal to the rightful owner of the ticker"); -// assert.equal(tx[3], name, `Name of the token should equal to ${name}`); -// assert.equal(tx[4], false, "Status if the symbol should be undeployed -- false"); -// }); - -// it("Should get the details of unregistered token", async() => { -// let tx = await I_STRProxied.getTickerDetails.call("TORO"); -// assert.equal(tx[0], "0x0000000000000000000000000000000000000000", "Should be 0x as ticker is not exists in the registry"); -// assert.equal(tx[3], "", "Should be an empty string"); -// assert.equal(tx[4], false, "Status if the symbol should be undeployed -- false"); -// }); -// }); - -// describe("Generate SecurityToken", async() => { - -// it("Should get the ticker details successfully and prove the data is not storing in to the logic contract", async() => { -// let data = await I_STRProxied.getTickerDetails(symbol, {from: token_owner}); -// assert.equal(data[0], token_owner, "Token owner should be equal"); -// assert.equal(data[3], name, "Name of the token should match with the registered symbol infor"); -// assert.equal(data[4], false, "Token is not launched yet so it should return False"); -// data = await I_SecurityTokenRegistry.getTickerDetails(symbol, {from:token_owner}); -// console.log("This is the data from the original securityTokenRegistry contract"); -// assert.equal(data[0], '0x0000000000000000000000000000000000000000', "Token owner should be 0x"); -// }) - -// it("Should fail to generate new security token if fee not provided", async() => { -// let errorThrown = false; -// await I_PolyToken.approve(I_STRProxied.address, 0, { from: token_owner}); -// try { -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> POLY allowance not provided for registration fee`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to generate token if registration is paused", async() => { -// let errorThrown = false; -// await I_STRProxied.pause({ from: account_polymath}); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// try { -// await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Registration is paused`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to generate the securityToken -- Because ticker length is 0", async() => { -// let errorThrown = false; -// await I_STRProxied.unpause({ from: account_polymath}); -// try { -// await I_STRProxied.generateSecurityToken(name, "", tokenDetails, false, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Zero ticker length is not allowed`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should fail to generate the securityToken -- Because name length is 0", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> 0 name length is not allowed`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should fail to generate the securityToken -- Because msg.sender is not the rightful owner of the ticker", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> Because msg.sender is not the rightful owner of the ticker`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTrasnferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), transferManagerKey, `Should be equal to the ${transferManagerKey}`); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should fail to generate the SecurityToken when token is already deployed with the same symbol", async() => { -// let errorThrown = false; -// try { -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> Because ticker is already in use`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// }); - -// describe("Generate SecurityToken v2", async() => { - -// it("Should deploy the st version 2", async() => { -// // Step 7: Deploy the STFactory contract - -// I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory002.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory002 contract was not deployed", -// ); -// await I_STRProxied.setProtocolVersion(I_STFactory002.address, 0, 2, 0, { from: account_polymath }); -// let _protocol = await I_STRProxied.getProtocolVersion.call(); -// assert.equal(_protocol[0], 0); -// assert.equal(_protocol[1], 2); -// assert.equal(_protocol[2], 0); -// }); - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol2, name2, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner, `Token owner should be ${token_owner}`); -// assert.equal(tx.logs[0].args._ticker, symbol2, `Symbol should be ${symbol2}`); -// }); - -// it("Should generate the new security token with version 2", async() => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol2, "SecurityToken doesn't get deployed"); - -// I_SecurityToken002 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); -// let tokens = await I_STRProxied.getTokensByOwner.call(token_owner); -// assert.equal(tokens[0], I_SecurityToken.address); -// assert.equal(tokens[1], I_SecurityToken002.address); - -// const log = await promisifyLogWatch(I_SecurityToken002.ModuleAdded({from: _blockNo}), 1); -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), transferManagerKey); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// }); - -// describe("Deploy the new SecurityTokenRegistry", async() => { - -// it("Should deploy the new SecurityTokenRegistry contract logic", async() => { -// I_SecurityTokenRegistryV2 = await SecurityTokenRegistryMock.new({ from: account_polymath }); -// assert.notEqual( -// I_SecurityTokenRegistryV2.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); -// }); - -// it("Should fail to upgrade the logic contract of the STRProxy -- bad owner", async() => { -// let errorThrown = false; -// await I_STRProxied.pause({from: account_polymath}); -// try { -// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, {from: account_temp}); -// } catch(error) { -// console.log(` tx revert -> bad owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should upgrade the logic contract into the STRProxy", async() =>{ -// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); -// assert.isTrue(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); -// }); - -// it("Should check the old data persist or not", async() => { -// let data = await I_STRProxied.getTickerDetails.call(symbol); -// assert.equal(data[0], token_owner, "Should be equal to the token owner address"); -// assert.equal(data[3], name, "Should be equal to the name of the token that is provided earlier"); -// assert.isTrue(data[4], "Token status should be deployed == true"); -// }); - -// it("Should unpause the logic contract", async() => { -// await I_STRProxied.unpause({from: account_polymath}); -// assert.isFalse(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); -// }); -// }) - -// describe("Generate custom tokens", async() => { - -// it("Should fail if msg.sender is not polymath", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_delegate}); -// } catch(error) { -// console.log(` tx revert -> msg.sender is not polymath account`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to generate the custom security token -- name should not be 0 length ", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifySecurityToken("", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> name should not be 0 length `.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail if ST address is 0 address", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, 0, "I am custom ST", latestTime(), {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> Security token address is 0`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail if symbol length is 0", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifySecurityToken("", "", account_temp, dummy_token, "I am custom ST",latestTime(), {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> zero length of the symbol is not allowed`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to generate the custom ST -- deployedAt param is 0", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifySecurityToken(name2, symbol2, token_owner, dummy_token, "I am custom ST", 0, {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> because deployedAt param is 0`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully generate custom token", async() => { -// // Register the new ticker -- Fulfiling the TickerStatus.ON condition -// await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); -// let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); -// console.log(tickersListArray); -// await I_STRProxied.registerTicker(account_temp, "LOG", "LOGAN", { from : account_temp }); -// tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); -// console.log(tickersListArray); -// // Generating the ST -// let tx = await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); -// tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); -// console.log(tickersListArray); -// assert.equal(tx.logs[1].args._ticker, "LOG", "Symbol should match with the registered symbol"); -// assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token,`Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); -// let symbolDetails = await I_STRProxied.getTickerDetails("LOG"); -// assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); -// assert.equal(symbolDetails[3], "LOGAN", `Name of the symbol should be LOGAN`); -// }); - -// it("Should successfully generate the custom token", async() => { -// // Fulfilling the TickerStatus.NN condition -// // let errorThrown = false; -// // try { -// // await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); -// // } catch(error) { -// // console.log(` tx revert -> because ticker not registered`.grey); -// // errorThrown = true; -// // ensureException(error); -// // } -// // assert.ok(errorThrown, message); -// // await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(10), false, {from: account_polymath}); -// // await increaseTime(duration.days(1)); -// let tx = await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); -// assert.equal(tx.logs[1].args._ticker, "LOG2", "Symbol should match with the registered symbol"); -// assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token, `Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); -// assert.equal(tx.logs[0].args._owner, account_temp, `Token owner should be ${account_temp}`); -// assert.equal(tx.logs[0].args._ticker, "LOG2", `Symbol should be LOG2`); -// let symbolDetails = await I_STRProxied.getTickerDetails("LOG2"); -// assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); -// assert.equal(symbolDetails[3], "LOGAN2", `Name of the symbol should be LOGAN`); -// }); - -// }); - -// describe("Test case for modifyTicker", async() => { - -// it("Should add the custom ticker --failed because of bad owner", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() + duration.days(10)), false, {from: account_temp}) -// } catch(error) { -// console.log(` tx revert -> failed beacause ticker length should not be 0`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should add the custom ticker --fail ticker length should not be 0", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifyTicker(token_owner, "", "Ether", latestTime(), (latestTime() + duration.days(10)), false, {from: account_polymath}) -// } catch(error) { -// console.log(` tx revert -> failed beacause ticker length should not be 0`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should add the custom ticker --failed because time should not be 0", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", 0, (latestTime() + duration.days(10)), false, {from: account_polymath}) -// } catch(error) { -// console.log(` tx revert -> failed because time should not be 0`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should add the custom ticker --failed because registeration date is greater than the expiryDate", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() - duration.minutes(10)), false, {from: account_polymath}) -// } catch(error) { -// console.log(` tx revert -> failed because registeration date is greater than the expiryDate`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should add the custom ticker --failed because owner should not be 0x", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.modifyTicker("0x000000000000000000000000000000000000000000", "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}) -// } catch(error) { -// console.log(` tx revert -> failed because owner should not be 0x`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should add the new custom ticker", async() => { -// let tx = await I_STRProxied.modifyTicker(account_temp, "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); -// assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); -// assert.equal(tx.logs[0].args._ticker, "ETH", "Should be equal to ETH"); -// }) - -// it("Should change the details of the existing ticker", async() => { -// let tx = await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); -// assert.equal(tx.logs[0].args._owner, token_owner); -// }); - -// }); - -// describe("Test cases for the transferTickerOwnership()", async() => { - -// it("Should able to transfer the ticker ownership -- failed because token is not deployed having the same ticker", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.transferTickerOwnership(account_issuer, "ETH", {from: account_temp}); -// } catch(error) { -// console.log(` tx revert -> failed because token is not deployed having the same ticker`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should able to transfer the ticker ownership -- failed because new owner is 0x", async() => { -// let errorThrown = false; -// await I_SecurityToken002.transferOwnership(account_temp, {from: token_owner}); -// try { -// await I_STRProxied.transferTickerOwnership("0x00000000000000000000000000000000000000000", symbol2, {from: token_owner}); -// } catch(error) { -// console.log(` tx revert -> failed because new owner is 0x`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should able to transfer the ticker ownership -- failed because ticker is of zero length", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.transferTickerOwnership(account_temp, "", {from: token_owner}); -// } catch(error) { -// console.log(` tx revert -> failed because ticker is of zero length`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should able to transfer the ticker ownership", async() => { -// let tx = await I_STRProxied.transferTickerOwnership(account_temp, symbol2, {from: token_owner, gas: 5000000 }); -// assert.equal(tx.logs[0].args._newOwner, account_temp); -// let symbolDetails = await I_STRProxied.getTickerDetails.call(symbol2); -// assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); -// assert.equal(symbolDetails[3], name2, `Name of the symbol should be ${name2}`); -// }) -// }) - -// describe("Test case for the changeSecurityLaunchFee()", async() => { - -// it("Should able to change the STLaunchFee-- failed because of bad owner", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), {from: account_temp}); -// } catch(error) { -// console.log(` tx revert -> failed because of bad owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should able to change the STLaunchFee-- failed because of putting the same fee", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.changeSecurityLaunchFee(initRegFee, {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> failed because of putting the same fee`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should able to change the STLaunchFee", async() => { -// let tx = await I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), {from: account_polymath}); -// assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("500")); -// let stLaunchFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("stLaunchFee")); -// assert.equal(stLaunchFee, web3.utils.toWei("500")); -// }); - -// }) - -// describe("Test cases for the changeExpiryLimit()", async() => { - -// it("Should able to change the ExpiryLimit-- failed because of bad owner", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.changeExpiryLimit(duration.days(15), {from: account_temp}); -// } catch(error) { -// console.log(` tx revert -> failed because of bad owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should able to change the ExpiryLimit-- failed because expirylimit is less than 1 day", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.changeExpiryLimit(duration.minutes(50), {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> failed because expirylimit is less than 1 day`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should able to change the ExpiryLimit", async() => { -// let tx = await I_STRProxied.changeExpiryLimit(duration.days(20), {from: account_polymath}); -// assert.equal(tx.logs[0].args._newExpiry, duration.days(20)); -// let expiry = await I_STRProxied.getUintValues(web3.utils.soliditySha3("expiryLimit")); -// assert.equal(expiry, duration.days(20)); -// }); -// }) - -// describe("Test cases for the changeTickerRegistrationFee()", async() => { - -// it("Should able to change the TickerRegFee-- failed because of bad owner", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("500"), {from: account_temp}); -// } catch(error) { -// console.log(` tx revert -> failed because of bad owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should able to change the TickerRegFee-- failed because of putting the same fee", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.changeTickerRegistrationFee(initRegFee, {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> failed because of putting the same fee`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should able to change the TickerRegFee", async() => { -// let tx = await I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("400"), {from: account_polymath}); -// assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("400")); -// let tickerRegFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("tickerRegFee")); -// assert.equal(tickerRegFee, web3.utils.toWei("400")); -// }); - -// it("Should fail to register the ticker with the old fee", async () => { -// let errorThrown = false; -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// try { -// await I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from : token_owner }); -// } catch(error) { -// console.log(` tx revert -> failed because of ticker registeration fee gets change`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should register the ticker with the new fee", async() => { -// await I_PolyToken.getTokens(web3.utils.toWei("1000"), token_owner); -// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner, `Token owner should be ${token_owner}`); -// assert.equal(tx.logs[0].args._ticker, "POLY", `Symbol should be POLY`); -// }); - -// it("Should fail to launch the securityToken with the old launch fee", async() => { -// let errorThrown = false; -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// try { -// await I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> failed because of old launch fee`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should launch the the securityToken", async() => { -// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner}); -// let tx = await I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, "POLY", "SecurityToken doesn't get deployed"); -// }); -// }); - -// describe("Test case for the update poly token", async() => { - -// it("Should change the polytoken address -- failed because of bad owner", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.updatePolyTokenAddress(dummy_token, {from: account_temp}); -// } catch(error) { -// console.log(` tx revert -> failed because of bad owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should change the polytoken address -- failed because of 0x address", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.updatePolyTokenAddress("0x0000000000000000000000000000000000000000000", {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> failed because 0x address`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should successfully change the polytoken address", async() => { -// let _id = await takeSnapshot(); -// await I_STRProxied.updatePolyTokenAddress(dummy_token, {from: account_polymath}); -// assert.equal(await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), dummy_token); -// await revertToSnapshot(_id); -// }); -// }) - -// describe("Test cases for getters", async() => { - -// it("Should get the security token address", async() => { -// let address = await I_STRProxied.getSecurityTokenAddress.call(symbol); -// assert.equal(address, I_SecurityToken.address); -// }); - -// it("Should get the security token data", async() => { -// let data = await I_STRProxied.getSecurityTokenData.call(I_SecurityToken.address); -// assert.equal(data[0], symbol); -// assert.equal(data[1], token_owner); -// }); - -// it("Should get the tickers by owner", async() => { -// let tickersList = await I_STRProxied.getTickersByOwner.call(token_owner); -// assert.equal(tickersList.length, 4); -// let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); -// console.log(tickersListArray); -// assert.equal(tickersListArray.length, 3); -// }); - -// }); - -// describe("Test case for the Removing the ticker", async() => { - -// it("Should remove the ticker from the polymath ecosystem -- bad owner", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.removeTicker(symbol2, {from: account_investor1}); -// } catch(error) { -// console.log(` tx revert -> failed because msg.sender should be account_polymath`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should remove the ticker from the polymath ecosystem -- fail because ticker doesn't exist in the ecosystem", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.removeTicker("HOLA", {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> failed because ticker doesn't exist in the polymath ecosystem`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should successfully remove the ticker from the polymath ecosystem", async() => { -// let tx = await I_STRProxied.removeTicker(symbol2, {from: account_polymath}); -// assert.equal(tx.logs[0].args._ticker, symbol2, "Ticker doesn't get deleted successfully"); -// }); -// }) - -// describe(" Test cases of the registerTicker", async() => { - -// it("Should register the ticker 1", async () => { -// await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); -// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); -// let tx = await I_STRProxied.registerTicker(account_temp, "TOK1", "", { from: account_temp }); -// assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); -// assert.equal(tx.logs[0].args._ticker, "TOK1", `Symbol should be TOK1`); -// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); -// }); - -// it("Should register the ticker 2", async () => { -// await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); -// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); -// let tx = await I_STRProxied.registerTicker(account_temp, "TOK2", "", { from: account_temp }); -// assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); -// assert.equal(tx.logs[0].args._ticker, "TOK2", `Symbol should be TOK2`); -// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); -// }); - -// it("Should register the ticker 3", async () => { -// await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); -// await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); -// let tx = await I_STRProxied.registerTicker(account_temp, "TOK3", "", { from: account_temp }); -// assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); -// assert.equal(tx.logs[0].args._ticker, "TOK3", `Symbol should be TOK3`); -// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); -// }); - -// it("Should successfully remove the ticker 2", async() => { -// let tx = await I_STRProxied.removeTicker("TOK2", {from: account_polymath}); -// assert.equal(tx.logs[0].args._ticker, "TOK2", "Ticker doesn't get deleted successfully"); -// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); -// }); - -// it("Should modify ticker 1", async() => { -// let tx = await I_STRProxied.modifyTicker(account_temp, "TOK1", "TOKEN 1", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); -// assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); -// assert.equal(tx.logs[0].args._ticker, "TOK1", "Should be equal to TOK1"); -// assert.equal(tx.logs[0].args._name, "TOKEN 1", "Should be equal to TOKEN 1"); -// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); -// }) - -// it("Should modify ticker 3", async() => { -// let tx = await I_STRProxied.modifyTicker(account_temp, "TOK3", "TOKEN 3", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); -// assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); -// assert.equal(tx.logs[0].args._ticker, "TOK3", "Should be equal to TOK3"); -// assert.equal(tx.logs[0].args._name, "TOKEN 3", "Should be equal to TOKEN 3"); -// console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); -// }) - -// }); -// describe("Test cases for IRegistry functionality", async() => { - -// describe("Test cases for reclaiming funds", async() => { - -// it("Should successfully reclaim POLY tokens", async() => { -// I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); -// let bal1 = await I_PolyToken.balanceOf.call(account_polymath); -// await I_STRProxied.reclaimERC20(I_PolyToken.address); -// let bal2 = await I_PolyToken.balanceOf.call(account_polymath); -// assert.isAtLeast(bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), bal2.dividedBy(new BigNumber(10).pow(18)).toNumber()); -// }); - -// }); - -// describe("Test cases for pausing the contract", async() => { - -// it("Should fail to pause if msg.sender is not owner", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.pause({ from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> msg.sender should be account_polymath`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully pause the contract", async() => { -// await I_STRProxied.pause({ from: account_polymath }); -// let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); -// assert.isOk(status); -// }); - -// it("Should fail to unpause if msg.sender is not owner", async() => { -// let errorThrown = false; -// try { -// await I_STRProxied.unpause({ from: account_temp }); -// } catch(error) { -// console.log(` tx revert -> msg.sender should be account_polymath`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully unpause the contract", async() => { -// await I_STRProxied.unpause({ from: account_polymath }); -// let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); -// assert.isNotOk(status); -// }); - -// }); - -// }); - -// }); + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 9 (a): Deploy the proxy + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 10: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + assert.notEqual( + I_FeatureRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "FeatureRegistry contract was not deployed", + ); + + //Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 4: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); + + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + DummySTOFactory: ${I_DummySTOFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + + describe(" Test cases of the registerTicker", async() => { + + it("verify the intial parameters", async() => { + let intialised = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); + assert.isTrue(intialised, "Should be true"); + + let expiry = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit")); + assert.equal(expiry.toNumber(), 5184000, "Expiry limit should be equal to 60 days"); + + let polytoken = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")); + assert.equal(polytoken, I_PolyToken.address, "Should be the polytoken address"); + + let stlaunchFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("stLaunchFee")); + assert.equal(stlaunchFee.toNumber(), initRegFee, "Should be provided reg fee"); + + let tickerRegFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee")); + assert.equal(tickerRegFee.toNumber(), tickerRegFee, "Should be provided reg fee"); + + let polymathRegistry = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); + assert.equal(polymathRegistry, I_PolymathRegistry.address, "Should be the address of the polymath registry"); + + let owner = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("owner")); + assert.equal(owner, account_polymath, "Should be the address of the registry owner"); + }); + + it("Can't call the intialize function again", async() => { + let errorThrown = false; + try { + await I_STRProxied.initialize(I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath); + } catch(error) { + console.log(` tx revert -> Can't call the intialize function again`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should fail to register ticker if tickerRegFee not approved", async() => { + let errorThrown = false; + try { + let tx = await I_STRProxied.registerTicker(account_temp, symbol, name, { from: account_temp }); + } catch(error) { + console.log(` tx revert -> POLY allowance not provided for registration fee`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to register ticker if owner is 0x", async() => { + let errorThrown = false; + try { + await I_PolyToken.getTokens(initRegFee, account_temp); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); + let tx = await I_STRProxied.registerTicker("0x0000000000000000000000000000000000000000", symbol, name, { from: account_temp }); + } catch(error) { + console.log(` tx revert -> owner should not be 0x`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to register ticker due to the symbol length is 0", async() => { + let errorThrown = false; + try { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); + let tx = await I_STRProxied.registerTicker(account_temp, "", name, { from: account_temp }); + } catch(error) { + console.log(` tx revert -> Symbol Length is 0`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to register ticker due to the symbol length is greater than 10", async() => { + let errorThrown = false; + try { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); + let tx = await I_STRProxied.registerTicker(account_temp, "POLYMATHNET", name, { from: account_temp }); + } catch(error) { + console.log(` tx revert -> Symbol Length is greater than 10`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should register the ticker before the generation of the security token", async () => { + let tx = await I_STRProxied.registerTicker(account_temp, symbol, name, { from: account_temp }); + assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, symbol, `Symbol should be ${symbol}`); + }); + + it("Should fail to register same symbol again", async() => { + // Give POLY to token issuer + await I_PolyToken.getTokens(initRegFee, token_owner); + + // Call registration function + let errorThrown = false; + try { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Symbol is already alloted to someone else`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully register pre registerd ticker if expiry is reached", async() => { + await increaseTime(5184000 + 100); // 60(5184000) days of expiry + 100 sec for buffer + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner, `Owner should be the ${token_owner}`); + assert.equal(tx.logs[0].args._ticker, symbol, `Symbol should be ${symbol}`); + }); + + it("Should fail to register ticker if registration is paused", async() => { + let errorThrown = false; + try { + await I_STRProxied.pause({ from: account_polymath}); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Registration is paused`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to pause if already paused", async() => { + let errorThrown = false; + try { + await I_STRProxied.pause({ from: account_polymath}); + } catch(error) { + console.log(` tx revert -> Registration is already paused`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully register ticker if registration is unpaused", async() => { + await I_STRProxied.unpause({ from: account_polymath}); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner, `Owner should be the ${token_owner}`); + assert.equal(tx.logs[0].args._ticker, "AAA", `Symbol should be AAA`); + }); + + it("Should fail to unpause if already unpaused", async() => { + let errorThrown = false; + try { + await I_STRProxied.unpause({ from: account_polymath}); + } catch(error) { + console.log(` tx revert -> Registration is already unpaused`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + }); + + describe("Test cases for the expiry limit", async() => { + + it("Should fail to set the expiry limit because msg.sender is not owner", async() => { + let errorThrown = false; + try { + let tx = await I_STRProxied.changeExpiryLimit(duration.days(10), {from: account_temp}); + } catch(error) { + console.log(` tx revert -> msg.sender is not owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully set the expiry limit", async() => { + await I_STRProxied.changeExpiryLimit(duration.days(10), {from: account_polymath}); + assert.equal( + (await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))) + .toNumber(), + duration.days(10), + "Failed to change the expiry limit"); + }); + + it("Should fail to set the expiry limit because new expiry limit is lesser than one day", async() => { + let errorThrown = false; + try { + let tx = await I_STRProxied.changeExpiryLimit(duration.seconds(5000), {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> New expiry limit is lesser than one day`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + }); + + describe("Test cases for the getTickerDetails", async() => { + + it("Should get the details of the symbol", async() => { + let tx = await I_STRProxied.getTickerDetails.call(symbol); + assert.equal(tx[0], token_owner, "Should equal to the rightful owner of the ticker"); + assert.equal(tx[3], name, `Name of the token should equal to ${name}`); + assert.equal(tx[4], false, "Status if the symbol should be undeployed -- false"); + }); + + it("Should get the details of unregistered token", async() => { + let tx = await I_STRProxied.getTickerDetails.call("TORO"); + assert.equal(tx[0], "0x0000000000000000000000000000000000000000", "Should be 0x as ticker is not exists in the registry"); + assert.equal(tx[3], "", "Should be an empty string"); + assert.equal(tx[4], false, "Status if the symbol should be undeployed -- false"); + }); + }); + + describe("Generate SecurityToken", async() => { + + it("Should get the ticker details successfully and prove the data is not storing in to the logic contract", async() => { + let data = await I_STRProxied.getTickerDetails(symbol, {from: token_owner}); + assert.equal(data[0], token_owner, "Token owner should be equal"); + assert.equal(data[3], name, "Name of the token should match with the registered symbol infor"); + assert.equal(data[4], false, "Token is not launched yet so it should return False"); + data = await I_SecurityTokenRegistry.getTickerDetails(symbol, {from:token_owner}); + console.log("This is the data from the original securityTokenRegistry contract"); + assert.equal(data[0], '0x0000000000000000000000000000000000000000', "Token owner should be 0x"); + }) + + it("Should fail to generate new security token if fee not provided", async() => { + let errorThrown = false; + await I_PolyToken.approve(I_STRProxied.address, 0, { from: token_owner}); + try { + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> POLY allowance not provided for registration fee`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to generate token if registration is paused", async() => { + let errorThrown = false; + await I_STRProxied.pause({ from: account_polymath}); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + try { + await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Registration is paused`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to generate the securityToken -- Because ticker length is 0", async() => { + let errorThrown = false; + await I_STRProxied.unpause({ from: account_polymath}); + try { + await I_STRProxied.generateSecurityToken(name, "", tokenDetails, false, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Zero ticker length is not allowed`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should fail to generate the securityToken -- Because name length is 0", async() => { + let errorThrown = false; + try { + await I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> 0 name length is not allowed`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should fail to generate the securityToken -- Because msg.sender is not the rightful owner of the ticker", async() => { + let errorThrown = false; + try { + await I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: account_temp }); + } catch(error) { + console.log(` tx revert -> Because msg.sender is not the rightful owner of the ticker`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should generate the new security token with the same symbol as registered above", async () => { + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTrasnferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), transferManagerKey, `Should be equal to the ${transferManagerKey}`); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should fail to generate the SecurityToken when token is already deployed with the same symbol", async() => { + let errorThrown = false; + try { + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Because ticker is already in use`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + }); + + describe("Generate SecurityToken v2", async() => { + + it("Should deploy the st version 2", async() => { + // Step 7: Deploy the STFactory contract + + I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory002.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory002 contract was not deployed", + ); + await I_STRProxied.setProtocolVersion(I_STFactory002.address, 0, 2, 0, { from: account_polymath }); + let _protocol = await I_STRProxied.getProtocolVersion.call(); + assert.equal(_protocol[0], 0); + assert.equal(_protocol[1], 2); + assert.equal(_protocol[2], 0); + }); + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, symbol2, name2, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner, `Token owner should be ${token_owner}`); + assert.equal(tx.logs[0].args._ticker, symbol2, `Symbol should be ${symbol2}`); + }); + + it("Should generate the new security token with version 2", async() => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol2, "SecurityToken doesn't get deployed"); + + I_SecurityToken002 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + let tokens = await I_STRProxied.getTokensByOwner.call(token_owner); + assert.equal(tokens[0], I_SecurityToken.address); + assert.equal(tokens[1], I_SecurityToken002.address); + + const log = await promisifyLogWatch(I_SecurityToken002.ModuleAdded({from: _blockNo}), 1); + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), transferManagerKey); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + }); + + describe("Deploy the new SecurityTokenRegistry", async() => { + + it("Should deploy the new SecurityTokenRegistry contract logic", async() => { + I_SecurityTokenRegistryV2 = await SecurityTokenRegistryMock.new({ from: account_polymath }); + assert.notEqual( + I_SecurityTokenRegistryV2.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + }); + + it("Should fail to upgrade the logic contract of the STRProxy -- bad owner", async() => { + let errorThrown = false; + await I_STRProxied.pause({from: account_polymath}); + try { + await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, {from: account_temp}); + } catch(error) { + console.log(` tx revert -> bad owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should upgrade the logic contract into the STRProxy", async() =>{ + await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + assert.isTrue(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); + }); + + it("Should check the old data persist or not", async() => { + let data = await I_STRProxied.getTickerDetails.call(symbol); + assert.equal(data[0], token_owner, "Should be equal to the token owner address"); + assert.equal(data[3], name, "Should be equal to the name of the token that is provided earlier"); + assert.isTrue(data[4], "Token status should be deployed == true"); + }); + + it("Should unpause the logic contract", async() => { + await I_STRProxied.unpause({from: account_polymath}); + assert.isFalse(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); + }); + }) + + describe("Generate custom tokens", async() => { + + it("Should fail if msg.sender is not polymath", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_delegate}); + } catch(error) { + console.log(` tx revert -> msg.sender is not polymath account`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to generate the custom security token -- name should not be 0 length ", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifySecurityToken("", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> name should not be 0 length `.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail if ST address is 0 address", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, 0, "I am custom ST", latestTime(), {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> Security token address is 0`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail if symbol length is 0", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifySecurityToken("", "", account_temp, dummy_token, "I am custom ST",latestTime(), {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> zero length of the symbol is not allowed`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to generate the custom ST -- deployedAt param is 0", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifySecurityToken(name2, symbol2, token_owner, dummy_token, "I am custom ST", 0, {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> because deployedAt param is 0`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully generate custom token", async() => { + // Register the new ticker -- Fulfiling the TickerStatus.ON condition + await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); + let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); + console.log(tickersListArray); + await I_STRProxied.registerTicker(account_temp, "LOG", "LOGAN", { from : account_temp }); + tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); + console.log(tickersListArray); + // Generating the ST + let tx = await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); + tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); + console.log(tickersListArray); + assert.equal(tx.logs[1].args._ticker, "LOG", "Symbol should match with the registered symbol"); + assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token,`Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); + let symbolDetails = await I_STRProxied.getTickerDetails("LOG"); + assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); + assert.equal(symbolDetails[3], "LOGAN", `Name of the symbol should be LOGAN`); + }); + + it("Should successfully generate the custom token", async() => { + // Fulfilling the TickerStatus.NN condition + // let errorThrown = false; + // try { + // await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); + // } catch(error) { + // console.log(` tx revert -> because ticker not registered`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(10), false, {from: account_polymath}); + // await increaseTime(duration.days(1)); + let tx = await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); + assert.equal(tx.logs[1].args._ticker, "LOG2", "Symbol should match with the registered symbol"); + assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token, `Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); + assert.equal(tx.logs[0].args._owner, account_temp, `Token owner should be ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "LOG2", `Symbol should be LOG2`); + let symbolDetails = await I_STRProxied.getTickerDetails("LOG2"); + assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); + assert.equal(symbolDetails[3], "LOGAN2", `Name of the symbol should be LOGAN`); + }); + + }); + + describe("Test case for modifyTicker", async() => { + + it("Should add the custom ticker --failed because of bad owner", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() + duration.days(10)), false, {from: account_temp}) + } catch(error) { + console.log(` tx revert -> failed beacause ticker length should not be 0`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should add the custom ticker --fail ticker length should not be 0", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifyTicker(token_owner, "", "Ether", latestTime(), (latestTime() + duration.days(10)), false, {from: account_polymath}) + } catch(error) { + console.log(` tx revert -> failed beacause ticker length should not be 0`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should add the custom ticker --failed because time should not be 0", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", 0, (latestTime() + duration.days(10)), false, {from: account_polymath}) + } catch(error) { + console.log(` tx revert -> failed because time should not be 0`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should add the custom ticker --failed because registeration date is greater than the expiryDate", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() - duration.minutes(10)), false, {from: account_polymath}) + } catch(error) { + console.log(` tx revert -> failed because registeration date is greater than the expiryDate`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should add the custom ticker --failed because owner should not be 0x", async() => { + let errorThrown = false; + try { + await I_STRProxied.modifyTicker("0x000000000000000000000000000000000000000000", "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}) + } catch(error) { + console.log(` tx revert -> failed because owner should not be 0x`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should add the new custom ticker", async() => { + let tx = await I_STRProxied.modifyTicker(account_temp, "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); + assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "ETH", "Should be equal to ETH"); + }) + + it("Should change the details of the existing ticker", async() => { + let tx = await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); + assert.equal(tx.logs[0].args._owner, token_owner); + }); + + }); + + describe("Test cases for the transferTickerOwnership()", async() => { + + it("Should able to transfer the ticker ownership -- failed because token is not deployed having the same ticker", async() => { + let errorThrown = false; + try { + await I_STRProxied.transferTickerOwnership(account_issuer, "ETH", {from: account_temp}); + } catch(error) { + console.log(` tx revert -> failed because token is not deployed having the same ticker`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should able to transfer the ticker ownership -- failed because new owner is 0x", async() => { + let errorThrown = false; + await I_SecurityToken002.transferOwnership(account_temp, {from: token_owner}); + try { + await I_STRProxied.transferTickerOwnership("0x00000000000000000000000000000000000000000", symbol2, {from: token_owner}); + } catch(error) { + console.log(` tx revert -> failed because new owner is 0x`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should able to transfer the ticker ownership -- failed because ticker is of zero length", async() => { + let errorThrown = false; + try { + await I_STRProxied.transferTickerOwnership(account_temp, "", {from: token_owner}); + } catch(error) { + console.log(` tx revert -> failed because ticker is of zero length`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should able to transfer the ticker ownership", async() => { + let tx = await I_STRProxied.transferTickerOwnership(account_temp, symbol2, {from: token_owner, gas: 5000000 }); + assert.equal(tx.logs[0].args._newOwner, account_temp); + let symbolDetails = await I_STRProxied.getTickerDetails.call(symbol2); + assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); + assert.equal(symbolDetails[3], name2, `Name of the symbol should be ${name2}`); + }) + }) + + describe("Test case for the changeSecurityLaunchFee()", async() => { + + it("Should able to change the STLaunchFee-- failed because of bad owner", async() => { + let errorThrown = false; + try { + await I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), {from: account_temp}); + } catch(error) { + console.log(` tx revert -> failed because of bad owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should able to change the STLaunchFee-- failed because of putting the same fee", async() => { + let errorThrown = false; + try { + await I_STRProxied.changeSecurityLaunchFee(initRegFee, {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> failed because of putting the same fee`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should able to change the STLaunchFee", async() => { + let tx = await I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), {from: account_polymath}); + assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("500")); + let stLaunchFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("stLaunchFee")); + assert.equal(stLaunchFee, web3.utils.toWei("500")); + }); + + }) + + describe("Test cases for the changeExpiryLimit()", async() => { + + it("Should able to change the ExpiryLimit-- failed because of bad owner", async() => { + let errorThrown = false; + try { + await I_STRProxied.changeExpiryLimit(duration.days(15), {from: account_temp}); + } catch(error) { + console.log(` tx revert -> failed because of bad owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should able to change the ExpiryLimit-- failed because expirylimit is less than 1 day", async() => { + let errorThrown = false; + try { + await I_STRProxied.changeExpiryLimit(duration.minutes(50), {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> failed because expirylimit is less than 1 day`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should able to change the ExpiryLimit", async() => { + let tx = await I_STRProxied.changeExpiryLimit(duration.days(20), {from: account_polymath}); + assert.equal(tx.logs[0].args._newExpiry, duration.days(20)); + let expiry = await I_STRProxied.getUintValues(web3.utils.soliditySha3("expiryLimit")); + assert.equal(expiry, duration.days(20)); + }); + }) + + describe("Test cases for the changeTickerRegistrationFee()", async() => { + + it("Should able to change the TickerRegFee-- failed because of bad owner", async() => { + let errorThrown = false; + try { + await I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("500"), {from: account_temp}); + } catch(error) { + console.log(` tx revert -> failed because of bad owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should able to change the TickerRegFee-- failed because of putting the same fee", async() => { + let errorThrown = false; + try { + await I_STRProxied.changeTickerRegistrationFee(initRegFee, {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> failed because of putting the same fee`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should able to change the TickerRegFee", async() => { + let tx = await I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("400"), {from: account_polymath}); + assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("400")); + let tickerRegFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("tickerRegFee")); + assert.equal(tickerRegFee, web3.utils.toWei("400")); + }); + + it("Should fail to register the ticker with the old fee", async () => { + let errorThrown = false; + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + try { + await I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from : token_owner }); + } catch(error) { + console.log(` tx revert -> failed because of ticker registeration fee gets change`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should register the ticker with the new fee", async() => { + await I_PolyToken.getTokens(web3.utils.toWei("1000"), token_owner); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner, `Token owner should be ${token_owner}`); + assert.equal(tx.logs[0].args._ticker, "POLY", `Symbol should be POLY`); + }); + + it("Should fail to launch the securityToken with the old launch fee", async() => { + let errorThrown = false; + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + try { + await I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> failed because of old launch fee`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should launch the the securityToken", async() => { + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner}); + let tx = await I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, "POLY", "SecurityToken doesn't get deployed"); + }); + }); + + describe("Test case for the update poly token", async() => { + + it("Should change the polytoken address -- failed because of bad owner", async() => { + let errorThrown = false; + try { + await I_STRProxied.updatePolyTokenAddress(dummy_token, {from: account_temp}); + } catch(error) { + console.log(` tx revert -> failed because of bad owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should change the polytoken address -- failed because of 0x address", async() => { + let errorThrown = false; + try { + await I_STRProxied.updatePolyTokenAddress("0x0000000000000000000000000000000000000000000", {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> failed because 0x address`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should successfully change the polytoken address", async() => { + let _id = await takeSnapshot(); + await I_STRProxied.updatePolyTokenAddress(dummy_token, {from: account_polymath}); + assert.equal(await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), dummy_token); + await revertToSnapshot(_id); + }); + }) + + describe("Test cases for getters", async() => { + + it("Should get the security token address", async() => { + let address = await I_STRProxied.getSecurityTokenAddress.call(symbol); + assert.equal(address, I_SecurityToken.address); + }); + + it("Should get the security token data", async() => { + let data = await I_STRProxied.getSecurityTokenData.call(I_SecurityToken.address); + assert.equal(data[0], symbol); + assert.equal(data[1], token_owner); + }); + + it("Should get the tickers by owner", async() => { + let tickersList = await I_STRProxied.getTickersByOwner.call(token_owner); + assert.equal(tickersList.length, 4); + let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); + console.log(tickersListArray); + assert.equal(tickersListArray.length, 3); + }); + + }); + + describe("Test case for the Removing the ticker", async() => { + + it("Should remove the ticker from the polymath ecosystem -- bad owner", async() => { + let errorThrown = false; + try { + await I_STRProxied.removeTicker(symbol2, {from: account_investor1}); + } catch(error) { + console.log(` tx revert -> failed because msg.sender should be account_polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should remove the ticker from the polymath ecosystem -- fail because ticker doesn't exist in the ecosystem", async() => { + let errorThrown = false; + try { + await I_STRProxied.removeTicker("HOLA", {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> failed because ticker doesn't exist in the polymath ecosystem`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should successfully remove the ticker from the polymath ecosystem", async() => { + let tx = await I_STRProxied.removeTicker(symbol2, {from: account_polymath}); + assert.equal(tx.logs[0].args._ticker, symbol2, "Ticker doesn't get deleted successfully"); + }); + }) + + describe(" Test cases of the registerTicker", async() => { + + it("Should register the ticker 1", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); + let tx = await I_STRProxied.registerTicker(account_temp, "TOK1", "", { from: account_temp }); + assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "TOK1", `Symbol should be TOK1`); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }); + + it("Should register the ticker 2", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); + let tx = await I_STRProxied.registerTicker(account_temp, "TOK2", "", { from: account_temp }); + assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "TOK2", `Symbol should be TOK2`); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }); + + it("Should register the ticker 3", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); + let tx = await I_STRProxied.registerTicker(account_temp, "TOK3", "", { from: account_temp }); + assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "TOK3", `Symbol should be TOK3`); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }); + + it("Should successfully remove the ticker 2", async() => { + let tx = await I_STRProxied.removeTicker("TOK2", {from: account_polymath}); + assert.equal(tx.logs[0].args._ticker, "TOK2", "Ticker doesn't get deleted successfully"); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }); + + it("Should modify ticker 1", async() => { + let tx = await I_STRProxied.modifyTicker(account_temp, "TOK1", "TOKEN 1", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); + assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "TOK1", "Should be equal to TOK1"); + assert.equal(tx.logs[0].args._name, "TOKEN 1", "Should be equal to TOKEN 1"); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }) + + it("Should modify ticker 3", async() => { + let tx = await I_STRProxied.modifyTicker(account_temp, "TOK3", "TOKEN 3", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); + assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "TOK3", "Should be equal to TOK3"); + assert.equal(tx.logs[0].args._name, "TOKEN 3", "Should be equal to TOKEN 3"); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }) + + }); + describe("Test cases for IRegistry functionality", async() => { + + describe("Test cases for reclaiming funds", async() => { + + it("Should successfully reclaim POLY tokens", async() => { + I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); + let bal1 = await I_PolyToken.balanceOf.call(account_polymath); + await I_STRProxied.reclaimERC20(I_PolyToken.address); + let bal2 = await I_PolyToken.balanceOf.call(account_polymath); + assert.isAtLeast(bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), bal2.dividedBy(new BigNumber(10).pow(18)).toNumber()); + }); + + }); + + describe("Test cases for pausing the contract", async() => { + + it("Should fail to pause if msg.sender is not owner", async() => { + let errorThrown = false; + try { + await I_STRProxied.pause({ from: account_temp }); + } catch(error) { + console.log(` tx revert -> msg.sender should be account_polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully pause the contract", async() => { + await I_STRProxied.pause({ from: account_polymath }); + let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + assert.isOk(status); + }); + + it("Should fail to unpause if msg.sender is not owner", async() => { + let errorThrown = false; + try { + await I_STRProxied.unpause({ from: account_temp }); + } catch(error) { + console.log(` tx revert -> msg.sender should be account_polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully unpause the contract", async() => { + await I_STRProxied.unpause({ from: account_polymath }); + let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + assert.isNotOk(status); + }); + + }); + + }); + +}); diff --git a/test/o_security_token.js b/test/o_security_token.js index 7453264bd..acbb830cf 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -1,1405 +1,1405 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -// const CappedSTO = artifacts.require('./CappedSTO.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - - -// contract('SecurityToken', accounts => { - - -// // Accounts Variable declaration -// let account_polymath; -// let account_investor1; -// let account_issuer; -// let token_owner; -// let account_investor2; -// let account_investor3; -// let account_affiliate1; -// let account_affiliate2; -// let account_fundsReceiver; -// let account_delegate; -// let account_temp; -// let account_controller; -// let address_zero = "0x0000000000000000000000000000000000000000"; - -// let balanceOfReceiver; -// // investor Details -// let fromTime; -// let toTime; -// let expiryTime; - -// let ID_snap; -// const message = "Transaction Should Fail!!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_CappedSTOFactory; -// let I_STFactory; -// let I_SecurityToken; -// let I_STRProxied; -// let I_MRProxied; -// let I_CappedSTO; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details (Launched ST on the behalf of the issuer) -// const name = "Demo Token"; -// const symbol = "DET"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// let snap_Id; -// // Module key -// const permissionManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; -// const budget = 0; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// // delagate details -// const delegateDetails = "I am delegate .."; -// const TM_Perm = 'FLAGS'; -// const TM_Perm_Whitelist = 'WHITELIST'; - -// // Capped STO details -// let startTime; -// let endTime; -// const cap = web3.utils.toWei("10000"); -// const rate = 1000; -// const fundRaiseType = [0]; -// const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); -// const maxCost = cappedSTOSetupCost; -// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { - -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; -// account_affiliate1 = accounts[2]; -// account_affiliate2 = accounts[3]; -// account_fundsReceiver = accounts[4]; -// account_delegate = accounts[5]; -// account_investor2 = accounts[6]; -// account_investor3 = accounts[7]; -// account_temp = accounts[8]; -// account_investor1 = accounts[9]; - -// token_owner = account_issuer; -// account_controller = account_temp; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4 (a): Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// address_zero, -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 4 (b): Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// address_zero, -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 4 (c): Deploy the CappedSTOFactory - -// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); - -// assert.notEqual( -// I_CappedSTOFactory.address.valueOf(), -// address_zero, -// "CappedSTOFactory contract was not deployed" -// ); - -// // STEP 5: Register the Modules with the ModuleRegistry contract - -// // Step 6: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 7: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 8: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 9: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// ModuleRegistry: ${ModuleRegistry.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// CappedSTOFactory: ${I_CappedSTOFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// console.log(log.args); -// assert.equal(log.args._types[0].toNumber(), transferManagerKey); -// assert.equal(web3.utils.toUtf8(log.args._name),"GeneralTransferManager"); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// assert.notEqual( -// I_GeneralTransferManager.address.valueOf(), -// address_zero, -// "GeneralTransferManager contract was not deployed", -// ); - -// }); - -// it("Should mint the tokens before attaching the STO -- fail only be called by the owner", async() => { -// let errorThrown = false; -// let fromTime = latestTime(); -// let toTime = fromTime + duration.days(100); -// let expiryTime = toTime + duration.days(100); - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_affiliate1, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: token_owner, -// gas: 6000000 -// }); -// assert.equal(tx.logs[0].args._investor, account_affiliate1, "Failed in adding the investor in whitelist"); -// try { -// await I_SecurityToken.mint(account_investor1, (100 * Math.pow(10, 18)), {from: account_delegate}); -// } catch(error) { -// console.log(` tx revert -> Mint only be called by the owner of the SecurityToken`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should mint the tokens before attaching the STO", async() => { -// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); -// let balance = await I_SecurityToken.balanceOf(account_affiliate1); -// assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); -// }); - -// it("Should mint the multi tokens before attaching the STO -- fail only be called by the owner", async() => { -// let errorThrown = false; -// let fromTime = latestTime(); -// let toTime = fromTime + duration.days(100); -// let expiryTime = toTime + duration.days(100); - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_affiliate2, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: token_owner, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_affiliate2, "Failed in adding the investor in whitelist"); -// try { -// await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: account_delegate, gas: 500000}); -// } catch(error) { -// console.log(` tx revert -> Mint only be called by the owner of the SecurityToken`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should mintMulti", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); -// } catch(error) { -// console.log(` tx revert -> Array length are un-equal`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should mint the tokens for multiple afiliated investors before attaching the STO", async() => { -// await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); -// let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); -// assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 200); -// let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); -// assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 110); -// }); - -// it("Should finish the minting -- fail because feature is not activated", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.freezeMinting({from: token_owner}); -// } catch(error) { -// console.log(` tx revert -> freezeMinting cannot be called before activated by polymath`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should finish the minting -- fail to activate the feature because msg.sender is not polymath", async() => { -// let errorThrown = false; -// try { -// await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: token_owner}); -// } catch(error) { -// console.log(` tx revert -> allowFreezeMinting must be called by polymath`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should finish the minting -- successfully activate the feature", async() => { -// let errorThrown1 = false; -// try { -// await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", false, {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> must change state`.grey); -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, message); - -// assert.equal(false, await I_FeatureRegistry.getFeatureStatus("freezeMintingAllowed", {from: account_temp})); -// await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: account_polymath}); -// assert.equal(true, await I_FeatureRegistry.getFeatureStatus("freezeMintingAllowed", {from: account_temp})); - -// let errorThrown2 = false; -// try { -// await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: account_polymath}); -// } catch(error) { -// console.log(` tx revert -> must change state`.grey); -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, message); -// }); - -// it("Should finish the minting -- fail because msg.sender is not the owner", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.freezeMinting({from: account_temp}); -// } catch(error) { -// console.log(` tx revert -> freezeMinting only be called by the owner of the SecurityToken`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should finish minting & restrict the further minting", async() => { -// let id = await takeSnapshot(); -// await I_SecurityToken.freezeMinting({from: token_owner}); -// let errorThrown = false; -// try { -// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); -// } catch(error) { -// console.log(` tx revert -> Minting is finished`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// await revertToSnapshot(id); -// }); - -// it("Should fail to attach the STO factory because not enough poly in contract", async () => { -// startTime = latestTime() + duration.seconds(5000); -// endTime = startTime + duration.days(30); -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); -// let errorThrown = false; -// try { -// let tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); -// } catch (error) { -// console.log(` tx revert -> not enough poly in contract`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to attach the STO factory because max cost too small", async () => { -// startTime = latestTime() + duration.seconds(5000); -// endTime = startTime + duration.days(30); -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); -// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); -// await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); -// let errorThrown = false; -// try { -// let tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, web3.utils.toWei("1000","ether"), 0, { from: token_owner }); -// } catch (error) { -// console.log(` tx revert -> max cost too small`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the STO factory with the security token", async () => { -// startTime = latestTime() + duration.seconds(5000); -// endTime = startTime + duration.days(30); -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - -// await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); -// await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); - -// const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - -// assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); -// assert.equal(web3.utils.toUtf8(tx.logs[3].args._name), "CappedSTO", "CappedSTOFactory module was not added"); -// I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); -// }); - -// it("Should successfully mint tokens while STO attached", async () => { -// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); -// let balance = await I_SecurityToken.balanceOf(account_affiliate1); -// assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 300); -// }); - -// it("Should fail to mint tokens while STO attached after freezeMinting called", async () => { -// let id = await takeSnapshot(); -// await I_SecurityToken.freezeMinting({from: token_owner}); -// let errorThrown = false; -// try { -// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); -// } catch(error) { -// console.log(` tx revert -> Minting is finished`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// await revertToSnapshot(id); -// }); - -// }); - -// describe("Module related functions", async() => { -// it("Should get the modules of the securityToken by index", async () => { -// let moduleData = await I_SecurityToken.getModule.call(I_CappedSTO.address); -// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "CappedSTO"); -// assert.equal(moduleData[1], I_CappedSTO.address); -// assert.equal(moduleData[2], I_CappedSTOFactory.address); -// assert.equal(moduleData[3], false); -// assert.equal(moduleData[4][0], 3); -// }); - -// it("Should get the modules of the securityToken by index (not added into the security token yet)", async () => { -// let moduleData = await I_SecurityToken.getModule.call(token_owner); -// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), ""); -// assert.equal(moduleData[1], address_zero); -// }); - -// it("Should get the modules of the securityToken by name", async () => { -// let moduleList = await I_SecurityToken.getModulesByName.call("CappedSTO"); -// assert.isTrue(moduleList.length == 1, "Only one STO"); -// let moduleData = await I_SecurityToken.getModule.call(moduleList[0]); -// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "CappedSTO"); -// assert.equal(moduleData[1], I_CappedSTO.address); -// }); - -// it("Should get the modules of the securityToken by name (not added into the security token yet)", async () => { -// let moduleData = await I_SecurityToken.getModulesByName.call("GeneralPermissionManager"); -// assert.isTrue(moduleData.length == 0, "No Permission Manager"); -// }); - -// it("Should get the modules of the securityToken by name (not added into the security token yet)", async () => { -// let moduleData = await I_SecurityToken.getModulesByName.call("CountTransferManager"); -// assert.isTrue(moduleData.length == 0, "No Permission Manager"); -// }); - -// it("Should fail in updating the token details", async() => { -// let errorThrown = false; -// try { -// let log = await I_SecurityToken.updateTokenDetails("new token details", {from: account_delegate}); -// } catch (error) { -// console.log(` tx revert -> msg.sender should be the owner of the token`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should update the token details", async() => { -// let log = await I_SecurityToken.updateTokenDetails("new token details", {from: token_owner}); -// assert.equal(log.logs[0].args._newDetails, "new token details"); -// }); - -// it("Should fail to remove the module - module not archived", async() => { -// let errorThrown = false; -// try { -// let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); -// } catch (error) { -// console.log(` tx -> Failed because address doesn't exist`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should successfully remove the general transfer manager module from the securityToken -- fails msg.sender should be Owner", async() => { -// let errorThrown = false; -// try { -// let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : account_temp }); -// } catch (error) { -// console.log(`Test Case passed by restricting the unknown account to call removeModule of the securityToken`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to remove the module - incorrect address", async() => { -// let errorThrown = false; -// try { -// let tx = await I_SecurityToken.removeModule(0, { from : token_owner }); -// } catch (error) { -// console.log(` tx -> Failed because address doesn't exist`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should successfully remove the general transfer manager module from the securityToken", async() => { -// let key = await takeSnapshot(); -// await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); -// let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); -// assert.equal(tx.logs[0].args._types[0], transferManagerKey); -// assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); -// await revertToSnapshot(key); -// }); - -// it("Should verify the revertion of snapshot works properly", async() => { -// let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); -// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); -// assert.equal(moduleData[1], I_GeneralTransferManager.address); -// }); - - -// it("Should successfully archive the general transfer manager module from the securityToken", async() => { -// let tx = await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); -// assert.equal(tx.logs[0].args._types[0], transferManagerKey); -// assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); -// let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); -// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); -// assert.equal(moduleData[1], I_GeneralTransferManager.address); -// assert.equal(moduleData[2], I_GeneralTransferManagerFactory.address); -// assert.equal(moduleData[3], true); -// }); - -// it("Should successfully mint tokens while GTM archived", async () => { -// let key = await takeSnapshot(); -// await I_SecurityToken.mint(1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); -// let balance = await I_SecurityToken.balanceOf(1); -// assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); -// await revertToSnapshot(key); -// }); - -// it("Should successfully unarchive the general transfer manager module from the securityToken", async() => { -// let tx = await I_SecurityToken.unarchiveModule(I_GeneralTransferManager.address, { from : token_owner }); -// assert.equal(tx.logs[0].args._types[0], transferManagerKey); -// assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); -// let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); -// assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); -// assert.equal(moduleData[1], I_GeneralTransferManager.address); -// assert.equal(moduleData[2], I_GeneralTransferManagerFactory.address); -// assert.equal(moduleData[3], false); -// }); - -// it("Should fail to mint tokens while GTM unarchived", async () => { -// let errorThrown = false; -// try { -// await I_SecurityToken.mint(1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); -// } catch(error) { -// console.log(` tx -> Failed because GTM`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); - -// }); - -// it("Should change the budget of the module - fail incorrect address", async() => { -// let errorThrown = false; -// try { -// let tx = await I_SecurityToken.changeModuleBudget(0, (100 * Math.pow(10, 18)),{ from : token_owner}); -// } catch(error) { -// console.log(` tx -> Failed because address is 0`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - - -// it("Should change the budget of the module", async() => { -// let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, (100 * Math.pow(10, 18)),{ from : token_owner}); -// assert.equal(tx.logs[1].args._moduleTypes[0], stoKey); -// assert.equal(tx.logs[1].args._module, I_CappedSTO.address); -// assert.equal(tx.logs[1].args._budget.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); -// }); - -// }); - -// describe("General Transfer manager Related test cases", async () => { - -// it("Should Buy the tokens", async() => { -// balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); -// // Add the Investor in to the whitelist - -// fromTime = latestTime(); -// toTime = fromTime + duration.days(100); -// expiryTime = toTime + duration.days(100); - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: token_owner, -// gas: 6000000 -// }); -// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); -// // Jump time -// await increaseTime(5000); -// // Fallback transaction -// console.log("BEFORE"); -// await web3.eth.sendTransaction({ -// from: account_investor1, -// to: I_CappedSTO.address, -// gas: 2100000, -// value: web3.utils.toWei('1', 'ether') -// }); -// console.log("AFTER"); -// assert.equal( -// (await I_CappedSTO.getRaised.call(0)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1 -// ); - -// assert.equal(await I_CappedSTO.investorCount.call(), 1); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000 -// ); -// }); - -// it("Should Fail in transferring the token from one whitelist investor 1 to non whitelist investor 2", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, (10 * Math.pow(10, 18)), { from : account_investor1}); -// } catch(error) { -// console.log(` tx revert -> Investor 2 is not in the whitelist`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to provide the permission to the delegate to change the transfer bools", async () => { -// let errorThrown = false; -// // Add permission to the deletgate (A regesteration process) -// await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: token_owner}); -// let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; -// I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); -// try { -// await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_temp }); -// } catch (error) { -// console.log(`${account_temp} doesn't have permissions to register the delegate`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should provide the permission to the delegate to change the transfer bools", async () => { -// // Add permission to the deletgate (A regesteration process) -// await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); -// // Providing the permission to the delegate -// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm, true, { from: token_owner }); - -// assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm)); -// }); - - -// it("Should fail to activate the bool allowAllTransfer", async() => { -// let errorThrown = false; -// try { -// let tx = await I_GeneralTransferManager.changeAllowAllTransfers(true, { from : account_temp }); -// } catch (error) { -// console.log(`${account_temp} doesn't have permissions to activate the bool allowAllTransfer`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should activate the bool allowAllTransfer", async() => { -// ID_snap = await takeSnapshot(); -// let tx = await I_GeneralTransferManager.changeAllowAllTransfers(true, { from : account_delegate }); - -// assert.isTrue(tx.logs[0].args._allowAllTransfers, "AllowTransfer variable is not successfully updated"); -// }); - - -// it("Should fail to send tokens with the wrong granularity", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(accounts[7], Math.pow(10, 17), { from : account_investor1}); -// } catch (error) { -// console.log(' tx revert -> Incorrect token granularity - expected'.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should adjust granularity", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.changeGranularity(0, {from: token_owner }); -// } catch(error) { -// console.log(' tx revert -> Incorrect token granularity - expected'.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should adjust granularity", async() => { -// let errorThrown = false; -// await I_SecurityToken.changeGranularity(Math.pow(10, 17), {from: token_owner }); -// await I_SecurityToken.transfer(accounts[7], Math.pow(10, 17), { from : account_investor1, gas: 2500000 }); -// await I_SecurityToken.transfer(account_investor1, Math.pow(10, 17), { from : accounts[7], gas: 2500000}); -// }); - -// it("Should transfer from whitelist investor to non-whitelist investor in first tx and in 2nd tx non-whitelist to non-whitelist transfer", async() => { -// await I_SecurityToken.transfer(accounts[7], (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); - -// assert.equal( -// (await I_SecurityToken.balanceOf(accounts[7])) -// .dividedBy(new BigNumber(10).pow(18)).toNumber(), -// 10, -// "Transfer doesn't take place properly" -// ); - -// await I_SecurityToken.transfer(account_temp, (5 * Math.pow(10, 18)), { from : accounts[7], gas: 2500000}); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_temp)) -// .dividedBy(new BigNumber(10).pow(18)).toNumber(), -// 5, -// "Transfer doesn't take place properly" -// ); -// await revertToSnapshot(ID_snap); -// }); - -// it("Should bool allowAllTransfer value is false", async() => { -// assert.isFalse(await I_GeneralTransferManager.allowAllTransfers.call(), "reverting of snapshot doesn't works properly"); -// }); - -// it("Should change the bool allowAllWhitelistTransfers to true", async () => { -// ID_snap = await takeSnapshot(); -// let tx = await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, { from : account_delegate }); - -// assert.isTrue(tx.logs[0].args._allowAllWhitelistTransfers, "allowAllWhitelistTransfers variable is not successfully updated"); -// }); - -// it("Should transfer from whitelist investor1 to whitelist investor 2", async() => { -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: token_owner, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - -// await I_SecurityToken.transfer(account_investor2, (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)) -// .dividedBy(new BigNumber(10).pow(18)).toNumber(), -// 10, -// "Transfer doesn't take place properly" -// ); -// }); - -// it("Should transfer from whitelist investor1 to whitelist investor 2 -- value = 0", async() => { -// let tx = await I_SecurityToken.transfer(account_investor2, 0, { from : account_investor1, gas: 2500000}); -// assert.equal((tx.logs[0].args.value).toNumber(),0); -// }); - -// it("Should transferFrom from one investor to other", async() => { -// await I_SecurityToken.approve(account_investor1, (2 * Math.pow(10, 18)),{from: account_investor2}); -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: token_owner, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); -// let log = await I_SecurityToken.transferFrom(account_investor2, account_investor3, (2 * Math.pow(10, 18)), {from: account_investor1}); -// assert.equal((log.logs[0].args.value).toNumber(), (2 * Math.pow(10, 18))); -// }); - -// it("Should Fail in trasferring from whitelist investor1 to non-whitelist investor", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_temp, (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); -// } catch(error) { -// console.log(`non-whitelist investor is not allowed`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// await revertToSnapshot(ID_snap); -// }); - -// it("Should successfully mint tokens while STO attached", async () => { -// await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); -// let balance = await I_SecurityToken.balanceOf(account_affiliate1); -// assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 400); -// }); - -// it("Should mint the tokens for multiple afiliated investors while STO attached", async() => { -// await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); -// let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); -// assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 500); -// let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); -// assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 220); -// }); - -// it("Should provide more permissions to the delegate", async() => { -// // Providing the permission to the delegate -// await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm_Whitelist, true, { from: token_owner }); - -// assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm_Whitelist)); -// }); - -// it("Should add the investor in the whitelist by the delegate", async() => { -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_temp, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: account_delegate, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_temp, "Failed in adding the investor in whitelist"); -// }); - -// it("should account_temp successfully buy the token", async() => { -// // Fallback transaction -// await web3.eth.sendTransaction({ -// from: account_temp, -// to: I_CappedSTO.address, -// gas: 2100000, -// value: web3.utils.toWei('1', 'ether') -// }); - -// assert.equal( -// (await I_CappedSTO.getRaised.call(0)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 2 -// ); - -// assert.equal(await I_CappedSTO.investorCount.call(), 2); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000 -// ); -// }); - -// it("STO should fail to mint tokens after minting is frozen", async() => { -// let id = await takeSnapshot(); -// await I_SecurityToken.freezeMinting({from: token_owner}); -// let errorThrown = false; -// try { -// await web3.eth.sendTransaction({ -// from: account_temp, -// to: I_CappedSTO.address, -// gas: 2100000, -// value: web3.utils.toWei('1', 'ether') -// }); -// } catch(error) { -// console.log(` tx revert -> Minting is finished`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// await revertToSnapshot(id); -// }); - -// it("Should remove investor from the whitelist by the delegate", async() => { -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_temp, -// 0, -// 0, -// 0, -// true, -// { -// from: account_delegate, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_temp, "Failed in removing the investor from whitelist"); -// }); - -// it("should account_temp fail in buying the token", async() => { -// let errorThrown = false; -// try { -// // Fallback transaction -// await web3.eth.sendTransaction({ -// from: account_temp, -// to: I_CappedSTO.address, -// gas: 2100000, -// value: web3.utils.toWei('1', 'ether') -// }); - -// } catch (error) { -// console.log(`non-whitelist investor is not allowed`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should freeze the transfers", async() => { -// let tx = await I_SecurityToken.freezeTransfers({from: token_owner}); -// assert.isTrue(tx.logs[0].args._status); -// }); - -// it("Should fail to freeze the transfers", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.freezeTransfers({from: token_owner}); -// } catch(error) { -// console.log(` tx -> Revert because freeze is already true`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in buying to tokens", async() => { -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_temp, -// fromTime, -// toTime, -// expiryTime, -// true, -// { -// from: account_delegate, -// gas: 6000000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_temp, "Failed in adding the investor in whitelist"); - -// let errorThrown = false; -// try { -// // Fallback transaction -// await web3.eth.sendTransaction({ -// from: account_temp, -// to: I_CappedSTO.address, -// gas: 2100000, -// value: web3.utils.toWei('1', 'ether') -// }); - -// } catch (error) { -// console.log(`Because all transfers get freezed`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail in trasfering the tokens from one user to another", async() => { -// await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); -// console.log(await I_SecurityToken.balanceOf(account_investor1)); -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); -// } catch(error) { -// console.log(' tx revert -> All transfers are at hold'.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should unfreeze all the transfers", async() => { -// let tx = await I_SecurityToken.unfreezeTransfers({from: token_owner}); -// assert.isFalse(tx.logs[0].args._status); -// }); - -// it("Should freeze the transfers", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.unfreezeTransfers({from: token_owner}); -// } catch(error) { -// console.log(` tx -> Revert because freeze is already false`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should able to transfers the tokens from one user to another", async() => { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); -// }); - -// it("Should check that the list of investors is correct", async ()=> { -// // Hardcode list of expected accounts based on transfers above - -// let investors = await I_SecurityToken.getInvestors(); -// let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1, account_temp]; -// for (let i = 0; i < expectedAccounts.length; i++) { -// assert.equal(investors[i], expectedAccounts[i]); -// } -// assert.equal(investors.length, 4); -// console.log("Total Seen Investors: " + investors.length); -// }); -// it("Should fail to set controller status because msg.sender not owner", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.setController(account_controller, {from: account_controller}); -// } catch (error) { -// console.log(` tx revert -> msg.sender not owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully set controller", async() => { -// let tx1 = await I_SecurityToken.setController(account_controller, {from: token_owner}); - -// // check event -// assert.equal(address_zero, tx1.logs[0].args._oldController, "Event not emitted as expected"); -// assert.equal(account_controller, tx1.logs[0].args._newController, "Event not emitted as expected"); - -// let tx2 = await I_SecurityToken.setController(address_zero, {from: token_owner}); - -// // check event -// assert.equal(account_controller, tx2.logs[0].args._oldController, "Event not emitted as expected"); -// assert.equal(address_zero, tx2.logs[0].args._newController, "Event not emitted as expected"); - -// let tx3 = await I_SecurityToken.setController(account_controller, {from: token_owner}); - -// // check event -// assert.equal(address_zero, tx3.logs[0].args._oldController, "Event not emitted as expected"); -// assert.equal(account_controller, tx3.logs[0].args._newController, "Event not emitted as expected"); - -// // check status -// let controller = await I_SecurityToken.controller.call(); -// assert.equal(account_controller, controller, "Status not set correctly"); -// }); - -// it("Should force burn the tokens - value too high", async ()=> { -// let errorThrown = false; -// await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); -// let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); -// let currentBalance = await I_SecurityToken.balanceOf(account_temp); -// try { -// let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance + web3.utils.toWei("500", "ether"), "", "", { from: account_controller }); -// } catch(error) { -// console.log(` tx revert -> value is greater than its current balance`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); -// it("Should force burn the tokens - wrong caller", async ()=> { -// let errorThrown = false; -// await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); -// let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); -// let currentBalance = await I_SecurityToken.balanceOf(account_temp); -// try { -// let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", "", { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> not owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should burn the tokens", async ()=> { -// let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); -// let currentBalance = await I_SecurityToken.balanceOf(account_temp); -// // console.log(currentInvestorCount.toString(), currentBalance.toString()); -// let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", "", { from: account_controller }); -// // console.log(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); -// assert.equal(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); -// let newInvestorCount = await I_SecurityToken.getInvestorCount.call(); -// // console.log(newInvestorCount.toString()); -// assert.equal(newInvestorCount.toNumber() + 1, currentInvestorCount.toNumber(), "Investor count drops by one"); -// }); - -// it("Should prune investor length", async ()=> { -// await I_SecurityToken.pruneInvestors(0, 10, {from: token_owner}); -// // Hardcode list of expected accounts based on transfers above - -// let investors = await I_SecurityToken.getInvestors.call(); -// let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1]; -// for (let i = 0; i < expectedAccounts.length; i++) { -// assert.equal(investors[i], expectedAccounts[i]); -// } -// assert.equal(investors.length, 3); -// }); - -// it("Should check the balance of investor at checkpoint", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.balanceOfAt(account_investor1, 5); -// } catch(error) { -// console.log(` tx -> Revert checkpoint ID is greator than current checkpoint`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should check the balance of investor at checkpoint", async() => { -// let balance = await I_SecurityToken.balanceOfAt(account_investor1, 0); -// assert.equal(balance.toNumber(), 0); -// }); -// }); - -// describe("Withdraw Poly", async() => { - -// it("Should successfully withdraw the poly", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), {from: account_temp}); -// } catch (error) { -// console.log(` tx revert -> withdrawPoly function can only be called by the owner of the seucrity token`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }) - -// it("Should successfully withdraw the poly", async() => { -// let balanceBefore = await I_PolyToken.balanceOf(token_owner); -// await I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), {from: token_owner}); -// let balanceAfter = await I_PolyToken.balanceOf(token_owner); -// assert.equal((BigNumber(balanceAfter).sub(BigNumber(balanceBefore))).toNumber(), web3.utils.toWei("20000", "ether")); -// }); - -// it("Should successfully withdraw the poly", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.withdrawPoly(web3.utils.toWei("10", "ether"), {from: token_owner}); -// } catch (error) { -// console.log(` tx revert -> token doesn't have any POLY`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); -// }); - -// describe("Force Transfer", async() => { - -// it("Should fail to forceTransfer because not approved controller", async() => { -// let errorThrown1 = false; -// try { -// await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_investor1}); -// } catch (error) { -// console.log(` tx revert -> not approved controller`.grey); -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, message); -// }); - -// it("Should fail to forceTransfer because insufficient balance", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.forceTransfer(account_investor2, account_investor1, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); -// } catch (error) { -// console.log(` tx revert -> insufficient balance`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to forceTransfer because recipient is zero address", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.forceTransfer(account_investor1, address_zero, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); -// } catch (error) { -// console.log(` tx revert -> recipient is zero address`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully forceTransfer", async() => { -// let sender = account_investor1; -// let receiver = account_investor2; - -// let start_investorCount = await I_SecurityToken.getInvestorCount.call(); -// let start_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); -// let start_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); - -// let tx = await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); - -// let end_investorCount = await I_SecurityToken.getInvestorCount.call(); -// let end_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); -// let end_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); - -// assert.equal(start_investorCount.add(1).toNumber(), end_investorCount.toNumber(), "Investor count not changed"); -// assert.equal(start_balInv1.sub(web3.utils.toWei("10", "ether")).toNumber(), end_balInv1.toNumber(), "Investor balance not changed"); -// assert.equal(start_balInv2.add(web3.utils.toWei("10", "ether")).toNumber(), end_balInv2.toNumber(), "Investor balance not changed"); -// console.log(tx.logs[0].args); -// console.log(tx.logs[1].args); -// assert.equal(account_controller, tx.logs[0].args._controller, "Event not emitted as expected"); -// assert.equal(account_investor1, tx.logs[0].args._from, "Event not emitted as expected"); -// assert.equal(account_investor2, tx.logs[0].args._to, "Event not emitted as expected"); -// assert.equal(web3.utils.toWei("10", "ether"), tx.logs[0].args._value, "Event not emitted as expected"); -// console.log(tx.logs[0].args._verifyTransfer); -// assert.equal(false, tx.logs[0].args._verifyTransfer, "Event not emitted as expected"); -// assert.equal("reason", web3.utils.hexToUtf8(tx.logs[0].args._data), "Event not emitted as expected"); - -// assert.equal(account_investor1, tx.logs[1].args.from, "Event not emitted as expected"); -// assert.equal(account_investor2, tx.logs[1].args.to, "Event not emitted as expected"); -// assert.equal(web3.utils.toWei("10", "ether"), tx.logs[1].args.value, "Event not emitted as expected"); -// }); - -// it("Should fail to freeze controller functionality because not owner", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.disableController({from: account_investor1}); -// } catch (error) { -// console.log(` tx revert -> not owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to freeze controller functionality because disableControllerAllowed not activated", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.disableController({from: token_owner}); -// } catch (error) { -// console.log(` tx revert -> disableControllerAllowed not activated`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully freeze controller functionality", async() => { -// let tx1 = await I_FeatureRegistry.setFeatureStatus("disableControllerAllowed", true, {from: account_polymath}); - -// // check event -// assert.equal("disableControllerAllowed", tx1.logs[0].args._nameKey, "Event not emitted as expected"); -// assert.equal(true, tx1.logs[0].args._newStatus, "Event not emitted as expected"); - -// let tx2 = await I_SecurityToken.disableController({from: token_owner}); - -// // check state -// assert.equal(address_zero, await I_SecurityToken.controller.call(), "State not changed"); -// assert.equal(true, await I_SecurityToken.controllerDisabled.call(), "State not changed"); -// }); - -// it("Should fail to freeze controller functionality because already frozen", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.disableController({from: token_owner}); -// } catch (error) { -// console.log(` tx revert -> already frozen`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to set controller because controller functionality frozen", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.setController(account_controller, {from: token_owner}); -// } catch (error) { -// console.log(` tx revert -> msg.sender not owner`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should fail to forceTransfer because controller functionality frozen", async() => { -// let errorThrown = false; -// try { -// await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); -// } catch (error) { -// console.log(` tx revert -> recipient is zero address`.grey); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// }); - -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +const CappedSTO = artifacts.require('./CappedSTO.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + + +contract('SecurityToken', accounts => { + + + // Accounts Variable declaration + let account_polymath; + let account_investor1; + let account_issuer; + let token_owner; + let account_investor2; + let account_investor3; + let account_affiliate1; + let account_affiliate2; + let account_fundsReceiver; + let account_delegate; + let account_temp; + let account_controller; + let address_zero = "0x0000000000000000000000000000000000000000"; + + let balanceOfReceiver; + // investor Details + let fromTime; + let toTime; + let expiryTime; + + let ID_snap; + const message = "Transaction Should Fail!!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_CappedSTOFactory; + let I_STFactory; + let I_SecurityToken; + let I_STRProxied; + let I_MRProxied; + let I_CappedSTO; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details (Launched ST on the behalf of the issuer) + const name = "Demo Token"; + const symbol = "DET"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + let snap_Id; + // Module key + const permissionManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + const budget = 0; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // delagate details + const delegateDetails = "I am delegate .."; + const TM_Perm = 'FLAGS'; + const TM_Perm_Whitelist = 'WHITELIST'; + + // Capped STO details + let startTime; + let endTime; + const cap = web3.utils.toWei("10000"); + const rate = 1000; + const fundRaiseType = [0]; + const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); + const maxCost = cappedSTOSetupCost; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + account_affiliate1 = accounts[2]; + account_affiliate2 = accounts[3]; + account_fundsReceiver = accounts[4]; + account_delegate = accounts[5]; + account_investor2 = accounts[6]; + account_investor3 = accounts[7]; + account_temp = accounts[8]; + account_investor1 = accounts[9]; + + token_owner = account_issuer; + account_controller = account_temp; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4 (a): Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + address_zero, + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 4 (b): Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + address_zero, + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 4 (c): Deploy the CappedSTOFactory + + I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); + + assert.notEqual( + I_CappedSTOFactory.address.valueOf(), + address_zero, + "CappedSTOFactory contract was not deployed" + ); + + // STEP 5: Register the Modules with the ModuleRegistry contract + + // Step 6: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 7: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 8: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 9: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + ModuleRegistry: ${ModuleRegistry.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + CappedSTOFactory: ${I_CappedSTOFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + console.log(log.args); + assert.equal(log.args._types[0].toNumber(), transferManagerKey); + assert.equal(web3.utils.toUtf8(log.args._name),"GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + assert.notEqual( + I_GeneralTransferManager.address.valueOf(), + address_zero, + "GeneralTransferManager contract was not deployed", + ); + + }); + + it("Should mint the tokens before attaching the STO -- fail only be called by the owner", async() => { + let errorThrown = false; + let fromTime = latestTime(); + let toTime = fromTime + duration.days(100); + let expiryTime = toTime + duration.days(100); + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_affiliate1, + fromTime, + toTime, + expiryTime, + true, + { + from: token_owner, + gas: 6000000 + }); + assert.equal(tx.logs[0].args._investor, account_affiliate1, "Failed in adding the investor in whitelist"); + try { + await I_SecurityToken.mint(account_investor1, (100 * Math.pow(10, 18)), {from: account_delegate}); + } catch(error) { + console.log(` tx revert -> Mint only be called by the owner of the SecurityToken`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should mint the tokens before attaching the STO", async() => { + await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); + let balance = await I_SecurityToken.balanceOf(account_affiliate1); + assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); + }); + + it("Should mint the multi tokens before attaching the STO -- fail only be called by the owner", async() => { + let errorThrown = false; + let fromTime = latestTime(); + let toTime = fromTime + duration.days(100); + let expiryTime = toTime + duration.days(100); + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_affiliate2, + fromTime, + toTime, + expiryTime, + true, + { + from: token_owner, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor, account_affiliate2, "Failed in adding the investor in whitelist"); + try { + await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: account_delegate, gas: 500000}); + } catch(error) { + console.log(` tx revert -> Mint only be called by the owner of the SecurityToken`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should mintMulti", async() => { + let errorThrown = false; + try { + await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); + } catch(error) { + console.log(` tx revert -> Array length are un-equal`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should mint the tokens for multiple afiliated investors before attaching the STO", async() => { + await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); + let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); + assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 200); + let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); + assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 110); + }); + + it("Should finish the minting -- fail because feature is not activated", async() => { + let errorThrown = false; + try { + await I_SecurityToken.freezeMinting({from: token_owner}); + } catch(error) { + console.log(` tx revert -> freezeMinting cannot be called before activated by polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should finish the minting -- fail to activate the feature because msg.sender is not polymath", async() => { + let errorThrown = false; + try { + await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: token_owner}); + } catch(error) { + console.log(` tx revert -> allowFreezeMinting must be called by polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should finish the minting -- successfully activate the feature", async() => { + let errorThrown1 = false; + try { + await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", false, {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> must change state`.grey); + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, message); + + assert.equal(false, await I_FeatureRegistry.getFeatureStatus("freezeMintingAllowed", {from: account_temp})); + await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: account_polymath}); + assert.equal(true, await I_FeatureRegistry.getFeatureStatus("freezeMintingAllowed", {from: account_temp})); + + let errorThrown2 = false; + try { + await I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> must change state`.grey); + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, message); + }); + + it("Should finish the minting -- fail because msg.sender is not the owner", async() => { + let errorThrown = false; + try { + await I_SecurityToken.freezeMinting({from: account_temp}); + } catch(error) { + console.log(` tx revert -> freezeMinting only be called by the owner of the SecurityToken`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should finish minting & restrict the further minting", async() => { + let id = await takeSnapshot(); + await I_SecurityToken.freezeMinting({from: token_owner}); + let errorThrown = false; + try { + await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); + } catch(error) { + console.log(` tx revert -> Minting is finished`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + await revertToSnapshot(id); + }); + + it("Should fail to attach the STO factory because not enough poly in contract", async () => { + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + let errorThrown = false; + try { + let tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + } catch (error) { + console.log(` tx revert -> not enough poly in contract`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to attach the STO factory because max cost too small", async () => { + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); + let errorThrown = false; + try { + let tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, web3.utils.toWei("1000","ether"), 0, { from: token_owner }); + } catch (error) { + console.log(` tx revert -> max cost too small`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the STO factory with the security token", async () => { + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + + await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); + + const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); + assert.equal(web3.utils.toUtf8(tx.logs[3].args._name), "CappedSTO", "CappedSTOFactory module was not added"); + I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); + }); + + it("Should successfully mint tokens while STO attached", async () => { + await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); + let balance = await I_SecurityToken.balanceOf(account_affiliate1); + assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 300); + }); + + it("Should fail to mint tokens while STO attached after freezeMinting called", async () => { + let id = await takeSnapshot(); + await I_SecurityToken.freezeMinting({from: token_owner}); + let errorThrown = false; + try { + await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); + } catch(error) { + console.log(` tx revert -> Minting is finished`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + await revertToSnapshot(id); + }); + + }); + + describe("Module related functions", async() => { + it("Should get the modules of the securityToken by index", async () => { + let moduleData = await I_SecurityToken.getModule.call(I_CappedSTO.address); + assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "CappedSTO"); + assert.equal(moduleData[1], I_CappedSTO.address); + assert.equal(moduleData[2], I_CappedSTOFactory.address); + assert.equal(moduleData[3], false); + assert.equal(moduleData[4][0], 3); + }); + + it("Should get the modules of the securityToken by index (not added into the security token yet)", async () => { + let moduleData = await I_SecurityToken.getModule.call(token_owner); + assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), ""); + assert.equal(moduleData[1], address_zero); + }); + + it("Should get the modules of the securityToken by name", async () => { + let moduleList = await I_SecurityToken.getModulesByName.call("CappedSTO"); + assert.isTrue(moduleList.length == 1, "Only one STO"); + let moduleData = await I_SecurityToken.getModule.call(moduleList[0]); + assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "CappedSTO"); + assert.equal(moduleData[1], I_CappedSTO.address); + }); + + it("Should get the modules of the securityToken by name (not added into the security token yet)", async () => { + let moduleData = await I_SecurityToken.getModulesByName.call("GeneralPermissionManager"); + assert.isTrue(moduleData.length == 0, "No Permission Manager"); + }); + + it("Should get the modules of the securityToken by name (not added into the security token yet)", async () => { + let moduleData = await I_SecurityToken.getModulesByName.call("CountTransferManager"); + assert.isTrue(moduleData.length == 0, "No Permission Manager"); + }); + + it("Should fail in updating the token details", async() => { + let errorThrown = false; + try { + let log = await I_SecurityToken.updateTokenDetails("new token details", {from: account_delegate}); + } catch (error) { + console.log(` tx revert -> msg.sender should be the owner of the token`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should update the token details", async() => { + let log = await I_SecurityToken.updateTokenDetails("new token details", {from: token_owner}); + assert.equal(log.logs[0].args._newDetails, "new token details"); + }); + + it("Should fail to remove the module - module not archived", async() => { + let errorThrown = false; + try { + let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); + } catch (error) { + console.log(` tx -> Failed because address doesn't exist`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should successfully remove the general transfer manager module from the securityToken -- fails msg.sender should be Owner", async() => { + let errorThrown = false; + try { + let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : account_temp }); + } catch (error) { + console.log(`Test Case passed by restricting the unknown account to call removeModule of the securityToken`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to remove the module - incorrect address", async() => { + let errorThrown = false; + try { + let tx = await I_SecurityToken.removeModule(0, { from : token_owner }); + } catch (error) { + console.log(` tx -> Failed because address doesn't exist`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should successfully remove the general transfer manager module from the securityToken", async() => { + let key = await takeSnapshot(); + await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); + let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); + assert.equal(tx.logs[0].args._types[0], transferManagerKey); + assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); + await revertToSnapshot(key); + }); + + it("Should verify the revertion of snapshot works properly", async() => { + let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); + assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); + assert.equal(moduleData[1], I_GeneralTransferManager.address); + }); + + + it("Should successfully archive the general transfer manager module from the securityToken", async() => { + let tx = await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); + assert.equal(tx.logs[0].args._types[0], transferManagerKey); + assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); + let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); + assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); + assert.equal(moduleData[1], I_GeneralTransferManager.address); + assert.equal(moduleData[2], I_GeneralTransferManagerFactory.address); + assert.equal(moduleData[3], true); + }); + + it("Should successfully mint tokens while GTM archived", async () => { + let key = await takeSnapshot(); + await I_SecurityToken.mint(1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); + let balance = await I_SecurityToken.balanceOf(1); + assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); + await revertToSnapshot(key); + }); + + it("Should successfully unarchive the general transfer manager module from the securityToken", async() => { + let tx = await I_SecurityToken.unarchiveModule(I_GeneralTransferManager.address, { from : token_owner }); + assert.equal(tx.logs[0].args._types[0], transferManagerKey); + assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); + let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); + assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); + assert.equal(moduleData[1], I_GeneralTransferManager.address); + assert.equal(moduleData[2], I_GeneralTransferManagerFactory.address); + assert.equal(moduleData[3], false); + }); + + it("Should fail to mint tokens while GTM unarchived", async () => { + let errorThrown = false; + try { + await I_SecurityToken.mint(1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); + } catch(error) { + console.log(` tx -> Failed because GTM`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + + }); + + it("Should change the budget of the module - fail incorrect address", async() => { + let errorThrown = false; + try { + let tx = await I_SecurityToken.changeModuleBudget(0, (100 * Math.pow(10, 18)),{ from : token_owner}); + } catch(error) { + console.log(` tx -> Failed because address is 0`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + + it("Should change the budget of the module", async() => { + let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, (100 * Math.pow(10, 18)),{ from : token_owner}); + assert.equal(tx.logs[1].args._moduleTypes[0], stoKey); + assert.equal(tx.logs[1].args._module, I_CappedSTO.address); + assert.equal(tx.logs[1].args._budget.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); + }); + + }); + + describe("General Transfer manager Related test cases", async () => { + + it("Should Buy the tokens", async() => { + balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); + // Add the Investor in to the whitelist + + fromTime = latestTime(); + toTime = fromTime + duration.days(100); + expiryTime = toTime + duration.days(100); + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + fromTime, + toTime, + expiryTime, + true, + { + from: token_owner, + gas: 6000000 + }); + assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); + // Jump time + await increaseTime(5000); + // Fallback transaction + console.log("BEFORE"); + await web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO.address, + gas: 2100000, + value: web3.utils.toWei('1', 'ether') + }); + console.log("AFTER"); + assert.equal( + (await I_CappedSTO.getRaised.call(0)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1 + ); + + assert.equal(await I_CappedSTO.investorCount.call(), 1); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000 + ); + }); + + it("Should Fail in transferring the token from one whitelist investor 1 to non whitelist investor 2", async() => { + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, (10 * Math.pow(10, 18)), { from : account_investor1}); + } catch(error) { + console.log(` tx revert -> Investor 2 is not in the whitelist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to provide the permission to the delegate to change the transfer bools", async () => { + let errorThrown = false; + // Add permission to the deletgate (A regesteration process) + await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: token_owner}); + let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; + I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); + try { + await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_temp }); + } catch (error) { + console.log(`${account_temp} doesn't have permissions to register the delegate`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should provide the permission to the delegate to change the transfer bools", async () => { + // Add permission to the deletgate (A regesteration process) + await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); + // Providing the permission to the delegate + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm, true, { from: token_owner }); + + assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm)); + }); + + + it("Should fail to activate the bool allowAllTransfer", async() => { + let errorThrown = false; + try { + let tx = await I_GeneralTransferManager.changeAllowAllTransfers(true, { from : account_temp }); + } catch (error) { + console.log(`${account_temp} doesn't have permissions to activate the bool allowAllTransfer`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should activate the bool allowAllTransfer", async() => { + ID_snap = await takeSnapshot(); + let tx = await I_GeneralTransferManager.changeAllowAllTransfers(true, { from : account_delegate }); + + assert.isTrue(tx.logs[0].args._allowAllTransfers, "AllowTransfer variable is not successfully updated"); + }); + + + it("Should fail to send tokens with the wrong granularity", async() => { + let errorThrown = false; + try { + await I_SecurityToken.transfer(accounts[7], Math.pow(10, 17), { from : account_investor1}); + } catch (error) { + console.log(' tx revert -> Incorrect token granularity - expected'.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should adjust granularity", async() => { + let errorThrown = false; + try { + await I_SecurityToken.changeGranularity(0, {from: token_owner }); + } catch(error) { + console.log(' tx revert -> Incorrect token granularity - expected'.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should adjust granularity", async() => { + let errorThrown = false; + await I_SecurityToken.changeGranularity(Math.pow(10, 17), {from: token_owner }); + await I_SecurityToken.transfer(accounts[7], Math.pow(10, 17), { from : account_investor1, gas: 2500000 }); + await I_SecurityToken.transfer(account_investor1, Math.pow(10, 17), { from : accounts[7], gas: 2500000}); + }); + + it("Should transfer from whitelist investor to non-whitelist investor in first tx and in 2nd tx non-whitelist to non-whitelist transfer", async() => { + await I_SecurityToken.transfer(accounts[7], (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); + + assert.equal( + (await I_SecurityToken.balanceOf(accounts[7])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), + 10, + "Transfer doesn't take place properly" + ); + + await I_SecurityToken.transfer(account_temp, (5 * Math.pow(10, 18)), { from : accounts[7], gas: 2500000}); + + assert.equal( + (await I_SecurityToken.balanceOf(account_temp)) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), + 5, + "Transfer doesn't take place properly" + ); + await revertToSnapshot(ID_snap); + }); + + it("Should bool allowAllTransfer value is false", async() => { + assert.isFalse(await I_GeneralTransferManager.allowAllTransfers.call(), "reverting of snapshot doesn't works properly"); + }); + + it("Should change the bool allowAllWhitelistTransfers to true", async () => { + ID_snap = await takeSnapshot(); + let tx = await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, { from : account_delegate }); + + assert.isTrue(tx.logs[0].args._allowAllWhitelistTransfers, "allowAllWhitelistTransfers variable is not successfully updated"); + }); + + it("Should transfer from whitelist investor1 to whitelist investor 2", async() => { + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + fromTime, + toTime, + expiryTime, + true, + { + from: token_owner, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + + await I_SecurityToken.transfer(account_investor2, (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), + 10, + "Transfer doesn't take place properly" + ); + }); + + it("Should transfer from whitelist investor1 to whitelist investor 2 -- value = 0", async() => { + let tx = await I_SecurityToken.transfer(account_investor2, 0, { from : account_investor1, gas: 2500000}); + assert.equal((tx.logs[0].args.value).toNumber(),0); + }); + + it("Should transferFrom from one investor to other", async() => { + await I_SecurityToken.approve(account_investor1, (2 * Math.pow(10, 18)),{from: account_investor2}); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + fromTime, + toTime, + expiryTime, + true, + { + from: token_owner, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor, account_investor3, "Failed in adding the investor in whitelist"); + let log = await I_SecurityToken.transferFrom(account_investor2, account_investor3, (2 * Math.pow(10, 18)), {from: account_investor1}); + assert.equal((log.logs[0].args.value).toNumber(), (2 * Math.pow(10, 18))); + }); + + it("Should Fail in trasferring from whitelist investor1 to non-whitelist investor", async() => { + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_temp, (10 * Math.pow(10, 18)), { from : account_investor1, gas: 2500000}); + } catch(error) { + console.log(`non-whitelist investor is not allowed`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + await revertToSnapshot(ID_snap); + }); + + it("Should successfully mint tokens while STO attached", async () => { + await I_SecurityToken.mint(account_affiliate1, (100 * Math.pow(10, 18)), {from: token_owner, gas: 500000}); + let balance = await I_SecurityToken.balanceOf(account_affiliate1); + assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 400); + }); + + it("Should mint the tokens for multiple afiliated investors while STO attached", async() => { + await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [(100 * Math.pow(10, 18)), (110 * Math.pow(10, 18))], {from: token_owner, gas: 500000}); + let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); + assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 500); + let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); + assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 220); + }); + + it("Should provide more permissions to the delegate", async() => { + // Providing the permission to the delegate + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, TM_Perm_Whitelist, true, { from: token_owner }); + + assert.isTrue(await I_GeneralPermissionManager.checkPermission(account_delegate, I_GeneralTransferManager.address, TM_Perm_Whitelist)); + }); + + it("Should add the investor in the whitelist by the delegate", async() => { + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_temp, + fromTime, + toTime, + expiryTime, + true, + { + from: account_delegate, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor, account_temp, "Failed in adding the investor in whitelist"); + }); + + it("should account_temp successfully buy the token", async() => { + // Fallback transaction + await web3.eth.sendTransaction({ + from: account_temp, + to: I_CappedSTO.address, + gas: 2100000, + value: web3.utils.toWei('1', 'ether') + }); + + assert.equal( + (await I_CappedSTO.getRaised.call(0)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 2 + ); + + assert.equal(await I_CappedSTO.investorCount.call(), 2); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000 + ); + }); + + it("STO should fail to mint tokens after minting is frozen", async() => { + let id = await takeSnapshot(); + await I_SecurityToken.freezeMinting({from: token_owner}); + let errorThrown = false; + try { + await web3.eth.sendTransaction({ + from: account_temp, + to: I_CappedSTO.address, + gas: 2100000, + value: web3.utils.toWei('1', 'ether') + }); + } catch(error) { + console.log(` tx revert -> Minting is finished`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + await revertToSnapshot(id); + }); + + it("Should remove investor from the whitelist by the delegate", async() => { + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_temp, + 0, + 0, + 0, + true, + { + from: account_delegate, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor, account_temp, "Failed in removing the investor from whitelist"); + }); + + it("should account_temp fail in buying the token", async() => { + let errorThrown = false; + try { + // Fallback transaction + await web3.eth.sendTransaction({ + from: account_temp, + to: I_CappedSTO.address, + gas: 2100000, + value: web3.utils.toWei('1', 'ether') + }); + + } catch (error) { + console.log(`non-whitelist investor is not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should freeze the transfers", async() => { + let tx = await I_SecurityToken.freezeTransfers({from: token_owner}); + assert.isTrue(tx.logs[0].args._status); + }); + + it("Should fail to freeze the transfers", async() => { + let errorThrown = false; + try { + await I_SecurityToken.freezeTransfers({from: token_owner}); + } catch(error) { + console.log(` tx -> Revert because freeze is already true`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in buying to tokens", async() => { + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_temp, + fromTime, + toTime, + expiryTime, + true, + { + from: account_delegate, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor, account_temp, "Failed in adding the investor in whitelist"); + + let errorThrown = false; + try { + // Fallback transaction + await web3.eth.sendTransaction({ + from: account_temp, + to: I_CappedSTO.address, + gas: 2100000, + value: web3.utils.toWei('1', 'ether') + }); + + } catch (error) { + console.log(`Because all transfers get freezed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in trasfering the tokens from one user to another", async() => { + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); + console.log(await I_SecurityToken.balanceOf(account_investor1)); + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); + } catch(error) { + console.log(' tx revert -> All transfers are at hold'.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should unfreeze all the transfers", async() => { + let tx = await I_SecurityToken.unfreezeTransfers({from: token_owner}); + assert.isFalse(tx.logs[0].args._status); + }); + + it("Should freeze the transfers", async() => { + let errorThrown = false; + try { + await I_SecurityToken.unfreezeTransfers({from: token_owner}); + } catch(error) { + console.log(` tx -> Revert because freeze is already false`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should able to transfers the tokens from one user to another", async() => { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); + }); + + it("Should check that the list of investors is correct", async ()=> { + // Hardcode list of expected accounts based on transfers above + + let investors = await I_SecurityToken.getInvestors(); + let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1, account_temp]; + for (let i = 0; i < expectedAccounts.length; i++) { + assert.equal(investors[i], expectedAccounts[i]); + } + assert.equal(investors.length, 4); + console.log("Total Seen Investors: " + investors.length); + }); + it("Should fail to set controller status because msg.sender not owner", async() => { + let errorThrown = false; + try { + await I_SecurityToken.setController(account_controller, {from: account_controller}); + } catch (error) { + console.log(` tx revert -> msg.sender not owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully set controller", async() => { + let tx1 = await I_SecurityToken.setController(account_controller, {from: token_owner}); + + // check event + assert.equal(address_zero, tx1.logs[0].args._oldController, "Event not emitted as expected"); + assert.equal(account_controller, tx1.logs[0].args._newController, "Event not emitted as expected"); + + let tx2 = await I_SecurityToken.setController(address_zero, {from: token_owner}); + + // check event + assert.equal(account_controller, tx2.logs[0].args._oldController, "Event not emitted as expected"); + assert.equal(address_zero, tx2.logs[0].args._newController, "Event not emitted as expected"); + + let tx3 = await I_SecurityToken.setController(account_controller, {from: token_owner}); + + // check event + assert.equal(address_zero, tx3.logs[0].args._oldController, "Event not emitted as expected"); + assert.equal(account_controller, tx3.logs[0].args._newController, "Event not emitted as expected"); + + // check status + let controller = await I_SecurityToken.controller.call(); + assert.equal(account_controller, controller, "Status not set correctly"); + }); + + it("Should force burn the tokens - value too high", async ()=> { + let errorThrown = false; + await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); + let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); + let currentBalance = await I_SecurityToken.balanceOf(account_temp); + try { + let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance + web3.utils.toWei("500", "ether"), "", "", { from: account_controller }); + } catch(error) { + console.log(` tx revert -> value is greater than its current balance`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + it("Should force burn the tokens - wrong caller", async ()=> { + let errorThrown = false; + await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); + let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); + let currentBalance = await I_SecurityToken.balanceOf(account_temp); + try { + let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", "", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> not owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should burn the tokens", async ()=> { + let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); + let currentBalance = await I_SecurityToken.balanceOf(account_temp); + // console.log(currentInvestorCount.toString(), currentBalance.toString()); + let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", "", { from: account_controller }); + // console.log(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); + assert.equal(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); + let newInvestorCount = await I_SecurityToken.getInvestorCount.call(); + // console.log(newInvestorCount.toString()); + assert.equal(newInvestorCount.toNumber() + 1, currentInvestorCount.toNumber(), "Investor count drops by one"); + }); + + it("Should prune investor length", async ()=> { + await I_SecurityToken.pruneInvestors(0, 10, {from: token_owner}); + // Hardcode list of expected accounts based on transfers above + + let investors = await I_SecurityToken.getInvestors.call(); + let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1]; + for (let i = 0; i < expectedAccounts.length; i++) { + assert.equal(investors[i], expectedAccounts[i]); + } + assert.equal(investors.length, 3); + }); + + it("Should check the balance of investor at checkpoint", async() => { + let errorThrown = false; + try { + await I_SecurityToken.balanceOfAt(account_investor1, 5); + } catch(error) { + console.log(` tx -> Revert checkpoint ID is greator than current checkpoint`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should check the balance of investor at checkpoint", async() => { + let balance = await I_SecurityToken.balanceOfAt(account_investor1, 0); + assert.equal(balance.toNumber(), 0); + }); + }); + + describe("Withdraw Poly", async() => { + + it("Should successfully withdraw the poly", async() => { + let errorThrown = false; + try { + await I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), {from: account_temp}); + } catch (error) { + console.log(` tx revert -> withdrawPoly function can only be called by the owner of the seucrity token`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) + + it("Should successfully withdraw the poly", async() => { + let balanceBefore = await I_PolyToken.balanceOf(token_owner); + await I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), {from: token_owner}); + let balanceAfter = await I_PolyToken.balanceOf(token_owner); + assert.equal((BigNumber(balanceAfter).sub(BigNumber(balanceBefore))).toNumber(), web3.utils.toWei("20000", "ether")); + }); + + it("Should successfully withdraw the poly", async() => { + let errorThrown = false; + try { + await I_SecurityToken.withdrawPoly(web3.utils.toWei("10", "ether"), {from: token_owner}); + } catch (error) { + console.log(` tx revert -> token doesn't have any POLY`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + }); + + describe("Force Transfer", async() => { + + it("Should fail to forceTransfer because not approved controller", async() => { + let errorThrown1 = false; + try { + await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_investor1}); + } catch (error) { + console.log(` tx revert -> not approved controller`.grey); + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, message); + }); + + it("Should fail to forceTransfer because insufficient balance", async() => { + let errorThrown = false; + try { + await I_SecurityToken.forceTransfer(account_investor2, account_investor1, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); + } catch (error) { + console.log(` tx revert -> insufficient balance`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to forceTransfer because recipient is zero address", async() => { + let errorThrown = false; + try { + await I_SecurityToken.forceTransfer(account_investor1, address_zero, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); + } catch (error) { + console.log(` tx revert -> recipient is zero address`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully forceTransfer", async() => { + let sender = account_investor1; + let receiver = account_investor2; + + let start_investorCount = await I_SecurityToken.getInvestorCount.call(); + let start_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); + let start_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); + + let tx = await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); + + let end_investorCount = await I_SecurityToken.getInvestorCount.call(); + let end_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); + let end_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); + + assert.equal(start_investorCount.add(1).toNumber(), end_investorCount.toNumber(), "Investor count not changed"); + assert.equal(start_balInv1.sub(web3.utils.toWei("10", "ether")).toNumber(), end_balInv1.toNumber(), "Investor balance not changed"); + assert.equal(start_balInv2.add(web3.utils.toWei("10", "ether")).toNumber(), end_balInv2.toNumber(), "Investor balance not changed"); + console.log(tx.logs[0].args); + console.log(tx.logs[1].args); + assert.equal(account_controller, tx.logs[0].args._controller, "Event not emitted as expected"); + assert.equal(account_investor1, tx.logs[0].args._from, "Event not emitted as expected"); + assert.equal(account_investor2, tx.logs[0].args._to, "Event not emitted as expected"); + assert.equal(web3.utils.toWei("10", "ether"), tx.logs[0].args._value, "Event not emitted as expected"); + console.log(tx.logs[0].args._verifyTransfer); + assert.equal(false, tx.logs[0].args._verifyTransfer, "Event not emitted as expected"); + assert.equal("reason", web3.utils.hexToUtf8(tx.logs[0].args._data), "Event not emitted as expected"); + + assert.equal(account_investor1, tx.logs[1].args.from, "Event not emitted as expected"); + assert.equal(account_investor2, tx.logs[1].args.to, "Event not emitted as expected"); + assert.equal(web3.utils.toWei("10", "ether"), tx.logs[1].args.value, "Event not emitted as expected"); + }); + + it("Should fail to freeze controller functionality because not owner", async() => { + let errorThrown = false; + try { + await I_SecurityToken.disableController({from: account_investor1}); + } catch (error) { + console.log(` tx revert -> not owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to freeze controller functionality because disableControllerAllowed not activated", async() => { + let errorThrown = false; + try { + await I_SecurityToken.disableController({from: token_owner}); + } catch (error) { + console.log(` tx revert -> disableControllerAllowed not activated`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully freeze controller functionality", async() => { + let tx1 = await I_FeatureRegistry.setFeatureStatus("disableControllerAllowed", true, {from: account_polymath}); + + // check event + assert.equal("disableControllerAllowed", tx1.logs[0].args._nameKey, "Event not emitted as expected"); + assert.equal(true, tx1.logs[0].args._newStatus, "Event not emitted as expected"); + + let tx2 = await I_SecurityToken.disableController({from: token_owner}); + + // check state + assert.equal(address_zero, await I_SecurityToken.controller.call(), "State not changed"); + assert.equal(true, await I_SecurityToken.controllerDisabled.call(), "State not changed"); + }); + + it("Should fail to freeze controller functionality because already frozen", async() => { + let errorThrown = false; + try { + await I_SecurityToken.disableController({from: token_owner}); + } catch (error) { + console.log(` tx revert -> already frozen`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to set controller because controller functionality frozen", async() => { + let errorThrown = false; + try { + await I_SecurityToken.setController(account_controller, {from: token_owner}); + } catch (error) { + console.log(` tx revert -> msg.sender not owner`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to forceTransfer because controller functionality frozen", async() => { + let errorThrown = false; + try { + await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", {from: account_controller}); + } catch (error) { + console.log(` tx revert -> recipient is zero address`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + }); + + }); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 0ba8056d0..20656b0bc 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1,3517 +1,3517 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); -// const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); -// const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); -// const MockOracle = artifacts.require('./MockOracle.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port - -// contract('USDTieredSTO', accounts => { -// // Accounts Variable declaration -// let POLYMATH; -// let ISSUER; -// let WALLET; -// let RESERVEWALLET; -// let INVESTOR1; -// let INVESTOR2; -// let INVESTOR3; -// let INVESTOR4; -// let ACCREDITED1; -// let ACCREDITED2; -// let NONACCREDITED1; -// let NONACCREDITED2; -// let ETH = 0; -// let POLY = 1; -// let DAI = 2; - -// let MESSAGE = "Transaction Should Fail!"; -// const GAS_PRICE = 0; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let I_USDTieredSTOProxyFactory; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistry; -// let I_ModuleRegistryProxy; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_USDTieredSTOFactory; -// let I_USDOracle; -// let I_POLYOracle; -// let I_STFactory; -// let I_SecurityToken; -// let I_STRProxied; -// let I_MRProxied; -// let I_USDTieredSTO_Array = []; -// let I_PolyToken; -// let I_DaiToken; -// let I_PolymathRegistry; - -// // SecurityToken Details for funds raise Type ETH -// const NAME = "Team"; -// const SYMBOL = "SAP"; -// const TOKENDETAILS = "This is equity type of issuance"; -// const DECIMALS = 18; - -// // Module key -// const TMKEY = 2; -// const STOKEY = 3; - -// // Initial fee for ticker registry and security token registry -// const REGFEE = web3.utils.toWei("250"); -// const STOSetupCost = 0; - -// // MockOracle USD prices -// const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH -// const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY - -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// // STO Configuration Arrays -// let _startTime = []; -// let _endTime = []; -// let _ratePerTier = []; -// let _ratePerTierDiscountPoly = []; -// let _tokensPerTierTotal = []; -// let _tokensPerTierDiscountPoly = []; -// let _nonAccreditedLimitUSD = []; -// let _minimumInvestmentUSD = []; -// let _fundRaiseTypes = []; -// let _wallet = []; -// let _reserveWallet = []; -// let _usdToken = []; - -// /* function configure( -// uint256 _startTime, -// uint256 _endTime, -// uint256[] _ratePerTier, -// uint256[] _ratePerTierDiscountPoly, -// uint256[] _tokensPerTier, -// uint256[] _tokensPerTierDiscountPoly, -// uint256 _nonAccreditedLimitUSD, -// uint256 _minimumInvestmentUSD, -// uint8[] _fundRaiseTypes, -// address _wallet, -// address _reserveWallet, -// address _usdToken -// ) */ -// const functionSignature = { -// name: 'configure', -// type: 'function', -// inputs: [{ -// type: 'uint256', -// name: '_startTime' -// },{ -// type: 'uint256', -// name: '_endTime' -// },{ -// type: 'uint256[]', -// name: '_ratePerTier' -// },{ -// type: 'uint256[]', -// name: '_ratePerTierDiscountPoly' -// },{ -// type: 'uint256[]', -// name: '_tokensPerTier' -// },{ -// type: 'uint256[]', -// name: '_tokensPerTierDiscountPoly' -// },{ -// type: 'uint256', -// name: '_nonAccreditedLimitUSD' -// },{ -// type: 'uint256', -// name: '_minimumInvestmentUSD' -// },{ -// type: 'uint8[]', -// name: '_fundRaiseTypes' -// },{ -// type: 'address', -// name: '_wallet' -// },{ -// type: 'address', -// name: '_reserveWallet' -// },{ -// type: 'address', -// name: '_usdToken' -// }] -// }; - -// async function convert(_stoID, _tier, _discount, _currencyFrom, _currencyTo, _amount) { -// let USDTOKEN; -// if (_discount) -// USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTierDiscountPoly.call(_tier); -// else -// USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTier.call(_tier); -// if (_currencyFrom == "TOKEN") { -// let tokenToUSD = _amount.div(10**18).mul(USDTOKEN.div(10**18)).mul(10**18); // TOKEN * USD/TOKEN = USD -// if (_currencyTo == "USD") -// return tokenToUSD; -// if (_currencyTo == "ETH") { -// return await I_USDTieredSTO_Array[_stoID].convertFromUSD(ETH, tokenToUSD); -// } else if (_currencyTo == "POLY") { -// return await I_USDTieredSTO_Array[_stoID].convertFromUSD(POLY, tokenToUSD); -// } -// } -// if (_currencyFrom == "USD") { -// if (_currencyTo == "TOKEN") -// return _amount.div(USDTOKEN).mul(10**18); // USD / USD/TOKEN = TOKEN -// if (_currencyTo == "ETH" || _currencyTo == "POLY") -// return await I_USDTieredSTO_Array[_stoID].convertFromUSD((_currencyTo == "ETH" ? ETH : POLY), _amount); -// } -// if (_currencyFrom == "ETH" || _currencyFrom == "POLY") { -// let ethToUSD = await I_USDTieredSTO_Array[_stoID].convertToUSD((_currencyTo == "ETH" ? ETH : POLY), _amount); -// if (_currencyTo == "USD") -// return ethToUSD; -// if (_currencyTo == "TOKEN") -// return ethToUSD.div(USDTOKEN).mul(10**18); // USD / USD/TOKEN = TOKEN -// } -// return 0; -// } - -// before(async() => { -// // Accounts setup -// POLYMATH = accounts[0]; -// ISSUER = accounts[1]; -// WALLET = accounts[2]; -// RESERVEWALLET = WALLET; -// ACCREDITED1 = accounts[3]; -// ACCREDITED2 = accounts[4]; -// NONACCREDITED1 = accounts[5]; -// NONACCREDITED2 = accounts[6]; -// INVESTOR1 = accounts[7]; -// INVESTOR2 = accounts[8]; -// INVESTOR3 = accounts[9]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// I_DaiToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: POLYMATH -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 3: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the proxy -// I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); - -// // STEP 6: Deploy the USDTieredSTOFactory - -// I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); - -// assert.notEqual( -// I_USDTieredSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "USDTieredSTOFactory contract was not deployed" -// ); - -// // Step 8: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 9: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); -// await I_MRProxied.updateFromRegistry({from: POLYMATH}); - - -// // STEP 7: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); - -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); -// await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); - -// // Step 12: Deploy & Register Mock Oracles -// I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY -// I_POLYOracle = await MockOracle.new(I_PolyToken.address, "POLY", "USD", USDPOLY, { from: POLYMATH }); // 25 cents per POLY -// await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); -// await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// USDOracle: ${I_USDOracle.address} -// POLYOracle: ${I_POLYOracle.address} -// USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} -// USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.getTokens(REGFEE, ISSUER); -// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); -// let tx = await I_STRProxied.registerTicker(ISSUER, SYMBOL, NAME, { from : ISSUER }); -// assert.equal(tx.logs[0].args._owner, ISSUER); -// assert.equal(tx.logs[0].args._ticker, SYMBOL); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.getTokens(REGFEE, ISSUER); -// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); -// assert.equal(tx.logs[1].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), TMKEY); -// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); -// }); - -// describe("Test sto deployment", async() => { - -// it("Should successfully attach the first STO module to the security token", async () => { -// let stoId = 0; // No discount - -// _startTime.push(latestTime() + duration.days(2)); -// _endTime.push(_startTime[stoId] + duration.days(100)); -// _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] -// _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(15*10**16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] -// _tokensPerTierTotal.push([BigNumber(100000000).mul(BigNumber(10**18)), BigNumber(200000000).mul(BigNumber(10**18))]); // [ 100m Token, 200m Token ] -// _tokensPerTierDiscountPoly.push([BigNumber(0),BigNumber(0)]); // [ 0, 0 ] -// _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); // 10k USD -// _minimumInvestmentUSD.push(BigNumber(5*10**18)); // 5 USD -// _fundRaiseTypes.push([0, 1, 2]); -// _wallet.push(WALLET); -// _reserveWallet.push(RESERVEWALLET); -// _usdToken.push(I_DaiToken.address); - -// let config = [ -// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], -// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], -// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] -// ]; - -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); -// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); -// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); -// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); - -// assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); -// for (var i = 0; i < _ratePerTier[stoId].length; i++) { -// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); -// } -// assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].usdToken.call()), _usdToken[stoId], "Incorrect _usdToken in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getNumberOfTiers()), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); -// }); - -// it("Should successfully attach the second STO module to the security token", async () => { -// let stoId = 1; // No discount - -// _startTime.push(latestTime() + duration.days(2)); -// _endTime.push(_startTime[stoId] + duration.days(100)); -// _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16)]); -// _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16)]); -// _tokensPerTierTotal.push([BigNumber(5*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(50*10**18)]); -// _tokensPerTierDiscountPoly.push([BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0)]); -// _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); -// _minimumInvestmentUSD.push(BigNumber(0)); -// _fundRaiseTypes.push([0, 1, 2]); -// _wallet.push(WALLET); -// _reserveWallet.push(RESERVEWALLET); -// _usdToken.push(I_DaiToken.address); - -// let config = [ -// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], -// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], -// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] -// ]; - -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); -// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); -// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); -// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); - -// assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); -// for (var i = 0; i < _ratePerTier[stoId].length; i++) { -// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); -// } -// assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].usdToken.call()), _usdToken[stoId], "Incorrect _usdToken in config"); -// assert.equal(await I_USDTieredSTO_Array[stoId].getNumberOfTiers(), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); -// }); - -// it("Should successfully attach the third STO module to the security token", async () => { -// let stoId = 2; // Poly discount - -// _startTime.push(latestTime() + duration.days(2)); -// _endTime.push(_startTime[stoId] + duration.days(100)); -// _ratePerTier.push([BigNumber(1*10**18), BigNumber(1.5*10**18)]); // [ 1 USD/Token, 1.5 USD/Token ] -// _ratePerTierDiscountPoly.push([BigNumber(0.5*10**18), BigNumber(1*10**18)]); // [ 0.5 USD/Token, 1.5 USD/Token ] -// _tokensPerTierTotal.push([BigNumber(100*10**18), BigNumber(50*10**18)]); // [ 100 Token, 50 Token ] -// _tokensPerTierDiscountPoly.push([BigNumber(100*10**18),BigNumber(25*10**18)]); // [ 100 Token, 25 Token ] -// _nonAccreditedLimitUSD.push(BigNumber(25*10**18)); // [ 25 USD ] -// _minimumInvestmentUSD.push(BigNumber(5)); -// _fundRaiseTypes.push([0, 1, 2]); -// _wallet.push(WALLET); -// _reserveWallet.push(RESERVEWALLET); -// _usdToken.push(I_DaiToken.address) - -// let config = [ -// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], -// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], -// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] -// ]; - -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); -// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); -// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); -// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); -// }); - -// it("Should successfully attach the fourth STO module to the security token", async () => { -// let stoId = 3; - -// _startTime.push(latestTime()+ duration.days(0.1)); -// _endTime.push(_startTime[stoId] + duration.days(0.1)); -// _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16)]); -// _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(12*10**16)]); -// _tokensPerTierTotal.push([BigNumber(100*10**18), BigNumber(200*10**18)]); -// _tokensPerTierDiscountPoly.push([BigNumber(0),BigNumber(50*10**18)]); -// _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); -// _minimumInvestmentUSD.push(BigNumber(0)); -// _fundRaiseTypes.push([0, 1, 2]); -// _wallet.push(WALLET); -// _reserveWallet.push(RESERVEWALLET); -// _usdToken.push(I_DaiToken.address); - -// let config = [ -// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], -// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], -// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] -// ]; - -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); -// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); -// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); -// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); -// }); - -// it("Should fail because rates and tier array of different length", async() => { -// let stoId = 0; - -// let ratePerTier = [10]; -// let ratePerTierDiscountPoly = [10]; -// let tokensPerTierTotal = [10]; -// let tokensPerTierDiscountPoly = [10]; -// let config = [ -// [_startTime[stoId], _endTime[stoId], ratePerTier, _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], -// [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], ratePerTierDiscountPoly, _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], -// [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], tokensPerTierTotal, _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], -// [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], tokensPerTierDiscountPoly, _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]] -// ]; -// for (var i = 0; i < config.length; i++) { -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config[i]); -// let errorThrown = false; -// try { -// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, MESSAGE); -// } -// }); - -// it("Should fail because rate of token should be greater than 0", async() => { -// let stoId = 0; - -// let ratePerTier = [BigNumber(10*10**16), BigNumber(0)]; -// let config = [_startTime[stoId], _endTime[stoId], ratePerTier, _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let errorThrown = false; -// try { -// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, MESSAGE); -// }); - -// it("Should fail because Zero address is not permitted for wallet", async() => { -// let stoId = 0; - -// let wallet = "0x0000000000000000000000000000000000000000"; -// let config = [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], wallet, _reserveWallet[stoId], _usdToken[stoId]]; -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let errorThrown = false; -// try { -// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, MESSAGE); -// }); - -// it("Should fail because Zero address is not permitted for reserveWallet", async() => { -// let stoId = 0; - -// let reserveWallet = "0x0000000000000000000000000000000000000000"; -// let config = [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], reserveWallet]; -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let errorThrown = false; -// try { -// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, MESSAGE); -// }); - -// it("Should fail because end time before start time", async() => { -// let stoId = 0; - -// let startTime = latestTime() + duration.days(35); -// let endTime = latestTime() + duration.days(1); -// let config = [startTime, endTime, _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let errorThrown = false; -// try { -// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, MESSAGE); -// }); - -// it("Should fail because start time is in the past", async() => { -// let stoId = 0; - -// let startTime = latestTime() - duration.days(35); -// let endTime = startTime + duration.days(50); -// let config = [startTime, endTime, _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let errorThrown = false; -// try { -// await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, MESSAGE); -// }); -// }); - -// describe("Test modifying configuration", async() => { - -// it("Should successfully change config before startTime - funding", async() => { -// let stoId = 3; -// await I_USDTieredSTO_Array[stoId].modifyFunding([0], { from: ISSUER }); -// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),true,"STO Configuration doesn't set as expected"); -// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),false,"STO Configuration doesn't set as expected"); - -// await I_USDTieredSTO_Array[stoId].modifyFunding([1], { from: ISSUER }); -// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),false,"STO Configuration doesn't set as expected"); -// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),true,"STO Configuration doesn't set as expected"); - -// await I_USDTieredSTO_Array[stoId].modifyFunding([0,1], { from: ISSUER }); -// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),true,"STO Configuration doesn't set as expected"); -// assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),true,"STO Configuration doesn't set as expected"); - - -// }); - -// it("Should successfully change config before startTime - limits and tiers, times, addresses", async() => { -// let stoId = 3; - -// await I_USDTieredSTO_Array[stoId].modifyLimits(BigNumber(1*10**18), BigNumber(15*10**18), { from: ISSUER }); -// assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(),BigNumber(15*10**18).toNumber(),"STO Configuration doesn't set as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(),BigNumber(1*10**18).toNumber(),"STO Configuration doesn't set as expected"); - -// await I_USDTieredSTO_Array[stoId].modifyTiers([BigNumber(15*10**18)], [BigNumber(13*10**18)], [BigNumber(15*10**20)], [BigNumber(15*10**20)], { from: ISSUER }); -// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(0)).toNumber(),BigNumber(15*10**18).toNumber(),"STO Configuration doesn't set as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(0)).toNumber(),BigNumber(13*10**18).toNumber(),"STO Configuration doesn't set as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(0)),BigNumber(15*10**20).toNumber(),"STO Configuration doesn't set as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(0)),BigNumber(15*10**20).toNumber(),"STO Configuration doesn't set as expected"); - -// let tempTime1 = latestTime() + duration.days(0.1); -// let tempTime2 = latestTime() + duration.days(0.2); - -// await I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER }); -// assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(),tempTime1,"STO Configuration doesn't set as expected"); -// assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(),tempTime2,"STO Configuration doesn't set as expected"); - -// await I_USDTieredSTO_Array[stoId].modifyAddresses("0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", "0x0000000000000000000000000000000000000000", { from: ISSUER }); -// assert.equal(await I_USDTieredSTO_Array[stoId].wallet.call(),"0x0000000000000000000000000400000000000000","STO Configuration doesn't set as expected"); -// assert.equal(await I_USDTieredSTO_Array[stoId].reserveWallet.call(),"0x0000000000000000000003000000000000000000","STO Configuration doesn't set as expected"); -// assert.equal(await I_USDTieredSTO_Array[stoId].usdToken.call(),"0x0000000000000000000000000000000000000000","STO Configuration doesn't set as expected"); -// }); - -// it("Should fail to change config after endTime", async() => { -// let stoId = 3; - -// let snapId = await takeSnapshot(); -// await increaseTime(duration.days(1)); - -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].modifyFunding([0,1], { from: ISSUER }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, MESSAGE); - -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].modifyLimits(BigNumber(15*10**18), BigNumber(1*10**18), { from: ISSUER }); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, MESSAGE); - -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].modifyTiers([BigNumber(15*10**18)], [BigNumber(13*10**18)], [BigNumber(15*10**20)], [BigNumber(15*10**20)], { from: ISSUER }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, MESSAGE); - -// let tempTime1 = latestTime(); -// let tempTime2 = latestTime() + duration.days(3); - -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER }); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, MESSAGE); - -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].modifyAddresses("0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", I_DaiToken.address, { from: ISSUER }); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, MESSAGE); - -// await revertToSnapshot(snapId); -// }); -// }); - -// describe("Test buying failure conditions", async() => { - -// it("should fail if before STO start time", async() => { -// let stoId = 0; -// let snapId = await takeSnapshot(); - -// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - -// // Whitelist -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(15); -// let expiryTime = toTime + duration.days(100); -// let whitelisted = true; - -// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - -// // // Advance time to after STO start -// // await increaseTime(duration.days(3)); - -// // Set as accredited -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - -// // Prep for investments -// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH -// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); -// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY -// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); -// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - -// // NONACCREDITED ETH -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - -// // NONACCREDITED POLY -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - -// // NONACCREDITED DAI -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, 'NONACCREDITED POLY investment succeeded when it should not'); - -// // ACCREDITED ETH -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - -// // ACCREDITED POLY -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - -// // ACCREDITED DAI -// let errorThrown6 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown6 = true; -// ensureException(error); -// } -// assert.ok(errorThrown6, 'ACCREDITED POLY investment succeeded when it should not'); - -// await revertToSnapshot(snapId); -// }); - -// it("should fail if not whitelisted", async() => { -// let stoId = 0; -// let snapId = await takeSnapshot(); - -// // // Whitelist -// // let fromTime = latestTime(); -// // let toTime = latestTime() + duration.days(15); -// // let expiryTime = toTime + duration.days(100); -// // let whitelisted = true; -// // -// // await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); -// // await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - -// // Advance time to after STO start -// await increaseTime(duration.days(3)); - -// // Set as accredited -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - -// // Prep for investments -// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH -// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); -// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY -// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); -// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - -// // NONACCREDITED ETH -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - -// // NONACCREDITED POLY -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - -// // NONACCREDITED DAI -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - -// // ACCREDITED ETH -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - -// // ACCREDITED POLY -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - -// // ACCREDITED DAI -// let errorThrown6 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown6 = true; -// ensureException(error); -// } -// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - -// await revertToSnapshot(snapId); -// }); - -// it("should fail if minimumInvestmentUSD not met", async() => { -// let stoId = 0; -// let tierId = 0; -// let snapId = await takeSnapshot(); - -// // Whitelist -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(15); -// let expiryTime = toTime + duration.days(100); -// let whitelisted = true; - -// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - -// // Advance time to after STO start -// await increaseTime(duration.days(3)); - -// // Set as accredited -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - -// let investment_USD = BigNumber(2).mul(10**18); -// let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); -// let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); -// let investment_DAI = investment_USD; - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - - -// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); -// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - -// // NONACCREDITED ETH -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - -// // NONACCREDITED POLY -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - -// // NONACCREDITED DAI -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - -// // ACCREDITED ETH -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - -// // ACCREDITED POLY -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - -// // ACCREDITED DAI -// let errorThrown6 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown6 = true; -// ensureException(error); -// } -// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - -// await revertToSnapshot(snapId); -// }); - -// it("should successfully pause the STO and make investments fail, then unpause and succeed", async() => { -// let stoId = 0; -// let snapId = await takeSnapshot(); - -// // Whitelist -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(15); -// let expiryTime = toTime + duration.days(100); -// let whitelisted = true; - -// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - -// // Advance time to after STO start -// await increaseTime(duration.days(3)); - -// // Set as accredited -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - -// // Pause the STO -// await I_USDTieredSTO_Array[stoId].pause({ from: ISSUER }); -// assert.equal(await I_USDTieredSTO_Array[stoId].paused.call(), true, 'STO did not pause successfully'); - -// // Prep for investments -// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH -// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - -// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY -// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); -// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - -// // NONACCREDITED ETH -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - -// // NONACCREDITED POLY -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - -// // NONACCREDITED DAI -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - -// // ACCREDITED ETH -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - -// // ACCREDITED POLY -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - - -// // ACCREDITED DAI -// let errorThrown6 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown6 = true; -// ensureException(error); -// } -// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - -// // Unpause the STO -// await I_USDTieredSTO_Array[stoId].unpause({ from: ISSUER }); -// assert.equal(await I_USDTieredSTO_Array[stoId].paused.call(), false, 'STO did not unpause successfully'); - -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); -// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); - -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); -// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); - -// await revertToSnapshot(snapId); -// }); - -// it("should fail if after STO end time", async() => { -// let stoId = 3; -// let snapId = await takeSnapshot(); - -// // Whitelist -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(15); -// let expiryTime = toTime + duration.days(100); -// let whitelisted = true; - -// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - -// // Advance time to after STO end -// await increaseTime(duration.days(3)); - -// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - -// // Set as accredited -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - -// // Prep for investments -// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH -// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); -// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY -// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); -// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - - -// // NONACCREDITED ETH -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - -// // NONACCREDITED POLY -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - -// // NONACCREDITED DAI -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - -// // ACCREDITED ETH -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - -// // ACCREDITED POLY -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - -// // ACCREDITED DAI -// let errorThrown6 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown6 = true; -// ensureException(error); -// } -// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - -// await revertToSnapshot(snapId); -// }); - -// it("should fail if finalized", async() => { -// let stoId = 0; -// let snapId = await takeSnapshot(); - -// // Whitelist -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(100); -// let whitelisted = true; - -// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(RESERVEWALLET, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); - -// // Advance time to after STO start -// await increaseTime(duration.days(3)); - -// // Set as accredited -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - -// // Finalize STO -// await I_USDTieredSTO_Array[stoId].finalize({ from: ISSUER }); -// assert.equal(await I_USDTieredSTO_Array[stoId].isFinalized.call(), true, "STO has not been finalized"); -// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - -// // Attempt to call function again -// let errorThrown = false; -// try { -// await I_USDTieredSTO_Array[stoId].finalize({ from: ISSUER }); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, 'STO was finalized a second time'); - -// // Prep for investments -// let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH -// let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); -// let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY -// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); -// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - -// // NONACCREDITED ETH -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); - -// // NONACCREDITED POLY -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); - -// // NONACCREDITED DAI -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); - -// // ACCREDITED ETH -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); - -// // ACCREDITED POLY -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); - -// // ACCREDITED DAI -// let errorThrown6 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); -// } catch(error) { -// errorThrown6 = true; -// ensureException(error); -// } -// assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); - -// await revertToSnapshot(snapId); -// }); -// }); - -// describe("Prep STO", async() => { - -// it("should jump forward to after STO start", async() => { -// let stoId = 0; -// await increaseTime(duration.days(3)); -// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),true,"STO is not showing correct status"); -// }); - -// it("should whitelist ACCREDITED1 and NONACCREDITED1", async() => { -// let stoId = 0; - -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(15); -// let expiryTime = toTime + duration.days(100); -// let whitelisted = true; - -// const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); -// assert.equal(tx1.logs[0].args._investor, NONACCREDITED1, "Failed in adding the investor in whitelist"); -// const tx2 = await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); -// assert.equal(tx2.logs[0].args._investor, ACCREDITED1, "Failed in adding the investor in whitelist"); -// }); - -// it("should successfully modify accredited addresses for first STO", async() => { -// let stoId = 0; - -// let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); -// assert.equal(status1, false, "Initial accreditation is set to true"); - -// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1], [true], { from: ISSUER }); -// let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); -// assert.equal(status2, true, "Failed to set single address"); - -// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); -// let status3 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); -// assert.equal(status3, false, "Failed to set multiple addresses"); -// let status4 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); -// assert.equal(status4, true, "Failed to set multiple addresses"); - -// let errorThrown = false; -// try { -// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [true], { from: ISSUER }); -// } catch(error) { -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, "Set accreditation despite input array of different size"); -// }); - -// it("should successfully modify accredited addresses for second STO", async() => { -// let stoId = 1; - -// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); -// let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); -// let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); -// assert.equal(status1, false, "Failed to set multiple address"); -// assert.equal(status2, true, "Failed to set multiple address"); -// }); -// }); - -// describe("Buy Tokens with no discount", async() => { - -// it("should successfully buy using fallback at tier 0 for NONACCREDITED1", async() => { -// let stoId = 0; -// let tierId = 0; - -// let investment_Token = BigNumber(50).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await web3.eth.sendTransaction({ from: NONACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); -// console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), "Raised USD not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional checks on getters -// assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 1, "Investor count not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), investment_Token.toNumber(), "getTokensSold not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), investment_Token.toNumber(), "getTokensMinted not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), investment_Token.toNumber(), "getTokensSoldForETH not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), 0, "getTokensSoldForPOLY not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), investment_USD.toNumber(), "investorInvestedUSD not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), investment_ETH.toNumber(), "investorInvestedETH not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), 0, "investorInvestedPOLY not changed as expected"); -// }); - -// it("should successfully buy using buyWithETH at tier 0 for NONACCREDITED1", async() => { -// let stoId = 0; -// let tierId = 0; - -// let investment_Token = BigNumber(50).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); -// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised DAI not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should successfully buy using buyWithPOLY at tier 0 for NONACCREDITED1", async() => { -// let stoId = 0; -// let tierId = 0; - -// let investment_Token = BigNumber(50).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// // Buy With POLY -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should successfully buy using buyWithUSD at tier 0 for NONACCREDITED1", async() => { -// let stoId = 0; -// let tierId = 0; - -// let investment_Token = BigNumber(50).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); -// let investment_DAI = investment_USD; - -// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_InvestorDAIBal = await I_DaiToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); -// let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - -// // Buy With DAI -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithUSD: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_InvestorDAIBal = await I_DaiToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); -// let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), "Investor DAI Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); -// assert.equal(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), "Wallet DAI Balance not changed as expected"); -// }); - -// it("should successfully buy using fallback at tier 0 for ACCREDITED1", async() => { -// let stoId = 0; -// let tierId = 0; - -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - -// let investment_Token = BigNumber(50).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await web3.eth.sendTransaction({ from: ACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); -// console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should successfully buy using buyWithETH at tier 0 for ACCREDITED1", async() => { -// let stoId = 0; -// let tierId = 0; - -// let investment_Token = BigNumber(50).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); -// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should successfully buy using buyWithPOLY at tier 0 for ACCREDITED1", async() => { -// let stoId = 0; -// let tierId = 0; - -// let investment_Token = BigNumber(50).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - -// // Additional checks on getters -// let init_getTokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_getTokensMinted = await I_USDTieredSTO_Array[stoId].getTokensMinted(); -// let init_getTokensSoldForETH = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH); -// let init_getTokensSoldForPOLY = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY); -// let init_investorInvestedUSD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1); -// let init_investorInvestedETH = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH); -// let init_investorInvestedPOLY = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// // Buy With POLY -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional checks on getters -// assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 2, "Investor count not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), init_getTokensSold.add(investment_Token).toNumber(), "getTokensSold not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), init_getTokensMinted.add(investment_Token).toNumber(), "getTokensMinted not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), init_getTokensSoldForETH.toNumber(), "getTokensSoldForETH not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), init_getTokensSoldForPOLY.add(investment_Token).toNumber(), "getTokensSoldForPOLY not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), init_investorInvestedUSD.add(investment_USD).toNumber(), "investorInvestedUSD not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), init_investorInvestedETH.toNumber(), "investorInvestedETH not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), init_investorInvestedPOLY.add(investment_POLY).toNumber(), "investorInvestedPOLY not changed as expected"); -// }); - -// it("should successfully modify NONACCREDITED cap for NONACCREDITED1", async() => { -// let stoId = 0; -// let tierId = 0; -// console.log("Current investment: " + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber()); -// await I_USDTieredSTO_Array[stoId].changeNonAccreditedLimit([NONACCREDITED1], [_nonAccreditedLimitUSD[stoId].div(2)], {from: ISSUER}); -// console.log("Current limit: " + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1)).toNumber()); -// }); - -// it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async() => { -// let stoId = 0; -// let tierId = 0; - -// let investment_USD = (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1));//_nonAccreditedLimitUSD[stoId]; -// let investment_Token = await convert(stoId, tierId, false, "USD", "TOKEN", investment_USD); -// let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); -// let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); - -// let refund_USD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); -// let refund_Token = await convert(stoId, tierId, false, "USD", "TOKEN", refund_USD); -// let refund_ETH = await convert(stoId, tierId, false, "USD", "ETH", refund_USD); -// let refund_POLY = await convert(stoId, tierId, false, "USD", "POLY", refund_USD); - -// console.log("Expected refund in tokens: " + refund_Token.toNumber()); - -// let snap = await takeSnapshot(); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// // Buy with ETH -// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); -// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).add(refund_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).sub(refund_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).sub(refund_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - -// await revertToSnapshot(snap); - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - -// init_TokenSupply = await I_SecurityToken.totalSupply(); -// init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// // Buy With POLY -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// final_TokenSupply = await I_SecurityToken.totalSupply(); -// final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).add(refund_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).sub(refund_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).sub(refund_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should fail and revert when NONACCREDITED cap reached", async() => { -// let stoId = 0; -// let tierId = 0; - -// let investment_Token = BigNumber(50).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1, gasPrice: GAS_PRICE}); - -// // Buy with ETH NONACCREDITED -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, MESSAGE); -// }); - -// it("should fail and revert despite oracle price change when NONACCREDITED cap reached", async() => { -// let stoId = 0; -// let tierId; - -// // set new exchange rates -// let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH -// let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY -// let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH -// let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY - -// let investment_USD = BigNumber(web3.utils.toWei('50')); // USD -// let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH -// let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY -// let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH -// let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - -// await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); - -// // Change exchange rates up -// await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); - -// // Buy with ETH NONACCREDITED -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, MESSAGE); - -// // Change exchange rates down -// await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); - -// // Buy with ETH NONACCREDITED -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, MESSAGE); - -// // Reset exchange rates -// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); -// }); - -// it("should successfully buy across tiers for NONACCREDITED ETH", async() => { -// let stoId = 1; -// let startTier = 0; -// let endTier = 1; - -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - -// let delta_Token = BigNumber(5).mul(10**18); -// let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); -// let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); - -// let investment_Token = delta_Token.add(delta_Token); // 10 Token -// let investment_ETH = ethTier0.add(ethTier1); // 0.0025 ETH - -// // Process investment -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); -// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional Checks -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); -// }); - -// it("should successfully buy across tiers for NONACCREDITED POLY", async() => { -// let stoId = 1; -// let startTier = 1; -// let endTier = 2; - -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - -// let delta_Token = BigNumber(5).mul(10**18); // Token -// let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); -// let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); - -// let investment_Token = delta_Token.add(delta_Token); // 10 Token -// let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - -// // Process investment -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional Checks -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); -// }); - -// it("should successfully buy across tiers for ACCREDITED ETH", async() => { -// let stoId = 1; -// let startTier = 2; -// let endTier = 3; - -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - -// let delta_Token = BigNumber(5).mul(10**18); // Token -// let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); -// let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); - -// let investment_Token = delta_Token.add(delta_Token); // 10 Token -// let investment_ETH = ethTier0.add(ethTier1); // 0.0025 ETH - -// // Process investment -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); -// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional Checks -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); -// }); - -// it("should successfully buy across tiers for ACCREDITED DAI", async() => { - -// let stoId = 1; -// let startTier = 3; -// let endTier = 4; - -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - -// let delta_Token = BigNumber(5).mul(10**18); // Token -// let daiTier0 = await convert(stoId, startTier, false, "TOKEN", "USD", delta_Token); -// let daiTier1 = await convert(stoId, endTier, false, "TOKEN", "USD", delta_Token); - -// let investment_Token = delta_Token.add(delta_Token); // 10 Token -// let investment_DAI = daiTier0.add(daiTier1); - -// await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); - -// // Process investment -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_InvestorDAIBal = await I_DaiToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); -// let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithUSD: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_InvestorDAIBal = await I_DaiToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); -// let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), "Raised DAI not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); -// assert.equal(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional Checks -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); - -// }); - -// it("should successfully buy across tiers for ACCREDITED POLY", async() => { -// let stoId = 1; -// let startTier = 4; -// let endTier = 5; - -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - -// let delta_Token = BigNumber(5).mul(10**18); // Token -// let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); -// let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); - -// let investment_Token = delta_Token.add(delta_Token); // 10 Token -// let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH - -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - -// // Process investment -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional Checks -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); -// }); - -// it("should buy out the rest of the sto", async() => { -// let stoId = 1; -// let tierId = 5; - -// let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); -// console.log(minted.toNumber() + ":"+ _tokensPerTierTotal[stoId][tierId]); -// let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); -// console.log(investment_Token.toNumber()); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - -// let tx = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// console.log(" Gas buyWithETH: ".grey+tx.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// // assert.equal((await I_USDTieredSTO_Array[1].getTokensMinted()).toNumber(), _tokensPerTierTotal[1].reduce((a, b) => a + b, 0).toNumber(), "STO Token Sold not changed as expected"); -// }); - -// it("should fail and revert when all tiers sold out", async() => { -// let stoId = 1; -// let tierId = 4; - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); -// let investment_DAI = investment_USD; - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - -// await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - -// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - -// // Buy with ETH NONACCREDITED -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, MESSAGE); - -// // Buy with DAI NONACCREDITED -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, MESSAGE); - -// // Buy with ETH ACCREDITED -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, MESSAGE); - -// // Buy with POLY ACCREDITED -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, MESSAGE); - -// // Buy with DAI ACCREDITED -// let errorThrown6 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown6 = true; -// ensureException(error); -// } -// assert.ok(errorThrown6, MESSAGE); -// }); - -// it("should fail and revert when all tiers sold out despite oracle price change", async() => { -// let stoId = 1; -// let tierId = 4; - -// // set new exchange rates -// let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH -// let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY -// let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH -// let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY - -// let investment_USD = BigNumber(web3.utils.toWei('50')); // USD -// let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH -// let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY -// let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH -// let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - -// await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); -// await I_PolyToken.getTokens(investment_POLY_low, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: ACCREDITED1}); - -// // Change exchange rates up -// await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); - -// // Buy with ETH NONACCREDITED -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, MESSAGE); - -// // Buy with ETH ACCREDITED -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, MESSAGE); - -// // Buy with POLY ACCREDITED -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_high, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, MESSAGE); - -// // Change exchange rates down -// await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); - -// // Buy with ETH NONACCREDITED -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown6 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown6 = true; -// ensureException(error); -// } -// assert.ok(errorThrown6, MESSAGE); - -// // Buy with ETH ACCREDITED -// let errorThrown7 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown7 = true; -// ensureException(error); -// } -// assert.ok(errorThrown7, MESSAGE); - -// // Buy with POLY ACCREDITED -// let errorThrown8 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_low, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown8 = true; -// ensureException(error); -// } -// assert.ok(errorThrown8, MESSAGE); - -// // Reset exchange rates -// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); -// }); -// }); - -// describe("Buy Tokens with POLY discount", async() => { - -// it("should successfully buy using fallback at tier 0 for NONACCREDITED1", async() => { -// let stoId = 2; -// let tierId = 0; - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await web3.eth.sendTransaction({ from: NONACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); -// console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), "Raised USD not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional checks on getters -// assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 1, "Investor count not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), investment_Token.toNumber(), "getTokensSold not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), investment_Token.toNumber(), "getTokensMinted not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), investment_Token.toNumber(), "getTokensSoldForETH not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), 0, "getTokensSoldForPOLY not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), investment_USD.toNumber(), "investorInvestedUSD not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), investment_ETH.toNumber(), "investorInvestedETH not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), 0, "investorInvestedPOLY not changed as expected"); -// }); - -// it("should successfully buy using buyWithETH at tier 0 for NONACCREDITED1", async() => { -// let stoId = 2; -// let tierId = 0; - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); -// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should successfully buy using buyWithPOLY at tier 0 for NONACCREDITED1", async() => { -// let stoId = 2; -// let tierId = 0; - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// // Buy With POLY -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should successfully buy using fallback at tier 0 for ACCREDITED1", async() => { -// let stoId = 2; -// let tierId = 0; - -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await web3.eth.sendTransaction({ from: ACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); -// console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should successfully buy using buyWithETH at tier 0 for ACCREDITED1", async() => { -// let stoId = 2; -// let tierId = 0; - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); -// console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should successfully buy using buyWithPOLY at tier 0 for ACCREDITED1", async() => { -// let stoId = 2; -// let tierId = 0; - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); - -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - -// // Additional checks on getters -// let init_getTokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_getTokensMinted = await I_USDTieredSTO_Array[stoId].getTokensMinted(); -// let init_getTokensSoldForETH = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH); -// let init_getTokensSoldForPOLY = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY); -// let init_investorInvestedUSD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1); -// let init_investorInvestedETH = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH); -// let init_investorInvestedPOLY = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// // Buy With POLY -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional checks on getters -// assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 2, "Investor count not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), init_getTokensSold.add(investment_Token).toNumber(), "getTokensSold not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), init_getTokensMinted.add(investment_Token).toNumber(), "getTokensMinted not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), init_getTokensSoldForETH.toNumber(), "getTokensSoldForETH not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), init_getTokensSoldForPOLY.add(investment_Token).toNumber(), "getTokensSoldForPOLY not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), init_investorInvestedUSD.add(investment_USD).toNumber(), "investorInvestedUSD not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), init_investorInvestedETH.toNumber(), "investorInvestedETH not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), init_investorInvestedPOLY.add(investment_POLY).toNumber(), "investorInvestedPOLY not changed as expected"); -// }); - -// it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async() => { -// let stoId = 2; -// let tierId = 0; - -// let investment_USD = _nonAccreditedLimitUSD[stoId]; -// let investment_Token = await convert(stoId, tierId, true, "USD", "TOKEN", investment_USD); -// let investment_ETH = await convert(stoId, tierId, true, "USD", "ETH", investment_USD); -// let investment_POLY = await convert(stoId, tierId, true, "USD", "POLY", investment_USD); - -// let refund_USD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); -// let refund_Token = await convert(stoId, tierId, true, "USD", "TOKEN", refund_USD); -// let refund_ETH = await convert(stoId, tierId, true, "USD", "ETH", refund_USD); -// let refund_POLY = await convert(stoId, tierId, true, "USD", "POLY", refund_USD); - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// // Buy With POLY -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).add(refund_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).sub(refund_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).sub(refund_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should fail and revert when NONACCREDITED cap reached", async() => { -// let stoId = 2; -// let tierId = 0; - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1, gasPrice: GAS_PRICE}); - -// // Buy with ETH NONACCREDITED -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, MESSAGE); -// }); - -// it("should fail and revert despite oracle price change when NONACCREDITED cap reached", async() => { -// let stoId = 2; -// let tierId = 0; - -// // set new exchange rates -// let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH -// let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY -// let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH -// let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); - -// let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH -// let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY -// let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH -// let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - -// await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); - -// // Change exchange rates up -// await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); - -// // Buy with ETH NONACCREDITED -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, MESSAGE); - -// // Change exchange rates down -// await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); - -// // Buy with ETH NONACCREDITED -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, MESSAGE); - -// // Reset exchange rates -// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); -// }); - -// it("should successfully buy across tiers for POLY", async() => { -// let stoId = 2; -// let startTier = 0; -// let endTier = 1; - -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); - -// let delta_Token = BigNumber(5).mul(10**18); // Token -// let polyTier0 = await convert(stoId, startTier, true, "TOKEN", "POLY", delta_Token); -// let polyTier1 = await convert(stoId, endTier, true, "TOKEN", "POLY", delta_Token); -// let investment_Token = delta_Token.add(delta_Token); // 10 Token -// let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH - -// let tokensRemaining = (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier)); -// let prep_Token = tokensRemaining.sub(delta_Token); -// let prep_POLY = await convert(stoId, startTier, true, "TOKEN", "POLY", prep_Token); - -// await I_PolyToken.getTokens(prep_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, prep_POLY, {from: ACCREDITED1}); -// let tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, prep_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// console.log(" Gas buyWithPOLY: ".grey+tx.receipt.gasUsed.toString().grey); - -// let Tier0Token = (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier)); -// let Tier0Minted = (await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier)); -// assert.equal(Tier0Minted.toNumber(), Tier0Token.sub(delta_Token).toNumber()); - -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - -// // Process investment -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); - -// // Additional Checks -// assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); -// }); - -// it("should successfully buy across the discount cap", async() => { -// let stoId = 2; -// let tierId = 1; - -// let discount_Token = BigNumber(20).mul(10**18); -// let discount_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", discount_Token); - -// let regular_Token = BigNumber(10).mul(10**18); -// let regular_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", regular_Token); - -// let investment_Token = discount_Token.add(regular_Token); -// let investment_POLY = discount_POLY.add(regular_POLY); - -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// // Buy With POLY -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); -// assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); -// assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); -// assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); -// assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); -// assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); -// assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); -// }); - -// it("should buy out the rest of the sto", async() => { -// let stoId = 2; -// let tierId = 1; - -// let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); -// let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - -// // Buy With POLY -// let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); -// console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - -// assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); -// assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); -// assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); -// }); - -// it("should fail and revert when all tiers sold out", async() => { -// let stoId = 2; -// let tierId = 1; - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); -// let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); -// let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); - -// await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - -// assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); - -// // Buy with ETH NONACCREDITED -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, MESSAGE); - -// // Buy with ETH ACCREDITED -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, MESSAGE); - -// // Buy with POLY ACCREDITED -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, MESSAGE); -// }); - -// it("should fail and revert when all tiers sold out despite oracle price change", async() => { -// let stoId = 2; -// let tierId = 1; - -// // set new exchange rates -// let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH -// let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY -// let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH -// let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY - -// let investment_Token = BigNumber(5).mul(10**18); -// let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); - -// let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH -// let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY -// let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH -// let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY - -// await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); -// await I_PolyToken.getTokens(investment_POLY_low, ACCREDITED1); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: ACCREDITED1}); - -// // Change exchange rates up -// await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); - -// // Buy with ETH NONACCREDITED -// let errorThrown1 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown1 = true; -// ensureException(error); -// } -// assert.ok(errorThrown1, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown2 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown2 = true; -// ensureException(error); -// } -// assert.ok(errorThrown2, MESSAGE); - -// // Buy with ETH ACCREDITED -// let errorThrown3 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown3 = true; -// ensureException(error); -// } -// assert.ok(errorThrown3, MESSAGE); - -// // Buy with POLY ACCREDITED -// let errorThrown4 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_high, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown4 = true; -// ensureException(error); -// } -// assert.ok(errorThrown4, MESSAGE); - -// // Change exchange rates down -// await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); - -// // Buy with ETH NONACCREDITED -// let errorThrown5 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown5 = true; -// ensureException(error); -// } -// assert.ok(errorThrown5, MESSAGE); - -// // Buy with POLY NONACCREDITED -// let errorThrown6 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown6 = true; -// ensureException(error); -// } -// assert.ok(errorThrown6, MESSAGE); - -// // Buy with ETH ACCREDITED -// let errorThrown7 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown7 = true; -// ensureException(error); -// } -// assert.ok(errorThrown7, MESSAGE); - -// // Buy with POLY ACCREDITED -// let errorThrown8 = false; -// try { -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_low, { from: ACCREDITED1, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown8 = true; -// ensureException(error); -// } -// assert.ok(errorThrown8, MESSAGE); - -// // Reset exchange rates -// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); -// }); -// }); - -// describe("Test getter functions", async() => { - -// describe("Generic", async() => { - -// it("should get the right number of investors", async() => { -// assert.equal((await I_USDTieredSTO_Array[0].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[0].investorCount()).toNumber(), "Investor count not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[1].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[1].investorCount()).toNumber(), "Investor count not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[2].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[2].investorCount()).toNumber(), "Investor count not changed as expected"); -// }); - -// it("should get the right amounts invested", async() => { -// assert.equal((await I_USDTieredSTO_Array[0].fundsRaised.call(ETH)).toNumber(), (await I_USDTieredSTO_Array[0].getRaised(0)).toNumber(), "getRaisedEther not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[0].fundsRaised.call(POLY)).toNumber(), (await I_USDTieredSTO_Array[0].getRaised(1)).toNumber(), "getRaisedPOLY not changed as expected"); -// assert.equal((await I_USDTieredSTO_Array[0].fundsRaisedUSD.call()).toNumber(), (await I_USDTieredSTO_Array[0].fundsRaisedUSD()).toNumber(), "fundsRaisedUSD not changed as expected"); -// }); -// }); - -// describe("convertToUSD", async() => { - -// it("should reset exchange rates", async() => { -// // Reset exchange rates -// await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); -// await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); -// }); - -// it("should get the right conversion for ETH to USD", async() => { -// // 20 ETH to 10000 USD -// let ethInWei = BigNumber(web3.utils.toWei('20', 'ether')); -// let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(ETH, ethInWei); -// assert.equal(usdInWei.div(10**18).toNumber(), ethInWei.div(10**18).mul(USDETH.div(10**18)).toNumber()); -// }); - -// it("should get the right conversion for POLY to USD", async() => { -// // 40000 POLY to 10000 USD -// let polyInWei = BigNumber(web3.utils.toWei('40000', 'ether')); -// let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(POLY, polyInWei); -// assert.equal(usdInWei.div(10**18).toNumber(), polyInWei.div(10**18).mul(USDPOLY.div(10**18)).toNumber()); -// }); -// }); - -// describe("convertFromUSD", async() => { - -// it("should get the right conversion for USD to ETH", async() => { -// // 10000 USD to 20 ETH -// let usdInWei = BigNumber(web3.utils.toWei('10000', 'ether')); -// let ethInWei = await I_USDTieredSTO_Array[0].convertFromUSD(ETH, usdInWei); -// assert.equal(ethInWei.div(10**18).toNumber(), usdInWei.div(10**18).div(USDETH.div(10**18)).toNumber()); -// }); - -// it("should get the right conversion for USD to POLY", async() => { -// // 10000 USD to 40000 POLY -// let usdInWei = BigNumber(web3.utils.toWei('10000', 'ether')); -// let polyInWei = await I_USDTieredSTO_Array[0].convertFromUSD(POLY, usdInWei); -// assert.equal(polyInWei.div(10**18).toNumber(), usdInWei.div(10**18).div(USDPOLY.div(10**18)).toNumber()); -// }); -// }); -// }); - -// describe("Test cases for the USDTieredSTOFactory", async() => { -// it("should get the exact details of the factory", async() => { -// assert.equal((await I_USDTieredSTOFactory.setupCost.call()).toNumber(), STOSetupCost); -// assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0],3); -// assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), -// "USDTieredSTO", -// "Wrong Module added"); -// assert.equal(await I_USDTieredSTOFactory.getDescription.call(), -// "USD Tiered STO", -// "Wrong Module added"); -// assert.equal(await I_USDTieredSTOFactory.getTitle.call(), -// "USD Tiered STO", -// "Wrong Module added"); -// assert.equal(await I_USDTieredSTOFactory.getInstructions.call(), -// "Initialises a USD tiered STO.", -// "Wrong Module added"); -// let tags = await I_USDTieredSTOFactory.getTags.call(); -// assert.equal(web3.utils.hexToString(tags[0]),"USD"); -// assert.equal(web3.utils.hexToString(tags[1]),"Tiered"); -// assert.equal(web3.utils.hexToString(tags[2]),"POLY"); -// assert.equal(web3.utils.hexToString(tags[3]),"ETH"); - -// }); -// }); -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); +const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); +const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); +const MockOracle = artifacts.require('./MockOracle.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port + +contract('USDTieredSTO', accounts => { + // Accounts Variable declaration + let POLYMATH; + let ISSUER; + let WALLET; + let RESERVEWALLET; + let INVESTOR1; + let INVESTOR2; + let INVESTOR3; + let INVESTOR4; + let ACCREDITED1; + let ACCREDITED2; + let NONACCREDITED1; + let NONACCREDITED2; + let ETH = 0; + let POLY = 1; + let DAI = 2; + + let MESSAGE = "Transaction Should Fail!"; + const GAS_PRICE = 0; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_USDTieredSTOProxyFactory; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistry; + let I_ModuleRegistryProxy; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_USDTieredSTOFactory; + let I_USDOracle; + let I_POLYOracle; + let I_STFactory; + let I_SecurityToken; + let I_STRProxied; + let I_MRProxied; + let I_USDTieredSTO_Array = []; + let I_PolyToken; + let I_DaiToken; + let I_PolymathRegistry; + + // SecurityToken Details for funds raise Type ETH + const NAME = "Team"; + const SYMBOL = "SAP"; + const TOKENDETAILS = "This is equity type of issuance"; + const DECIMALS = 18; + + // Module key + const TMKEY = 2; + const STOKEY = 3; + + // Initial fee for ticker registry and security token registry + const REGFEE = web3.utils.toWei("250"); + const STOSetupCost = 0; + + // MockOracle USD prices + const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH + const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY + + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + // STO Configuration Arrays + let _startTime = []; + let _endTime = []; + let _ratePerTier = []; + let _ratePerTierDiscountPoly = []; + let _tokensPerTierTotal = []; + let _tokensPerTierDiscountPoly = []; + let _nonAccreditedLimitUSD = []; + let _minimumInvestmentUSD = []; + let _fundRaiseTypes = []; + let _wallet = []; + let _reserveWallet = []; + let _usdToken = []; + + /* function configure( + uint256 _startTime, + uint256 _endTime, + uint256[] _ratePerTier, + uint256[] _ratePerTierDiscountPoly, + uint256[] _tokensPerTier, + uint256[] _tokensPerTierDiscountPoly, + uint256 _nonAccreditedLimitUSD, + uint256 _minimumInvestmentUSD, + uint8[] _fundRaiseTypes, + address _wallet, + address _reserveWallet, + address _usdToken + ) */ + const functionSignature = { + name: 'configure', + type: 'function', + inputs: [{ + type: 'uint256', + name: '_startTime' + },{ + type: 'uint256', + name: '_endTime' + },{ + type: 'uint256[]', + name: '_ratePerTier' + },{ + type: 'uint256[]', + name: '_ratePerTierDiscountPoly' + },{ + type: 'uint256[]', + name: '_tokensPerTier' + },{ + type: 'uint256[]', + name: '_tokensPerTierDiscountPoly' + },{ + type: 'uint256', + name: '_nonAccreditedLimitUSD' + },{ + type: 'uint256', + name: '_minimumInvestmentUSD' + },{ + type: 'uint8[]', + name: '_fundRaiseTypes' + },{ + type: 'address', + name: '_wallet' + },{ + type: 'address', + name: '_reserveWallet' + },{ + type: 'address', + name: '_usdToken' + }] + }; + + async function convert(_stoID, _tier, _discount, _currencyFrom, _currencyTo, _amount) { + let USDTOKEN; + if (_discount) + USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTierDiscountPoly.call(_tier); + else + USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTier.call(_tier); + if (_currencyFrom == "TOKEN") { + let tokenToUSD = _amount.div(10**18).mul(USDTOKEN.div(10**18)).mul(10**18); // TOKEN * USD/TOKEN = USD + if (_currencyTo == "USD") + return tokenToUSD; + if (_currencyTo == "ETH") { + return await I_USDTieredSTO_Array[_stoID].convertFromUSD(ETH, tokenToUSD); + } else if (_currencyTo == "POLY") { + return await I_USDTieredSTO_Array[_stoID].convertFromUSD(POLY, tokenToUSD); + } + } + if (_currencyFrom == "USD") { + if (_currencyTo == "TOKEN") + return _amount.div(USDTOKEN).mul(10**18); // USD / USD/TOKEN = TOKEN + if (_currencyTo == "ETH" || _currencyTo == "POLY") + return await I_USDTieredSTO_Array[_stoID].convertFromUSD((_currencyTo == "ETH" ? ETH : POLY), _amount); + } + if (_currencyFrom == "ETH" || _currencyFrom == "POLY") { + let ethToUSD = await I_USDTieredSTO_Array[_stoID].convertToUSD((_currencyTo == "ETH" ? ETH : POLY), _amount); + if (_currencyTo == "USD") + return ethToUSD; + if (_currencyTo == "TOKEN") + return ethToUSD.div(USDTOKEN).mul(10**18); // USD / USD/TOKEN = TOKEN + } + return 0; + } + + before(async() => { + // Accounts setup + POLYMATH = accounts[0]; + ISSUER = accounts[1]; + WALLET = accounts[2]; + RESERVEWALLET = WALLET; + ACCREDITED1 = accounts[3]; + ACCREDITED2 = accounts[4]; + NONACCREDITED1 = accounts[5]; + NONACCREDITED2 = accounts[6]; + INVESTOR1 = accounts[7]; + INVESTOR2 = accounts[8]; + INVESTOR3 = accounts[9]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + I_DaiToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: POLYMATH + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 3: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 4: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the proxy + I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); + + // STEP 6: Deploy the USDTieredSTOFactory + + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); + + assert.notEqual( + I_USDTieredSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "USDTieredSTOFactory contract was not deployed" + ); + + // Step 8: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 9: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); + await I_MRProxied.updateFromRegistry({from: POLYMATH}); + + + // STEP 7: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); + + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); + + // Step 12: Deploy & Register Mock Oracles + I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY + I_POLYOracle = await MockOracle.new(I_PolyToken.address, "POLY", "USD", USDPOLY, { from: POLYMATH }); // 25 cents per POLY + await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); + await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + USDOracle: ${I_USDOracle.address} + POLYOracle: ${I_POLYOracle.address} + USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} + USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.getTokens(REGFEE, ISSUER); + await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); + let tx = await I_STRProxied.registerTicker(ISSUER, SYMBOL, NAME, { from : ISSUER }); + assert.equal(tx.logs[0].args._owner, ISSUER); + assert.equal(tx.logs[0].args._ticker, SYMBOL); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.getTokens(REGFEE, ISSUER); + await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); + assert.equal(tx.logs[1].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), TMKEY); + assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + }); + + describe("Test sto deployment", async() => { + + it("Should successfully attach the first STO module to the security token", async () => { + let stoId = 0; // No discount + + _startTime.push(latestTime() + duration.days(2)); + _endTime.push(_startTime[stoId] + duration.days(100)); + _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] + _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(15*10**16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] + _tokensPerTierTotal.push([BigNumber(100000000).mul(BigNumber(10**18)), BigNumber(200000000).mul(BigNumber(10**18))]); // [ 100m Token, 200m Token ] + _tokensPerTierDiscountPoly.push([BigNumber(0),BigNumber(0)]); // [ 0, 0 ] + _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); // 10k USD + _minimumInvestmentUSD.push(BigNumber(5*10**18)); // 5 USD + _fundRaiseTypes.push([0, 1, 2]); + _wallet.push(WALLET); + _reserveWallet.push(RESERVEWALLET); + _usdToken.push(I_DaiToken.address); + + let config = [ + _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], + _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], + _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] + ]; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); + console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); + I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + + assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); + for (var i = 0; i < _ratePerTier[stoId].length; i++) { + assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); + } + assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].usdToken.call()), _usdToken[stoId], "Incorrect _usdToken in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].getNumberOfTiers()), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); + assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); + }); + + it("Should successfully attach the second STO module to the security token", async () => { + let stoId = 1; // No discount + + _startTime.push(latestTime() + duration.days(2)); + _endTime.push(_startTime[stoId] + duration.days(100)); + _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16)]); + _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16), BigNumber(15*10**16)]); + _tokensPerTierTotal.push([BigNumber(5*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(10*10**18), BigNumber(50*10**18)]); + _tokensPerTierDiscountPoly.push([BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0)]); + _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); + _minimumInvestmentUSD.push(BigNumber(0)); + _fundRaiseTypes.push([0, 1, 2]); + _wallet.push(WALLET); + _reserveWallet.push(RESERVEWALLET); + _usdToken.push(I_DaiToken.address); + + let config = [ + _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], + _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], + _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] + ]; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); + console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); + I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + + assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); + for (var i = 0; i < _ratePerTier[stoId].length; i++) { + assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); + } + assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].usdToken.call()), _usdToken[stoId], "Incorrect _usdToken in config"); + assert.equal(await I_USDTieredSTO_Array[stoId].getNumberOfTiers(), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); + assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); + }); + + it("Should successfully attach the third STO module to the security token", async () => { + let stoId = 2; // Poly discount + + _startTime.push(latestTime() + duration.days(2)); + _endTime.push(_startTime[stoId] + duration.days(100)); + _ratePerTier.push([BigNumber(1*10**18), BigNumber(1.5*10**18)]); // [ 1 USD/Token, 1.5 USD/Token ] + _ratePerTierDiscountPoly.push([BigNumber(0.5*10**18), BigNumber(1*10**18)]); // [ 0.5 USD/Token, 1.5 USD/Token ] + _tokensPerTierTotal.push([BigNumber(100*10**18), BigNumber(50*10**18)]); // [ 100 Token, 50 Token ] + _tokensPerTierDiscountPoly.push([BigNumber(100*10**18),BigNumber(25*10**18)]); // [ 100 Token, 25 Token ] + _nonAccreditedLimitUSD.push(BigNumber(25*10**18)); // [ 25 USD ] + _minimumInvestmentUSD.push(BigNumber(5)); + _fundRaiseTypes.push([0, 1, 2]); + _wallet.push(WALLET); + _reserveWallet.push(RESERVEWALLET); + _usdToken.push(I_DaiToken.address) + + let config = [ + _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], + _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], + _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] + ]; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); + console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); + I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + }); + + it("Should successfully attach the fourth STO module to the security token", async () => { + let stoId = 3; + + _startTime.push(latestTime()+ duration.days(0.1)); + _endTime.push(_startTime[stoId] + duration.days(0.1)); + _ratePerTier.push([BigNumber(10*10**16), BigNumber(15*10**16)]); + _ratePerTierDiscountPoly.push([BigNumber(10*10**16), BigNumber(12*10**16)]); + _tokensPerTierTotal.push([BigNumber(100*10**18), BigNumber(200*10**18)]); + _tokensPerTierDiscountPoly.push([BigNumber(0),BigNumber(50*10**18)]); + _nonAccreditedLimitUSD.push(BigNumber(10000).mul(BigNumber(10**18))); + _minimumInvestmentUSD.push(BigNumber(0)); + _fundRaiseTypes.push([0, 1, 2]); + _wallet.push(WALLET); + _reserveWallet.push(RESERVEWALLET); + _usdToken.push(I_DaiToken.address); + + let config = [ + _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], + _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], + _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] + ]; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); + console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); + I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + }); + + it("Should fail because rates and tier array of different length", async() => { + let stoId = 0; + + let ratePerTier = [10]; + let ratePerTierDiscountPoly = [10]; + let tokensPerTierTotal = [10]; + let tokensPerTierDiscountPoly = [10]; + let config = [ + [_startTime[stoId], _endTime[stoId], ratePerTier, _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], + [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], ratePerTierDiscountPoly, _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], + [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], tokensPerTierTotal, _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]], + [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], tokensPerTierDiscountPoly, _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]] + ]; + for (var i = 0; i < config.length; i++) { + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config[i]); + let errorThrown = false; + try { + await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); + } catch(error) { + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, MESSAGE); + } + }); + + it("Should fail because rate of token should be greater than 0", async() => { + let stoId = 0; + + let ratePerTier = [BigNumber(10*10**16), BigNumber(0)]; + let config = [_startTime[stoId], _endTime[stoId], ratePerTier, _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let errorThrown = false; + try { + await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); + } catch(error) { + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, MESSAGE); + }); + + it("Should fail because Zero address is not permitted for wallet", async() => { + let stoId = 0; + + let wallet = "0x0000000000000000000000000000000000000000"; + let config = [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], wallet, _reserveWallet[stoId], _usdToken[stoId]]; + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let errorThrown = false; + try { + await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); + } catch(error) { + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, MESSAGE); + }); + + it("Should fail because Zero address is not permitted for reserveWallet", async() => { + let stoId = 0; + + let reserveWallet = "0x0000000000000000000000000000000000000000"; + let config = [_startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], reserveWallet]; + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let errorThrown = false; + try { + await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); + } catch(error) { + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, MESSAGE); + }); + + it("Should fail because end time before start time", async() => { + let stoId = 0; + + let startTime = latestTime() + duration.days(35); + let endTime = latestTime() + duration.days(1); + let config = [startTime, endTime, _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let errorThrown = false; + try { + await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); + } catch(error) { + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, MESSAGE); + }); + + it("Should fail because start time is in the past", async() => { + let stoId = 0; + + let startTime = latestTime() - duration.days(35); + let endTime = startTime + duration.days(50); + let config = [startTime, endTime, _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId]]; + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let errorThrown = false; + try { + await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER }); + } catch(error) { + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, MESSAGE); + }); + }); + + describe("Test modifying configuration", async() => { + + it("Should successfully change config before startTime - funding", async() => { + let stoId = 3; + await I_USDTieredSTO_Array[stoId].modifyFunding([0], { from: ISSUER }); + assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),true,"STO Configuration doesn't set as expected"); + assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),false,"STO Configuration doesn't set as expected"); + + await I_USDTieredSTO_Array[stoId].modifyFunding([1], { from: ISSUER }); + assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),false,"STO Configuration doesn't set as expected"); + assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),true,"STO Configuration doesn't set as expected"); + + await I_USDTieredSTO_Array[stoId].modifyFunding([0,1], { from: ISSUER }); + assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(0),true,"STO Configuration doesn't set as expected"); + assert.equal(await I_USDTieredSTO_Array[stoId].fundRaiseTypes.call(1),true,"STO Configuration doesn't set as expected"); + + + }); + + it("Should successfully change config before startTime - limits and tiers, times, addresses", async() => { + let stoId = 3; + + await I_USDTieredSTO_Array[stoId].modifyLimits(BigNumber(1*10**18), BigNumber(15*10**18), { from: ISSUER }); + assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(),BigNumber(15*10**18).toNumber(),"STO Configuration doesn't set as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(),BigNumber(1*10**18).toNumber(),"STO Configuration doesn't set as expected"); + + await I_USDTieredSTO_Array[stoId].modifyTiers([BigNumber(15*10**18)], [BigNumber(13*10**18)], [BigNumber(15*10**20)], [BigNumber(15*10**20)], { from: ISSUER }); + assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(0)).toNumber(),BigNumber(15*10**18).toNumber(),"STO Configuration doesn't set as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(0)).toNumber(),BigNumber(13*10**18).toNumber(),"STO Configuration doesn't set as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(0)),BigNumber(15*10**20).toNumber(),"STO Configuration doesn't set as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(0)),BigNumber(15*10**20).toNumber(),"STO Configuration doesn't set as expected"); + + let tempTime1 = latestTime() + duration.days(0.1); + let tempTime2 = latestTime() + duration.days(0.2); + + await I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER }); + assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(),tempTime1,"STO Configuration doesn't set as expected"); + assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(),tempTime2,"STO Configuration doesn't set as expected"); + + await I_USDTieredSTO_Array[stoId].modifyAddresses("0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", "0x0000000000000000000000000000000000000000", { from: ISSUER }); + assert.equal(await I_USDTieredSTO_Array[stoId].wallet.call(),"0x0000000000000000000000000400000000000000","STO Configuration doesn't set as expected"); + assert.equal(await I_USDTieredSTO_Array[stoId].reserveWallet.call(),"0x0000000000000000000003000000000000000000","STO Configuration doesn't set as expected"); + assert.equal(await I_USDTieredSTO_Array[stoId].usdToken.call(),"0x0000000000000000000000000000000000000000","STO Configuration doesn't set as expected"); + }); + + it("Should fail to change config after endTime", async() => { + let stoId = 3; + + let snapId = await takeSnapshot(); + await increaseTime(duration.days(1)); + + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].modifyFunding([0,1], { from: ISSUER }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, MESSAGE); + + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].modifyLimits(BigNumber(15*10**18), BigNumber(1*10**18), { from: ISSUER }); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, MESSAGE); + + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].modifyTiers([BigNumber(15*10**18)], [BigNumber(13*10**18)], [BigNumber(15*10**20)], [BigNumber(15*10**20)], { from: ISSUER }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, MESSAGE); + + let tempTime1 = latestTime(); + let tempTime2 = latestTime() + duration.days(3); + + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER }); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, MESSAGE); + + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].modifyAddresses("0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", I_DaiToken.address, { from: ISSUER }); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, MESSAGE); + + await revertToSnapshot(snapId); + }); + }); + + describe("Test buying failure conditions", async() => { + + it("should fail if before STO start time", async() => { + let stoId = 0; + let snapId = await takeSnapshot(); + + assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + + // Whitelist + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(15); + let expiryTime = toTime + duration.days(100); + let whitelisted = true; + + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + + // // Advance time to after STO start + // await increaseTime(duration.days(3)); + + // Set as accredited + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + // Prep for investments + let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH + let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY + await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); + await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + + // NONACCREDITED ETH + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + + // NONACCREDITED POLY + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + + // NONACCREDITED DAI + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, 'NONACCREDITED POLY investment succeeded when it should not'); + + // ACCREDITED ETH + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + + // ACCREDITED POLY + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + + // ACCREDITED DAI + let errorThrown6 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); + } catch(error) { + errorThrown6 = true; + ensureException(error); + } + assert.ok(errorThrown6, 'ACCREDITED POLY investment succeeded when it should not'); + + await revertToSnapshot(snapId); + }); + + it("should fail if not whitelisted", async() => { + let stoId = 0; + let snapId = await takeSnapshot(); + + // // Whitelist + // let fromTime = latestTime(); + // let toTime = latestTime() + duration.days(15); + // let expiryTime = toTime + duration.days(100); + // let whitelisted = true; + // + // await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + // await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + + // Advance time to after STO start + await increaseTime(duration.days(3)); + + // Set as accredited + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + // Prep for investments + let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH + let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY + await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); + await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + + // NONACCREDITED ETH + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + + // NONACCREDITED POLY + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + + // NONACCREDITED DAI + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + + // ACCREDITED ETH + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + + // ACCREDITED POLY + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + + // ACCREDITED DAI + let errorThrown6 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); + } catch(error) { + errorThrown6 = true; + ensureException(error); + } + assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + + await revertToSnapshot(snapId); + }); + + it("should fail if minimumInvestmentUSD not met", async() => { + let stoId = 0; + let tierId = 0; + let snapId = await takeSnapshot(); + + // Whitelist + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(15); + let expiryTime = toTime + duration.days(100); + let whitelisted = true; + + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + + // Advance time to after STO start + await increaseTime(duration.days(3)); + + // Set as accredited + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + let investment_USD = BigNumber(2).mul(10**18); + let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); + let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); + let investment_DAI = investment_USD; + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + + + await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); + await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + + // NONACCREDITED ETH + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + + // NONACCREDITED POLY + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + + // NONACCREDITED DAI + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + + // ACCREDITED ETH + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + + // ACCREDITED POLY + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + + // ACCREDITED DAI + let errorThrown6 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); + } catch(error) { + errorThrown6 = true; + ensureException(error); + } + assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + + await revertToSnapshot(snapId); + }); + + it("should successfully pause the STO and make investments fail, then unpause and succeed", async() => { + let stoId = 0; + let snapId = await takeSnapshot(); + + // Whitelist + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(15); + let expiryTime = toTime + duration.days(100); + let whitelisted = true; + + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + + // Advance time to after STO start + await increaseTime(duration.days(3)); + + // Set as accredited + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + // Pause the STO + await I_USDTieredSTO_Array[stoId].pause({ from: ISSUER }); + assert.equal(await I_USDTieredSTO_Array[stoId].paused.call(), true, 'STO did not pause successfully'); + + // Prep for investments + let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH + let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + + let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY + await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); + await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + + // NONACCREDITED ETH + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + + // NONACCREDITED POLY + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + + // NONACCREDITED DAI + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + + // ACCREDITED ETH + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + + // ACCREDITED POLY + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + + + // ACCREDITED DAI + let errorThrown6 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); + } catch(error) { + errorThrown6 = true; + ensureException(error); + } + assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + + // Unpause the STO + await I_USDTieredSTO_Array[stoId].unpause({ from: ISSUER }); + assert.equal(await I_USDTieredSTO_Array[stoId].paused.call(), false, 'STO did not unpause successfully'); + + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); + + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); + + await revertToSnapshot(snapId); + }); + + it("should fail if after STO end time", async() => { + let stoId = 3; + let snapId = await takeSnapshot(); + + // Whitelist + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(15); + let expiryTime = toTime + duration.days(100); + let whitelisted = true; + + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + + // Advance time to after STO end + await increaseTime(duration.days(3)); + + assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + + // Set as accredited + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + // Prep for investments + let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH + let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY + await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); + await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + + + // NONACCREDITED ETH + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + + // NONACCREDITED POLY + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + + // NONACCREDITED DAI + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + + // ACCREDITED ETH + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + + // ACCREDITED POLY + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + + // ACCREDITED DAI + let errorThrown6 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); + } catch(error) { + errorThrown6 = true; + ensureException(error); + } + assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + + await revertToSnapshot(snapId); + }); + + it("should fail if finalized", async() => { + let stoId = 0; + let snapId = await takeSnapshot(); + + // Whitelist + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(100); + let whitelisted = true; + + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(RESERVEWALLET, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + + // Advance time to after STO start + await increaseTime(duration.days(3)); + + // Set as accredited + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + // Finalize STO + await I_USDTieredSTO_Array[stoId].finalize({ from: ISSUER }); + assert.equal(await I_USDTieredSTO_Array[stoId].isFinalized.call(), true, "STO has not been finalized"); + assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + + // Attempt to call function again + let errorThrown = false; + try { + await I_USDTieredSTO_Array[stoId].finalize({ from: ISSUER }); + } catch(error) { + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, 'STO was finalized a second time'); + + // Prep for investments + let investment_ETH = web3.utils.toWei('1', 'ether'); // Invest 1 ETH + let investment_POLY = web3.utils.toWei('10000', 'ether'); // Invest 10000 POLY + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + let investment_DAI = web3.utils.toWei('500', 'ether'); // Invest 10000 POLY + await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); + await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + + // NONACCREDITED ETH + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, 'NONACCREDITED ETH investment succeeded when it should not'); + + // NONACCREDITED POLY + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, {from: NONACCREDITED1}); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, 'NONACCREDITED POLY investment succeeded when it should not'); + + // NONACCREDITED DAI + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, {from: NONACCREDITED1}); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, 'NONACCREDITED DAI investment succeeded when it should not'); + + // ACCREDITED ETH + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, 'ACCREDITED ETH investment succeeded when it should not'); + + // ACCREDITED POLY + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, {from: ACCREDITED1}); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, 'ACCREDITED POLY investment succeeded when it should not'); + + // ACCREDITED DAI + let errorThrown6 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, {from: ACCREDITED1}); + } catch(error) { + errorThrown6 = true; + ensureException(error); + } + assert.ok(errorThrown6, 'ACCREDITED DAI investment succeeded when it should not'); + + await revertToSnapshot(snapId); + }); + }); + + describe("Prep STO", async() => { + + it("should jump forward to after STO start", async() => { + let stoId = 0; + await increaseTime(duration.days(3)); + assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),true,"STO is not showing correct status"); + }); + + it("should whitelist ACCREDITED1 and NONACCREDITED1", async() => { + let stoId = 0; + + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(15); + let expiryTime = toTime + duration.days(100); + let whitelisted = true; + + const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + assert.equal(tx1.logs[0].args._investor, NONACCREDITED1, "Failed in adding the investor in whitelist"); + const tx2 = await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + assert.equal(tx2.logs[0].args._investor, ACCREDITED1, "Failed in adding the investor in whitelist"); + }); + + it("should successfully modify accredited addresses for first STO", async() => { + let stoId = 0; + + let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); + assert.equal(status1, false, "Initial accreditation is set to true"); + + await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1], [true], { from: ISSUER }); + let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); + assert.equal(status2, true, "Failed to set single address"); + + await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); + let status3 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); + assert.equal(status3, false, "Failed to set multiple addresses"); + let status4 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); + assert.equal(status4, true, "Failed to set multiple addresses"); + + let errorThrown = false; + try { + await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [true], { from: ISSUER }); + } catch(error) { + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, "Set accreditation despite input array of different size"); + }); + + it("should successfully modify accredited addresses for second STO", async() => { + let stoId = 1; + + await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); + let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); + let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); + assert.equal(status1, false, "Failed to set multiple address"); + assert.equal(status2, true, "Failed to set multiple address"); + }); + }); + + describe("Buy Tokens with no discount", async() => { + + it("should successfully buy using fallback at tier 0 for NONACCREDITED1", async() => { + let stoId = 0; + let tierId = 0; + + let investment_Token = BigNumber(50).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await web3.eth.sendTransaction({ from: NONACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); + console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), "Raised USD not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional checks on getters + assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 1, "Investor count not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), investment_Token.toNumber(), "getTokensSold not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), investment_Token.toNumber(), "getTokensMinted not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), investment_Token.toNumber(), "getTokensSoldForETH not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), 0, "getTokensSoldForPOLY not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), investment_USD.toNumber(), "investorInvestedUSD not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), investment_ETH.toNumber(), "investorInvestedETH not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), 0, "investorInvestedPOLY not changed as expected"); + }); + + it("should successfully buy using buyWithETH at tier 0 for NONACCREDITED1", async() => { + let stoId = 0; + let tierId = 0; + + let investment_Token = BigNumber(50).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); + console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised DAI not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should successfully buy using buyWithPOLY at tier 0 for NONACCREDITED1", async() => { + let stoId = 0; + let tierId = 0; + + let investment_Token = BigNumber(50).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should successfully buy using buyWithUSD at tier 0 for NONACCREDITED1", async() => { + let stoId = 0; + let tierId = 0; + + let investment_Token = BigNumber(50).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + let investment_DAI = investment_USD; + + await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: NONACCREDITED1}); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_InvestorDAIBal = await I_DaiToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + + // Buy With DAI + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithUSD: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_InvestorDAIBal = await I_DaiToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), "Investor DAI Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + assert.equal(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), "Wallet DAI Balance not changed as expected"); + }); + + it("should successfully buy using fallback at tier 0 for ACCREDITED1", async() => { + let stoId = 0; + let tierId = 0; + + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + let investment_Token = BigNumber(50).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await web3.eth.sendTransaction({ from: ACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); + console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should successfully buy using buyWithETH at tier 0 for ACCREDITED1", async() => { + let stoId = 0; + let tierId = 0; + + let investment_Token = BigNumber(50).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); + console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should successfully buy using buyWithPOLY at tier 0 for ACCREDITED1", async() => { + let stoId = 0; + let tierId = 0; + + let investment_Token = BigNumber(50).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + + // Additional checks on getters + let init_getTokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_getTokensMinted = await I_USDTieredSTO_Array[stoId].getTokensMinted(); + let init_getTokensSoldForETH = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH); + let init_getTokensSoldForPOLY = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY); + let init_investorInvestedUSD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1); + let init_investorInvestedETH = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH); + let init_investorInvestedPOLY = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional checks on getters + assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 2, "Investor count not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), init_getTokensSold.add(investment_Token).toNumber(), "getTokensSold not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), init_getTokensMinted.add(investment_Token).toNumber(), "getTokensMinted not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), init_getTokensSoldForETH.toNumber(), "getTokensSoldForETH not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), init_getTokensSoldForPOLY.add(investment_Token).toNumber(), "getTokensSoldForPOLY not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), init_investorInvestedUSD.add(investment_USD).toNumber(), "investorInvestedUSD not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), init_investorInvestedETH.toNumber(), "investorInvestedETH not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), init_investorInvestedPOLY.add(investment_POLY).toNumber(), "investorInvestedPOLY not changed as expected"); + }); + + it("should successfully modify NONACCREDITED cap for NONACCREDITED1", async() => { + let stoId = 0; + let tierId = 0; + console.log("Current investment: " + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber()); + await I_USDTieredSTO_Array[stoId].changeNonAccreditedLimit([NONACCREDITED1], [_nonAccreditedLimitUSD[stoId].div(2)], {from: ISSUER}); + console.log("Current limit: " + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1)).toNumber()); + }); + + it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async() => { + let stoId = 0; + let tierId = 0; + + let investment_USD = (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1));//_nonAccreditedLimitUSD[stoId]; + let investment_Token = await convert(stoId, tierId, false, "USD", "TOKEN", investment_USD); + let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); + let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); + + let refund_USD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); + let refund_Token = await convert(stoId, tierId, false, "USD", "TOKEN", refund_USD); + let refund_ETH = await convert(stoId, tierId, false, "USD", "ETH", refund_USD); + let refund_POLY = await convert(stoId, tierId, false, "USD", "POLY", refund_USD); + + console.log("Expected refund in tokens: " + refund_Token.toNumber()); + + let snap = await takeSnapshot(); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + // Buy with ETH + let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); + console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).add(refund_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).sub(refund_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).sub(refund_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + + await revertToSnapshot(snap); + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + + init_TokenSupply = await I_SecurityToken.totalSupply(); + init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + final_TokenSupply = await I_SecurityToken.totalSupply(); + final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).add(refund_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).sub(refund_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).sub(refund_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should fail and revert when NONACCREDITED cap reached", async() => { + let stoId = 0; + let tierId = 0; + + let investment_Token = BigNumber(50).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1, gasPrice: GAS_PRICE}); + + // Buy with ETH NONACCREDITED + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, MESSAGE); + }); + + it("should fail and revert despite oracle price change when NONACCREDITED cap reached", async() => { + let stoId = 0; + let tierId; + + // set new exchange rates + let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH + let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY + let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH + let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY + + let investment_USD = BigNumber(web3.utils.toWei('50')); // USD + let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH + let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH + let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + + await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); + + // Change exchange rates up + await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); + + // Buy with ETH NONACCREDITED + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, MESSAGE); + + // Change exchange rates down + await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); + + // Buy with ETH NONACCREDITED + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, MESSAGE); + + // Reset exchange rates + await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); + }); + + it("should successfully buy across tiers for NONACCREDITED ETH", async() => { + let stoId = 1; + let startTier = 0; + let endTier = 1; + + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + + let delta_Token = BigNumber(5).mul(10**18); + let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); + let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); + + let investment_Token = delta_Token.add(delta_Token); // 10 Token + let investment_ETH = ethTier0.add(ethTier1); // 0.0025 ETH + + // Process investment + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); + console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional Checks + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); + }); + + it("should successfully buy across tiers for NONACCREDITED POLY", async() => { + let stoId = 1; + let startTier = 1; + let endTier = 2; + + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + + let delta_Token = BigNumber(5).mul(10**18); // Token + let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); + let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); + + let investment_Token = delta_Token.add(delta_Token); // 10 Token + let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + + // Process investment + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional Checks + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); + }); + + it("should successfully buy across tiers for ACCREDITED ETH", async() => { + let stoId = 1; + let startTier = 2; + let endTier = 3; + + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + + let delta_Token = BigNumber(5).mul(10**18); // Token + let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); + let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); + + let investment_Token = delta_Token.add(delta_Token); // 10 Token + let investment_ETH = ethTier0.add(ethTier1); // 0.0025 ETH + + // Process investment + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); + console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional Checks + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); + }); + + it("should successfully buy across tiers for ACCREDITED DAI", async() => { + + let stoId = 1; + let startTier = 3; + let endTier = 4; + + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + + let delta_Token = BigNumber(5).mul(10**18); // Token + let daiTier0 = await convert(stoId, startTier, false, "TOKEN", "USD", delta_Token); + let daiTier1 = await convert(stoId, endTier, false, "TOKEN", "USD", delta_Token); + + let investment_Token = delta_Token.add(delta_Token); // 10 Token + let investment_DAI = daiTier0.add(daiTier1); + + await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: ACCREDITED1}); + + // Process investment + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_InvestorDAIBal = await I_DaiToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithUSD: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_InvestorDAIBal = await I_DaiToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(DAI); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), "Raised DAI not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + assert.equal(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional Checks + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); + + }); + + it("should successfully buy across tiers for ACCREDITED POLY", async() => { + let stoId = 1; + let startTier = 4; + let endTier = 5; + + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + + let delta_Token = BigNumber(5).mul(10**18); // Token + let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); + let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); + + let investment_Token = delta_Token.add(delta_Token); // 10 Token + let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH + + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + + // Process investment + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional Checks + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); + }); + + it("should buy out the rest of the sto", async() => { + let stoId = 1; + let tierId = 5; + + let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); + console.log(minted.toNumber() + ":"+ _tokensPerTierTotal[stoId][tierId]); + let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); + console.log(investment_Token.toNumber()); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + + let tx = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + console.log(" Gas buyWithETH: ".grey+tx.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + // assert.equal((await I_USDTieredSTO_Array[1].getTokensMinted()).toNumber(), _tokensPerTierTotal[1].reduce((a, b) => a + b, 0).toNumber(), "STO Token Sold not changed as expected"); + }); + + it("should fail and revert when all tiers sold out", async() => { + let stoId = 1; + let tierId = 4; + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + let investment_DAI = investment_USD; + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + + await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + + assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + + // Buy with ETH NONACCREDITED + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, MESSAGE); + + // Buy with DAI NONACCREDITED + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, MESSAGE); + + // Buy with ETH ACCREDITED + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, MESSAGE); + + // Buy with POLY ACCREDITED + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, MESSAGE); + + // Buy with DAI ACCREDITED + let errorThrown6 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown6 = true; + ensureException(error); + } + assert.ok(errorThrown6, MESSAGE); + }); + + it("should fail and revert when all tiers sold out despite oracle price change", async() => { + let stoId = 1; + let tierId = 4; + + // set new exchange rates + let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH + let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY + let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH + let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY + + let investment_USD = BigNumber(web3.utils.toWei('50')); // USD + let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH + let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH + let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + + await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); + await I_PolyToken.getTokens(investment_POLY_low, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: ACCREDITED1}); + + // Change exchange rates up + await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); + + // Buy with ETH NONACCREDITED + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, MESSAGE); + + // Buy with ETH ACCREDITED + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, MESSAGE); + + // Buy with POLY ACCREDITED + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_high, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, MESSAGE); + + // Change exchange rates down + await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); + + // Buy with ETH NONACCREDITED + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown6 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown6 = true; + ensureException(error); + } + assert.ok(errorThrown6, MESSAGE); + + // Buy with ETH ACCREDITED + let errorThrown7 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown7 = true; + ensureException(error); + } + assert.ok(errorThrown7, MESSAGE); + + // Buy with POLY ACCREDITED + let errorThrown8 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_low, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown8 = true; + ensureException(error); + } + assert.ok(errorThrown8, MESSAGE); + + // Reset exchange rates + await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); + }); + }); + + describe("Buy Tokens with POLY discount", async() => { + + it("should successfully buy using fallback at tier 0 for NONACCREDITED1", async() => { + let stoId = 2; + let tierId = 0; + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await web3.eth.sendTransaction({ from: NONACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); + console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), "Raised USD not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional checks on getters + assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 1, "Investor count not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), investment_Token.toNumber(), "getTokensSold not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), investment_Token.toNumber(), "getTokensMinted not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), investment_Token.toNumber(), "getTokensSoldForETH not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), 0, "getTokensSoldForPOLY not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), investment_USD.toNumber(), "investorInvestedUSD not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), investment_ETH.toNumber(), "investorInvestedETH not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), 0, "investorInvestedPOLY not changed as expected"); + }); + + it("should successfully buy using buyWithETH at tier 0 for NONACCREDITED1", async() => { + let stoId = 2; + let tierId = 0; + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); + console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should successfully buy using buyWithPOLY at tier 0 for NONACCREDITED1", async() => { + let stoId = 2; + let tierId = 0; + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should successfully buy using fallback at tier 0 for ACCREDITED1", async() => { + let stoId = 2; + let tierId = 0; + + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await web3.eth.sendTransaction({ from: ACCREDITED1, to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, gas:1000000 }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.gasUsed); + console.log(" Gas fallback purchase: ".grey+tx1.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should successfully buy using buyWithETH at tier 0 for ACCREDITED1", async() => { + let stoId = 2; + let tierId = 0; + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + let gasCost1 = BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); + console.log(" Gas buyWithETH: ".grey+tx1.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost1).sub(investment_ETH).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should successfully buy using buyWithPOLY at tier 0 for ACCREDITED1", async() => { + let stoId = 2; + let tierId = 0; + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); + + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + + // Additional checks on getters + let init_getTokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_getTokensMinted = await I_USDTieredSTO_Array[stoId].getTokensMinted(); + let init_getTokensSoldForETH = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH); + let init_getTokensSoldForPOLY = await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY); + let init_investorInvestedUSD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1); + let init_investorInvestedETH = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH); + let init_investorInvestedPOLY = await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional checks on getters + assert.equal((await I_USDTieredSTO_Array[stoId].investorCount.call()).toNumber(), 2, "Investor count not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), init_getTokensSold.add(investment_Token).toNumber(), "getTokensSold not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), init_getTokensMinted.add(investment_Token).toNumber(), "getTokensMinted not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), init_getTokensSoldForETH.toNumber(), "getTokensSoldForETH not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), init_getTokensSoldForPOLY.add(investment_Token).toNumber(), "getTokensSoldForPOLY not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), init_investorInvestedUSD.add(investment_USD).toNumber(), "investorInvestedUSD not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), init_investorInvestedETH.toNumber(), "investorInvestedETH not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), init_investorInvestedPOLY.add(investment_POLY).toNumber(), "investorInvestedPOLY not changed as expected"); + }); + + it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async() => { + let stoId = 2; + let tierId = 0; + + let investment_USD = _nonAccreditedLimitUSD[stoId]; + let investment_Token = await convert(stoId, tierId, true, "USD", "TOKEN", investment_USD); + let investment_ETH = await convert(stoId, tierId, true, "USD", "ETH", investment_USD); + let investment_POLY = await convert(stoId, tierId, true, "USD", "POLY", investment_USD); + + let refund_USD = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); + let refund_Token = await convert(stoId, tierId, true, "USD", "TOKEN", refund_USD); + let refund_ETH = await convert(stoId, tierId, true, "USD", "ETH", refund_USD); + let refund_POLY = await convert(stoId, tierId, true, "USD", "POLY", refund_USD); + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1}); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).sub(refund_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).sub(refund_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).add(refund_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).sub(refund_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).sub(refund_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).sub(refund_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should fail and revert when NONACCREDITED cap reached", async() => { + let stoId = 2; + let tierId = 0; + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Token); + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: NONACCREDITED1, gasPrice: GAS_PRICE}); + + // Buy with ETH NONACCREDITED + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, MESSAGE); + }); + + it("should fail and revert despite oracle price change when NONACCREDITED cap reached", async() => { + let stoId = 2; + let tierId = 0; + + // set new exchange rates + let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH + let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY + let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH + let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); + + let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH + let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH + let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + + await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); + + // Change exchange rates up + await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); + + // Buy with ETH NONACCREDITED + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, MESSAGE); + + // Change exchange rates down + await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); + + // Buy with ETH NONACCREDITED + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, MESSAGE); + + // Reset exchange rates + await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); + }); + + it("should successfully buy across tiers for POLY", async() => { + let stoId = 2; + let startTier = 0; + let endTier = 1; + + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), startTier, "currentTier not changed as expected"); + + let delta_Token = BigNumber(5).mul(10**18); // Token + let polyTier0 = await convert(stoId, startTier, true, "TOKEN", "POLY", delta_Token); + let polyTier1 = await convert(stoId, endTier, true, "TOKEN", "POLY", delta_Token); + let investment_Token = delta_Token.add(delta_Token); // 10 Token + let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH + + let tokensRemaining = (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier)); + let prep_Token = tokensRemaining.sub(delta_Token); + let prep_POLY = await convert(stoId, startTier, true, "TOKEN", "POLY", prep_Token); + + await I_PolyToken.getTokens(prep_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, prep_POLY, {from: ACCREDITED1}); + let tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, prep_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + console.log(" Gas buyWithPOLY: ".grey+tx.receipt.gasUsed.toString().grey); + + let Tier0Token = (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier)); + let Tier0Minted = (await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier)); + assert.equal(Tier0Minted.toNumber(), Tier0Token.sub(delta_Token).toNumber()); + + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + + // Process investment + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + + // Additional Checks + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), endTier, "currentTier not changed as expected"); + }); + + it("should successfully buy across the discount cap", async() => { + let stoId = 2; + let tierId = 1; + + let discount_Token = BigNumber(20).mul(10**18); + let discount_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", discount_Token); + + let regular_Token = BigNumber(10).mul(10**18); + let regular_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", regular_Token); + + let investment_Token = discount_Token.add(regular_Token); + let investment_POLY = discount_POLY.add(regular_POLY); + + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost2).toNumber(), "Investor ETH Balance not changed as expected"); + assert.equal(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), "Investor POLY Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), "Wallet POLY Balance not changed as expected"); + }); + + it("should buy out the rest of the sto", async() => { + let stoId = 2; + let tierId = 1; + + let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); + let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: ACCREDITED1}); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey+tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + + assert.equal(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), "Token Supply not changed as expected"); + assert.equal(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), "Investor Token Balance not changed as expected"); + assert.equal(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), "STO Token Sold not changed as expected"); + }); + + it("should fail and revert when all tiers sold out", async() => { + let stoId = 2; + let tierId = 1; + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); + + await I_PolyToken.getTokens(investment_POLY, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + + assert.equal(await I_USDTieredSTO_Array[stoId].isOpen(),false,"STO is not showing correct status"); + + // Buy with ETH NONACCREDITED + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, MESSAGE); + + // Buy with ETH ACCREDITED + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, MESSAGE); + + // Buy with POLY ACCREDITED + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, MESSAGE); + }); + + it("should fail and revert when all tiers sold out despite oracle price change", async() => { + let stoId = 2; + let tierId = 1; + + // set new exchange rates + let high_USDETH = BigNumber(1000).mul(10**18); // 1000 USD per ETH + let high_USDPOLY = BigNumber(50).mul(10**16); // 0.5 USD per POLY + let low_USDETH = BigNumber(250).mul(10**18); // 250 USD per ETH + let low_USDPOLY = BigNumber(20).mul(10**16); // 0.2 USD per POLY + + let investment_Token = BigNumber(5).mul(10**18); + let investment_USD = await convert(stoId, tierId, true, "TOKEN", "USD", investment_Token); + + let investment_ETH_high = investment_USD.div(high_USDETH).mul(10**18); // USD / USD/ETH = ETH + let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + let investment_ETH_low = investment_USD.div(low_USDETH).mul(10**18); // USD / USD/ETH = ETH + let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(10**18); // USD / USD/POLY = POLY + + await I_PolyToken.getTokens(investment_POLY_low, NONACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: NONACCREDITED1}); + await I_PolyToken.getTokens(investment_POLY_low, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY_low, {from: ACCREDITED1}); + + // Change exchange rates up + await I_USDOracle.changePrice(high_USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(high_USDPOLY, { from: POLYMATH }); + + // Buy with ETH NONACCREDITED + let errorThrown1 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown1 = true; + ensureException(error); + } + assert.ok(errorThrown1, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown2 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_high, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown2 = true; + ensureException(error); + } + assert.ok(errorThrown2, MESSAGE); + + // Buy with ETH ACCREDITED + let errorThrown3 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_high, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown3 = true; + ensureException(error); + } + assert.ok(errorThrown3, MESSAGE); + + // Buy with POLY ACCREDITED + let errorThrown4 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_high, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown4 = true; + ensureException(error); + } + assert.ok(errorThrown4, MESSAGE); + + // Change exchange rates down + await I_USDOracle.changePrice(low_USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(low_USDPOLY, { from: POLYMATH }); + + // Buy with ETH NONACCREDITED + let errorThrown5 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown5 = true; + ensureException(error); + } + assert.ok(errorThrown5, MESSAGE); + + // Buy with POLY NONACCREDITED + let errorThrown6 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY_low, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown6 = true; + ensureException(error); + } + assert.ok(errorThrown6, MESSAGE); + + // Buy with ETH ACCREDITED + let errorThrown7 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH_low, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown7 = true; + ensureException(error); + } + assert.ok(errorThrown7, MESSAGE); + + // Buy with POLY ACCREDITED + let errorThrown8 = false; + try { + await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY_low, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown8 = true; + ensureException(error); + } + assert.ok(errorThrown8, MESSAGE); + + // Reset exchange rates + await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); + }); + }); + + describe("Test getter functions", async() => { + + describe("Generic", async() => { + + it("should get the right number of investors", async() => { + assert.equal((await I_USDTieredSTO_Array[0].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[0].investorCount()).toNumber(), "Investor count not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[1].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[1].investorCount()).toNumber(), "Investor count not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[2].investorCount.call()).toNumber(), (await I_USDTieredSTO_Array[2].investorCount()).toNumber(), "Investor count not changed as expected"); + }); + + it("should get the right amounts invested", async() => { + assert.equal((await I_USDTieredSTO_Array[0].fundsRaised.call(ETH)).toNumber(), (await I_USDTieredSTO_Array[0].getRaised(0)).toNumber(), "getRaisedEther not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[0].fundsRaised.call(POLY)).toNumber(), (await I_USDTieredSTO_Array[0].getRaised(1)).toNumber(), "getRaisedPOLY not changed as expected"); + assert.equal((await I_USDTieredSTO_Array[0].fundsRaisedUSD.call()).toNumber(), (await I_USDTieredSTO_Array[0].fundsRaisedUSD()).toNumber(), "fundsRaisedUSD not changed as expected"); + }); + }); + + describe("convertToUSD", async() => { + + it("should reset exchange rates", async() => { + // Reset exchange rates + await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); + await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); + }); + + it("should get the right conversion for ETH to USD", async() => { + // 20 ETH to 10000 USD + let ethInWei = BigNumber(web3.utils.toWei('20', 'ether')); + let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(ETH, ethInWei); + assert.equal(usdInWei.div(10**18).toNumber(), ethInWei.div(10**18).mul(USDETH.div(10**18)).toNumber()); + }); + + it("should get the right conversion for POLY to USD", async() => { + // 40000 POLY to 10000 USD + let polyInWei = BigNumber(web3.utils.toWei('40000', 'ether')); + let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(POLY, polyInWei); + assert.equal(usdInWei.div(10**18).toNumber(), polyInWei.div(10**18).mul(USDPOLY.div(10**18)).toNumber()); + }); + }); + + describe("convertFromUSD", async() => { + + it("should get the right conversion for USD to ETH", async() => { + // 10000 USD to 20 ETH + let usdInWei = BigNumber(web3.utils.toWei('10000', 'ether')); + let ethInWei = await I_USDTieredSTO_Array[0].convertFromUSD(ETH, usdInWei); + assert.equal(ethInWei.div(10**18).toNumber(), usdInWei.div(10**18).div(USDETH.div(10**18)).toNumber()); + }); + + it("should get the right conversion for USD to POLY", async() => { + // 10000 USD to 40000 POLY + let usdInWei = BigNumber(web3.utils.toWei('10000', 'ether')); + let polyInWei = await I_USDTieredSTO_Array[0].convertFromUSD(POLY, usdInWei); + assert.equal(polyInWei.div(10**18).toNumber(), usdInWei.div(10**18).div(USDPOLY.div(10**18)).toNumber()); + }); + }); + }); + + describe("Test cases for the USDTieredSTOFactory", async() => { + it("should get the exact details of the factory", async() => { + assert.equal((await I_USDTieredSTOFactory.setupCost.call()).toNumber(), STOSetupCost); + assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0],3); + assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), + "USDTieredSTO", + "Wrong Module added"); + assert.equal(await I_USDTieredSTOFactory.getDescription.call(), + "USD Tiered STO", + "Wrong Module added"); + assert.equal(await I_USDTieredSTOFactory.getTitle.call(), + "USD Tiered STO", + "Wrong Module added"); + assert.equal(await I_USDTieredSTOFactory.getInstructions.call(), + "Initialises a USD tiered STO.", + "Wrong Module added"); + let tags = await I_USDTieredSTOFactory.getTags.call(); + assert.equal(web3.utils.hexToString(tags[0]),"USD"); + assert.equal(web3.utils.hexToString(tags[1]),"Tiered"); + assert.equal(web3.utils.hexToString(tags[2]),"POLY"); + assert.equal(web3.utils.hexToString(tags[3]),"ETH"); + + }); + }); +}); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 738373341..96015926d 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -1,775 +1,775 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); -// const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); -// const MockOracle = artifacts.require('./MockOracle.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port - -// const TOLERANCE = 2; // Allow balances to be off by 2 WEI for rounding purposes - -// contract('USDTieredSTO Sim', accounts => { -// // Accounts Variable declaration -// let POLYMATH; -// let ISSUER; -// let WALLET; -// let RESERVEWALLET; -// let INVESTOR1; -// let ACCREDITED1; -// let ACCREDITED2; -// let NONACCREDITED1; -// let NONACCREDITED2; -// let NOTWHITELISTED; -// let NOTAPPROVED; - -// let MESSAGE = "Transaction Should Fail!"; -// const GAS_PRICE = 10000000000; // 10 GWEI - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_GeneralTransferManagerFactory; -// let I_USDTieredSTOProxyFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_USDTieredSTOFactory; -// let I_USDOracle; -// let I_POLYOracle; -// let I_STFactory; -// let I_MRProxied; -// let I_STRProxied; -// let I_SecurityToken; -// let I_USDTieredSTO_Array = []; -// let I_PolyToken; -// let I_DaiToken; -// let I_PolymathRegistry; - -// // SecurityToken Details for funds raise Type ETH -// const NAME = "Team"; -// const SYMBOL = "SAP"; -// const TOKENDETAILS = "This is equity type of issuance"; -// const DECIMALS = 18; - -// // Module key -// const TMKEY = 2; -// const STOKEY = 3; - -// // Initial fee for ticker registry and security token registry -// const REGFEE = web3.utils.toWei("250"); -// const STOSetupCost = 0; - -// // MockOracle USD prices -// const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH -// const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY - -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// // STO Configuration Arrays -// let _startTime = []; -// let _endTime = []; -// let _ratePerTier = []; -// let _ratePerTierDiscountPoly = []; -// let _tokensPerTierTotal = []; -// let _tokensPerTierDiscountPoly = []; -// let _nonAccreditedLimitUSD = []; -// let _minimumInvestmentUSD = []; -// let _fundRaiseTypes = []; -// let _wallet = []; -// let _reserveWallet = []; -// let _usdToken = []; - -// /* function configure( -// uint256 _startTime, -// uint256 _endTime, -// uint256[] _ratePerTier, -// uint256[] _ratePerTierDiscountPoly, -// uint256[] _tokensPerTier, -// uint256[] _tokensPerTierDiscountPoly, -// uint256 _nonAccreditedLimitUSD, -// uint256 _minimumInvestmentUSD, -// uint8[] _fundRaiseTypes, -// address _wallet, -// address _reserveWallet, -// address _usdToken -// ) */ -// const functionSignature = { -// name: 'configure', -// type: 'function', -// inputs: [{ -// type: 'uint256', -// name: '_startTime' -// },{ -// type: 'uint256', -// name: '_endTime' -// },{ -// type: 'uint256[]', -// name: '_ratePerTier' -// },{ -// type: 'uint256[]', -// name: '_ratePerTierDiscountPoly' -// },{ -// type: 'uint256[]', -// name: '_tokensPerTier' -// },{ -// type: 'uint256[]', -// name: '_tokensPerTierDiscountPoly' -// },{ -// type: 'uint256', -// name: '_nonAccreditedLimitUSD' -// },{ -// type: 'uint256', -// name: '_minimumInvestmentUSD' -// },{ -// type: 'uint8[]', -// name: '_fundRaiseTypes' -// },{ -// type: 'address', -// name: '_wallet' -// },{ -// type: 'address', -// name: '_reserveWallet' -// },{ -// type: 'address', -// name: '_usdToken' -// }] -// }; - -// function getRandomInt(min, max) { -// return Math.floor(Math.random() * (max - min + 1)) + min; -// } - -// before(async() => { -// // Accounts setup -// POLYMATH = accounts[0]; -// ISSUER = accounts[1]; -// WALLET = accounts[2]; -// RESERVEWALLET = WALLET; -// ACCREDITED1 = accounts[3]; -// ACCREDITED2 = accounts[4]; -// NONACCREDITED1 = accounts[5]; -// NONACCREDITED2 = accounts[6]; -// NOTWHITELISTED = accounts[7]; -// NOTAPPROVED = accounts[8]; -// INVESTOR1 = accounts[9]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// I_DaiToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: POLYMATH -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - -// // STEP 3: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the proxy -// I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); - -// // STEP 6: Deploy the USDTieredSTOFactory - -// I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); - -// assert.notEqual( -// I_USDTieredSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "USDTieredSTOFactory contract was not deployed" -// ); - - - -// // Step 8: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 9: Deploy the SecurityTokenRegistry - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: update the registries addresses from the PolymathRegistry contract -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); -// await I_MRProxied.updateFromRegistry({from: POLYMATH}); - -// // STEP 7: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); - -// // (C) : Register the STOFactory -// await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); -// await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); - -// // Step 12: Deploy & Register Mock Oracles -// I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY -// I_POLYOracle = await MockOracle.new(I_PolyToken.address, "POLY", "USD", USDPOLY, { from: POLYMATH }); // 25 cents per POLY -// await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); -// await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// ModuleRegistry: ${ModuleRegistry.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// USDOracle: ${I_USDOracle.address} -// POLYOracle: ${I_POLYOracle.address} -// USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} -// USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Deploy the STO", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.getTokens(REGFEE, ISSUER); -// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); -// let tx = await I_STRProxied.registerTicker(ISSUER, SYMBOL, NAME, { from : ISSUER }); -// assert.equal(tx.logs[0].args._owner, ISSUER); -// assert.equal(tx.logs[0].args._ticker, SYMBOL); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.getTokens(REGFEE, ISSUER); -// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); -// assert.equal(tx.logs[1].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), TMKEY); -// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); - -// it("Should successfully attach the first STO module to the security token", async () => { -// let stoId = 0; - -// _startTime.push(latestTime() + duration.days(2)); -// _endTime.push(_startTime[stoId] + duration.days(100)); -// _ratePerTier.push([ -// BigNumber(0.05*10**18), BigNumber(0.13*10**18), BigNumber(0.17*10**18) -// ]); // [ 0.05 USD/Token, 0.10 USD/Token, 0.15 USD/Token ] -// _ratePerTierDiscountPoly.push([ -// BigNumber(0.05*10**18), BigNumber(0.08*10**18), BigNumber(0.13*10**18) -// ]); // [ 0.05 USD/Token, 0.08 USD/Token, 0.13 USD/Token ] -// _tokensPerTierTotal.push([ -// BigNumber(200*10**18), BigNumber(500*10**18), BigNumber(300*10**18) -// ]); // [ 1000 Token, 2000 Token, 1500 Token ] -// _tokensPerTierDiscountPoly.push([ -// BigNumber(0), BigNumber(50*10**18), BigNumber(300*10**18) -// ]); // [ 0 Token, 1000 Token, 1500 Token ] -// _nonAccreditedLimitUSD.push(BigNumber(10*10**18)); // 20 USD -// _minimumInvestmentUSD.push(BigNumber(0)); // 1 wei USD -// _fundRaiseTypes.push([0,1,2]); -// _wallet.push(WALLET); -// _reserveWallet.push(RESERVEWALLET); -// _usdToken.push(I_DaiToken.address); - -// let config = [ -// _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], -// _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], -// _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] -// ]; - -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); -// let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); -// console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); -// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); -// I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); - -// assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); -// for (var i = 0; i < _ratePerTier[stoId].length; i++) { -// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); -// } -// assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getNumberOfTiers()), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); -// assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); -// }); - -// it("Should successfully prepare the STO", async() => { -// let stoId = 0; - -// // Start STO -// await increaseTime(duration.days(3)); - -// // Whitelist -// let fromTime = latestTime() + duration.days(15); -// let toTime = latestTime() + duration.days(15); -// let expiryTime = toTime + duration.days(100); -// let canBuyFromSTO = true; - -// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); -// await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, { from: ISSUER }); - -// await increaseTime(duration.days(3)); - -// // Accreditation -// await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1, ACCREDITED2], [true, true], { from: ISSUER }); -// await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, NONACCREDITED2], [false, false], { from: ISSUER }); -// }); -// }); - -// describe("Simulate purchasing", async() => { - -// it("Should successfully complete simulation", async() => { -// let stoId = 0; - -// console.log(` -// ------------------- Investor Addresses ------------------- -// ACCREDITED1: ${ACCREDITED1} -// ACCREDITED2: ${ACCREDITED2} -// NONACCREDITED1: ${NONACCREDITED1} -// NONACCREDITED2: ${NONACCREDITED2} -// NOTWHITELISTED: ${NOTWHITELISTED} -// NOTAPPROVED: ${NOTAPPROVED} -// ---------------------------------------------------------- -// `); - -// let totalTokens = BigNumber(0); -// for (var i = 0; i < _tokensPerTierTotal[stoId].length; i++) { -// totalTokens = totalTokens.add(_tokensPerTierTotal[stoId][i]); -// } -// console.log('totalTokens: '+totalTokens.div(10**18).toNumber()); -// let tokensSold = BigNumber(0); -// while (true) { -// switch (getRandomInt(0,5)) { -// case 0: // ACCREDITED1 -// await invest(ACCREDITED1, true); -// break; -// case 1: // ACCREDITED2 -// await invest(ACCREDITED2, true); -// break; -// case 2: // NONACCREDITED1 -// let usd_NONACCREDITED1 = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); -// if (_nonAccreditedLimitUSD[stoId].gt(usd_NONACCREDITED1)) // under non-accredited cap -// await invest(NONACCREDITED1, false); -// else // over non-accredited cap -// await investFAIL(NONACCREDITED1); -// break; -// case 3: // NONACCREDITED2 -// let usd_NONACCREDITED2 = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED2); -// if (_nonAccreditedLimitUSD[stoId].gt(usd_NONACCREDITED2)) // under non-accredited cap -// await invest(NONACCREDITED2, false); -// else // over non-accredited cap -// await investFAIL(NONACCREDITED2); -// break; -// case 4: // NOTWHITELISTED -// await investFAIL(NOTWHITELISTED); -// break; -// case 5: // NOTAPPROVED -// await investFAIL(NOTAPPROVED); -// break; -// } -// console.log("Next round"); -// tokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// console.log("Tokens Sold: " + tokensSold.toString()); -// if (tokensSold.gte(totalTokens.sub(1*10**18))) { -// console.log(`${tokensSold} tokens sold, simulation completed successfully!`.green); -// break; -// } -// } - -// async function invest(_investor, _isAccredited) { // need to add check if reached non-accredited cap -// let USD_remaining; -// if (!_isAccredited) { -// let USD_to_date = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(_investor); -// USD_remaining = _nonAccreditedLimitUSD[stoId].sub(USD_to_date); -// } else { -// USD_remaining = totalTokens.mul(2); -// } - -// let log_remaining = USD_remaining; -// let isPoly = Math.random() >= 0.33; -// let isDai = Math.random() >= 0.33; - -// let Token_counter = BigNumber(getRandomInt(1*10**10,50*10**10)).mul(10**8); -// let investment_USD = BigNumber(0); -// let investment_ETH = BigNumber(0); -// let investment_POLY = BigNumber(0); -// let investment_DAI = BigNumber(0); -// let investment_Token = BigNumber(0); - -// let Tokens_total = []; -// let Tokens_discount = []; -// for (var i = 0; i < _ratePerTier[stoId].length; i++) { -// Tokens_total.push((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(i))); -// Tokens_discount.push((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierDiscountPoly.call(i))); -// } - -// let tier = 0; -// let Token_Tier; -// let USD_Tier; -// let POLY_Tier; -// let ETH_Tier; -// let DAI_Tier; - - -// let USD_overflow; -// let Token_overflow; - -// while (Token_counter.gt(0)) { -// if (tier == _ratePerTier[stoId].length) { -// break; -// } -// if (Tokens_total[tier].gt(0)) { -// if (isPoly) { -// // 1. POLY and discount (consume up to cap then move to regular) -// if (Tokens_discount[tier].gt(0)) { -// Token_Tier = BigNumber.min([Tokens_total[tier], Tokens_discount[tier], Token_counter]); -// USD_Tier = Token_Tier.mul(_ratePerTierDiscountPoly[stoId][tier].div(10**18)); -// if (USD_Tier.gte(USD_remaining)) { -// USD_overflow = USD_Tier.sub(USD_remaining); -// Token_overflow = USD_overflow.mul(10**18).div(_ratePerTierDiscountPoly[stoId][tier]); -// USD_Tier = USD_Tier.sub(USD_overflow); -// Token_Tier = Token_Tier.sub(Token_overflow); -// Token_counter = BigNumber(0); -// } -// POLY_Tier = USD_Tier.mul(10**18).round(0).div(USDPOLY).round(0); -// USD_remaining = USD_remaining.sub(USD_Tier); -// Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); -// Tokens_discount[tier] = Tokens_discount[tier].sub(Token_Tier); -// Token_counter = Token_counter.sub(Token_Tier); -// investment_Token = investment_Token.add(Token_Tier); -// investment_USD = investment_USD.add(USD_Tier); -// investment_POLY = investment_POLY.add(POLY_Tier); -// } -// // 2. POLY and regular (consume up to cap then skip to next tier) -// if (Tokens_total[tier].gt(0) && Token_counter.gt(0)) { -// Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); -// USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); -// if (USD_Tier.gte(USD_remaining)) { -// USD_overflow = USD_Tier.sub(USD_remaining); -// Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); -// USD_Tier = USD_Tier.sub(USD_overflow); -// Token_Tier = Token_Tier.sub(Token_overflow); -// Token_counter = BigNumber(0); -// } -// POLY_Tier = USD_Tier.mul(10**18).round(0).div(USDPOLY).round(0); -// USD_remaining = USD_remaining.sub(USD_Tier); -// Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); -// Token_counter = Token_counter.sub(Token_Tier); -// investment_Token = investment_Token.add(Token_Tier); -// investment_USD = investment_USD.add(USD_Tier); -// investment_POLY = investment_POLY.add(POLY_Tier); -// } -// } else if (isDai) { -// // 3. DAI (consume up to cap then skip to next tier) -// Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); -// USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); -// if (USD_Tier.gte(USD_remaining)) { -// USD_overflow = USD_Tier.sub(USD_remaining); -// Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); -// USD_Tier = USD_Tier.sub(USD_overflow); -// Token_Tier = Token_Tier.sub(Token_overflow); -// Token_counter = BigNumber(0); -// } -// DAI_Tier = USD_Tier.round(0); -// USD_remaining = USD_remaining.sub(USD_Tier); -// Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); -// Token_counter = Token_counter.sub(Token_Tier); -// investment_Token = investment_Token.add(Token_Tier); -// investment_USD = investment_USD.add(USD_Tier); -// investment_DAI = investment_USD; -// } else { -// // 4. ETH (consume up to cap then skip to next tier) -// Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); -// USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); -// if (USD_Tier.gte(USD_remaining)) { -// USD_overflow = USD_Tier.sub(USD_remaining); -// Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); -// USD_Tier = USD_Tier.sub(USD_overflow); -// Token_Tier = Token_Tier.sub(Token_overflow); -// Token_counter = BigNumber(0); -// } -// ETH_Tier = USD_Tier.mul(10**18).round(0).div(USDETH).round(0); -// USD_remaining = USD_remaining.sub(USD_Tier); -// Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); -// Token_counter = Token_counter.sub(Token_Tier); -// investment_Token = investment_Token.add(Token_Tier); -// investment_USD = investment_USD.add(USD_Tier); -// investment_ETH = investment_ETH.add(ETH_Tier); -// } -// } -// tier++ -// } - -// await processInvestment(_investor, investment_Token, investment_USD, investment_POLY, investment_DAI, investment_ETH, isPoly, isDai, log_remaining, Tokens_total, Tokens_discount, tokensSold); -// } - -// async function investFAIL(_investor) { -// let isPoly = Math.random() >= 0.3; -// let isDAI = Math.random() >= 0.3; -// let investment_POLY = BigNumber(40*10**18); // 10 USD = 40 POLY -// let investment_ETH = BigNumber(0.02*10**18); // 10 USD = 0.02 ETH -// let investment_DAI = BigNumber(10*10**18); // 10 USD = DAI DAI - -// let errorThrown = false; -// try { -// if (isPoly) { -// await I_PolyToken.getTokens(investment_POLY, _investor); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: _investor}); -// await I_USDTieredSTO_Array[stoId].buyWithPOLY(_investor, investment_POLY, { from: _investor, gasPrice: GAS_PRICE }); -// } else if (isDAI) { -// await I_DaiToken.getTokens(investment_DAI, _investor); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: _investor}); -// await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); -// } else await I_USDTieredSTO_Array[stoId].buyWithETH(_investor, { from: _investor, value: investment_ETH, gasPrice: GAS_PRICE }); -// } catch(error) { -// errorThrown = true; -// console.log(`Purchase failed as expected: ${_investor}`.yellow); -// ensureException(error); -// } -// assert.ok(errorThrown, MESSAGE); -// } - -// async function processInvestment(_investor, investment_Token, investment_USD, investment_POLY, investment_DAI, investment_ETH, isPoly, isDai, log_remaining, Tokens_total, Tokens_discount, tokensSold) { -// investment_Token = investment_Token.round(0); -// investment_USD = investment_USD.round(0); -// investment_POLY = investment_POLY.round(0); -// investment_DAI = investment_DAI.round(0); -// investment_ETH = investment_ETH.round(0); -// console.log(` -// ------------------- New Investment ------------------- -// Investor: ${_investor} -// N-A USD Remaining: ${log_remaining.div(10**18)} -// Total Cap Remaining: ${Tokens_total} -// Discount Cap Remaining: ${Tokens_discount} -// Total Tokens Sold: ${tokensSold.div(10**18)} -// Token Investment: ${investment_Token.div(10**18)} -// USD Investment: ${investment_USD.div(10**18)} -// POLY Investment: ${investment_POLY.div(10**18)} -// DAI Investment: ${investment_DAI.div(10**18)} -// ETH Investment: ${investment_ETH.div(10**18)} -// ------------------------------------------------------ -// `); - -// if (isPoly) { -// await I_PolyToken.getTokens(investment_POLY, _investor); -// await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: _investor}); -// } else if (isDai) { -// await I_DaiToken.getTokens(investment_DAI, _investor); -// await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: _investor}); -// } - -// // console.log(await I_USDTieredSTO_Array[stoId].isOpen()); - -// let init_TokenSupply = await I_SecurityToken.totalSupply(); -// let init_InvestorTokenBal = await I_SecurityToken.balanceOf(_investor); -// let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(_investor)); -// let init_InvestorPOLYBal = await I_PolyToken.balanceOf(_investor); -// let init_InvestorDAIBal = await I_DaiToken.balanceOf(_investor); -// let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_STODAIBal = await I_DaiToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); -// let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(0); -// let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(1); -// let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(2); -// let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); -// let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - -// let tx; -// let gasCost = BigNumber(0); - -// if (isPoly && investment_POLY.gt(10)) { -// tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(_investor, investment_POLY, { from: _investor, gasPrice: GAS_PRICE }); -// gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); -// console.log(`buyWithPOLY: ${investment_Token.div(10**18)} tokens for ${investment_POLY.div(10**18)} POLY by ${_investor}`.yellow); -// } else if (isDai && investment_DAI.gt(10)) { -// tx = await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); -// gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); -// console.log(`buyWithUSD: ${investment_Token.div(10**18)} tokens for ${investment_DAI.div(10**18)} DAI by ${_investor}`.yellow); -// } else if (investment_ETH.gt(0)) { -// tx = await I_USDTieredSTO_Array[stoId].buyWithETH(_investor, { from: _investor, value: investment_ETH, gasPrice: GAS_PRICE }); -// gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); -// console.log(`buyWithETH: ${investment_Token.div(10**18)} tokens for ${investment_ETH.div(10**18)} ETH by ${_investor}`.yellow); -// } -// console.log(investment_POLY.toNumber()); - -// let final_TokenSupply = await I_SecurityToken.totalSupply(); -// let final_InvestorTokenBal = await I_SecurityToken.balanceOf(_investor); -// let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(_investor)); -// let final_InvestorPOLYBal = await I_PolyToken.balanceOf(_investor); -// let final_InvestorDAIBal = await I_DaiToken.balanceOf(_investor); -// let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); -// let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); -// let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_STODAIBal = await I_DaiToken.balanceOf(I_USDTieredSTO_Array[stoId].address); -// let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); -// let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(0); -// let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(1); -// let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(2); -// let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); -// let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); -// let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - -// // console.log('init_TokenSupply: '+init_TokenSupply.div(10**18).toNumber()); -// // console.log('final_TokenSupply: '+final_TokenSupply.div(10**18).toNumber()); - -// if (isPoly) { -// assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); -// assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); -// assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); -// assert.closeTo(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), TOLERANCE, "Investor POLY Balance not changed as expected"); -// assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); -// assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); -// assert.closeTo(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), TOLERANCE, "STO POLY Balance not changed as expected"); -// assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); -// assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), TOLERANCE, "Raised ETH not changed as expected"); -// assert.closeTo(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), TOLERANCE, "Raised POLY not changed as expected"); -// assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); -// assert.closeTo(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), TOLERANCE, "Wallet POLY Balance not changed as expected"); -// } else if (isDai) { -// assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); -// assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); -// assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); -// assert.closeTo(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), TOLERANCE, "Investor DAI Balance not changed as expected"); -// assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); -// assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); -// assert.closeTo(final_STODAIBal.toNumber(), init_STODAIBal.toNumber(), TOLERANCE, "STO DAI Balance not changed as expected"); -// assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); -// assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), TOLERANCE, "Raised ETH not changed as expected"); -// assert.closeTo(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), TOLERANCE, "Raised DAI not changed as expected"); -// assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); -// assert.closeTo(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), TOLERANCE, "Wallet DAI Balance not changed as expected"); -// } else { -// assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); -// assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); -// assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).sub(investment_ETH).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); -// assert.closeTo(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), TOLERANCE, "Investor POLY Balance not changed as expected"); -// assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); -// assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); -// assert.closeTo(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), TOLERANCE, "STO POLY Balance not changed as expected"); -// assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); -// assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), TOLERANCE, "Raised ETH not changed as expected"); -// assert.closeTo(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), TOLERANCE, "Raised POLY not changed as expected"); -// assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); -// assert.closeTo(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), TOLERANCE, "Wallet POLY Balance not changed as expected"); -// } -// } -// }); -// }); -// }); - -// function near(x, y, message) { -// assert.isAtMost(x, y) - -// } +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); +const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); +const MockOracle = artifacts.require('./MockOracle.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port + +const TOLERANCE = 2; // Allow balances to be off by 2 WEI for rounding purposes + +contract('USDTieredSTO Sim', accounts => { + // Accounts Variable declaration + let POLYMATH; + let ISSUER; + let WALLET; + let RESERVEWALLET; + let INVESTOR1; + let ACCREDITED1; + let ACCREDITED2; + let NONACCREDITED1; + let NONACCREDITED2; + let NOTWHITELISTED; + let NOTAPPROVED; + + let MESSAGE = "Transaction Should Fail!"; + const GAS_PRICE = 10000000000; // 10 GWEI + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_USDTieredSTOProxyFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_USDTieredSTOFactory; + let I_USDOracle; + let I_POLYOracle; + let I_STFactory; + let I_MRProxied; + let I_STRProxied; + let I_SecurityToken; + let I_USDTieredSTO_Array = []; + let I_PolyToken; + let I_DaiToken; + let I_PolymathRegistry; + + // SecurityToken Details for funds raise Type ETH + const NAME = "Team"; + const SYMBOL = "SAP"; + const TOKENDETAILS = "This is equity type of issuance"; + const DECIMALS = 18; + + // Module key + const TMKEY = 2; + const STOKEY = 3; + + // Initial fee for ticker registry and security token registry + const REGFEE = web3.utils.toWei("250"); + const STOSetupCost = 0; + + // MockOracle USD prices + const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH + const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY + + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + // STO Configuration Arrays + let _startTime = []; + let _endTime = []; + let _ratePerTier = []; + let _ratePerTierDiscountPoly = []; + let _tokensPerTierTotal = []; + let _tokensPerTierDiscountPoly = []; + let _nonAccreditedLimitUSD = []; + let _minimumInvestmentUSD = []; + let _fundRaiseTypes = []; + let _wallet = []; + let _reserveWallet = []; + let _usdToken = []; + + /* function configure( + uint256 _startTime, + uint256 _endTime, + uint256[] _ratePerTier, + uint256[] _ratePerTierDiscountPoly, + uint256[] _tokensPerTier, + uint256[] _tokensPerTierDiscountPoly, + uint256 _nonAccreditedLimitUSD, + uint256 _minimumInvestmentUSD, + uint8[] _fundRaiseTypes, + address _wallet, + address _reserveWallet, + address _usdToken + ) */ + const functionSignature = { + name: 'configure', + type: 'function', + inputs: [{ + type: 'uint256', + name: '_startTime' + },{ + type: 'uint256', + name: '_endTime' + },{ + type: 'uint256[]', + name: '_ratePerTier' + },{ + type: 'uint256[]', + name: '_ratePerTierDiscountPoly' + },{ + type: 'uint256[]', + name: '_tokensPerTier' + },{ + type: 'uint256[]', + name: '_tokensPerTierDiscountPoly' + },{ + type: 'uint256', + name: '_nonAccreditedLimitUSD' + },{ + type: 'uint256', + name: '_minimumInvestmentUSD' + },{ + type: 'uint8[]', + name: '_fundRaiseTypes' + },{ + type: 'address', + name: '_wallet' + },{ + type: 'address', + name: '_reserveWallet' + },{ + type: 'address', + name: '_usdToken' + }] + }; + + function getRandomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + before(async() => { + // Accounts setup + POLYMATH = accounts[0]; + ISSUER = accounts[1]; + WALLET = accounts[2]; + RESERVEWALLET = WALLET; + ACCREDITED1 = accounts[3]; + ACCREDITED2 = accounts[4]; + NONACCREDITED1 = accounts[5]; + NONACCREDITED2 = accounts[6]; + NOTWHITELISTED = accounts[7]; + NOTAPPROVED = accounts[8]; + INVESTOR1 = accounts[9]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + I_DaiToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: POLYMATH + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + + // STEP 3: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 4: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the proxy + I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); + + // STEP 6: Deploy the USDTieredSTOFactory + + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); + + assert.notEqual( + I_USDTieredSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "USDTieredSTOFactory contract was not deployed" + ); + + + + // Step 8: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 9: Deploy the SecurityTokenRegistry + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: update the registries addresses from the PolymathRegistry contract + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); + await I_MRProxied.updateFromRegistry({from: POLYMATH}); + + // STEP 7: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); + + // (C) : Register the STOFactory + await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); + + // Step 12: Deploy & Register Mock Oracles + I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY + I_POLYOracle = await MockOracle.new(I_PolyToken.address, "POLY", "USD", USDPOLY, { from: POLYMATH }); // 25 cents per POLY + await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); + await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + ModuleRegistry: ${ModuleRegistry.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + USDOracle: ${I_USDOracle.address} + POLYOracle: ${I_POLYOracle.address} + USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} + USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Deploy the STO", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.getTokens(REGFEE, ISSUER); + await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); + let tx = await I_STRProxied.registerTicker(ISSUER, SYMBOL, NAME, { from : ISSUER }); + assert.equal(tx.logs[0].args._owner, ISSUER); + assert.equal(tx.logs[0].args._ticker, SYMBOL); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.getTokens(REGFEE, ISSUER); + await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); + assert.equal(tx.logs[1].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), TMKEY); + assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + it("Should successfully attach the first STO module to the security token", async () => { + let stoId = 0; + + _startTime.push(latestTime() + duration.days(2)); + _endTime.push(_startTime[stoId] + duration.days(100)); + _ratePerTier.push([ + BigNumber(0.05*10**18), BigNumber(0.13*10**18), BigNumber(0.17*10**18) + ]); // [ 0.05 USD/Token, 0.10 USD/Token, 0.15 USD/Token ] + _ratePerTierDiscountPoly.push([ + BigNumber(0.05*10**18), BigNumber(0.08*10**18), BigNumber(0.13*10**18) + ]); // [ 0.05 USD/Token, 0.08 USD/Token, 0.13 USD/Token ] + _tokensPerTierTotal.push([ + BigNumber(200*10**18), BigNumber(500*10**18), BigNumber(300*10**18) + ]); // [ 1000 Token, 2000 Token, 1500 Token ] + _tokensPerTierDiscountPoly.push([ + BigNumber(0), BigNumber(50*10**18), BigNumber(300*10**18) + ]); // [ 0 Token, 1000 Token, 1500 Token ] + _nonAccreditedLimitUSD.push(BigNumber(10*10**18)); // 20 USD + _minimumInvestmentUSD.push(BigNumber(0)); // 1 wei USD + _fundRaiseTypes.push([0,1,2]); + _wallet.push(WALLET); + _reserveWallet.push(RESERVEWALLET); + _usdToken.push(I_DaiToken.address); + + let config = [ + _startTime[stoId], _endTime[stoId], _ratePerTier[stoId], _ratePerTierDiscountPoly[stoId], _tokensPerTierTotal[stoId], + _tokensPerTierDiscountPoly[stoId], _nonAccreditedLimitUSD[stoId], _minimumInvestmentUSD[stoId], + _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], _usdToken[stoId] + ]; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); + console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); + I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + + assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()), _startTime[stoId], "Incorrect _startTime in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()), _endTime[stoId], "Incorrect _endTime in config"); + for (var i = 0; i < _ratePerTier[stoId].length; i++) { + assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), _ratePerTier[stoId][i].toNumber(), "Incorrect _ratePerTier in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), _ratePerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _ratePerTierDiscountPoly in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), _tokensPerTierTotal[stoId][i].toNumber(), "Incorrect _tokensPerTierTotal in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config"); + } + assert.equal((await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), "Incorrect _nonAccreditedLimitUSD in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), _minimumInvestmentUSD[stoId].toNumber(), "Incorrect _minimumInvestmentUSD in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].wallet.call()), _wallet[stoId], "Incorrect _wallet in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].reserveWallet.call()), _reserveWallet[stoId], "Incorrect _reserveWallet in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].getNumberOfTiers()), _tokensPerTierTotal[stoId].length, "Incorrect number of tiers"); + assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); + }); + + it("Should successfully prepare the STO", async() => { + let stoId = 0; + + // Start STO + await increaseTime(duration.days(3)); + + // Whitelist + let fromTime = latestTime() + duration.days(15); + let toTime = latestTime() + duration.days(15); + let expiryTime = toTime + duration.days(100); + let canBuyFromSTO = true; + + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, { from: ISSUER }); + + await increaseTime(duration.days(3)); + + // Accreditation + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1, ACCREDITED2], [true, true], { from: ISSUER }); + await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, NONACCREDITED2], [false, false], { from: ISSUER }); + }); + }); + + describe("Simulate purchasing", async() => { + + it("Should successfully complete simulation", async() => { + let stoId = 0; + + console.log(` + ------------------- Investor Addresses ------------------- + ACCREDITED1: ${ACCREDITED1} + ACCREDITED2: ${ACCREDITED2} + NONACCREDITED1: ${NONACCREDITED1} + NONACCREDITED2: ${NONACCREDITED2} + NOTWHITELISTED: ${NOTWHITELISTED} + NOTAPPROVED: ${NOTAPPROVED} + ---------------------------------------------------------- + `); + + let totalTokens = BigNumber(0); + for (var i = 0; i < _tokensPerTierTotal[stoId].length; i++) { + totalTokens = totalTokens.add(_tokensPerTierTotal[stoId][i]); + } + console.log('totalTokens: '+totalTokens.div(10**18).toNumber()); + let tokensSold = BigNumber(0); + while (true) { + switch (getRandomInt(0,5)) { + case 0: // ACCREDITED1 + await invest(ACCREDITED1, true); + break; + case 1: // ACCREDITED2 + await invest(ACCREDITED2, true); + break; + case 2: // NONACCREDITED1 + let usd_NONACCREDITED1 = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1); + if (_nonAccreditedLimitUSD[stoId].gt(usd_NONACCREDITED1)) // under non-accredited cap + await invest(NONACCREDITED1, false); + else // over non-accredited cap + await investFAIL(NONACCREDITED1); + break; + case 3: // NONACCREDITED2 + let usd_NONACCREDITED2 = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED2); + if (_nonAccreditedLimitUSD[stoId].gt(usd_NONACCREDITED2)) // under non-accredited cap + await invest(NONACCREDITED2, false); + else // over non-accredited cap + await investFAIL(NONACCREDITED2); + break; + case 4: // NOTWHITELISTED + await investFAIL(NOTWHITELISTED); + break; + case 5: // NOTAPPROVED + await investFAIL(NOTAPPROVED); + break; + } + console.log("Next round"); + tokensSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + console.log("Tokens Sold: " + tokensSold.toString()); + if (tokensSold.gte(totalTokens.sub(1*10**18))) { + console.log(`${tokensSold} tokens sold, simulation completed successfully!`.green); + break; + } + } + + async function invest(_investor, _isAccredited) { // need to add check if reached non-accredited cap + let USD_remaining; + if (!_isAccredited) { + let USD_to_date = await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(_investor); + USD_remaining = _nonAccreditedLimitUSD[stoId].sub(USD_to_date); + } else { + USD_remaining = totalTokens.mul(2); + } + + let log_remaining = USD_remaining; + let isPoly = Math.random() >= 0.33; + let isDai = Math.random() >= 0.33; + + let Token_counter = BigNumber(getRandomInt(1*10**10,50*10**10)).mul(10**8); + let investment_USD = BigNumber(0); + let investment_ETH = BigNumber(0); + let investment_POLY = BigNumber(0); + let investment_DAI = BigNumber(0); + let investment_Token = BigNumber(0); + + let Tokens_total = []; + let Tokens_discount = []; + for (var i = 0; i < _ratePerTier[stoId].length; i++) { + Tokens_total.push((await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(i))); + Tokens_discount.push((await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).sub(await I_USDTieredSTO_Array[stoId].mintedPerTierDiscountPoly.call(i))); + } + + let tier = 0; + let Token_Tier; + let USD_Tier; + let POLY_Tier; + let ETH_Tier; + let DAI_Tier; + + + let USD_overflow; + let Token_overflow; + + while (Token_counter.gt(0)) { + if (tier == _ratePerTier[stoId].length) { + break; + } + if (Tokens_total[tier].gt(0)) { + if (isPoly) { + // 1. POLY and discount (consume up to cap then move to regular) + if (Tokens_discount[tier].gt(0)) { + Token_Tier = BigNumber.min([Tokens_total[tier], Tokens_discount[tier], Token_counter]); + USD_Tier = Token_Tier.mul(_ratePerTierDiscountPoly[stoId][tier].div(10**18)); + if (USD_Tier.gte(USD_remaining)) { + USD_overflow = USD_Tier.sub(USD_remaining); + Token_overflow = USD_overflow.mul(10**18).div(_ratePerTierDiscountPoly[stoId][tier]); + USD_Tier = USD_Tier.sub(USD_overflow); + Token_Tier = Token_Tier.sub(Token_overflow); + Token_counter = BigNumber(0); + } + POLY_Tier = USD_Tier.mul(10**18).round(0).div(USDPOLY).round(0); + USD_remaining = USD_remaining.sub(USD_Tier); + Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); + Tokens_discount[tier] = Tokens_discount[tier].sub(Token_Tier); + Token_counter = Token_counter.sub(Token_Tier); + investment_Token = investment_Token.add(Token_Tier); + investment_USD = investment_USD.add(USD_Tier); + investment_POLY = investment_POLY.add(POLY_Tier); + } + // 2. POLY and regular (consume up to cap then skip to next tier) + if (Tokens_total[tier].gt(0) && Token_counter.gt(0)) { + Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); + USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); + if (USD_Tier.gte(USD_remaining)) { + USD_overflow = USD_Tier.sub(USD_remaining); + Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); + USD_Tier = USD_Tier.sub(USD_overflow); + Token_Tier = Token_Tier.sub(Token_overflow); + Token_counter = BigNumber(0); + } + POLY_Tier = USD_Tier.mul(10**18).round(0).div(USDPOLY).round(0); + USD_remaining = USD_remaining.sub(USD_Tier); + Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); + Token_counter = Token_counter.sub(Token_Tier); + investment_Token = investment_Token.add(Token_Tier); + investment_USD = investment_USD.add(USD_Tier); + investment_POLY = investment_POLY.add(POLY_Tier); + } + } else if (isDai) { + // 3. DAI (consume up to cap then skip to next tier) + Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); + USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); + if (USD_Tier.gte(USD_remaining)) { + USD_overflow = USD_Tier.sub(USD_remaining); + Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); + USD_Tier = USD_Tier.sub(USD_overflow); + Token_Tier = Token_Tier.sub(Token_overflow); + Token_counter = BigNumber(0); + } + DAI_Tier = USD_Tier.round(0); + USD_remaining = USD_remaining.sub(USD_Tier); + Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); + Token_counter = Token_counter.sub(Token_Tier); + investment_Token = investment_Token.add(Token_Tier); + investment_USD = investment_USD.add(USD_Tier); + investment_DAI = investment_USD; + } else { + // 4. ETH (consume up to cap then skip to next tier) + Token_Tier = BigNumber.min([Tokens_total[tier], Token_counter]); + USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10**18)); + if (USD_Tier.gte(USD_remaining)) { + USD_overflow = USD_Tier.sub(USD_remaining); + Token_overflow = USD_overflow.mul(10**18).div(_ratePerTier[stoId][tier]); + USD_Tier = USD_Tier.sub(USD_overflow); + Token_Tier = Token_Tier.sub(Token_overflow); + Token_counter = BigNumber(0); + } + ETH_Tier = USD_Tier.mul(10**18).round(0).div(USDETH).round(0); + USD_remaining = USD_remaining.sub(USD_Tier); + Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); + Token_counter = Token_counter.sub(Token_Tier); + investment_Token = investment_Token.add(Token_Tier); + investment_USD = investment_USD.add(USD_Tier); + investment_ETH = investment_ETH.add(ETH_Tier); + } + } + tier++ + } + + await processInvestment(_investor, investment_Token, investment_USD, investment_POLY, investment_DAI, investment_ETH, isPoly, isDai, log_remaining, Tokens_total, Tokens_discount, tokensSold); + } + + async function investFAIL(_investor) { + let isPoly = Math.random() >= 0.3; + let isDAI = Math.random() >= 0.3; + let investment_POLY = BigNumber(40*10**18); // 10 USD = 40 POLY + let investment_ETH = BigNumber(0.02*10**18); // 10 USD = 0.02 ETH + let investment_DAI = BigNumber(10*10**18); // 10 USD = DAI DAI + + let errorThrown = false; + try { + if (isPoly) { + await I_PolyToken.getTokens(investment_POLY, _investor); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: _investor}); + await I_USDTieredSTO_Array[stoId].buyWithPOLY(_investor, investment_POLY, { from: _investor, gasPrice: GAS_PRICE }); + } else if (isDAI) { + await I_DaiToken.getTokens(investment_DAI, _investor); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: _investor}); + await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); + } else await I_USDTieredSTO_Array[stoId].buyWithETH(_investor, { from: _investor, value: investment_ETH, gasPrice: GAS_PRICE }); + } catch(error) { + errorThrown = true; + console.log(`Purchase failed as expected: ${_investor}`.yellow); + ensureException(error); + } + assert.ok(errorThrown, MESSAGE); + } + + async function processInvestment(_investor, investment_Token, investment_USD, investment_POLY, investment_DAI, investment_ETH, isPoly, isDai, log_remaining, Tokens_total, Tokens_discount, tokensSold) { + investment_Token = investment_Token.round(0); + investment_USD = investment_USD.round(0); + investment_POLY = investment_POLY.round(0); + investment_DAI = investment_DAI.round(0); + investment_ETH = investment_ETH.round(0); + console.log(` + ------------------- New Investment ------------------- + Investor: ${_investor} + N-A USD Remaining: ${log_remaining.div(10**18)} + Total Cap Remaining: ${Tokens_total} + Discount Cap Remaining: ${Tokens_discount} + Total Tokens Sold: ${tokensSold.div(10**18)} + Token Investment: ${investment_Token.div(10**18)} + USD Investment: ${investment_USD.div(10**18)} + POLY Investment: ${investment_POLY.div(10**18)} + DAI Investment: ${investment_DAI.div(10**18)} + ETH Investment: ${investment_ETH.div(10**18)} + ------------------------------------------------------ + `); + + if (isPoly) { + await I_PolyToken.getTokens(investment_POLY, _investor); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, {from: _investor}); + } else if (isDai) { + await I_DaiToken.getTokens(investment_DAI, _investor); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, {from: _investor}); + } + + // console.log(await I_USDTieredSTO_Array[stoId].isOpen()); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(_investor); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(_investor)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(_investor); + let init_InvestorDAIBal = await I_DaiToken.balanceOf(_investor); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_STODAIBal = await I_DaiToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(0); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(1); + let init_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(2); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + + let tx; + let gasCost = BigNumber(0); + + if (isPoly && investment_POLY.gt(10)) { + tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(_investor, investment_POLY, { from: _investor, gasPrice: GAS_PRICE }); + gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); + console.log(`buyWithPOLY: ${investment_Token.div(10**18)} tokens for ${investment_POLY.div(10**18)} POLY by ${_investor}`.yellow); + } else if (isDai && investment_DAI.gt(10)) { + tx = await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); + gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); + console.log(`buyWithUSD: ${investment_Token.div(10**18)} tokens for ${investment_DAI.div(10**18)} DAI by ${_investor}`.yellow); + } else if (investment_ETH.gt(0)) { + tx = await I_USDTieredSTO_Array[stoId].buyWithETH(_investor, { from: _investor, value: investment_ETH, gasPrice: GAS_PRICE }); + gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); + console.log(`buyWithETH: ${investment_Token.div(10**18)} tokens for ${investment_ETH.div(10**18)} ETH by ${_investor}`.yellow); + } + console.log(investment_POLY.toNumber()); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(_investor); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(_investor)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(_investor); + let final_InvestorDAIBal = await I_DaiToken.balanceOf(_investor); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_STODAIBal = await I_DaiToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedUSD = await I_USDTieredSTO_Array[stoId].fundsRaisedUSD.call(); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(0); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(1); + let final_RaisedDAI = await I_USDTieredSTO_Array[stoId].fundsRaised.call(2); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); + + // console.log('init_TokenSupply: '+init_TokenSupply.div(10**18).toNumber()); + // console.log('final_TokenSupply: '+final_TokenSupply.div(10**18).toNumber()); + + if (isPoly) { + assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); + assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); + assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); + assert.closeTo(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.sub(investment_POLY).toNumber(), TOLERANCE, "Investor POLY Balance not changed as expected"); + assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); + assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); + assert.closeTo(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), TOLERANCE, "STO POLY Balance not changed as expected"); + assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); + assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), TOLERANCE, "Raised ETH not changed as expected"); + assert.closeTo(final_RaisedPOLY.toNumber(), init_RaisedPOLY.add(investment_POLY).toNumber(), TOLERANCE, "Raised POLY not changed as expected"); + assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); + assert.closeTo(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.add(investment_POLY).toNumber(), TOLERANCE, "Wallet POLY Balance not changed as expected"); + } else if (isDai) { + assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); + assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); + assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); + assert.closeTo(final_InvestorDAIBal.toNumber(), init_InvestorDAIBal.sub(investment_DAI).toNumber(), TOLERANCE, "Investor DAI Balance not changed as expected"); + assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); + assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); + assert.closeTo(final_STODAIBal.toNumber(), init_STODAIBal.toNumber(), TOLERANCE, "STO DAI Balance not changed as expected"); + assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); + assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), TOLERANCE, "Raised ETH not changed as expected"); + assert.closeTo(final_RaisedDAI.toNumber(), init_RaisedDAI.add(investment_DAI).toNumber(), TOLERANCE, "Raised DAI not changed as expected"); + assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); + assert.closeTo(final_WalletDAIBal.toNumber(), init_WalletDAIBal.add(investment_DAI).toNumber(), TOLERANCE, "Wallet DAI Balance not changed as expected"); + } else { + assert.closeTo(final_TokenSupply.toNumber(), init_TokenSupply.add(investment_Token).toNumber(), TOLERANCE, "Token Supply not changed as expected"); + assert.closeTo(final_InvestorTokenBal.toNumber(), init_InvestorTokenBal.add(investment_Token).toNumber(), TOLERANCE, "Investor Token Balance not changed as expected"); + assert.closeTo(final_InvestorETHBal.toNumber(), init_InvestorETHBal.sub(gasCost).sub(investment_ETH).toNumber(), TOLERANCE, "Investor ETH Balance not changed as expected"); + assert.closeTo(final_InvestorPOLYBal.toNumber(), init_InvestorPOLYBal.toNumber(), TOLERANCE, "Investor POLY Balance not changed as expected"); + assert.closeTo(final_STOTokenSold.toNumber(), init_STOTokenSold.add(investment_Token).toNumber(), TOLERANCE, "STO Token Sold not changed as expected"); + assert.closeTo(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), TOLERANCE, "STO ETH Balance not changed as expected"); + assert.closeTo(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), TOLERANCE, "STO POLY Balance not changed as expected"); + assert.closeTo(final_RaisedUSD.toNumber(), init_RaisedUSD.add(investment_USD).toNumber(), TOLERANCE, "Raised USD not changed as expected"); + assert.closeTo(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).toNumber(), TOLERANCE, "Raised ETH not changed as expected"); + assert.closeTo(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), TOLERANCE, "Raised POLY not changed as expected"); + assert.closeTo(final_WalletETHBal.toNumber(), init_WalletETHBal.add(investment_ETH).toNumber(), TOLERANCE, "Wallet ETH Balance not changed as expected"); + assert.closeTo(final_WalletPOLYBal.toNumber(), init_WalletPOLYBal.toNumber(), TOLERANCE, "Wallet POLY Balance not changed as expected"); + } + } + }); + }); +}); + +function near(x, y, message) { + assert.isAtMost(x, y) + +} diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 592c5cc1c..569534cad 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -1,365 +1,365 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// // Import contract ABIs -// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -// const CappedSTO = artifacts.require('./CappedSTO.sol'); -// const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); -// const DummySTO = artifacts.require('./DummySTO.sol'); -// const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); -// const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('Concurrent STO', accounts => { -// // Accounts variable declaration -// let account_polymath; -// let account_issuer; -// let account_fundsReceiver; -// let account_investor1; -// let account_investor2; -// let account_investor3; - -// // Contract instance declaration -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManagerFactory; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_STFactory; -// let I_MRProxied; -// let I_STRProxied; -// let I_SecurityTokenRegistry; -// let I_SecurityToken; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // STO instance declaration -// let I_CappedSTOFactory; -// let I_DummySTOFactory; -// let I_PreSaleSTOFactory; -// let I_STO_Array = []; - -// // Error message -// let message = "Transaction Should Fail!"; - -// // Initial fees -// const initRegFee = web3.utils.toWei("250"); -// const STOSetupCost = 200 * Math.pow(10, 18); - -// // Module keys -// const transferManagerKey = 2; -// const stoKey = 3; - -// // Configure function signature for STO deployment - -// const CappedSTOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; -// const DummySTOParameters = ['uint256', 'uint256', 'uint256', 'string']; -// const PresaleSTOParameters = ['uint256']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; -// account_fundsReceiver = accounts[2]; -// account_investor1 = accounts[3]; -// account_investor2 = accounts[4]; -// account_investor3 = accounts[5] - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_issuer); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 2: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 3: Deploy the GeneralPermissionManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the STO Factories - -// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); -// I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); -// I_PreSaleSTOFactory = await PreSaleSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); - -// assert.notEqual( -// I_CappedSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CappedSTOFactory contract was not deployed" -// ); - - -// // Step 8: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +// Import contract ABIs +const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +const CappedSTO = artifacts.require('./CappedSTO.sol'); +const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); +const DummySTO = artifacts.require('./DummySTO.sol'); +const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); +const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('Concurrent STO', accounts => { + // Accounts variable declaration + let account_polymath; + let account_issuer; + let account_fundsReceiver; + let account_investor1; + let account_investor2; + let account_investor3; + + // Contract instance declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralPermissionManager; + let I_GeneralTransferManagerFactory; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_STFactory; + let I_MRProxied; + let I_STRProxied; + let I_SecurityTokenRegistry; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + // STO instance declaration + let I_CappedSTOFactory; + let I_DummySTOFactory; + let I_PreSaleSTOFactory; + let I_STO_Array = []; + + // Error message + let message = "Transaction Should Fail!"; + + // Initial fees + const initRegFee = web3.utils.toWei("250"); + const STOSetupCost = 200 * Math.pow(10, 18); + + // Module keys + const transferManagerKey = 2; + const stoKey = 3; + + // Configure function signature for STO deployment + + const CappedSTOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + const DummySTOParameters = ['uint256', 'uint256', 'uint256', 'string']; + const PresaleSTOParameters = ['uint256']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + account_fundsReceiver = accounts[2]; + account_investor1 = accounts[3]; + account_investor2 = accounts[4]; + account_investor3 = accounts[5] + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_issuer); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 2: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 3: Deploy the GeneralPermissionManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 4: Deploy the STO Factories + + I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); + I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); + I_PreSaleSTOFactory = await PreSaleSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: account_issuer }); + + assert.notEqual( + I_CappedSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CappedSTOFactory contract was not deployed" + ); + + + // Step 8: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); -// // Step 9: Deploy the SecurityTokenRegistry contract + // Step 9: Deploy the SecurityTokenRegistry contract -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 5: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the STO Factories -// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - -// await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - -// await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - -// CappedSTOFactory: ${I_CappedSTOFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate Security Token", async() => { -// // SecurityToken Details for funds raise Type ETH -// const name = "Team"; -// const symbol = "SAP"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.getTokens(initRegFee, account_issuer); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_issuer }); -// let tx = await I_STRProxied.registerTicker(account_issuer, symbol, name, { from : account_issuer }); -// assert.equal(tx.logs[0].args._owner, account_issuer); -// assert.equal(tx.logs[0].args._ticker, symbol); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.getTokens(initRegFee, account_issuer); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_issuer}); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_issuer }); -// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), transferManagerKey); -// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); - -// it("Should whitelist account_investor1", async() => { -// let fromTime = latestTime(); -// let toTime = latestTime() + duration.days(15); -// let expiryTime = toTime + duration.days(100); -// let canBuyFromSTO = true; - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// fromTime, -// toTime, -// expiryTime, -// canBuyFromSTO, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); -// }); -// }); - -// describe("Add STO and verify transfer", async() => { - -// it("Should attach STO modules up to the max number, then fail", async() => { -// const MAX_MODULES = 10; -// const startTime = latestTime() + duration.days(1); -// const endTime = latestTime() + duration.days(90); -// const cap = web3.utils.toWei("10000"); -// const rate = 1000; -// const fundRaiseType = [0]; -// const budget = 0; -// const maxCost = STOSetupCost; -// const cappedBytesSig = encodeModuleCall(CappedSTOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); -// const dummyBytesSig = encodeModuleCall(DummySTOParameters, [startTime, endTime, cap, 'Hello']); -// const presaleBytesSig = encodeModuleCall(PresaleSTOParameters, [endTime]); - -// for (var STOIndex = 0; STOIndex < MAX_MODULES; STOIndex++) { -// await I_PolyToken.getTokens(STOSetupCost, account_issuer); -// await I_PolyToken.transfer(I_SecurityToken.address, STOSetupCost, { from: account_issuer }); -// switch (STOIndex % 3) { -// case 0: -// // Capped STO -// let tx1 = await I_SecurityToken.addModule(I_CappedSTOFactory.address, cappedBytesSig, maxCost, budget, { from: account_issuer }); -// assert.equal(tx1.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); -// assert.equal(web3.utils.hexToString(tx1.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); -// I_STO_Array.push(CappedSTO.at(tx1.logs[3].args._module)); -// break; -// case 1: -// // Dummy STO -// let tx2 = await I_SecurityToken.addModule(I_DummySTOFactory.address, dummyBytesSig, maxCost, budget, { from: account_issuer }); -// assert.equal(tx2.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); -// assert.equal(web3.utils.hexToString(tx2.logs[3].args._name),"DummySTO",`Wrong STO module added at index ${STOIndex}`); -// I_STO_Array.push(DummySTO.at(tx2.logs[3].args._module)); -// break; -// case 2: -// // Pre Sale STO -// let tx3 = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, presaleBytesSig, maxCost, budget, { from: account_issuer }); -// assert.equal(tx3.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); -// assert.equal(web3.utils.hexToString(tx3.logs[3].args._name),"PreSaleSTO",`Wrong STO module added at index ${STOIndex}`); -// I_STO_Array.push(PreSaleSTO.at(tx3.logs[3].args._module)); -// break; -// } -// } - -// }); - -// it("Should successfully invest in all modules attached", async() => { -// const MAX_MODULES = 10; -// await increaseTime(duration.days(2)); -// for (var STOIndex = 0; STOIndex < MAX_MODULES; STOIndex++) { -// switch (STOIndex % 3) { -// case 0: -// // Capped STO ETH -// await I_STO_Array[STOIndex].buyTokens(account_investor1, { from : account_investor1, value: web3.utils.toWei('1', 'ether') }); -// assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(0)).toString()), 1); -// assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); -// break; -// case 1: -// // Dummy STO -// await I_STO_Array[STOIndex].generateTokens(account_investor1, web3.utils.toWei('1000'), { from : account_issuer }); -// assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); -// assert.equal( -// (await I_STO_Array[STOIndex].investors.call(account_investor1)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000 -// ); -// break; -// case 2: -// // Pre Sale STO -// await I_STO_Array[STOIndex].allocateTokens(account_investor1, web3.utils.toWei('1000'), web3.utils.toWei('1'), 0, { from : account_issuer }); -// assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(0)).toString()), 1); -// assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(1)).toString()), 0); -// assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); -// assert.equal( -// (await I_STO_Array[STOIndex].investors.call(account_investor1)) -// .dividedBy(new BigNumber(10).pow(18)) -// .toNumber(), -// 1000 -// ); -// break; -// } -// } -// }); -// }); -// }); + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 5: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the STO Factories + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + + await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); + + await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + + CappedSTOFactory: ${I_CappedSTOFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate Security Token", async() => { + // SecurityToken Details for funds raise Type ETH + const name = "Team"; + const symbol = "SAP"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.getTokens(initRegFee, account_issuer); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_issuer }); + let tx = await I_STRProxied.registerTicker(account_issuer, symbol, name, { from : account_issuer }); + assert.equal(tx.logs[0].args._owner, account_issuer); + assert.equal(tx.logs[0].args._ticker, symbol); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.getTokens(initRegFee, account_issuer); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_issuer}); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_issuer }); + assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), transferManagerKey); + assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + it("Should whitelist account_investor1", async() => { + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(15); + let expiryTime = toTime + duration.days(100); + let canBuyFromSTO = true; + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + fromTime, + toTime, + expiryTime, + canBuyFromSTO, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); + }); + }); + + describe("Add STO and verify transfer", async() => { + + it("Should attach STO modules up to the max number, then fail", async() => { + const MAX_MODULES = 10; + const startTime = latestTime() + duration.days(1); + const endTime = latestTime() + duration.days(90); + const cap = web3.utils.toWei("10000"); + const rate = 1000; + const fundRaiseType = [0]; + const budget = 0; + const maxCost = STOSetupCost; + const cappedBytesSig = encodeModuleCall(CappedSTOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + const dummyBytesSig = encodeModuleCall(DummySTOParameters, [startTime, endTime, cap, 'Hello']); + const presaleBytesSig = encodeModuleCall(PresaleSTOParameters, [endTime]); + + for (var STOIndex = 0; STOIndex < MAX_MODULES; STOIndex++) { + await I_PolyToken.getTokens(STOSetupCost, account_issuer); + await I_PolyToken.transfer(I_SecurityToken.address, STOSetupCost, { from: account_issuer }); + switch (STOIndex % 3) { + case 0: + // Capped STO + let tx1 = await I_SecurityToken.addModule(I_CappedSTOFactory.address, cappedBytesSig, maxCost, budget, { from: account_issuer }); + assert.equal(tx1.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); + assert.equal(web3.utils.hexToString(tx1.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); + I_STO_Array.push(CappedSTO.at(tx1.logs[3].args._module)); + break; + case 1: + // Dummy STO + let tx2 = await I_SecurityToken.addModule(I_DummySTOFactory.address, dummyBytesSig, maxCost, budget, { from: account_issuer }); + assert.equal(tx2.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); + assert.equal(web3.utils.hexToString(tx2.logs[3].args._name),"DummySTO",`Wrong STO module added at index ${STOIndex}`); + I_STO_Array.push(DummySTO.at(tx2.logs[3].args._module)); + break; + case 2: + // Pre Sale STO + let tx3 = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, presaleBytesSig, maxCost, budget, { from: account_issuer }); + assert.equal(tx3.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); + assert.equal(web3.utils.hexToString(tx3.logs[3].args._name),"PreSaleSTO",`Wrong STO module added at index ${STOIndex}`); + I_STO_Array.push(PreSaleSTO.at(tx3.logs[3].args._module)); + break; + } + } + + }); + + it("Should successfully invest in all modules attached", async() => { + const MAX_MODULES = 10; + await increaseTime(duration.days(2)); + for (var STOIndex = 0; STOIndex < MAX_MODULES; STOIndex++) { + switch (STOIndex % 3) { + case 0: + // Capped STO ETH + await I_STO_Array[STOIndex].buyTokens(account_investor1, { from : account_investor1, value: web3.utils.toWei('1', 'ether') }); + assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(0)).toString()), 1); + assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); + break; + case 1: + // Dummy STO + await I_STO_Array[STOIndex].generateTokens(account_investor1, web3.utils.toWei('1000'), { from : account_issuer }); + assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); + assert.equal( + (await I_STO_Array[STOIndex].investors.call(account_investor1)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000 + ); + break; + case 2: + // Pre Sale STO + await I_STO_Array[STOIndex].allocateTokens(account_investor1, web3.utils.toWei('1000'), web3.utils.toWei('1'), 0, { from : account_issuer }); + assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(0)).toString()), 1); + assert.equal(web3.utils.fromWei((await I_STO_Array[STOIndex].getRaised.call(1)).toString()), 0); + assert.equal(await I_STO_Array[STOIndex].investorCount.call(), 1); + assert.equal( + (await I_STO_Array[STOIndex].investors.call(account_investor1)) + .dividedBy(new BigNumber(10).pow(18)) + .toNumber(), + 1000 + ); + break; + } + } + }); + }); +}); diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js index ee367a2a8..f4dee4bf2 100644 --- a/test/s_v130_to_v140_upgrade.js +++ b/test/s_v130_to_v140_upgrade.js @@ -1,532 +1,532 @@ -// const Web3 = require('web3'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -// const BigNumber = require('bignumber.js'); - -// import latestTime from './helpers/latestTime'; -// import { duration } from './helpers/utils'; -// import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); -// const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); -// const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); -// const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); -// const CappedSTO = artifacts.require('./CappedSTO.sol'); -// const PolyOracle = artifacts.require('./PolyOracle.sol'); -// const ETHOracle = artifacts.require('./MakerDAOOracle.sol'); -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); -// const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol'); - -// contract('Upgrade from v1.3.0 to v1.4.0', accounts => { -// // Accounts Variable declaration -// let POLYMATH; -// let ISSUER1; -// let ISSUER2; -// let ISSUER3; -// let MULTISIG; - -// //const GAS_PRICE = 10000000000; // 10 GWEI - -// let tx; - -// // Initial fee for ticker registry and security token registry -// const REGFEE = web3.utils.toWei("250"); -// const STOSetupCost = 0; - -// // Module key -// const STOKEY = 3; -// const TMKEY = 2; - -// // SecurityToken 1 Details -// const symbol1 = "TOK1"; -// const name1 = "TOK1 Token"; -// const tokenDetails1 = "This is equity type of issuance"; - -// //SecurityToken 2 Details -// const symbol2 = "TOK2"; -// const name2 = "TOK2 Token"; -// const tokenDetails2 = "This is equity type of issuance"; - -// //SecurityToken 3 Details -// const symbol3 = "TOK3"; -// const name3 = "TOK3 Token"; -// const tokenDetails3 = "This is equity type of issuance"; - -// // Contract Instance Declaration -// let I_PolymathRegistry; -// let I_PolyToken; -// let I_DaiToken; -// let I_ModuleRegistry; -// let I_ModuleRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_FeatureRegistry; -// let I_STFactory; -// let I_MRProxied; -// let I_STRProxied; -// let I_STRProxiedNew; - -// let I_SecurityTokenRegistry; -// //let I_UpgradedSecurityTokenRegistry - -// let I_SecurityToken1; -// let I_SecurityToken2; -// //let I_SecurityToken3; - -// let I_USDTieredSTOFactory; -// let I_USDTieredSTOProxyFactory -// let I_USDOracle; -// let I_POLYOracle; -// let I_USDTieredSTO; - -// let I_CappedSTOFactory; -// let I_UpgradedCappedSTOFactory; -// let I_CappedSTO; -// let I_ManualApprovalTransferManagerFactory; - -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; -// const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; -// // Prepare polymath network status -// before(async() => { -// // Accounts setup -// POLYMATH = accounts[0]; -// ISSUER1 = accounts[1]; -// ISSUER2 = accounts[2]; -// ISSUER3 = accounts[3]; -// MULTISIG = accounts[4]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); -// assert.notEqual( -// I_PolymathRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "PolymathRegistry contract was not deployed" -// ); - -// // Step 1: Deploy the token Faucet -// I_PolyToken = await PolyTokenFaucet.new({from: POLYMATH}); -// I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); -// assert.notEqual( -// I_PolyToken.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "PolyToken contract was not deployed" -// ); -// tx = await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) -// assert.equal(tx.logs[0].args._nameKey, "PolyToken"); -// assert.equal(tx.logs[0].args._newAddress, I_PolyToken.address); - -// // STEP 2: Deploy the ModuleRegistry -// I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// tx = await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); -// assert.equal(tx.logs[0].args._nameKey, "ModuleRegistry"); -// assert.equal(tx.logs[0].args._newAddress, I_ModuleRegistryProxy.address); - -// // STEP 3: Deploy the GeneralTransferManagerFactory -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the GeneralDelegateManagerFactory -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the CappedSTOFactory -// I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); -// assert.notEqual( -// I_CappedSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CappedSTOFactory contract was not deployed" -// ); - -// // Step 8: Deploy the STFactory contract -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 9: Deploy the SecurityTokenRegistry - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 10: update the registries addresses from the PolymathRegistry contract -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 10: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: POLYMATH -// }); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); - -// assert.notEqual( -// I_FeatureRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "FeatureRegistry contract was not deployed", -// ); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: POLYMATH}); -// await I_MRProxied.updateFromRegistry({from: POLYMATH}); - -// // STEP 6: Register the Modules with the ModuleRegistry contract -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); - -// // (C) : Register the CappedSTOFactory -// await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: POLYMATH }); -// await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: POLYMATH }); - -// // Step 12: Mint tokens to ISSUERs -// await I_PolyToken.getTokens(REGFEE * 2, ISSUER1); -// await I_PolyToken.getTokens(REGFEE * 2, ISSUER2); -// await I_PolyToken.getTokens(REGFEE * 2, ISSUER3); - -// // Step 13: Register tokens -// // (A) : TOK1 -// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER1 }); -// tx = await I_STRProxied.registerTicker(ISSUER1, symbol1, name1, { from : ISSUER1 }); -// assert.equal(tx.logs[0].args._owner, ISSUER1); -// assert.equal(tx.logs[0].args._ticker, symbol1); - -// // (B) : TOK2 -// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER2 }); -// tx = await I_STRProxied.registerTicker(ISSUER2, symbol2, name2, { from : ISSUER2 }); -// assert.equal(tx.logs[0].args._owner, ISSUER2); -// assert.equal(tx.logs[0].args._ticker, symbol2); - -// // (C) : TOK3 -// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER3 }); -// tx = await I_STRProxied.registerTicker(ISSUER3, symbol3, name3, { from : ISSUER3 }); -// assert.equal(tx.logs[0].args._owner, ISSUER3); -// assert.equal(tx.logs[0].args._ticker, symbol3); - -// // Step 14: Deploy tokens -// // (A) : TOK1 -// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER1}); -// let tx = await I_STRProxied.generateSecurityToken(name1, symbol1, tokenDetails1, false, { from: ISSUER1 }); -// assert.equal(tx.logs[1].args._ticker, symbol1, "SecurityToken doesn't get deployed"); -// I_SecurityToken1 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// // (B) : TOK2 -// await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER2}); -// tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails2, false, { from: ISSUER2 }); -// assert.equal(tx.logs[1].args._ticker, symbol2, "SecurityToken doesn't get deployed"); -// I_SecurityToken2 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// ModuleRegistry: ${ModuleRegistry.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// SecurityToken TOK1: ${I_SecurityToken1.address} -// SecurityToken TOK2: ${I_SecurityToken2.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("USDTieredSTOFactory deploy", async() => { -// // Step 1: Deploy Oracles -// // 1a - Deploy POLY Oracle -// it("Should successfully deploy POLY Oracle and register on PolymathRegistry", async() => { -// I_POLYOracle = await PolyOracle.new({ from: POLYMATH, value: web3.utils.toWei("1")}); -// console.log(I_POLYOracle.address); -// assert.notEqual( -// I_POLYOracle.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "POLYOracle contract was not deployed", -// ); -// tx = await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); -// assert.equal(tx.logs[0].args._nameKey, "PolyUsdOracle"); -// assert.equal(tx.logs[0].args._newAddress, I_POLYOracle.address); -// }); -// // 1b - Deploy ETH Oracle -// it("Should successfully deploy ETH Oracle and register on PolymathRegistry", async() => { -// I_USDOracle = await ETHOracle.new("0x216d678c14be600cb88338e763bb57755ca2b1cf", "0x0000000000000000000000000000000000000000", "ETH", { from: POLYMATH }); -// assert.notEqual( -// I_USDOracle.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "USDOracle contract was not deployed", -// ); -// tx = await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); -// assert.equal(tx.logs[0].args._nameKey, "EthUsdOracle"); -// assert.equal(tx.logs[0].args._newAddress, I_USDOracle.address); -// }); -// }); - -// describe("USDTieredSTOFactory deploy", async() => { -// // Step 1: Deploy USDTieredSTOFactory\ -// it("Should successfully deploy USDTieredSTOFactory", async() => { -// I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new(); -// I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: POLYMATH }); -// assert.notEqual( -// I_USDTieredSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "USDTieredSTOFactory contract was not deployed" -// ); -// let setupCost = await I_USDTieredSTOFactory.setupCost({ from: POLYMATH }); -// assert.equal(setupCost, STOSetupCost); -// }); -// // Step 2: Register and verify -// it("Should successfully register and verify USDTieredSTOFactory contract", async() => { -// let tx = await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); -// assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); -// tx = await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); -// assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); -// assert.isTrue(tx.logs[0].args._verified); -// }); -// }); - -// describe("CappedSTOFactory deploy", async() => { -// // Step 1: Deploy new CappedSTOFactory -// it("Should successfully deploy CappedSTOFactory", async() => { -// I_UpgradedCappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); -// assert.notEqual( -// I_UpgradedCappedSTOFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "CappedSTOFactory contract was not deployed" -// ); -// let setupCost = await I_UpgradedCappedSTOFactory.setupCost({ from: POLYMATH }); -// assert.equal(setupCost, STOSetupCost); -// }); - -// // Step 2: Register and verify -// it("Should successfully register and verify new CappedSTOFactory contract", async() => { -// let tx = await I_MRProxied.registerModule(I_UpgradedCappedSTOFactory.address, { from: POLYMATH }); -// assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); -// tx = await I_MRProxied.verifyModule(I_UpgradedCappedSTOFactory.address, true, { from: POLYMATH }); -// assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); -// assert.isTrue(tx.logs[0].args._verified); -// }); - -// // Step 3: Unverify old CappedSTOFactory -// it("Should successfully unverify old CappedSTOFactory contract", async() => { -// let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory.address, false, { from: POLYMATH }); -// assert.equal(tx.logs[0].args._moduleFactory, I_CappedSTOFactory.address); -// assert.isFalse(tx.logs[0].args._verified); -// }); -// }); - -// describe("ManualApprovalTransferManagerFactory deploy", async() => { -// // Step 1: Deploy new ManualApprovalTransferManager -// it("Should successfully deploy ManualApprovalTransferManagerFactory", async() => { -// I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); -// assert.notEqual( -// I_ManualApprovalTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "ManualApprovalTransferManagerFactory contract was not deployed" -// ); -// }); - -// // Step 2: Register and verify -// it("Should successfully register and verify new ManualApprovalTransferManagerFactory contract", async() => { -// let tx = await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: POLYMATH }); -// assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); -// tx = await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: POLYMATH }); -// assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); -// assert.isTrue(tx.logs[0].args._verified); -// }); -// }); - -// describe("Change ownerships", async() => { -// /* -// // Step 1: SecurityTokenRegistry -// it("Should successfully change ownership of new SecurityTokenRegistry contract", async() => { -// let tx = await I_STRProxiedNew.transferOwnership(MULTISIG, { from: POLYMATH }); -// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous owner was not Polymath account"); -// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New owner is not Multisig account"); -// }); -// */ - -// // Step 2: Oracles -// it("Should successfully change ownership of both Oracles contract", async() => { -// let tx = await I_USDOracle.transferOwnership(MULTISIG, { from: POLYMATH }); -// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous ETH Oracle owner was not Polymath account"); -// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New ETH Oracle owner is not Multisig account"); - -// tx = await I_POLYOracle.transferOwnership(MULTISIG, { from: POLYMATH }); -// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous POLY Oracle owner was not Polymath account"); -// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New POLY Oracle owner is not Multisig account"); -// }); - -// // Step 3: USDTieredSTOFactory -// it("Should successfully change ownership of USDTieredSTOFactory contract", async() => { -// let tx = await I_USDTieredSTOFactory.transferOwnership(MULTISIG, { from: POLYMATH }); -// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous USDTieredSTOFactory owner was not Polymath account"); -// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New USDTieredSTOFactory owner is not Multisig account"); -// }); - -// // Step 3: CappedSTOFactory -// it("Should successfully change ownership of CappedSTOFactory contract", async() => { -// let tx = await I_UpgradedCappedSTOFactory.transferOwnership(MULTISIG, { from: POLYMATH }); -// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous USDTieredSTOFactory owner was not Polymath account"); -// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New USDTieredSTOFactory owner is not Multisig account"); -// }); - -// // Step 4: ManualApprovalTransferManagerFactory -// it("Should successfully change ownership of ManualApprovalTransferManagerFactory contract", async() => { -// let tx = await I_ManualApprovalTransferManagerFactory.transferOwnership(MULTISIG, { from: POLYMATH }); -// assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous ManualApprovalTransferManagerFactory owner was not Polymath account"); -// assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New ManualApprovalTransferManagerFactory owner is not Multisig account"); -// }); -// }); - -// describe("Polymath network status post migration", async() => { -// // Launch STO for TOK1 -// it("Should successfully launch USDTieredSTO for first security token", async() => { -// let _startTime = latestTime() + duration.days(1); -// let _endTime = _startTime + duration.days(180); -// let _ratePerTier = [BigNumber(0.1).mul(10**18), BigNumber(0.15).mul(10**18), BigNumber(0.2).mul(10**18)]; -// let _ratePerTierDiscountPoly = [BigNumber(0), BigNumber(0), BigNumber(0)]; -// let _tokensPerTierTotal = [BigNumber(100).mul(10**18), BigNumber(200).mul(10**18), BigNumber(300).mul(10**18)]; -// let _tokensPerTierDiscountPoly = [BigNumber(0), BigNumber(0), BigNumber(0)]; -// let _nonAccreditedLimitUSD = BigNumber(100).mul(10**18); -// let _minimumInvestmentUSD = BigNumber(5).mul(10**18); -// let _fundRaiseTypes = [0, 1]; -// let _wallet = ISSUER1; -// let _reserveWallet = ISSUER1; -// let _usdToken = I_DaiToken.address; - -// let config = [ -// _startTime, _endTime, _ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, -// _tokensPerTierDiscountPoly, _nonAccreditedLimitUSD, _minimumInvestmentUSD, -// _fundRaiseTypes, _wallet, _reserveWallet, _usdToken -// ]; - -// let functionSignature = { -// name: 'configure', -// type: 'function', -// inputs: [{ -// type: 'uint256', -// name: '_startTime' -// },{ -// type: 'uint256', -// name: '_endTime' -// },{ -// type: 'uint256[]', -// name: '_ratePerTier' -// },{ -// type: 'uint256[]', -// name: '_ratePerTierDiscountPoly' -// },{ -// type: 'uint256[]', -// name: '_tokensPerTier' -// },{ -// type: 'uint256[]', -// name: '_tokensPerTierDiscountPoly' -// },{ -// type: 'uint256', -// name: '_nonAccreditedLimitUSD' -// },{ -// type: 'uint256', -// name: '_minimumInvestmentUSD' -// },{ -// type: 'uint8[]', -// name: '_fundRaiseTypes' -// },{ -// type: 'address', -// name: '_wallet' -// },{ -// type: 'address', -// name: '_reserveWallet' -// },{ -// type: 'address', -// name: '_usdToken' -// }] -// }; - -// let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - -// let tx = await I_SecurityToken1.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER1 }); -// assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); -// I_USDTieredSTO = USDTieredSTO.at(tx.logs[2].args._module); -// }); - -// /* -// // Deploy TOK3 -// it("Should successfully deploy third security token", async() => { -// await I_PolyToken.approve(I_STRProxiedNew.address, REGFEE, { from: ISSUER3}); -// tx = await I_STRProxiedNew.generateSecurityToken(name3, symbol3, tokenDetails3, false, { from: ISSUER3 }); -// assert.equal(tx.logs[1].args._ticker, symbol3, "SecurityToken doesn't get deployed"); -// I_SecurityToken3 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); -// }); -// */ - -// // Launch NewCappedSTO for TOK2 -// it("Should successfully launch CappedSTO for third security token", async() => { -// let startTime = latestTime() + duration.days(1); -// let endTime = startTime + duration.days(30); -// let cap = web3.utils.toWei("500000"); -// let rate = 1000; -// let fundRaiseType = 0; -// let fundsReceiver = ISSUER3; - -// let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [fundRaiseType], fundsReceiver]); - -// let tx = await I_SecurityToken2.addModule(I_UpgradedCappedSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER2 }); -// assert.equal(tx.logs[2].args._types[0], STOKEY, "CappedSTO doesn't get deployed"); -// assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"CappedSTO","CappedSTOFactory module was not added"); -// }); - -// // Attach ManualApprovalTransferManager module for TOK2 -// it("Should successfully attach the ManualApprovalTransferManagerFactory with the second token", async () => { -// const tx = await I_SecurityToken2.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: ISSUER2 }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), TMKEY, "ManualApprovalTransferManagerFactory doesn't get deployed"); -// assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManagerFactory module was not added"); -// I_ManualApprovalTransferManagerFactory = ManualApprovalTransferManagerFactory.at(tx.logs[2].args._module); -// }); -// }); -// }); +const Web3 = require('web3'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port +const BigNumber = require('bignumber.js'); + +import latestTime from './helpers/latestTime'; +import { duration } from './helpers/utils'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); +const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); +const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); +const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); +const CappedSTO = artifacts.require('./CappedSTO.sol'); +const PolyOracle = artifacts.require('./PolyOracle.sol'); +const ETHOracle = artifacts.require('./MakerDAOOracle.sol'); +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); +const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol'); + +contract('Upgrade from v1.3.0 to v1.4.0', accounts => { + // Accounts Variable declaration + let POLYMATH; + let ISSUER1; + let ISSUER2; + let ISSUER3; + let MULTISIG; + + //const GAS_PRICE = 10000000000; // 10 GWEI + + let tx; + + // Initial fee for ticker registry and security token registry + const REGFEE = web3.utils.toWei("250"); + const STOSetupCost = 0; + + // Module key + const STOKEY = 3; + const TMKEY = 2; + + // SecurityToken 1 Details + const symbol1 = "TOK1"; + const name1 = "TOK1 Token"; + const tokenDetails1 = "This is equity type of issuance"; + + //SecurityToken 2 Details + const symbol2 = "TOK2"; + const name2 = "TOK2 Token"; + const tokenDetails2 = "This is equity type of issuance"; + + //SecurityToken 3 Details + const symbol3 = "TOK3"; + const name3 = "TOK3 Token"; + const tokenDetails3 = "This is equity type of issuance"; + + // Contract Instance Declaration + let I_PolymathRegistry; + let I_PolyToken; + let I_DaiToken; + let I_ModuleRegistry; + let I_ModuleRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_FeatureRegistry; + let I_STFactory; + let I_MRProxied; + let I_STRProxied; + let I_STRProxiedNew; + + let I_SecurityTokenRegistry; + //let I_UpgradedSecurityTokenRegistry + + let I_SecurityToken1; + let I_SecurityToken2; + //let I_SecurityToken3; + + let I_USDTieredSTOFactory; + let I_USDTieredSTOProxyFactory + let I_USDOracle; + let I_POLYOracle; + let I_USDTieredSTO; + + let I_CappedSTOFactory; + let I_UpgradedCappedSTOFactory; + let I_CappedSTO; + let I_ManualApprovalTransferManagerFactory; + + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + // Prepare polymath network status + before(async() => { + // Accounts setup + POLYMATH = accounts[0]; + ISSUER1 = accounts[1]; + ISSUER2 = accounts[2]; + ISSUER3 = accounts[3]; + MULTISIG = accounts[4]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); + assert.notEqual( + I_PolymathRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "PolymathRegistry contract was not deployed" + ); + + // Step 1: Deploy the token Faucet + I_PolyToken = await PolyTokenFaucet.new({from: POLYMATH}); + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); + assert.notEqual( + I_PolyToken.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "PolyToken contract was not deployed" + ); + tx = await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) + assert.equal(tx.logs[0].args._nameKey, "PolyToken"); + assert.equal(tx.logs[0].args._newAddress, I_PolyToken.address); + + // STEP 2: Deploy the ModuleRegistry + I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + tx = await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); + assert.equal(tx.logs[0].args._nameKey, "ModuleRegistry"); + assert.equal(tx.logs[0].args._newAddress, I_ModuleRegistryProxy.address); + + // STEP 3: Deploy the GeneralTransferManagerFactory + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 4: Deploy the GeneralDelegateManagerFactory + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the CappedSTOFactory + I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); + assert.notEqual( + I_CappedSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CappedSTOFactory contract was not deployed" + ); + + // Step 8: Deploy the STFactory contract + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 9: Deploy the SecurityTokenRegistry + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: update the registries addresses from the PolymathRegistry contract + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 10: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: POLYMATH + }); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); + + assert.notEqual( + I_FeatureRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "FeatureRegistry contract was not deployed", + ); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: POLYMATH}); + await I_MRProxied.updateFromRegistry({from: POLYMATH}); + + // STEP 6: Register the Modules with the ModuleRegistry contract + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); + + // (C) : Register the CappedSTOFactory + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: POLYMATH }); + + // Step 12: Mint tokens to ISSUERs + await I_PolyToken.getTokens(REGFEE * 2, ISSUER1); + await I_PolyToken.getTokens(REGFEE * 2, ISSUER2); + await I_PolyToken.getTokens(REGFEE * 2, ISSUER3); + + // Step 13: Register tokens + // (A) : TOK1 + await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER1 }); + tx = await I_STRProxied.registerTicker(ISSUER1, symbol1, name1, { from : ISSUER1 }); + assert.equal(tx.logs[0].args._owner, ISSUER1); + assert.equal(tx.logs[0].args._ticker, symbol1); + + // (B) : TOK2 + await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER2 }); + tx = await I_STRProxied.registerTicker(ISSUER2, symbol2, name2, { from : ISSUER2 }); + assert.equal(tx.logs[0].args._owner, ISSUER2); + assert.equal(tx.logs[0].args._ticker, symbol2); + + // (C) : TOK3 + await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER3 }); + tx = await I_STRProxied.registerTicker(ISSUER3, symbol3, name3, { from : ISSUER3 }); + assert.equal(tx.logs[0].args._owner, ISSUER3); + assert.equal(tx.logs[0].args._ticker, symbol3); + + // Step 14: Deploy tokens + // (A) : TOK1 + await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER1}); + let tx = await I_STRProxied.generateSecurityToken(name1, symbol1, tokenDetails1, false, { from: ISSUER1 }); + assert.equal(tx.logs[1].args._ticker, symbol1, "SecurityToken doesn't get deployed"); + I_SecurityToken1 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + // (B) : TOK2 + await I_PolyToken.approve(I_STRProxied.address, REGFEE, { from: ISSUER2}); + tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails2, false, { from: ISSUER2 }); + assert.equal(tx.logs[1].args._ticker, symbol2, "SecurityToken doesn't get deployed"); + I_SecurityToken2 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + ModuleRegistry: ${ModuleRegistry.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + SecurityToken TOK1: ${I_SecurityToken1.address} + SecurityToken TOK2: ${I_SecurityToken2.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("USDTieredSTOFactory deploy", async() => { + // Step 1: Deploy Oracles + // 1a - Deploy POLY Oracle + it("Should successfully deploy POLY Oracle and register on PolymathRegistry", async() => { + I_POLYOracle = await PolyOracle.new({ from: POLYMATH, value: web3.utils.toWei("1")}); + console.log(I_POLYOracle.address); + assert.notEqual( + I_POLYOracle.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "POLYOracle contract was not deployed", + ); + tx = await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); + assert.equal(tx.logs[0].args._nameKey, "PolyUsdOracle"); + assert.equal(tx.logs[0].args._newAddress, I_POLYOracle.address); + }); + // 1b - Deploy ETH Oracle + it("Should successfully deploy ETH Oracle and register on PolymathRegistry", async() => { + I_USDOracle = await ETHOracle.new("0x216d678c14be600cb88338e763bb57755ca2b1cf", "0x0000000000000000000000000000000000000000", "ETH", { from: POLYMATH }); + assert.notEqual( + I_USDOracle.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "USDOracle contract was not deployed", + ); + tx = await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); + assert.equal(tx.logs[0].args._nameKey, "EthUsdOracle"); + assert.equal(tx.logs[0].args._newAddress, I_USDOracle.address); + }); + }); + + describe("USDTieredSTOFactory deploy", async() => { + // Step 1: Deploy USDTieredSTOFactory\ + it("Should successfully deploy USDTieredSTOFactory", async() => { + I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new(); + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: POLYMATH }); + assert.notEqual( + I_USDTieredSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "USDTieredSTOFactory contract was not deployed" + ); + let setupCost = await I_USDTieredSTOFactory.setupCost({ from: POLYMATH }); + assert.equal(setupCost, STOSetupCost); + }); + // Step 2: Register and verify + it("Should successfully register and verify USDTieredSTOFactory contract", async() => { + let tx = await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); + assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); + tx = await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); + assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); + assert.isTrue(tx.logs[0].args._verified); + }); + }); + + describe("CappedSTOFactory deploy", async() => { + // Step 1: Deploy new CappedSTOFactory + it("Should successfully deploy CappedSTOFactory", async() => { + I_UpgradedCappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); + assert.notEqual( + I_UpgradedCappedSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CappedSTOFactory contract was not deployed" + ); + let setupCost = await I_UpgradedCappedSTOFactory.setupCost({ from: POLYMATH }); + assert.equal(setupCost, STOSetupCost); + }); + + // Step 2: Register and verify + it("Should successfully register and verify new CappedSTOFactory contract", async() => { + let tx = await I_MRProxied.registerModule(I_UpgradedCappedSTOFactory.address, { from: POLYMATH }); + assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); + tx = await I_MRProxied.verifyModule(I_UpgradedCappedSTOFactory.address, true, { from: POLYMATH }); + assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); + assert.isTrue(tx.logs[0].args._verified); + }); + + // Step 3: Unverify old CappedSTOFactory + it("Should successfully unverify old CappedSTOFactory contract", async() => { + let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory.address, false, { from: POLYMATH }); + assert.equal(tx.logs[0].args._moduleFactory, I_CappedSTOFactory.address); + assert.isFalse(tx.logs[0].args._verified); + }); + }); + + describe("ManualApprovalTransferManagerFactory deploy", async() => { + // Step 1: Deploy new ManualApprovalTransferManager + it("Should successfully deploy ManualApprovalTransferManagerFactory", async() => { + I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); + assert.notEqual( + I_ManualApprovalTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "ManualApprovalTransferManagerFactory contract was not deployed" + ); + }); + + // Step 2: Register and verify + it("Should successfully register and verify new ManualApprovalTransferManagerFactory contract", async() => { + let tx = await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: POLYMATH }); + assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); + tx = await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: POLYMATH }); + assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); + assert.isTrue(tx.logs[0].args._verified); + }); + }); + + describe("Change ownerships", async() => { + /* + // Step 1: SecurityTokenRegistry + it("Should successfully change ownership of new SecurityTokenRegistry contract", async() => { + let tx = await I_STRProxiedNew.transferOwnership(MULTISIG, { from: POLYMATH }); + assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous owner was not Polymath account"); + assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New owner is not Multisig account"); + }); + */ + + // Step 2: Oracles + it("Should successfully change ownership of both Oracles contract", async() => { + let tx = await I_USDOracle.transferOwnership(MULTISIG, { from: POLYMATH }); + assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous ETH Oracle owner was not Polymath account"); + assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New ETH Oracle owner is not Multisig account"); + + tx = await I_POLYOracle.transferOwnership(MULTISIG, { from: POLYMATH }); + assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous POLY Oracle owner was not Polymath account"); + assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New POLY Oracle owner is not Multisig account"); + }); + + // Step 3: USDTieredSTOFactory + it("Should successfully change ownership of USDTieredSTOFactory contract", async() => { + let tx = await I_USDTieredSTOFactory.transferOwnership(MULTISIG, { from: POLYMATH }); + assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous USDTieredSTOFactory owner was not Polymath account"); + assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New USDTieredSTOFactory owner is not Multisig account"); + }); + + // Step 3: CappedSTOFactory + it("Should successfully change ownership of CappedSTOFactory contract", async() => { + let tx = await I_UpgradedCappedSTOFactory.transferOwnership(MULTISIG, { from: POLYMATH }); + assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous USDTieredSTOFactory owner was not Polymath account"); + assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New USDTieredSTOFactory owner is not Multisig account"); + }); + + // Step 4: ManualApprovalTransferManagerFactory + it("Should successfully change ownership of ManualApprovalTransferManagerFactory contract", async() => { + let tx = await I_ManualApprovalTransferManagerFactory.transferOwnership(MULTISIG, { from: POLYMATH }); + assert.equal(tx.logs[0].args.previousOwner, POLYMATH, "Previous ManualApprovalTransferManagerFactory owner was not Polymath account"); + assert.equal(tx.logs[0].args.newOwner, MULTISIG, "New ManualApprovalTransferManagerFactory owner is not Multisig account"); + }); + }); + + describe("Polymath network status post migration", async() => { + // Launch STO for TOK1 + it("Should successfully launch USDTieredSTO for first security token", async() => { + let _startTime = latestTime() + duration.days(1); + let _endTime = _startTime + duration.days(180); + let _ratePerTier = [BigNumber(0.1).mul(10**18), BigNumber(0.15).mul(10**18), BigNumber(0.2).mul(10**18)]; + let _ratePerTierDiscountPoly = [BigNumber(0), BigNumber(0), BigNumber(0)]; + let _tokensPerTierTotal = [BigNumber(100).mul(10**18), BigNumber(200).mul(10**18), BigNumber(300).mul(10**18)]; + let _tokensPerTierDiscountPoly = [BigNumber(0), BigNumber(0), BigNumber(0)]; + let _nonAccreditedLimitUSD = BigNumber(100).mul(10**18); + let _minimumInvestmentUSD = BigNumber(5).mul(10**18); + let _fundRaiseTypes = [0, 1]; + let _wallet = ISSUER1; + let _reserveWallet = ISSUER1; + let _usdToken = I_DaiToken.address; + + let config = [ + _startTime, _endTime, _ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, + _tokensPerTierDiscountPoly, _nonAccreditedLimitUSD, _minimumInvestmentUSD, + _fundRaiseTypes, _wallet, _reserveWallet, _usdToken + ]; + + let functionSignature = { + name: 'configure', + type: 'function', + inputs: [{ + type: 'uint256', + name: '_startTime' + },{ + type: 'uint256', + name: '_endTime' + },{ + type: 'uint256[]', + name: '_ratePerTier' + },{ + type: 'uint256[]', + name: '_ratePerTierDiscountPoly' + },{ + type: 'uint256[]', + name: '_tokensPerTier' + },{ + type: 'uint256[]', + name: '_tokensPerTierDiscountPoly' + },{ + type: 'uint256', + name: '_nonAccreditedLimitUSD' + },{ + type: 'uint256', + name: '_minimumInvestmentUSD' + },{ + type: 'uint8[]', + name: '_fundRaiseTypes' + },{ + type: 'address', + name: '_wallet' + },{ + type: 'address', + name: '_reserveWallet' + },{ + type: 'address', + name: '_usdToken' + }] + }; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + + let tx = await I_SecurityToken1.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER1 }); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); + I_USDTieredSTO = USDTieredSTO.at(tx.logs[2].args._module); + }); + + /* + // Deploy TOK3 + it("Should successfully deploy third security token", async() => { + await I_PolyToken.approve(I_STRProxiedNew.address, REGFEE, { from: ISSUER3}); + tx = await I_STRProxiedNew.generateSecurityToken(name3, symbol3, tokenDetails3, false, { from: ISSUER3 }); + assert.equal(tx.logs[1].args._ticker, symbol3, "SecurityToken doesn't get deployed"); + I_SecurityToken3 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + }); + */ + + // Launch NewCappedSTO for TOK2 + it("Should successfully launch CappedSTO for third security token", async() => { + let startTime = latestTime() + duration.days(1); + let endTime = startTime + duration.days(30); + let cap = web3.utils.toWei("500000"); + let rate = 1000; + let fundRaiseType = 0; + let fundsReceiver = ISSUER3; + + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [fundRaiseType], fundsReceiver]); + + let tx = await I_SecurityToken2.addModule(I_UpgradedCappedSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER2 }); + assert.equal(tx.logs[2].args._types[0], STOKEY, "CappedSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"CappedSTO","CappedSTOFactory module was not added"); + }); + + // Attach ManualApprovalTransferManager module for TOK2 + it("Should successfully attach the ManualApprovalTransferManagerFactory with the second token", async () => { + const tx = await I_SecurityToken2.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: ISSUER2 }); + assert.equal(tx.logs[2].args._types[0].toNumber(), TMKEY, "ManualApprovalTransferManagerFactory doesn't get deployed"); + assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManagerFactory module was not added"); + I_ManualApprovalTransferManagerFactory = ManualApprovalTransferManagerFactory.at(tx.logs[2].args._module); + }); + }); +}); diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 7b2c2c54f..7032337f7 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -1,348 +1,348 @@ -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import { encodeProxyCall } from './helpers/encodeCall'; - -// const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); -// const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); -// const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); -// const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); -// const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') -// const STFactory = artifacts.require('./STFactory.sol'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract ("SecurityTokenRegistryProxy", accounts => { - - -// let I_SecurityTokenRegistry; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let I_SecurityTokenRegistryMock; -// let I_STFactory; -// let I_PolymathRegistry; -// let I_ModuleRegistryProxy; -// let I_PolyToken; -// let I_STRProxied; -// let I_MRProxied; -// let I_SecurityToken; -// let I_ModuleRegistry; -// let I_FeatureRegistry; - -// let account_polymath; -// let account_temp; -// let token_owner; -// let account_polymath_new; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); -// const version = "1.0.0"; -// const message = "Transaction Should Fail!"; - -// // SecurityToken Details for funds raise Type ETH -// const name = "Team"; -// const symbol = "SAP"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; - -// const transferManagerKey = 2; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// async function readStorage(contractAddress, slot) { -// return await web3.eth.getStorageAt(contractAddress, slot); -// } - -// before(async() => { -// account_polymath = accounts[0]; -// account_temp = accounts[1]; -// token_owner = accounts[2]; -// account_polymath_new = accounts[3]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // Register the Modules with the ModuleRegistry contract - - -// // Step 3: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 4: Deploy the SecurityTokenRegistry -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Attach the implementation address", async() => { - -// // Storage -// // __version -- index 11 -// // __implementation -- index 12 -// // __upgradeabilityOwner -- index 13 - -// it("Should attach the implementation and version", async() => { -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); -// assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address); -// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.0.0"); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); -// }); - -// it("Verify the initialize data", async() => { -// assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), 60*24*60*60, "Should equal to 60 days"); -// assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee"))).toNumber(), web3.utils.toWei("250")); -// }); - -// }) - -// describe("Feed some data in storage", async() => { - -// it("Register the ticker", async() => { -// await I_PolyToken.getTokens(web3.utils.toWei("1000"), token_owner); -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner, "Owner should be the same as registered with the ticker"); -// assert.equal(tx.logs[0].args._ticker, symbol, "Same as the symbol registered in the registerTicker function call"); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), transferManagerKey); -// assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); -// }); -// }) - -// describe("Upgrade the imlplementation address", async() => { - -// it("Should upgrade the version and implementation address -- fail bad owner", async() => { -// let errorThrown = false; -// I_SecurityTokenRegistryMock = await SecurityTokenRegistryMock.new({from: account_polymath}); -// try { -// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryMock.address, {from: account_temp}); -// } catch(error) { -// console.log(` tx -> revert bad owner of the proxy contract`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- Implementaion address should be a contract address", async() => { -// let errorThrown = false; -// try { -// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", account_temp, {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert Implementaion address should be a contract address`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async() => { -// let errorThrown = false; -// try { -// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert Implemenation address should not be 0x`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- Implemenation address should not be the same address", async() => { -// let errorThrown = false; -// try { -// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistry.address, {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert Implemenation address should not be the same address`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- same version as previous is not allowed", async() => { -// let errorThrown = false; -// try { -// await I_SecurityTokenRegistryProxy.upgradeTo("1.0.0", I_SecurityTokenRegistryMock.address, {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert same version as previous is not allowed`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- empty version string is not allowed", async() => { -// let errorThrown = false; -// try { -// await I_SecurityTokenRegistryProxy.upgradeTo("", I_SecurityTokenRegistryMock.address, {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert empty version string is not allowed`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and the implementation address successfully", async() => { -// await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryMock.address, {from: account_polymath}); -// let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); -// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.1.0", "Version mis-match"); -// assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistryMock.address, "Implemnted address is not matched"); -// I_STRProxied = await SecurityTokenRegistryMock.at(I_SecurityTokenRegistryProxy.address); -// }); -// }); - -// describe("Execute functionality of the implementation contract on the earlier storage", async() => { - -// it("Should get the previous data", async() => { -// let _tokenAddress = await I_STRProxied.getSecurityTokenAddress.call(symbol); -// let _data = await I_STRProxied.getSecurityTokenData.call(_tokenAddress); -// assert.equal(_data[0], symbol, "Symbol should match with registered symbol"); -// assert.equal(_data[1], token_owner, "Owner should be the deployer of token"); -// assert.equal(_data[2], tokenDetails, "Token details should matched with deployed ticker"); -// }); - -// it("Should alter the old storage", async() => { -// await I_STRProxied.changeTheDeployedAddress(symbol, account_temp, {from: account_polymath}); -// let _tokenAddress = await I_STRProxied.getSecurityTokenAddress.call(symbol); -// assert.equal(_tokenAddress, account_temp, "Should match with the changed address"); -// }); -// }) - -// describe("Transfer the ownership of the proxy contract", async() => { - -// it("Should change the ownership of the contract -- because of bad owner", async()=> { -// let errorThrown = false; -// try { -// await I_SecurityTokenRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_temp}); -// } catch(error) { -// console.log(` tx -> revert because of bad owner`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should change the ownership of the contract -- new address should not be 0x", async()=> { -// let errorThrown = false; -// try { -// await I_SecurityTokenRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert because new owner address should not be 0x`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should change the ownership of the contract", async()=> { -// await I_SecurityTokenRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_polymath}); -// let _currentOwner = await I_SecurityTokenRegistryProxy.proxyOwner.call({from: account_polymath_new}); -// assert.equal(_currentOwner, account_polymath_new, "Should equal to the new owner"); -// }); - -// it("Should change the implementation contract and version by the new owner", async() => { -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath}); -// await I_SecurityTokenRegistryProxy.upgradeTo("1.2.0", I_SecurityTokenRegistry.address, {from: account_polymath_new}); -// let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); -// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.2.0", "Version mis-match"); -// assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address, "Implemnted address is not matched"); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); -// }); -// }) - - -// }) +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); +const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); +const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); +const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); +const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') +const STFactory = artifacts.require('./STFactory.sol'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract ("SecurityTokenRegistryProxy", accounts => { + + + let I_SecurityTokenRegistry; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_SecurityTokenRegistryMock; + let I_STFactory; + let I_PolymathRegistry; + let I_ModuleRegistryProxy; + let I_PolyToken; + let I_STRProxied; + let I_MRProxied; + let I_SecurityToken; + let I_ModuleRegistry; + let I_FeatureRegistry; + + let account_polymath; + let account_temp; + let token_owner; + let account_polymath_new; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + const version = "1.0.0"; + const message = "Transaction Should Fail!"; + + // SecurityToken Details for funds raise Type ETH + const name = "Team"; + const symbol = "SAP"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + + const transferManagerKey = 2; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + async function readStorage(contractAddress, slot) { + return await web3.eth.getStorageAt(contractAddress, slot); + } + + before(async() => { + account_polymath = accounts[0]; + account_temp = accounts[1]; + token_owner = accounts[2]; + account_polymath_new = accounts[3]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // Register the Modules with the ModuleRegistry contract + + + // Step 3: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 4: Deploy the SecurityTokenRegistry + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Attach the implementation address", async() => { + + // Storage + // __version -- index 11 + // __implementation -- index 12 + // __upgradeabilityOwner -- index 13 + + it("Should attach the implementation and version", async() => { + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); + assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address); + assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.0.0"); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + }); + + it("Verify the initialize data", async() => { + assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), 60*24*60*60, "Should equal to 60 days"); + assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee"))).toNumber(), web3.utils.toWei("250")); + }); + + }) + + describe("Feed some data in storage", async() => { + + it("Register the ticker", async() => { + await I_PolyToken.getTokens(web3.utils.toWei("1000"), token_owner); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner, "Owner should be the same as registered with the ticker"); + assert.equal(tx.logs[0].args._ticker, symbol, "Same as the symbol registered in the registerTicker function call"); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), transferManagerKey); + assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); + }); + }) + + describe("Upgrade the imlplementation address", async() => { + + it("Should upgrade the version and implementation address -- fail bad owner", async() => { + let errorThrown = false; + I_SecurityTokenRegistryMock = await SecurityTokenRegistryMock.new({from: account_polymath}); + try { + await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryMock.address, {from: account_temp}); + } catch(error) { + console.log(` tx -> revert bad owner of the proxy contract`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- Implementaion address should be a contract address", async() => { + let errorThrown = false; + try { + await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", account_temp, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert Implementaion address should be a contract address`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async() => { + let errorThrown = false; + try { + await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert Implemenation address should not be 0x`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- Implemenation address should not be the same address", async() => { + let errorThrown = false; + try { + await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistry.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert Implemenation address should not be the same address`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- same version as previous is not allowed", async() => { + let errorThrown = false; + try { + await I_SecurityTokenRegistryProxy.upgradeTo("1.0.0", I_SecurityTokenRegistryMock.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert same version as previous is not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- empty version string is not allowed", async() => { + let errorThrown = false; + try { + await I_SecurityTokenRegistryProxy.upgradeTo("", I_SecurityTokenRegistryMock.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert empty version string is not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and the implementation address successfully", async() => { + await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryMock.address, {from: account_polymath}); + let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); + assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.1.0", "Version mis-match"); + assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistryMock.address, "Implemnted address is not matched"); + I_STRProxied = await SecurityTokenRegistryMock.at(I_SecurityTokenRegistryProxy.address); + }); + }); + + describe("Execute functionality of the implementation contract on the earlier storage", async() => { + + it("Should get the previous data", async() => { + let _tokenAddress = await I_STRProxied.getSecurityTokenAddress.call(symbol); + let _data = await I_STRProxied.getSecurityTokenData.call(_tokenAddress); + assert.equal(_data[0], symbol, "Symbol should match with registered symbol"); + assert.equal(_data[1], token_owner, "Owner should be the deployer of token"); + assert.equal(_data[2], tokenDetails, "Token details should matched with deployed ticker"); + }); + + it("Should alter the old storage", async() => { + await I_STRProxied.changeTheDeployedAddress(symbol, account_temp, {from: account_polymath}); + let _tokenAddress = await I_STRProxied.getSecurityTokenAddress.call(symbol); + assert.equal(_tokenAddress, account_temp, "Should match with the changed address"); + }); + }) + + describe("Transfer the ownership of the proxy contract", async() => { + + it("Should change the ownership of the contract -- because of bad owner", async()=> { + let errorThrown = false; + try { + await I_SecurityTokenRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_temp}); + } catch(error) { + console.log(` tx -> revert because of bad owner`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should change the ownership of the contract -- new address should not be 0x", async()=> { + let errorThrown = false; + try { + await I_SecurityTokenRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert because new owner address should not be 0x`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should change the ownership of the contract", async()=> { + await I_SecurityTokenRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_polymath}); + let _currentOwner = await I_SecurityTokenRegistryProxy.proxyOwner.call({from: account_polymath_new}); + assert.equal(_currentOwner, account_polymath_new, "Should equal to the new owner"); + }); + + it("Should change the implementation contract and version by the new owner", async() => { + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath}); + await I_SecurityTokenRegistryProxy.upgradeTo("1.2.0", I_SecurityTokenRegistry.address, {from: account_polymath_new}); + let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); + assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.2.0", "Version mis-match"); + assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address, "Implemnted address is not matched"); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + }); + }) + + +}) diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 61de1a2fa..b6fcc5db5 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -1,339 +1,339 @@ -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import { encodeProxyCall } from './helpers/encodeCall'; - -// const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); -// const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); -// const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const MockModuleRegistry = artifacts.require("./MockModuleRegistry.sol"); -// const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') -// const STFactory = artifacts.require('./STFactory.sol'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract ("ModuleRegistryProxy", accounts => { - - -// let I_SecurityTokenRegistry; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let I_GeneralPermissionManagerfactory; -// let I_MockModuleRegistry; -// let I_STFactory; -// let I_PolymathRegistry; -// let I_ModuleRegistryProxy; -// let I_PolyToken; -// let I_STRProxied; -// let I_MRProxied; -// let I_SecurityToken; -// let I_ModuleRegistry; -// let I_FeatureRegistry; - -// let account_polymath; -// let account_temp; -// let token_owner; -// let account_polymath_new; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); -// const version = "1.0.0"; -// const message = "Transaction Should Fail!"; - -// // SecurityToken Details for funds raise Type ETH -// const name = "Team"; -// const symbol = "SAP"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; - -// const transferManagerKey = 2; -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// async function readStorage(contractAddress, slot) { -// return await web3.eth.getStorageAt(contractAddress, slot); -// } - -// before(async() => { -// account_polymath = accounts[0]; -// account_temp = accounts[1]; -// token_owner = accounts[2]; -// account_polymath_new = accounts[3]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // Step 4: Deploy the SecurityTokenRegistry -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - -// // Step 11: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Attach the implementation address", async() => { - -// // Storage -// // __version -- index 11 -// // __implementation -- index 12 -// // __upgradeabilityOwner -- index 13 - -// it("Should attach the MR implementation and version", async() => { -// let bytesProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, {from: account_polymath}); -// let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); -// assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address); -// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.0.0"); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); -// }); - -// it("Deploy the essential smart contracts", async() => { -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - -// // Step 3: Deploy the STFactory contract -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); -// }) - -// it("Verify the initialize data", async() => { -// assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("owner"))), account_polymath, "Should equal to right address"); -// assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry"))), I_PolymathRegistry.address); -// }); - -// }) - -// describe("Feed some data in storage", async() => { - -// it("Register and verify the new module", async() => { - -// I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerfactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralPermissionManagerFactory contract was not deployed" -// ); - -// await I_MRProxied.registerModule(I_GeneralPermissionManagerfactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerfactory.address, true, { from: account_polymath }); - -// }); - -// }) - -// describe("Upgrade the imlplementation address", async() => { - -// it("Should upgrade the version and implementation address -- fail bad owner", async() => { -// let errorThrown = false; -// I_MockModuleRegistry = await MockModuleRegistry.new({from: account_polymath}); -// try { -// await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_MockModuleRegistry.address, {from: account_temp}); -// } catch(error) { -// console.log(` tx -> revert bad owner of the proxy contract`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- Implementaion address should be a contract address", async() => { -// let errorThrown = false; -// try { -// await I_ModuleRegistryProxy.upgradeTo("1.1.0", account_temp, {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert Implementaion address should be a contract address`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async() => { -// let errorThrown = false; -// try { -// await I_ModuleRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert Implemenation address should not be 0x`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- Implemenation address should not be the same address", async() => { -// let errorThrown = false; -// try { -// await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_ModuleRegistry.address, {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert Implemenation address should not be the same address`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- same version as previous is not allowed", async() => { -// let errorThrown = false; -// try { -// await I_ModuleRegistryProxy.upgradeTo("1.0.0", I_MockModuleRegistry.address, {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert same version as previous is not allowed`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and implementation address -- empty version string is not allowed", async() => { -// let errorThrown = false; -// try { -// await I_ModuleRegistryProxy.upgradeTo("", I_MockModuleRegistry.address, {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert empty version string is not allowed`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should upgrade the version and the implementation address successfully", async() => { -// await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_MockModuleRegistry.address, {from: account_polymath}); -// let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); -// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.1.0", "Version mis-match"); -// assert.equal(await readStorage(c.address, 12), I_MockModuleRegistry.address, "Implemnted address is not matched"); -// I_MRProxied = await MockModuleRegistry.at(I_ModuleRegistryProxy.address); -// }); -// }); - -// describe("Execute functionality of the implementation contract on the earlier storage", async() => { - -// it("Should get the previous data", async() => { -// let _data = await I_MRProxied.getReputationByFactory.call(I_GeneralTransferManagerFactory.address); -// assert.equal(_data.length, 0, "Should give the original length"); -// }); - -// it("Should alter the old storage", async() => { -// await I_MRProxied.addMoreReputation(I_GeneralTransferManagerFactory.address, [account_polymath, account_temp], {from: account_polymath}); -// let _data = await I_MRProxied.getReputationByFactory.call(I_GeneralTransferManagerFactory.address); -// assert.equal(_data.length, 2, "Should give the updated length"); -// }); -// }) - -// describe("Transfer the ownership of the proxy contract", async() => { - -// it("Should change the ownership of the contract -- because of bad owner", async()=> { -// let errorThrown = false; -// try { -// await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_temp}); -// } catch(error) { -// console.log(` tx -> revert because of bad owner`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should change the ownership of the contract -- new address should not be 0x", async()=> { -// let errorThrown = false; -// try { -// await I_ModuleRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", {from: account_polymath}); -// } catch(error) { -// console.log(` tx -> revert because new owner address should not be 0x`); -// errorThrown = true; -// ensureException(error); -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should change the ownership of the contract", async()=> { -// await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_polymath}); -// let _currentOwner = await I_ModuleRegistryProxy.proxyOwner.call({from: account_polymath_new}); -// assert.equal(_currentOwner, account_polymath_new, "Should equal to the new owner"); -// }); - -// it("Should change the implementation contract and version by the new owner", async() => { -// I_ModuleRegistry = await ModuleRegistry.new({from: account_polymath}); -// await I_ModuleRegistryProxy.upgradeTo("1.2.0", I_ModuleRegistry.address, {from: account_polymath_new}); -// let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); -// assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.2.0", "Version mis-match"); -// assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address, "Implemnted address is not matched"); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); -// }); -// }) - - -// }) +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); +const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); +const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const MockModuleRegistry = artifacts.require("./MockModuleRegistry.sol"); +const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') +const STFactory = artifacts.require('./STFactory.sol'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract ("ModuleRegistryProxy", accounts => { + + + let I_SecurityTokenRegistry; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManagerfactory; + let I_MockModuleRegistry; + let I_STFactory; + let I_PolymathRegistry; + let I_ModuleRegistryProxy; + let I_PolyToken; + let I_STRProxied; + let I_MRProxied; + let I_SecurityToken; + let I_ModuleRegistry; + let I_FeatureRegistry; + + let account_polymath; + let account_temp; + let token_owner; + let account_polymath_new; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + const version = "1.0.0"; + const message = "Transaction Should Fail!"; + + // SecurityToken Details for funds raise Type ETH + const name = "Team"; + const symbol = "SAP"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + + const transferManagerKey = 2; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + async function readStorage(contractAddress, slot) { + return await web3.eth.getStorageAt(contractAddress, slot); + } + + before(async() => { + account_polymath = accounts[0]; + account_temp = accounts[1]; + token_owner = accounts[2]; + account_polymath_new = accounts[3]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // Step 4: Deploy the SecurityTokenRegistry + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Attach the implementation address", async() => { + + // Storage + // __version -- index 11 + // __implementation -- index 12 + // __upgradeabilityOwner -- index 13 + + it("Should attach the MR implementation and version", async() => { + let bytesProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, {from: account_polymath}); + let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); + assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address); + assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.0.0"); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + }); + + it("Deploy the essential smart contracts", async() => { + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + + // Step 3: Deploy the STFactory contract + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + }) + + it("Verify the initialize data", async() => { + assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("owner"))), account_polymath, "Should equal to right address"); + assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry"))), I_PolymathRegistry.address); + }); + + }) + + describe("Feed some data in storage", async() => { + + it("Register and verify the new module", async() => { + + I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerfactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralPermissionManagerFactory contract was not deployed" + ); + + await I_MRProxied.registerModule(I_GeneralPermissionManagerfactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerfactory.address, true, { from: account_polymath }); + + }); + + }) + + describe("Upgrade the imlplementation address", async() => { + + it("Should upgrade the version and implementation address -- fail bad owner", async() => { + let errorThrown = false; + I_MockModuleRegistry = await MockModuleRegistry.new({from: account_polymath}); + try { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_MockModuleRegistry.address, {from: account_temp}); + } catch(error) { + console.log(` tx -> revert bad owner of the proxy contract`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- Implementaion address should be a contract address", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", account_temp, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert Implementaion address should be a contract address`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert Implemenation address should not be 0x`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- Implemenation address should not be the same address", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_ModuleRegistry.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert Implemenation address should not be the same address`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- same version as previous is not allowed", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("1.0.0", I_MockModuleRegistry.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert same version as previous is not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- empty version string is not allowed", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("", I_MockModuleRegistry.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert empty version string is not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and the implementation address successfully", async() => { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_MockModuleRegistry.address, {from: account_polymath}); + let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); + assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.1.0", "Version mis-match"); + assert.equal(await readStorage(c.address, 12), I_MockModuleRegistry.address, "Implemnted address is not matched"); + I_MRProxied = await MockModuleRegistry.at(I_ModuleRegistryProxy.address); + }); + }); + + describe("Execute functionality of the implementation contract on the earlier storage", async() => { + + it("Should get the previous data", async() => { + let _data = await I_MRProxied.getReputationByFactory.call(I_GeneralTransferManagerFactory.address); + assert.equal(_data.length, 0, "Should give the original length"); + }); + + it("Should alter the old storage", async() => { + await I_MRProxied.addMoreReputation(I_GeneralTransferManagerFactory.address, [account_polymath, account_temp], {from: account_polymath}); + let _data = await I_MRProxied.getReputationByFactory.call(I_GeneralTransferManagerFactory.address); + assert.equal(_data.length, 2, "Should give the updated length"); + }); + }) + + describe("Transfer the ownership of the proxy contract", async() => { + + it("Should change the ownership of the contract -- because of bad owner", async()=> { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_temp}); + } catch(error) { + console.log(` tx -> revert because of bad owner`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should change the ownership of the contract -- new address should not be 0x", async()=> { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert because new owner address should not be 0x`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should change the ownership of the contract", async()=> { + await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_polymath}); + let _currentOwner = await I_ModuleRegistryProxy.proxyOwner.call({from: account_polymath_new}); + assert.equal(_currentOwner, account_polymath_new, "Should equal to the new owner"); + }); + + it("Should change the implementation contract and version by the new owner", async() => { + I_ModuleRegistry = await ModuleRegistry.new({from: account_polymath}); + await I_ModuleRegistryProxy.upgradeTo("1.2.0", I_ModuleRegistry.address, {from: account_polymath_new}); + let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); + assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.2.0", "Version mis-match"); + assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address, "Implemnted address is not matched"); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + }); + }) + + +}) diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 6bdea7f65..4330616ea 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -1,379 +1,379 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const TrackedRedemptionFactory = artifacts.require('./TrackedRedemptionFactory.sol'); -// const TrackedRedemption = artifacts.require('./TrackedRedemption'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('TrackedRedemption', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; -// let account_temp; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let I_GeneralTransferManagerFactory; -// let I_TrackedRedemptionFactory; -// let I_GeneralPermissionManager; -// let I_TrackedRedemption; -// let I_GeneralTransferManager; -// let I_ExchangeTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_STRProxied; -// let I_STFactory; -// let I_SecurityToken; -// let I_PolyToken; -// let I_MRProxied; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; -// let snapId; -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; -// const checkpointKey = 4; -// const burnKey = 5; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; - -// account_investor1 = accounts[6]; -// account_investor2 = accounts[7]; -// account_investor3 = accounts[8]; -// account_investor4 = accounts[9]; -// account_temp = accounts[2]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4: Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 5: Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the TrackedRedemption -// I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); -// assert.notEqual( -// I_TrackedRedemptionFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "TrackedRedemptionFactory contract was not deployed" -// ); - - -// // Step 6: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 7: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 8: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 9: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 5: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the TrackedRedemptionFactory -// await I_MRProxied.registerModule(I_TrackedRedemptionFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_TrackedRedemptionFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// TrackedRedemptionFactory: ${I_TrackedRedemptionFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - -// }); - -// it("Should successfully attach the TrackedRedemption with the security token", async () => { -// const tx = await I_SecurityToken.addModule(I_TrackedRedemptionFactory.address, "", 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "TrackedRedemption", -// "TrackedRedemption module was not added" -// ); -// I_TrackedRedemption = TrackedRedemption.at(tx.logs[2].args._module); -// }); -// }); - -// describe("Make Redemptions", async() => { - -// it("Buy some tokens for account_investor1 (1 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(30), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(5000); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); - -// it("Buy some tokens for account_investor2 (2 ETH)", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(30), -// true, -// { -// from: account_issuer, -// gas: 500000 -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('2', 'ether') -// ); -// }); - -// it("Redeem some tokens - fail insufficient allowance", async() => { -// await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); - -// let errorThrown = false; -// try { -// let tx = await I_TrackedRedemption.redeemTokens(web3.utils.toWei('1', 'ether'), {from: account_investor1}); -// } catch(error) { -// console.log(` tx -> failed insufficent allowance`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Redeem some tokens", async() => { -// await I_SecurityToken.approve(I_TrackedRedemption.address, web3.utils.toWei('1', 'ether'), {from: account_investor1}); -// let tx = await I_TrackedRedemption.redeemTokens(web3.utils.toWei('1', 'ether'), {from: account_investor1}); -// console.log(JSON.stringify(tx.logs)); -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Mismatch address"); -// assert.equal(tx.logs[0].args._value, web3.utils.toWei('1', 'ether'), "Wrong value"); -// }); - -// it("Get the init data", async() => { -// let tx = await I_TrackedRedemption.getInitFunction.call(); -// assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); -// }); - -// it("Should get the listed permissions", async() => { -// let tx = await I_TrackedRedemption.getPermissions.call(); -// assert.equal(tx.length,0); -// }); - -// describe("Test cases for the TrackedRedemptionFactory", async() => { -// it("should get the exact details of the factory", async() => { -// assert.equal((await I_TrackedRedemptionFactory.setupCost.call()).toNumber(), 0); -// assert.equal((await I_TrackedRedemptionFactory.getTypes.call())[0], 5); -// assert.equal(web3.utils.toAscii(await I_TrackedRedemptionFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "TrackedRedemption", -// "Wrong Module added"); -// assert.equal(await I_TrackedRedemptionFactory.getDescription.call(), -// "Track token redemptions", -// "Wrong Module added"); -// assert.equal(await I_TrackedRedemptionFactory.getTitle.call(), -// "Tracked Redemption", -// "Wrong Module added"); -// assert.equal(await I_TrackedRedemptionFactory.getInstructions.call(), -// "Allows an investor to redeem security tokens which are tracked by this module", -// "Wrong Module added"); -// let tags = await I_TrackedRedemptionFactory.getTags.call(); -// assert.equal(tags.length, 2); - -// }); -// }); - -// }); - -// }); +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const TrackedRedemptionFactory = artifacts.require('./TrackedRedemptionFactory.sol'); +const TrackedRedemption = artifacts.require('./TrackedRedemption'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('TrackedRedemption', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_temp; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_TrackedRedemptionFactory; + let I_GeneralPermissionManager; + let I_TrackedRedemption; + let I_GeneralTransferManager; + let I_ExchangeTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_MRProxied; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + let snapId; + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + const checkpointKey = 4; + const burnKey = 5; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[6]; + account_investor2 = accounts[7]; + account_investor3 = accounts[8]; + account_investor4 = accounts[9]; + account_temp = accounts[2]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 5: Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 4: Deploy the TrackedRedemption + I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + assert.notEqual( + I_TrackedRedemptionFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "TrackedRedemptionFactory contract was not deployed" + ); + + + // Step 6: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 7: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 8: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 9: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 5: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the TrackedRedemptionFactory + await I_MRProxied.registerModule(I_TrackedRedemptionFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_TrackedRedemptionFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + TrackedRedemptionFactory: ${I_TrackedRedemptionFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + it("Should successfully attach the TrackedRedemption with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_TrackedRedemptionFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "TrackedRedemption", + "TrackedRedemption module was not added" + ); + I_TrackedRedemption = TrackedRedemption.at(tx.logs[2].args._module); + }); + }); + + describe("Make Redemptions", async() => { + + it("Buy some tokens for account_investor1 (1 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(30), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Buy some tokens for account_investor2 (2 ETH)", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(30), + true, + { + from: account_issuer, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Redeem some tokens - fail insufficient allowance", async() => { + await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); + + let errorThrown = false; + try { + let tx = await I_TrackedRedemption.redeemTokens(web3.utils.toWei('1', 'ether'), {from: account_investor1}); + } catch(error) { + console.log(` tx -> failed insufficent allowance`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Redeem some tokens", async() => { + await I_SecurityToken.approve(I_TrackedRedemption.address, web3.utils.toWei('1', 'ether'), {from: account_investor1}); + let tx = await I_TrackedRedemption.redeemTokens(web3.utils.toWei('1', 'ether'), {from: account_investor1}); + console.log(JSON.stringify(tx.logs)); + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Mismatch address"); + assert.equal(tx.logs[0].args._value, web3.utils.toWei('1', 'ether'), "Wrong value"); + }); + + it("Get the init data", async() => { + let tx = await I_TrackedRedemption.getInitFunction.call(); + assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ''),0); + }); + + it("Should get the listed permissions", async() => { + let tx = await I_TrackedRedemption.getPermissions.call(); + assert.equal(tx.length,0); + }); + + describe("Test cases for the TrackedRedemptionFactory", async() => { + it("should get the exact details of the factory", async() => { + assert.equal((await I_TrackedRedemptionFactory.setupCost.call()).toNumber(), 0); + assert.equal((await I_TrackedRedemptionFactory.getTypes.call())[0], 5); + assert.equal(web3.utils.toAscii(await I_TrackedRedemptionFactory.getName.call()) + .replace(/\u0000/g, ''), + "TrackedRedemption", + "Wrong Module added"); + assert.equal(await I_TrackedRedemptionFactory.getDescription.call(), + "Track token redemptions", + "Wrong Module added"); + assert.equal(await I_TrackedRedemptionFactory.getTitle.call(), + "Tracked Redemption", + "Wrong Module added"); + assert.equal(await I_TrackedRedemptionFactory.getInstructions.call(), + "Allows an investor to redeem security tokens which are tracked by this module", + "Wrong Module added"); + let tags = await I_TrackedRedemptionFactory.getTags.call(); + assert.equal(tags.length, 2); + + }); + }); + + }); + +}); diff --git a/test/w_volume_restriction_transfer_manager.js b/test/w_volume_restriction_transfer_manager.js index 8165c15a4..b117511c8 100644 --- a/test/w_volume_restriction_transfer_manager.js +++ b/test/w_volume_restriction_transfer_manager.js @@ -1,1070 +1,1070 @@ -// import latestTime from './helpers/latestTime'; -// import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -// import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -// import { encodeProxyCall } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const VolumeRestrictionTransferManagerFactory = artifacts.require('./VolumeRestrictionTransferManagerFactory.sol'); -// const VolumeRestrictionTransferManager = artifacts.require('./VolumeRestrictionTransferManager'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('VolumeRestrictionTransferManager', accounts => { - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; - -// // Contract Instance Declaration -// let I_GeneralPermissionManagerFactory; -// let P_VolumeRestrictionTransferManagerFactory; -// let I_SecurityTokenRegistryProxy; -// let P_VolumeRestrictionTransferManager; -// let I_GeneralTransferManagerFactory; -// let I_VolumeRestrictionTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_VolumeRestrictionTransferManager; -// let I_GeneralTransferManager; -// let I_ModuleRegistryProxy; -// let I_ModuleRegistry; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_STRProxied; -// let I_MRProxied; -// let I_STFactory; -// let I_SecurityToken; -// let I_PolyToken; -// let I_PolymathRegistry; - -// // SecurityToken Details -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; - -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// before(async() => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; - -// account_investor1 = accounts[7]; -// account_investor2 = accounts[8]; -// account_investor3 = accounts[9]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// // Step 2: Deploy the FeatureRegistry - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, -// { -// from: account_polymath -// }); - -// // STEP 3: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); -// // Step 3 (b): Deploy the proxy and attach the implementation contract to it -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - -// // STEP 4(a): Deploy the GeneralTransferManagerFactory - -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 4(b): Deploy the GeneralDelegateManagerFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 4(c): Deploy the VolumeRestrictionTransferManager -// I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); -// assert.notEqual( -// I_VolumeRestrictionTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "VolumeRestrictionTransferManagerFactory contract was not deployed" -// ); - -// // STEP 4(d): Deploy the VolumeRestrictionTransferManager -// P_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); -// assert.notEqual( -// P_VolumeRestrictionTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "VolumeRestrictionTransferManagerFactory contract was not deployed" -// ); - - -// // Step 6: Deploy the STFactory contract - -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 7: Deploy the SecurityTokenRegistry contract +import latestTime from './helpers/latestTime'; +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const VolumeRestrictionTransferManagerFactory = artifacts.require('./VolumeRestrictionTransferManagerFactory.sol'); +const VolumeRestrictionTransferManager = artifacts.require('./VolumeRestrictionTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('VolumeRestrictionTransferManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let P_VolumeRestrictionTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let P_VolumeRestrictionTransferManager; + let I_GeneralTransferManagerFactory; + let I_VolumeRestrictionTransferManagerFactory; + let I_GeneralPermissionManager; + let I_VolumeRestrictionTransferManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_MRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[7]; + account_investor2 = accounts[8]; + account_investor3 = accounts[9]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4(a): Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 4(b): Deploy the GeneralDelegateManagerFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 4(c): Deploy the VolumeRestrictionTransferManager + I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + assert.notEqual( + I_VolumeRestrictionTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "VolumeRestrictionTransferManagerFactory contract was not deployed" + ); + + // STEP 4(d): Deploy the VolumeRestrictionTransferManager + P_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); + assert.notEqual( + P_VolumeRestrictionTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "VolumeRestrictionTransferManagerFactory contract was not deployed" + ); + + + // Step 6: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 7: Deploy the SecurityTokenRegistry contract -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 8: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - -// // Step 9: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); -// await I_MRProxied.updateFromRegistry({from: account_polymath}); - -// // STEP 5: Register the Modules with the ModuleRegistry contract - -// // (A) : Register the GeneralTransferManagerFactory -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the VolumeRestrictionTransferManagerFactory -// await I_MRProxied.registerModule(I_VolumeRestrictionTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(I_VolumeRestrictionTransferManagerFactory.address, true, { from: account_polymath }); - -// // (C) : Register the Paid VolumeRestrictionTransferManagerFactory -// await I_MRProxied.registerModule(P_VolumeRestrictionTransferManagerFactory.address, { from: account_polymath }); -// await I_MRProxied.verifyModule(P_VolumeRestrictionTransferManagerFactory.address, true, { from: account_polymath }); - -// // Printing all the contract addresses -// console.log(` -// --------------------- Polymath Network Smart Contracts: --------------------- -// PolymathRegistry: ${PolymathRegistry.address} -// SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} -// SecurityTokenRegistry: ${SecurityTokenRegistry.address} -// ModuleRegistry: ${ModuleRegistry.address} -// ModuleRegistryProxy: ${ModuleRegistryProxy.address} -// FeatureRegistry: ${FeatureRegistry.address} - -// STFactory: ${STFactory.address} -// GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} -// GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - -// VolumeRestrictionTransferManagerFactory: ${I_VolumeRestrictionTransferManagerFactory.address} -// ----------------------------------------------------------------------------- -// `); -// }); - -// describe("Generate the SecurityToken", async() => { - -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); -// }); - -// }); - -// describe("Buy tokens using on-chain whitelist and test locking them up and attempting to transfer", async() => { - -// it("Should Buy the tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(5000); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('2', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('2', 'ether') -// ); -// }); - -// it("Should Buy some more tokens", async() => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('10', 'ether') -// ); -// }); - -// it("Should unsuccessfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { -// let errorThrown = false; -// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); -// try { -// const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx -> failed because Token is not paid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should successfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { -// let snapId = await takeSnapshot(); -// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); -// const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); -// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManagerFactory doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[3].args._name) -// .replace(/\u0000/g, ''), -// "VolumeRestrictionTransferManager", -// "VolumeRestrictionTransferManagerFactory module was not added" -// ); -// P_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[3].args._module); -// await revertToSnapshot(snapId); -// }); - -// it("Should successfully attach the VolumeRestrictionTransferManager with the security token", async () => { -// const tx = await I_SecurityToken.addModule(I_VolumeRestrictionTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManager doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "VolumeRestrictionTransferManager", -// "VolumeRestrictionTransferManager module was not added" -// ); -// I_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[2].args._module); -// }); - -// it("Add a new token holder", async() => { - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, -// { -// from: account_issuer -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), -// web3.utils.toWei('10', 'ether') -// ); -// }); - -// it("Should pause the tranfers at transferManager level", async() => { -// let tx = await I_VolumeRestrictionTransferManager.pause({from: token_owner}); -// }); - -// it("Should still be able to transfer between existing token holders up to limit", async() => { -// // Add the Investor in to the whitelist -// // Mint some tokens -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('3', 'ether') -// ); -// }); - -// it("Should unpause the tranfers at transferManager level", async() => { -// await I_VolumeRestrictionTransferManager.unpause({from: token_owner}); -// }); - -// it("Should prevent the creation of a lockup with bad parameters where the totalAmount is zero", async() => { -// let errorThrown = false; -// try { -// // create a lockup -// // this will generate an exception because the totalAmount is zero -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, 0, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> couldn't create lock up because totalAmount is zero`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should prevent the creation of a lockup with bad parameters where the releaseFrequencySeconds is zero", async() => { -// let errorThrown = false; -// try { -// // create a lockup -// // this will generate an exception because the releaseFrequencySeconds is zero -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 0, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> couldn't create lock up because releaseFrequencySeconds is zero`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is zero", async() => { -// let errorThrown = false; -// try { -// // create a lockup -// // this will generate an exception because the lockUpPeriodSeconds is zero -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 0, 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> couldn't create lock up because lockUpPeriodSeconds is zero`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - - -// it("Should prevent the creation of a lockup with bad parameters where the total amount to be released is more granular than allowed by the token", async() => { -// let errorThrown = false; -// try { -// // create a lockup -// // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, web3.utils.toWei('0.5', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> couldn't create lock up because the total amount to be released is more granular than allowed by the token`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - - -// it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is not evenly divisible by releaseFrequencySeconds", async() => { - -// // balance should be 9000000000000000000 here (9 eth) -// let balance = await I_SecurityToken.balanceOf(account_investor2) - - -// let errorThrown = false; -// try { -// // create a lockup -// // over 17 seconds total, with 4 periods. -// // this will generate an exception because 17 is not evenly divisble by 4. -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 17, 4, 0, balance, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> couldn't create lock up because lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should prevent the creation of a lockup with bad parameters where the total amount being locked up isn't evenly divisible by the number of total periods", async() => { - -// let errorThrown = false; -// try { -// // create a lockup for a balance of 1 eth -// // over 16e18 seconds total, with 4e18 periods of 4 seconds each. -// // this will generate an exception because 16e18 / 4e18 = 4e18 but the token granularity is 1e18 and 1e18 % 4e18 != 0 -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, web3.utils.toWei('16', 'ether'), 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> couldn't create lock up because the total amount being locked up must be evenly divisible by the number of total periods`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should prevent the creation of a lockup with bad parameters where the amount to be released per period is too granular for the token", async() => { - -// // balance should be 9000000000000000000 here (9 eth) -// let balance = await I_SecurityToken.balanceOf(account_investor2) - - -// let errorThrown = false; -// try { -// // create a lockup for their entire balance -// // over 16 seconds total, with 4 periods of 4 seconds each. -// // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }); -// } catch(error) { -// console.log(` tx revert -> couldn't create lock up because amount to be released per period is more granular than allowed by the token`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should prevent the transfer of tokens in a lockup", async() => { - -// let balance = await I_SecurityToken.balanceOf(account_investor2) - -// // create a lockup for their entire balance -// // over 12 seconds total, with 3 periods of 4 seconds each. -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from: token_owner }); - -// // read only - check if transfer will pass. it should return INVALID -// let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('1', 'ether'), 0, false) -// // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 -// assert.equal(result.toString(), '0') - - -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { - -// // wait 4 seconds -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); -// }); - -// it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { - -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { - -// // wait 4 more seconds -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); -// }); - -// it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async() => { - -// let balance = await I_SecurityToken.balanceOf(account_investor2) - -// // wait 4 more seconds -// await new Promise(resolve => setTimeout(resolve, 4000)); + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 8: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 9: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // STEP 5: Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the VolumeRestrictionTransferManagerFactory + await I_MRProxied.registerModule(I_VolumeRestrictionTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_VolumeRestrictionTransferManagerFactory.address, true, { from: account_polymath }); + + // (C) : Register the Paid VolumeRestrictionTransferManagerFactory + await I_MRProxied.registerModule(P_VolumeRestrictionTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_VolumeRestrictionTransferManagerFactory.address, true, { from: account_polymath }); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + VolumeRestrictionTransferManagerFactory: ${I_VolumeRestrictionTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + + }); + + describe("Buy tokens using on-chain whitelist and test locking them up and attempting to transfer", async() => { + + it("Should Buy the tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should Buy some more tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('10', 'ether') + ); + }); + + it("Should unsuccessfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + try { + const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + } catch(error) { + console.log(` tx -> failed because Token is not paid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should successfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManagerFactory doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "VolumeRestrictionTransferManager", + "VolumeRestrictionTransferManagerFactory module was not added" + ); + P_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the VolumeRestrictionTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_VolumeRestrictionTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "VolumeRestrictionTransferManager", + "VolumeRestrictionTransferManager module was not added" + ); + I_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[2].args._module); + }); + + it("Add a new token holder", async() => { + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('10', 'ether') + ); + }); + + it("Should pause the tranfers at transferManager level", async() => { + let tx = await I_VolumeRestrictionTransferManager.pause({from: token_owner}); + }); + + it("Should still be able to transfer between existing token holders up to limit", async() => { + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('3', 'ether') + ); + }); + + it("Should unpause the tranfers at transferManager level", async() => { + await I_VolumeRestrictionTransferManager.unpause({from: token_owner}); + }); + + it("Should prevent the creation of a lockup with bad parameters where the totalAmount is zero", async() => { + let errorThrown = false; + try { + // create a lockup + // this will generate an exception because the totalAmount is zero + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, 0, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> couldn't create lock up because totalAmount is zero`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should prevent the creation of a lockup with bad parameters where the releaseFrequencySeconds is zero", async() => { + let errorThrown = false; + try { + // create a lockup + // this will generate an exception because the releaseFrequencySeconds is zero + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 0, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> couldn't create lock up because releaseFrequencySeconds is zero`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is zero", async() => { + let errorThrown = false; + try { + // create a lockup + // this will generate an exception because the lockUpPeriodSeconds is zero + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 0, 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> couldn't create lock up because lockUpPeriodSeconds is zero`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + + it("Should prevent the creation of a lockup with bad parameters where the total amount to be released is more granular than allowed by the token", async() => { + let errorThrown = false; + try { + // create a lockup + // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, web3.utils.toWei('0.5', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> couldn't create lock up because the total amount to be released is more granular than allowed by the token`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + + it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is not evenly divisible by releaseFrequencySeconds", async() => { + + // balance should be 9000000000000000000 here (9 eth) + let balance = await I_SecurityToken.balanceOf(account_investor2) + + + let errorThrown = false; + try { + // create a lockup + // over 17 seconds total, with 4 periods. + // this will generate an exception because 17 is not evenly divisble by 4. + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 17, 4, 0, balance, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> couldn't create lock up because lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should prevent the creation of a lockup with bad parameters where the total amount being locked up isn't evenly divisible by the number of total periods", async() => { + + let errorThrown = false; + try { + // create a lockup for a balance of 1 eth + // over 16e18 seconds total, with 4e18 periods of 4 seconds each. + // this will generate an exception because 16e18 / 4e18 = 4e18 but the token granularity is 1e18 and 1e18 % 4e18 != 0 + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, web3.utils.toWei('16', 'ether'), 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }); + } catch(error) { + console.log(` tx revert -> couldn't create lock up because the total amount being locked up must be evenly divisible by the number of total periods`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should prevent the creation of a lockup with bad parameters where the amount to be released per period is too granular for the token", async() => { + + // balance should be 9000000000000000000 here (9 eth) + let balance = await I_SecurityToken.balanceOf(account_investor2) + + + let errorThrown = false; + try { + // create a lockup for their entire balance + // over 16 seconds total, with 4 periods of 4 seconds each. + // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> couldn't create lock up because amount to be released per period is more granular than allowed by the token`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should prevent the transfer of tokens in a lockup", async() => { + + let balance = await I_SecurityToken.balanceOf(account_investor2) + + // create a lockup for their entire balance + // over 12 seconds total, with 3 periods of 4 seconds each. + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from: token_owner }); + + // read only - check if transfer will pass. it should return INVALID + let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('1', 'ether'), 0, false) + // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 + assert.equal(result.toString(), '0') + + + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { + + // wait 4 seconds + await new Promise(resolve => setTimeout(resolve, 4000)); + + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); + }); + + it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { + + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { + + // wait 4 more seconds + await new Promise(resolve => setTimeout(resolve, 4000)); + + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); + }); + + it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async() => { + + let balance = await I_SecurityToken.balanceOf(account_investor2) + + // wait 4 more seconds + await new Promise(resolve => setTimeout(resolve, 4000)); -// await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); -// }); + await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); + }); -// it("Should prevent the transfer of tokens in an edited lockup", async() => { + it("Should prevent the transfer of tokens in an edited lockup", async() => { -// // balance here should be 12000000000000000000 (12e18 or 12 eth) -// let balance = await I_SecurityToken.balanceOf(account_investor1) + // balance here should be 12000000000000000000 (12e18 or 12 eth) + let balance = await I_SecurityToken.balanceOf(account_investor1) -// // create a lockup for their entire balance -// // over 16 seconds total, with 4 periods of 4 seconds each. -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, balance, { from: token_owner }); + // create a lockup for their entire balance + // over 16 seconds total, with 4 periods of 4 seconds each. + await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, balance, { from: token_owner }); -// // let blockNumber = await web3.eth.getBlockNumber(); -// // console.log('blockNumber',blockNumber) -// let now = (await web3.eth.getBlock('latest')).timestamp + // let blockNumber = await web3.eth.getBlockNumber(); + // console.log('blockNumber',blockNumber) + let now = (await web3.eth.getBlock('latest')).timestamp -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); -// // check and get the lockup -// let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); -// assert.equal(lockUpCount, 1) + // check and get the lockup + let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); + assert.equal(lockUpCount, 1) -// let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 0); -// // console.log(lockUp); -// // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount -// assert.equal(lockUp[0].toString(), '16'); -// assert.equal(lockUp[1].toString(), '4'); -// assert.equal(lockUp[2].toNumber(), now); -// assert.equal(lockUp[3].toString(), balance.toString()); + let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 0); + // console.log(lockUp); + // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount + assert.equal(lockUp[0].toString(), '16'); + assert.equal(lockUp[1].toString(), '4'); + assert.equal(lockUp[2].toNumber(), now); + assert.equal(lockUp[3].toString(), balance.toString()); -// // edit the lockup -// await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 0, 8, 4, 0, balance, { from: token_owner }); + // edit the lockup + await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 0, 8, 4, 0, balance, { from: token_owner }); -// // attempt a transfer -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); + // attempt a transfer + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); -// // wait 4 seconds -// await new Promise(resolve => setTimeout(resolve, 4000)); + // wait 4 seconds + await new Promise(resolve => setTimeout(resolve, 4000)); -// // transfer should succeed -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); + // transfer should succeed + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); -// }); + }); -// it("Should be possible to remove a lockup", async() => { + it("Should be possible to remove a lockup", async() => { -// let acct1Balance = await I_SecurityToken.balanceOf(account_investor1) + let acct1Balance = await I_SecurityToken.balanceOf(account_investor1) -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); -// // check and get the lockup -// let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); -// assert.equal(lockUpCount, 1) + // check and get the lockup + let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); + assert.equal(lockUpCount, 1) -// // remove the lockup -// await I_VolumeRestrictionTransferManager.removeLockUp(account_investor1, 0, { from: token_owner }); + // remove the lockup + await I_VolumeRestrictionTransferManager.removeLockUp(account_investor1, 0, { from: token_owner }); -// lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); -// assert.equal(lockUpCount, 0) + lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); + assert.equal(lockUpCount, 0) -// let acct2BalanceBefore = await I_SecurityToken.balanceOf(account_investor2) -// await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); -// let acct2BalanceAfter = await I_SecurityToken.balanceOf(account_investor2) + let acct2BalanceBefore = await I_SecurityToken.balanceOf(account_investor2) + await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); + let acct2BalanceAfter = await I_SecurityToken.balanceOf(account_investor2) -// assert.equal(acct2BalanceAfter.sub(acct2BalanceBefore).toString(), acct1Balance.toString()) -// }); + assert.equal(acct2BalanceAfter.sub(acct2BalanceBefore).toString(), acct1Balance.toString()) + }); -// it("Should be possible to create multiple lockups at once", async() => { - -// let balancesBefore = {} - -// // should be 12000000000000000000 -// balancesBefore[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - - -// // should be 10000000000000000000 -// balancesBefore[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - - -// let lockUpCountsBefore = {} - -// // get lockups for acct 2 -// lockUpCountsBefore[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); -// assert.equal(lockUpCountsBefore[account_investor2], 1) // there's one old, expired lockup on acct already - -// // get lockups for acct 3 -// lockUpCountsBefore[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); -// assert.equal(lockUpCountsBefore[account_investor3], 0) - -// // create lockups for their entire balances -// await I_VolumeRestrictionTransferManager.addLockUpMulti( -// [account_investor2, account_investor3], -// [24, 8], -// [4, 4], -// [0, 0], -// [balancesBefore[account_investor2], balancesBefore[account_investor3]], -// { from: token_owner } -// ); - -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// let balancesAfter = {} -// balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) -// assert.equal(balancesBefore[account_investor2].toString(), balancesAfter[account_investor2].toString()) - -// balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) -// assert.equal(balancesBefore[account_investor3].toString(), balancesAfter[account_investor3].toString()) + it("Should be possible to create multiple lockups at once", async() => { + + let balancesBefore = {} + + // should be 12000000000000000000 + balancesBefore[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) + + + // should be 10000000000000000000 + balancesBefore[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) + + + let lockUpCountsBefore = {} + + // get lockups for acct 2 + lockUpCountsBefore[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); + assert.equal(lockUpCountsBefore[account_investor2], 1) // there's one old, expired lockup on acct already + + // get lockups for acct 3 + lockUpCountsBefore[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); + assert.equal(lockUpCountsBefore[account_investor3], 0) + + // create lockups for their entire balances + await I_VolumeRestrictionTransferManager.addLockUpMulti( + [account_investor2, account_investor3], + [24, 8], + [4, 4], + [0, 0], + [balancesBefore[account_investor2], balancesBefore[account_investor3]], + { from: token_owner } + ); + + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + let balancesAfter = {} + balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) + assert.equal(balancesBefore[account_investor2].toString(), balancesAfter[account_investor2].toString()) + + balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) + assert.equal(balancesBefore[account_investor3].toString(), balancesAfter[account_investor3].toString()) -// let lockUpCountsAfter = {} + let lockUpCountsAfter = {} -// // get lockups for acct 2 -// lockUpCountsAfter[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); -// assert.equal(lockUpCountsAfter[account_investor2], 2); - -// // get lockups for acct 3 -// lockUpCountsAfter[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); -// assert.equal(lockUpCountsAfter[account_investor3], 1); - -// // wait 4 seconds -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// // try transfers again -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); - - -// balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) -// assert.equal(balancesBefore[account_investor2].sub(web3.utils.toWei('2', 'ether')).toString(), balancesAfter[account_investor2].toString()) - -// balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) -// assert.equal(balancesBefore[account_investor3].sub(web3.utils.toWei('5', 'ether')).toString(), balancesAfter[account_investor3].toString()) + // get lockups for acct 2 + lockUpCountsAfter[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); + assert.equal(lockUpCountsAfter[account_investor2], 2); + + // get lockups for acct 3 + lockUpCountsAfter[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); + assert.equal(lockUpCountsAfter[account_investor3], 1); + + // wait 4 seconds + await new Promise(resolve => setTimeout(resolve, 4000)); + + // try transfers again + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); + + + balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) + assert.equal(balancesBefore[account_investor2].sub(web3.utils.toWei('2', 'ether')).toString(), balancesAfter[account_investor2].toString()) + + balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) + assert.equal(balancesBefore[account_investor3].sub(web3.utils.toWei('5', 'ether')).toString(), balancesAfter[account_investor3].toString()) -// }); - -// it("Should revert if the parameters are bad when creating multiple lockups", async() => { -// let errorThrown = false; -// try { -// // pass in the wrong number of params. txn should revert -// await I_VolumeRestrictionTransferManager.addLockUpMulti( -// [account_investor2, account_investor3], -// [16, 8], -// [2], // this array should have 2 elements but it has 1, which should cause a revert -// [0, 0], -// [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], -// { from: token_owner } -// ); -// } catch(error) { -// console.log(` tx revert -> passed in wrong number of array elements`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should be possible to create a lockup with a specific start time in the future", async() => { - -// // remove all lockups for account 2 -// let lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); -// assert.equal(lockUpsLength, 2); -// await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); -// await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); -// lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); -// assert.equal(lockUpsLength, 0); - -// let now = (await web3.eth.getBlock('latest')).timestamp - -// // balance here should be 10000000000000000000 -// let balance = await I_SecurityToken.balanceOf(account_investor2) - -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 100, 10, now + 4, balance, { from: token_owner }); - -// // try a transfer. it should fail because the lockup hasn't started yet. -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// now = (await web3.eth.getBlock('latest')).timestamp - -// // wait 4 seconds for the lockup to begin -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// // try another transfer. it should also fail because the lockup has just begun -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// now = (await web3.eth.getBlock('latest')).timestamp - -// assert.ok(errorThrown, message); - -// }); - -// it("Should be possible to edit a lockup with a specific start time in the future", async() => { - -// // edit the lockup -// let now = (await web3.eth.getBlock('latest')).timestamp - -// // should be 10000000000000000000 -// let balance = await I_SecurityToken.balanceOf(account_investor2) - -// // check and get the lockup -// let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); -// assert.equal(lockUpCount, 1) - -// let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - -// // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount -// assert.equal(lockUp[0].toString(), '100'); -// assert.equal(lockUp[1].toString(), '10'); -// assert.isAtMost(lockUp[2].toNumber(), now); -// assert.equal(lockUp[3].toString(), balance.toString()); - -// // edit the lockup -// await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor2, 0, 8, 4, now + 4, balance, { from: token_owner }); - -// // check and get the lockup again -// lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); -// assert.equal(lockUpCount, 1) - -// lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - -// // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount -// assert.equal(lockUp[0].toString(), '8'); -// assert.equal(lockUp[1].toString(), '4'); -// assert.isAtMost(lockUp[2].toNumber(), now + 4); -// assert.equal(lockUp[3].toString(), balance.toString()); - -// // try a transfer. it should fail because again, the lockup hasn't started yet. -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// // wait 4 seconds for the lockup to begin -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// // try another transfer. it should fail because the lockup has just begun -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// // wait 4 seconds for the lockup's first period to elapse -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// // try another transfer. it should pass -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); - - -// // try another transfer without waiting for another period to pass. it should fail -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// // wait 4 seconds for the lockup's first period to elapse -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// let lockUpBeforeVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); -// // check if transfer will pass in read-only operation -// let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('5', 'ether'), 0, false) -// // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 -// assert.equal(result.toString(), '2') -// let lockUpAfterVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - -// assert.equal(lockUpBeforeVerify[4].toString(), lockUpAfterVerify[4].toString()) - -// // try another transfer. it should pass -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); - -// // wait 4 seconds for the lockup's first period to elapse. but, we are all out of periods. -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// // try one final transfer. this should fail because the user has already withdrawn their entire balance -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - -// it("Should be possible to stack lockups", async() => { -// // should be 17000000000000000000 -// let balance = await I_SecurityToken.balanceOf(account_investor1) - -// // check and make sure that acct1 has no lockups so far -// let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); -// assert.equal(lockUpCount.toString(), 0) - -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 12, 4, 0, web3.utils.toWei('6', 'ether'), { from: token_owner }); - -// // try to transfer 11 tokens that aren't locked up yet be locked up. should succeed -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('11', 'ether'), { from: account_investor1 }); - -// // try a transfer. it should fail because it's locked up from the first lockups -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// // wait 4 seconds for the lockup's first period to elapse. -// await new Promise(resolve => setTimeout(resolve, 4000)); - - -// // should succeed -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); - -// // send 8 back to investor1 so that we can lock them up -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('8', 'ether'), { from: account_investor2 }); - -// // let's add another lockup to stack them -// await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, web3.utils.toWei('8', 'ether'), { from: token_owner }); - -// // try a transfer. it should fail because it's locked up from both lockups -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// // wait 4 seconds for the 1st lockup's second period to elapse, and the 2nd lockup's first period to elapse -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - -// // try aother transfer. it should fail because it's locked up from both lockups again -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// } catch(error) { -// console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); - -// // wait 4 seconds for the 1st lockup's final period to elapse, and the 2nd lockup's second period to elapse -// await new Promise(resolve => setTimeout(resolve, 4000)); - -// // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - -// // // try aother transfer. it should fail because it's locked up from both lockups again -// // errorThrown = false; -// // try { -// // await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); -// // } catch(error) { -// // console.log(` tx revert -> couldn't transfer because of lock up`.grey); -// // ensureException(error); -// // errorThrown = true; -// // } -// // assert.ok(errorThrown, message); - -// // wait 8 seconds for 2nd lockup's third and fourth periods to elapse -// await new Promise(resolve => setTimeout(resolve, 8000)); - -// // should now be able to transfer 4, because there are 2 allowed per period in the 2nd lockup, and 2 periods have elapsed -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - -// // send the 3 back from acct2 that we sent over in the beginning of this test -// await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); - -// // try another transfer. it should pass because both lockups have been entirely used -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - -// balance = await I_SecurityToken.balanceOf(account_investor1) -// assert.equal(balance.toString(), web3.utils.toWei('2', 'ether')) -// }); - - -// it("Should get configuration function signature", async() => { -// let sig = await I_VolumeRestrictionTransferManager.getInitFunction.call(); -// assert.equal(web3.utils.hexToNumber(sig), 0); -// }); - - -// it("Should get the permission", async() => { -// let perm = await I_VolumeRestrictionTransferManager.getPermissions.call(); -// assert.equal(perm.length, 1); -// // console.log(web3.utils.toAscii(perm[0]).replace(/\u0000/g, '')) -// assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "ADMIN") -// }); - -// }); - -// describe("VolumeRestriction Transfer Manager Factory test cases", async() => { - -// it("Should get the exact details of the factory", async() => { -// assert.equal(await I_VolumeRestrictionTransferManagerFactory.setupCost.call(),0); -// assert.equal((await I_VolumeRestrictionTransferManagerFactory.getTypes.call())[0],2); -// assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTransferManagerFactory.getName.call()) -// .replace(/\u0000/g, ''), -// "VolumeRestrictionTransferManager", -// "Wrong Module added"); -// assert.equal(await I_VolumeRestrictionTransferManagerFactory.getDescription.call(), -// "Manage transfers using lock ups over time", -// "Wrong Module added"); -// assert.equal(await I_VolumeRestrictionTransferManagerFactory.getTitle.call(), -// "Volume Restriction Transfer Manager", -// "Wrong Module added"); -// assert.equal(await I_VolumeRestrictionTransferManagerFactory.getInstructions.call(), -// "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", -// "Wrong Module added"); - -// }); - -// it("Should get the tags of the factory", async() => { -// let tags = await I_VolumeRestrictionTransferManagerFactory.getTags.call(); -// assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Volume"); -// }); -// }); - -// }); + }); + + it("Should revert if the parameters are bad when creating multiple lockups", async() => { + let errorThrown = false; + try { + // pass in the wrong number of params. txn should revert + await I_VolumeRestrictionTransferManager.addLockUpMulti( + [account_investor2, account_investor3], + [16, 8], + [2], // this array should have 2 elements but it has 1, which should cause a revert + [0, 0], + [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], + { from: token_owner } + ); + } catch(error) { + console.log(` tx revert -> passed in wrong number of array elements`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should be possible to create a lockup with a specific start time in the future", async() => { + + // remove all lockups for account 2 + let lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); + assert.equal(lockUpsLength, 2); + await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); + await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); + lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); + assert.equal(lockUpsLength, 0); + + let now = (await web3.eth.getBlock('latest')).timestamp + + // balance here should be 10000000000000000000 + let balance = await I_SecurityToken.balanceOf(account_investor2) + + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 100, 10, now + 4, balance, { from: token_owner }); + + // try a transfer. it should fail because the lockup hasn't started yet. + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + now = (await web3.eth.getBlock('latest')).timestamp + + // wait 4 seconds for the lockup to begin + await new Promise(resolve => setTimeout(resolve, 4000)); + + // try another transfer. it should also fail because the lockup has just begun + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + now = (await web3.eth.getBlock('latest')).timestamp + + assert.ok(errorThrown, message); + + }); + + it("Should be possible to edit a lockup with a specific start time in the future", async() => { + + // edit the lockup + let now = (await web3.eth.getBlock('latest')).timestamp + + // should be 10000000000000000000 + let balance = await I_SecurityToken.balanceOf(account_investor2) + + // check and get the lockup + let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); + assert.equal(lockUpCount, 1) + + let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); + + // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount + assert.equal(lockUp[0].toString(), '100'); + assert.equal(lockUp[1].toString(), '10'); + assert.isAtMost(lockUp[2].toNumber(), now); + assert.equal(lockUp[3].toString(), balance.toString()); + + // edit the lockup + await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor2, 0, 8, 4, now + 4, balance, { from: token_owner }); + + // check and get the lockup again + lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); + assert.equal(lockUpCount, 1) + + lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); + + // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount + assert.equal(lockUp[0].toString(), '8'); + assert.equal(lockUp[1].toString(), '4'); + assert.isAtMost(lockUp[2].toNumber(), now + 4); + assert.equal(lockUp[3].toString(), balance.toString()); + + // try a transfer. it should fail because again, the lockup hasn't started yet. + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + // wait 4 seconds for the lockup to begin + await new Promise(resolve => setTimeout(resolve, 4000)); + + // try another transfer. it should fail because the lockup has just begun + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + // wait 4 seconds for the lockup's first period to elapse + await new Promise(resolve => setTimeout(resolve, 4000)); + + // try another transfer. it should pass + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); + + + // try another transfer without waiting for another period to pass. it should fail + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + // wait 4 seconds for the lockup's first period to elapse + await new Promise(resolve => setTimeout(resolve, 4000)); + + let lockUpBeforeVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); + // check if transfer will pass in read-only operation + let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('5', 'ether'), 0, false) + // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 + assert.equal(result.toString(), '2') + let lockUpAfterVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); + + assert.equal(lockUpBeforeVerify[4].toString(), lockUpAfterVerify[4].toString()) + + // try another transfer. it should pass + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); + + // wait 4 seconds for the lockup's first period to elapse. but, we are all out of periods. + await new Promise(resolve => setTimeout(resolve, 4000)); + + // try one final transfer. this should fail because the user has already withdrawn their entire balance + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + it("Should be possible to stack lockups", async() => { + // should be 17000000000000000000 + let balance = await I_SecurityToken.balanceOf(account_investor1) + + // check and make sure that acct1 has no lockups so far + let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); + assert.equal(lockUpCount.toString(), 0) + + await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 12, 4, 0, web3.utils.toWei('6', 'ether'), { from: token_owner }); + + // try to transfer 11 tokens that aren't locked up yet be locked up. should succeed + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('11', 'ether'), { from: account_investor1 }); + + // try a transfer. it should fail because it's locked up from the first lockups + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + // wait 4 seconds for the lockup's first period to elapse. + await new Promise(resolve => setTimeout(resolve, 4000)); + + + // should succeed + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); + + // send 8 back to investor1 so that we can lock them up + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('8', 'ether'), { from: account_investor2 }); + + // let's add another lockup to stack them + await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, web3.utils.toWei('8', 'ether'), { from: token_owner }); + + // try a transfer. it should fail because it's locked up from both lockups + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + // wait 4 seconds for the 1st lockup's second period to elapse, and the 2nd lockup's first period to elapse + await new Promise(resolve => setTimeout(resolve, 4000)); + + // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); + + // try aother transfer. it should fail because it's locked up from both lockups again + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> couldn't transfer because of lock up`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + + // wait 4 seconds for the 1st lockup's final period to elapse, and the 2nd lockup's second period to elapse + await new Promise(resolve => setTimeout(resolve, 4000)); + + // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); + + // // try aother transfer. it should fail because it's locked up from both lockups again + // errorThrown = false; + // try { + // await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + // } catch(error) { + // console.log(` tx revert -> couldn't transfer because of lock up`.grey); + // ensureException(error); + // errorThrown = true; + // } + // assert.ok(errorThrown, message); + + // wait 8 seconds for 2nd lockup's third and fourth periods to elapse + await new Promise(resolve => setTimeout(resolve, 8000)); + + // should now be able to transfer 4, because there are 2 allowed per period in the 2nd lockup, and 2 periods have elapsed + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); + + // send the 3 back from acct2 that we sent over in the beginning of this test + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); + + // try another transfer. it should pass because both lockups have been entirely used + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + + balance = await I_SecurityToken.balanceOf(account_investor1) + assert.equal(balance.toString(), web3.utils.toWei('2', 'ether')) + }); + + + it("Should get configuration function signature", async() => { + let sig = await I_VolumeRestrictionTransferManager.getInitFunction.call(); + assert.equal(web3.utils.hexToNumber(sig), 0); + }); + + + it("Should get the permission", async() => { + let perm = await I_VolumeRestrictionTransferManager.getPermissions.call(); + assert.equal(perm.length, 1); + // console.log(web3.utils.toAscii(perm[0]).replace(/\u0000/g, '')) + assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "ADMIN") + }); + + }); + + describe("VolumeRestriction Transfer Manager Factory test cases", async() => { + + it("Should get the exact details of the factory", async() => { + assert.equal(await I_VolumeRestrictionTransferManagerFactory.setupCost.call(),0); + assert.equal((await I_VolumeRestrictionTransferManagerFactory.getTypes.call())[0],2); + assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTransferManagerFactory.getName.call()) + .replace(/\u0000/g, ''), + "VolumeRestrictionTransferManager", + "Wrong Module added"); + assert.equal(await I_VolumeRestrictionTransferManagerFactory.getDescription.call(), + "Manage transfers using lock ups over time", + "Wrong Module added"); + assert.equal(await I_VolumeRestrictionTransferManagerFactory.getTitle.call(), + "Volume Restriction Transfer Manager", + "Wrong Module added"); + assert.equal(await I_VolumeRestrictionTransferManagerFactory.getInstructions.call(), + "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", + "Wrong Module added"); + + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_VolumeRestrictionTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Volume"); + }); + }); + +}); diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index afbcdb07f..64813eed1 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -1,1178 +1,1178 @@ -// import latestTime from './helpers/latestTime'; -// import { -// duration, -// ensureException, -// promisifyLogWatch, -// latestBlock -// } from './helpers/utils'; -// import takeSnapshot, { -// increaseTime, -// revertToSnapshot -// } from './helpers/time'; -// import { -// encodeProxyCall -// } from './helpers/encodeCall'; - -// const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -// const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -// const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -// const SecurityToken = artifacts.require('./SecurityToken.sol'); -// const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -// const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -// const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -// const STFactory = artifacts.require('./STFactory.sol'); -// const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -// const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -// const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -// const SingleTradeVolumeRestrictionManagerFactory = artifacts.require('./SingleTradeVolumeRestrictionManagerFactory.sol'); -// const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionManager'); -// const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); -// const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -// const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); - -// const Web3 = require('web3'); -// const BigNumber = require('bignumber.js'); -// const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -// contract('SingleTradeVolumeRestrictionManager', accounts => { - - - -// // Accounts Variable declaration -// let account_polymath; -// let account_issuer; -// let token_owner; -// let account_investor1; -// let account_investor2; -// let account_investor3; -// let account_investor4; -// let account_investor5; -// let zero_address = '0x0000000000000000000000000000000000000000'; - -// // investor Details -// let fromTime = latestTime(); -// let toTime = latestTime(); -// let expiryTime = toTime + duration.days(15); - -// let message = "Transaction Should Fail!"; - -// // Contract Instance Declaration -// let I_SecurityTokenRegistryProxy -// let I_GeneralPermissionManagerFactory; -// let I_GeneralTransferManagerFactory; -// let I_GeneralPermissionManager; -// let I_GeneralTransferManager; -// let I_SingleTradeVolumeRestrictionManagerFactory; -// let I_SingleTradeVolumeRestrictionManager; -// let P_SingleTradeVolumeRestrictionManagerFactory; -// let P_SingleTradeVolumeRestrictionManager; -// let I_SingleTradeVolumeRestrictionPercentageManager; -// let I_ModuleRegistry; -// let I_MRProxied; -// let I_ModuleRegistryProxy; -// let I_FeatureRegistry; -// let I_SecurityTokenRegistry; -// let I_STRProxied; -// let I_STFactory; -// let I_SecurityToken; -// let I_PolyToken; -// let I_PolymathRegistry; - -// const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; -// const MRProxyParameters = ['address', 'address']; - -// // SecurityToken Details -// const swarmHash = "dagwrgwgvwergwrvwrg"; -// const name = "Team"; -// const symbol = "sap"; -// const tokenDetails = "This is equity type of issuance"; -// const decimals = 18; -// const contact = "team@polymath.network"; - -// // Module key -// const delegateManagerKey = 1; -// const transferManagerKey = 2; -// const stoKey = 3; - -// // Initial fee for ticker registry and security token registry -// const initRegFee = web3.utils.toWei("250"); - -// before(async () => { -// // Accounts setup -// account_polymath = accounts[0]; -// account_issuer = accounts[1]; - -// token_owner = account_issuer; - -// account_investor1 = accounts[6]; -// account_investor2 = accounts[7]; -// account_investor3 = accounts[8]; -// account_investor4 = accounts[9]; -// account_investor5 = accounts[5]; - -// // ----------- POLYMATH NETWORK Configuration ------------ - -// // Step 0: Deploy the PolymathRegistry -// I_PolymathRegistry = await PolymathRegistry.new({ -// from: account_polymath -// }); - -// // Step 1: Deploy the token Faucet and Mint tokens for token_owner -// I_PolyToken = await PolyTokenFaucet.new(); -// await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - -// I_FeatureRegistry = await FeatureRegistry.new( -// I_PolymathRegistry.address, { -// from: account_polymath -// }); - -// // STEP 2: Deploy the ModuleRegistry - -// I_ModuleRegistry = await ModuleRegistry.new({ -// from: account_polymath -// }); -// // -// I_ModuleRegistryProxy = await ModuleRegistryProxy.new({ -// from: account_polymath -// }); - -// let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); -// await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, { -// from: account_polymath -// }); -// I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - -// // -// // -// // // STEP 2: Deploy the GeneralTransferManagerFactory -// // -// I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { -// from: account_polymath -// }); - -// assert.notEqual( -// I_GeneralTransferManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralTransferManagerFactory contract was not deployed" -// ); - -// // STEP 3: Deploy the GeneralDelegateManagerFactoryFactory - -// I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { -// from: account_polymath -// }); - -// assert.notEqual( -// I_GeneralPermissionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "GeneralDelegateManagerFactory contract was not deployed" -// ); - -// // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory -// I_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { -// from: account_polymath -// }); - -// assert.notEqual( -// I_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" -// ); - - -// P_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, { -// from: account_polymath -// }); -// assert.notEqual( -// P_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" -// ); -// // -// // -// // // Step 6: Deploy the STFactory contract -// // -// I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, { -// from: account_polymath -// }); - -// assert.notEqual( -// I_STFactory.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "STFactory contract was not deployed", -// ); - -// // Step 7: Deploy the SecurityTokenRegistry contract - -// I_SecurityTokenRegistry = await SecurityTokenRegistry.new({ -// from: account_polymath -// }); - -// assert.notEqual( -// I_SecurityTokenRegistry.address.valueOf(), -// "0x0000000000000000000000000000000000000000", -// "SecurityTokenRegistry contract was not deployed", -// ); - -// // Step 8: Deploy the proxy and attach the implementation contract to it. -// I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({ -// from: account_polymath -// }); -// let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); -// await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { -// from: account_polymath -// }); -// I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); -// // -// // // Step 9: update the registries addresses from the PolymathRegistry contract -// await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, { -// from: account_polymath -// }) -// await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, { -// from: account_polymath -// }); -// await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, { -// from: account_polymath -// }); -// await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, { -// from: account_polymath -// }); -// await I_MRProxied.updateFromRegistry({ -// from: account_polymath -// }); - -// await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { -// from: account_polymath -// }); -// await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { -// from: account_polymath -// }); - -// // (B) : Register the GeneralDelegateManagerFactory -// await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { -// from: account_polymath -// }); -// await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { -// from: account_polymath -// }); - -// // (C) : Register the SingleTradeVolumeRestrictionManagerFactory -// await I_MRProxied.registerModule(I_SingleTradeVolumeRestrictionManagerFactory.address, { -// from: account_polymath -// }); -// await I_MRProxied.verifyModule(I_SingleTradeVolumeRestrictionManagerFactory.address, true, { -// from: account_polymath -// }); - -// // (C) : Register the Paid SingleTradeVolumeRestrictionManagerFactory -// await I_MRProxied.registerModule(P_SingleTradeVolumeRestrictionManagerFactory.address, { -// from: account_polymath -// }); -// await I_MRProxied.verifyModule(P_SingleTradeVolumeRestrictionManagerFactory.address, true, { -// from: account_polymath -// }); -// }) - -// describe("Generate the SecurityToken", async () => { -// it("Should register the ticker before the generation of the security token", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { -// from: token_owner -// }); -// let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { -// from: token_owner -// }); -// assert.equal(tx.logs[0].args._owner, token_owner); -// assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); -// }); - -// it("Should generate the new security token with the same symbol as registered above", async () => { -// await I_PolyToken.approve(I_STRProxied.address, initRegFee, { -// from: token_owner -// }); -// let _blockNo = latestBlock(); -// let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { -// from: token_owner -// }); - -// // Verify the successful generation of the security token -// assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - -// I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - -// const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ -// from: _blockNo -// }), 1); - -// // Verify that GeneralTransferManager module get added successfully or not -// assert.equal(log.args._types[0].toNumber(), 2); -// assert.equal( -// web3.utils.toAscii(log.args._name) -// .replace(/\u0000/g, ''), -// "GeneralTransferManager" -// ); -// }); - -// it("Should intialize the auto attached modules", async () => { -// let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; -// I_GeneralTransferManager = GeneralTransferManager.at(moduleData); -// }); -// }); -// // -// describe("Buy tokens using whitelist & manual approvals", async () => { - -// it("Should Buy the tokens", async () => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor1, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, { -// from: account_issuer -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Jump time -// await increaseTime(5000); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor1, web3.utils.toWei('100', 'ether'), { -// from: token_owner -// }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), -// web3.utils.toWei('100', 'ether') -// ); -// }); - -// it("Should Buy some more tokens", async () => { -// // Add the Investor in to the whitelist - -// let tx = await I_GeneralTransferManager.modifyWhitelist( -// account_investor2, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, { -// from: account_issuer -// }); - -// assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - -// // Mint some tokens -// await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { -// from: token_owner -// }); - -// assert.equal( -// (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), -// web3.utils.toWei('1', 'ether') -// ); -// }); -// // -// it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { -// let managerArgs = web3.eth.abi.encodeFunctionCall({ -// name: 'configure', -// type: 'function', -// inputs: [{ -// type: 'bool', -// name: '_isTransferLimitInPercentage' -// }, -// { -// type: 'uint256', -// name: '_globalTransferLimitInPercentageOrToken' -// }, -// { -// type: 'bool', -// name: '_allowPrimaryIssuance' -// } -// ] -// }, [true, 90, false]) -// let errorThrown = false; -// await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); -// try { -// const tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { -// from: token_owner -// }); -// } catch (error) { -// console.log(` tx -> failed because Token is not paid`.grey); -// ensureException(error); -// errorThrown = true; -// } -// assert.ok(errorThrown, message); -// }); - - - -// it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { -// let managerArgs = web3.eth.abi.encodeFunctionCall({ -// name: 'configure', -// type: 'function', -// inputs: [{ -// type: 'bool', -// name: '_isTransferLimitInPercentage' -// }, -// { -// type: 'uint256', -// name: '_globalTransferLimitInPercentageOrToken' -// }, -// { -// type: 'bool', -// name: '_allowPrimaryIssuance' -// } -// ] -// }, [false, 90, false]); -// await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { -// from: token_owner -// }); -// let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { -// from: token_owner -// }); -// assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "SingleTradeVolumeRestrictionManager did not get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[3].args._name) -// .replace(/\u0000/g, ''), -// "SingleTradeVolumeRestriction", -// "SingleTradeVolumeRestrictionManagerFactory module was not added" -// ); -// P_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[3].args._module); -// }); - -// it("Should successfully attach the SingleTradeVolumeRestrictionManager with the security token", async () => { -// let managerArgs = web3.eth.abi.encodeFunctionCall({ -// name: 'configure', -// type: 'function', -// inputs: [{ -// type: 'bool', -// name: '_isTransferLimitInPercentage' -// }, -// { -// type: 'uint256', -// name: '_globalTransferLimitInPercentageOrToken' -// }, -// { -// type: 'bool', -// name: '_allowPrimaryIssuance' -// } -// ] -// }, [false, 7 * 10 ** 16, false]) -// const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { -// from: token_owner -// }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "SingleTradeVolumeRestriction", -// "SingleTradeVolumeRestriction module was not added" -// ); -// I_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); -// }); - -// it("Should successfully attach the SingleTradeVolumeRestrictionManager (Percentage) with the security token", async () => { -// let managerArgs = web3.eth.abi.encodeFunctionCall({ -// name: 'configure', -// type: 'function', -// inputs: [{ -// type: 'bool', -// name: '_isTransferLimitInPercentage' -// }, -// { -// type: 'uint256', -// name: '_globalTransferLimitInPercentageOrToken' -// }, -// { -// type: 'bool', -// name: '_allowPrimaryIssuance' -// } -// ] -// }, [true, 90, false]); -// const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { -// from: token_owner -// }); -// assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); -// assert.equal( -// web3.utils.toAscii(tx.logs[2].args._name) -// .replace(/\u0000/g, ''), -// "SingleTradeVolumeRestriction", -// "SingleTradeVolumeRestriction module was not added" -// ); -// I_SingleTradeVolumeRestrictionPercentageManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); -// }); - -// it('should return get permissions', async () => { -// let permissions = await I_SingleTradeVolumeRestrictionPercentageManager.getPermissions(); -// assert.equal(permissions.length, 1, "Invalid Permissions"); -// assert.equal( -// web3.utils.toAscii(permissions[0]).replace(/\u0000/g, ''), -// "ADMIN", -// 'Wrong permissions' -// ); -// }); - -// it('add exempt wallet', async () => { -// let errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]); -// } catch (e) { -// errorThrown = true; -// } -// assert.ok(errorThrown, "Non Admins cannot add exempt wallets"); - -// errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { -// from: token_owner -// }); -// } catch (e) { -// ensureException(e); -// errorThrown = true; -// } - -// assert.ok(errorThrown, "Exempt wallet cannot be zero"); - -// let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { -// from: token_owner -// }); -// assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet added as exempt"); -// }); - -// it('should remove an exempt wallet', async () => { -// let errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5]); -// } catch (e) { -// errorThrown = true; -// } -// assert.ok(errorThrown, "Non Admins cannot add exempt wallets"); - -// errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(zero_address, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } - -// assert.ok(errorThrown, "Zero address cannot be added to exempt wallet"); - -// let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { -// from: token_owner -// }); -// assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet removed from exempt"); -// }); - -// it('should set transfer limit for a wallet', async () => { -// let errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100); -// } catch (e) { -// errorThrown = true; -// } -// assert.ok(errorThrown, "Non Admins cannot set transfer limits"); - -// errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 0, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Transfer limit cannot be set to 0") -// errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInPercentage(accounts[4], 10, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Transfer limit cannot be set in percentage") -// let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { -// from: token_owner -// }); -// assert.equal(tx.logs[0].args._wallet, accounts[4]); -// assert.equal(tx.logs[0].args._amount, 100); - -// errorThrown = false; -// try { -// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 0, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// errorThrown = false -// try { -// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Transfer limit can not be set to more 0") -// errorThrown = false; -// try { -// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } - -// assert.ok(errorThrown, "Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage") -// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 50, { -// from: token_owner -// }); -// assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet added to transfer limits"); -// assert.equal(tx.logs[0].args._percentage, 50, "Wrong percentage set"); -// }); - -// it('should remove transfer limit for wallet', async () => { -// let errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4]); -// } catch (e) { -// errorThrown = true; -// } -// assert.ok(errorThrown, "Non Admins cannot set/remove transfer limits"); - -// errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[0], { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// } -// assert.ok(errorThrown, "Non Admins cannot set/remove transfer limits"); - -// let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4], { -// from: token_owner -// }); -// assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet removed"); -// }); - -// it("Should pause the tranfers at Manager level", async () => { -// let tx = await I_SingleTradeVolumeRestrictionManager.pause({ -// from: token_owner -// }); -// }); - -// it('should be able to set a global transfer limit', async () => { -// let errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(100 * 10 ** 18); -// } catch (e) { -// errorThrown = true; -// } -// assert.ok(errorThrown, "only owner is allowed"); - -// errorThrown = false; - -// try { -// let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(100 * 10 ** 18, { -// from: token_owner -// }); -// } catch (e) { -// ensureException(e); -// errorThrown = true; -// } -// assert.ok(errorThrown, "Cannot change global limit in percentage when set to tokens"); - -// errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(0, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Global limit cannot be set to 0"); -// let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { -// from: token_owner -// }); -// assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - -// errorThrown = false; - -// try { -// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Global limit can be set by non-admins"); - -// errorThrown = false; - -// try { -// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "cannot change global limit in tokens if transfer limit is set to percentage"); - -// errorThrown = false; -// try { -// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(0, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Cannot set global limit in tokens to 0"); - -// tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(40, { -// from: token_owner -// }); -// assert.equal(tx.logs[0].args._percentage, 40, "Global Limit not set"); - -// errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(101 * 10 ** 16, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Global limit cannot be set to more than 100"); - -// errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(10, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Global limit in percentage cannot be set when limit is in tokens"); -// errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(10, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Global limit in tokens cannot be set when limit is in percentage"); -// }); - -// it('should perform batch updates', async () => { -// let wallets = [accounts[0], accounts[1], accounts[2]]; -// let tokenLimits = [1, 2, 3]; -// let percentageLimits = [5, 6, 7]; - -// let errorThrown = false; -// try { -// await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti([], { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Exempt wallet multi cannot be empty wallet"); - -// // add exempt wallet multi -// let tx = await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { -// from: token_owner -// }); -// let logs = tx.logs.filter(log => log.event === 'ExemptWalletAdded'); -// assert.equal(logs.length, wallets.length, "Batch Exempt wallets not added"); -// for (let i = 0; i < logs.length; i++) { -// assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); -// } - -// errorThrown = false; -// try { -// await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti([], { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Exempt wallet multi cannot be empty wallet"); - -// // remove exempt wallet multi -// tx = await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { -// from: token_owner -// }) -// logs = tx.logs.filter(log => log.event === 'ExemptWalletRemoved'); -// assert.equal(logs.length, wallets.length, "Batch Exempt wallets not removed"); - -// for (let i = 0; i < logs.length; i++) { -// assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); -// } - -// errorThrown = false; -// try { -// tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([], tokenLimits, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "wallets cannot be empty"); - -// errorThrown = false; -// try { -// tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([accounts[0]], tokenLimits, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "wallet array length dont match"); - -// tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { -// from: token_owner -// }); -// logs = tx.logs.filter(log => log.event == 'TransferLimitInTokensSet'); -// assert.equal(wallets.length, logs.length, "Transfer limit not set"); -// for (let i = 0; i < wallets.length; i++) { -// assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not set for wallet"); -// assert.equal(logs[i].args._amount.toNumber(), tokenLimits[i]); -// } -// errorThrown = false -// try { -// await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti([], { -// from: token_owner -// }); -// } catch (e) { -// ensureException(e); -// errorThrown = true; -// } -// assert.ok(errorThrown, "Wallets cannot be empty"); -// tx = await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, { -// from: token_owner -// }); -// logs = tx.logs.filter(log => log.event === 'TransferLimitInTokensRemoved'); -// assert.equal(logs.length, wallets.length, "Transfer limit not removed"); -// for (let i = 0; i < wallets.length; i++) { -// assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not removed for wallet"); -// } - -// errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti([], percentageLimits, { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "wallets cannot be empty"); - -// errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, [], { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "wallets and amounts dont match be empty"); -// tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { -// from: token_owner -// }); -// logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageSet'); -// assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - -// for (let i = 0; i < wallets.length; i++) { -// assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); -// assert.equal(logs[i].args._percentage.toNumber(), percentageLimits[i]); -// } - -// errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti([], { -// from: token_owner -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Wallets cannot be empty"); - -// tx = await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { -// from: token_owner -// }); -// logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageRemoved'); -// assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - -// for (let i = 0; i < wallets.length; i++) { -// assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); -// } - -// errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentage(wallets[0], { -// from: token_owner -// }); -// } catch (e) { -// ensureException(e) -// errorThrown = true; -// } -// assert.ok(errorThrown, "Wallet should not be removed"); -// }) - -// it('should be able to transfer tokens SingleTradeVolumeRestriction', async () => { -// await I_SingleTradeVolumeRestrictionManager.unpause({ -// from: token_owner -// }) -// await I_SingleTradeVolumeRestrictionPercentageManager.pause({ -// from: token_owner -// }) -// await P_SingleTradeVolumeRestrictionManager.pause({ -// from: token_owner -// }); - -// await I_GeneralTransferManager.modifyWhitelist( -// account_investor3, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, { -// from: account_issuer -// } -// ); - -// await I_GeneralTransferManager.modifyWhitelist( -// account_investor4, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, { -// from: account_issuer -// } -// ); - -// await I_GeneralTransferManager.modifyWhitelist( -// account_investor5, -// latestTime(), -// latestTime(), -// latestTime() + duration.days(10), -// true, { -// from: account_issuer -// } -// ); - - -// //setting a max of 5 tokens -// await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(web3.utils.toWei('5', 'ether'), { -// from: token_owner -// }) - -// let errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('6', 'ether'), { -// from: account_investor1 -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Transfer should have not happened"); -// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('4', 'ether'), { -// from: account_investor1 -// }); -// assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('4', 'ether')); - -// // exempt wallet -// await I_SingleTradeVolumeRestrictionManager.addExemptWallet(account_investor1, { -// from: token_owner -// }); -// await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('7', 'ether'), { -// from: account_investor1 -// }); -// assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toNumber(), web3.utils.toWei('7', 'ether')); - -// //special limits wallet -// await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(account_investor5, web3.utils.toWei('5', 'ether'), { -// from: token_owner -// }); -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('7', 'ether'), { -// from: account_investor5 -// }); -// } catch (e) { -// errorThrown = true; -// ensureException(e); -// } -// assert.ok(errorThrown, "Transfer should have not happened"); -// await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('4', 'ether'), { -// from: account_investor5 -// }) -// assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei('4', 'ether')) -// }) - -// it('should be able to transfer tokens (percentage transfer limit)', async () => { -// await I_SingleTradeVolumeRestrictionManager.pause({ -// from: token_owner -// }); -// let balance = (await I_SecurityToken.balanceOf(account_investor2)).toNumber(); -// await I_SecurityToken.transfer(account_investor1, balance, { -// from: account_investor2 -// }); - - -// balance = (await I_SecurityToken.balanceOf(account_investor3)).toNumber(); - -// await I_SecurityToken.transfer(account_investor1, balance, { -// from: account_investor3 -// }); - - -// balance = (await I_SecurityToken.balanceOf(account_investor4)).toNumber(); -// await I_SecurityToken.transfer(account_investor1, balance, { -// from: account_investor4 -// }); - -// balance = (await I_SecurityToken.balanceOf(account_investor5)).toNumber(); -// await I_SecurityToken.transfer(account_investor1, balance, { -// from: account_investor5 -// }); - -// await I_SingleTradeVolumeRestrictionPercentageManager.unpause({ -// from: token_owner -// }); -// // // -// await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(49 * 10 ** 16, { -// from: token_owner -// }); - -// let errorThrown = false; -// try { -// // more than the limit -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('90', 'ether'), { -// from: account_investor1 -// }); -// } catch (e) { -// ensureException(e); -// errorThrown = true; -// } -// assert.ok(errorThrown, "Transfer above limit happened"); - - -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('20', 'ether'), { -// from: account_investor1 -// }); -// assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei('20', 'ether')) - -// await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(account_investor1, 5 * 10 ** 16, { -// from: token_owner -// }); -// errorThrown = false; -// try { -// await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('35', 'ether'), { -// from: account_investor1 -// }); -// } catch (e) { -// ensureException(e); -// errorThrown = true; -// } -// assert.ok(errorThrown, "transfer happened above limit"); - -// await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { -// from: account_investor1 -// }); -// assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('1', 'ether')); -// }); - -// it('should change transfer limits to tokens', async () => { -// let errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { -// from: token_owner -// }); -// } catch (e) { - -// ensureException(e); -// errorThrown = true; -// } -// assert.equal(errorThrown, true, "Should not change to percentage again"); - - -// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { -// from: token_owner -// }); -// assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); -// assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); -// }) - -// it('should change transfer limits to percentage', async () => { -// let errorThrown = false; -// try { -// await I_SingleTradeVolumeRestrictionManager.changeTransferLimitToTokens(1, { -// from: token_owner -// }); -// } catch (e) { -// ensureException(e); -// errorThrown = true; -// } -// assert.equal(errorThrown, true, "Should not change to tokens again"); - -// let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { -// from: token_owner -// }); -// assert.ok(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), "Error Changing"); -// assert.equal(tx.logs[0].args._percentage.toNumber(), 1, "Transfer limit not changed"); -// }) - - - -// }); - -// describe("SingleTradeVolumeRestrictionManager Factory test cases", async () => { - -// it("Should get the exact details of the factory", async () => { -// assert.equal(await I_SingleTradeVolumeRestrictionManagerFactory.setupCost.call(), 0); -// assert.equal((await I_SingleTradeVolumeRestrictionManagerFactory.getTypes.call())[0], 2); -// let name = web3.utils.toUtf8(await I_SingleTradeVolumeRestrictionManagerFactory.getName.call()); -// assert.equal(name, "SingleTradeVolumeRestriction", "Wrong Module added"); -// let desc = await I_SingleTradeVolumeRestrictionManagerFactory.getDescription.call(); -// assert.equal(desc, "Imposes volume restriction on a single trade", "Wrong Module added"); -// let title = await I_SingleTradeVolumeRestrictionManagerFactory.getTitle.call(); -// assert.equal(title, "Single Trade Volume Restriction Manager", "Wrong Module added"); -// let inst = await I_SingleTradeVolumeRestrictionManagerFactory.getInstructions.call(); -// assert.equal(inst, "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens", "Wrong Module added"); -// let version = await I_SingleTradeVolumeRestrictionManagerFactory.getVersion.call(); -// assert.equal(version, "1.0.0", "Version not correct"); -// }); - -// it("Should get the tags of the factory", async () => { -// let tags = await I_SingleTradeVolumeRestrictionManagerFactory.getTags.call(); -// assert.equal(web3.utils.toUtf8(tags[0]), "Single Trade"); -// assert.equal(web3.utils.toUtf8(tags[1]), "Transfer"); -// assert.equal(web3.utils.toUtf8(tags[2]), "Volume"); -// }); - - -// }); -// }); +import latestTime from './helpers/latestTime'; +import { + duration, + ensureException, + promisifyLogWatch, + latestBlock +} from './helpers/utils'; +import takeSnapshot, { + increaseTime, + revertToSnapshot +} from './helpers/time'; +import { + encodeProxyCall +} from './helpers/encodeCall'; + +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); +const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); +const STFactory = artifacts.require('./STFactory.sol'); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const SingleTradeVolumeRestrictionManagerFactory = artifacts.require('./SingleTradeVolumeRestrictionManagerFactory.sol'); +const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionManager'); +const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('SingleTradeVolumeRestrictionManager', accounts => { + + + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_investor5; + let zero_address = '0x0000000000000000000000000000000000000000'; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_SecurityTokenRegistryProxy + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_SingleTradeVolumeRestrictionManagerFactory; + let I_SingleTradeVolumeRestrictionManager; + let P_SingleTradeVolumeRestrictionManagerFactory; + let P_SingleTradeVolumeRestrictionManager; + let I_SingleTradeVolumeRestrictionPercentageManager; + let I_ModuleRegistry; + let I_MRProxied; + let I_ModuleRegistryProxy; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + // SecurityToken Details + const swarmHash = "dagwrgwgvwergwrvwrg"; + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + before(async () => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[6]; + account_investor2 = accounts[7]; + account_investor3 = accounts[8]; + account_investor4 = accounts[9]; + account_investor5 = accounts[5]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({ + from: account_polymath + }); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, { + from: account_polymath + }); + + // STEP 2: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({ + from: account_polymath + }); + // + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({ + from: account_polymath + }); + + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, { + from: account_polymath + }); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + + // + // + // // STEP 2: Deploy the GeneralTransferManagerFactory + // + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { + from: account_polymath + }); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // STEP 3: Deploy the GeneralDelegateManagerFactoryFactory + + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { + from: account_polymath + }); + + assert.notEqual( + I_GeneralPermissionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralDelegateManagerFactory contract was not deployed" + ); + + // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory + I_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { + from: account_polymath + }); + + assert.notEqual( + I_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" + ); + + + P_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, { + from: account_polymath + }); + assert.notEqual( + P_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" + ); + // + // + // // Step 6: Deploy the STFactory contract + // + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, { + from: account_polymath + }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 7: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({ + from: account_polymath + }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 8: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({ + from: account_polymath + }); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { + from: account_polymath + }); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + // + // // Step 9: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, { + from: account_polymath + }) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, { + from: account_polymath + }); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, { + from: account_polymath + }); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, { + from: account_polymath + }); + await I_MRProxied.updateFromRegistry({ + from: account_polymath + }); + + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { + from: account_polymath + }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { + from: account_polymath + }); + + // (B) : Register the GeneralDelegateManagerFactory + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { + from: account_polymath + }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { + from: account_polymath + }); + + // (C) : Register the SingleTradeVolumeRestrictionManagerFactory + await I_MRProxied.registerModule(I_SingleTradeVolumeRestrictionManagerFactory.address, { + from: account_polymath + }); + await I_MRProxied.verifyModule(I_SingleTradeVolumeRestrictionManagerFactory.address, true, { + from: account_polymath + }); + + // (C) : Register the Paid SingleTradeVolumeRestrictionManagerFactory + await I_MRProxied.registerModule(P_SingleTradeVolumeRestrictionManagerFactory.address, { + from: account_polymath + }); + await I_MRProxied.verifyModule(P_SingleTradeVolumeRestrictionManagerFactory.address, true, { + from: account_polymath + }); + }) + + describe("Generate the SecurityToken", async () => { + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { + from: token_owner + }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { + from: token_owner + }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { + from: token_owner + }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { + from: token_owner + }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ + from: _blockNo + }), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + }); + // + describe("Buy tokens using whitelist & manual approvals", async () => { + + it("Should Buy the tokens", async () => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('100', 'ether'), { + from: token_owner + }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('100', 'ether') + ); + }); + + it("Should Buy some more tokens", async () => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { + from: token_owner + }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + // + it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { + let managerArgs = web3.eth.abi.encodeFunctionCall({ + name: 'configure', + type: 'function', + inputs: [{ + type: 'bool', + name: '_isTransferLimitInPercentage' + }, + { + type: 'uint256', + name: '_globalTransferLimitInPercentageOrToken' + }, + { + type: 'bool', + name: '_allowPrimaryIssuance' + } + ] + }, [true, 90, false]) + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + try { + const tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { + from: token_owner + }); + } catch (error) { + console.log(` tx -> failed because Token is not paid`.grey); + ensureException(error); + errorThrown = true; + } + assert.ok(errorThrown, message); + }); + + + + it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { + let managerArgs = web3.eth.abi.encodeFunctionCall({ + name: 'configure', + type: 'function', + inputs: [{ + type: 'bool', + name: '_isTransferLimitInPercentage' + }, + { + type: 'uint256', + name: '_globalTransferLimitInPercentageOrToken' + }, + { + type: 'bool', + name: '_allowPrimaryIssuance' + } + ] + }, [false, 90, false]); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { + from: token_owner + }); + let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { + from: token_owner + }); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "SingleTradeVolumeRestrictionManager did not get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "SingleTradeVolumeRestriction", + "SingleTradeVolumeRestrictionManagerFactory module was not added" + ); + P_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[3].args._module); + }); + + it("Should successfully attach the SingleTradeVolumeRestrictionManager with the security token", async () => { + let managerArgs = web3.eth.abi.encodeFunctionCall({ + name: 'configure', + type: 'function', + inputs: [{ + type: 'bool', + name: '_isTransferLimitInPercentage' + }, + { + type: 'uint256', + name: '_globalTransferLimitInPercentageOrToken' + }, + { + type: 'bool', + name: '_allowPrimaryIssuance' + } + ] + }, [false, 7 * 10 ** 16, false]) + const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { + from: token_owner + }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "SingleTradeVolumeRestriction", + "SingleTradeVolumeRestriction module was not added" + ); + I_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); + }); + + it("Should successfully attach the SingleTradeVolumeRestrictionManager (Percentage) with the security token", async () => { + let managerArgs = web3.eth.abi.encodeFunctionCall({ + name: 'configure', + type: 'function', + inputs: [{ + type: 'bool', + name: '_isTransferLimitInPercentage' + }, + { + type: 'uint256', + name: '_globalTransferLimitInPercentageOrToken' + }, + { + type: 'bool', + name: '_allowPrimaryIssuance' + } + ] + }, [true, 90, false]); + const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { + from: token_owner + }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "SingleTradeVolumeRestriction", + "SingleTradeVolumeRestriction module was not added" + ); + I_SingleTradeVolumeRestrictionPercentageManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); + }); + + it('should return get permissions', async () => { + let permissions = await I_SingleTradeVolumeRestrictionPercentageManager.getPermissions(); + assert.equal(permissions.length, 1, "Invalid Permissions"); + assert.equal( + web3.utils.toAscii(permissions[0]).replace(/\u0000/g, ''), + "ADMIN", + 'Wrong permissions' + ); + }); + + it('add exempt wallet', async () => { + let errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]); + } catch (e) { + errorThrown = true; + } + assert.ok(errorThrown, "Non Admins cannot add exempt wallets"); + + errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { + from: token_owner + }); + } catch (e) { + ensureException(e); + errorThrown = true; + } + + assert.ok(errorThrown, "Exempt wallet cannot be zero"); + + let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { + from: token_owner + }); + assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet added as exempt"); + }); + + it('should remove an exempt wallet', async () => { + let errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5]); + } catch (e) { + errorThrown = true; + } + assert.ok(errorThrown, "Non Admins cannot add exempt wallets"); + + errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(zero_address, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + + assert.ok(errorThrown, "Zero address cannot be added to exempt wallet"); + + let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { + from: token_owner + }); + assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet removed from exempt"); + }); + + it('should set transfer limit for a wallet', async () => { + let errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100); + } catch (e) { + errorThrown = true; + } + assert.ok(errorThrown, "Non Admins cannot set transfer limits"); + + errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 0, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Transfer limit cannot be set to 0") + errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInPercentage(accounts[4], 10, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Transfer limit cannot be set in percentage") + let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { + from: token_owner + }); + assert.equal(tx.logs[0].args._wallet, accounts[4]); + assert.equal(tx.logs[0].args._amount, 100); + + errorThrown = false; + try { + tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 0, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + errorThrown = false + try { + tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Transfer limit can not be set to more 0") + errorThrown = false; + try { + tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + + assert.ok(errorThrown, "Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage") + tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 50, { + from: token_owner + }); + assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet added to transfer limits"); + assert.equal(tx.logs[0].args._percentage, 50, "Wrong percentage set"); + }); + + it('should remove transfer limit for wallet', async () => { + let errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4]); + } catch (e) { + errorThrown = true; + } + assert.ok(errorThrown, "Non Admins cannot set/remove transfer limits"); + + errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[0], { + from: token_owner + }); + } catch (e) { + errorThrown = true; + } + assert.ok(errorThrown, "Non Admins cannot set/remove transfer limits"); + + let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4], { + from: token_owner + }); + assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet removed"); + }); + + it("Should pause the tranfers at Manager level", async () => { + let tx = await I_SingleTradeVolumeRestrictionManager.pause({ + from: token_owner + }); + }); + + it('should be able to set a global transfer limit', async () => { + let errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(100 * 10 ** 18); + } catch (e) { + errorThrown = true; + } + assert.ok(errorThrown, "only owner is allowed"); + + errorThrown = false; + + try { + let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(100 * 10 ** 18, { + from: token_owner + }); + } catch (e) { + ensureException(e); + errorThrown = true; + } + assert.ok(errorThrown, "Cannot change global limit in percentage when set to tokens"); + + errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(0, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Global limit cannot be set to 0"); + let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { + from: token_owner + }); + assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); + + errorThrown = false; + + try { + let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Global limit can be set by non-admins"); + + errorThrown = false; + + try { + let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "cannot change global limit in tokens if transfer limit is set to percentage"); + + errorThrown = false; + try { + let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(0, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Cannot set global limit in tokens to 0"); + + tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(40, { + from: token_owner + }); + assert.equal(tx.logs[0].args._percentage, 40, "Global Limit not set"); + + errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(101 * 10 ** 16, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Global limit cannot be set to more than 100"); + + errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(10, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Global limit in percentage cannot be set when limit is in tokens"); + errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(10, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Global limit in tokens cannot be set when limit is in percentage"); + }); + + it('should perform batch updates', async () => { + let wallets = [accounts[0], accounts[1], accounts[2]]; + let tokenLimits = [1, 2, 3]; + let percentageLimits = [5, 6, 7]; + + let errorThrown = false; + try { + await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti([], { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Exempt wallet multi cannot be empty wallet"); + + // add exempt wallet multi + let tx = await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { + from: token_owner + }); + let logs = tx.logs.filter(log => log.event === 'ExemptWalletAdded'); + assert.equal(logs.length, wallets.length, "Batch Exempt wallets not added"); + for (let i = 0; i < logs.length; i++) { + assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); + } + + errorThrown = false; + try { + await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti([], { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Exempt wallet multi cannot be empty wallet"); + + // remove exempt wallet multi + tx = await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { + from: token_owner + }) + logs = tx.logs.filter(log => log.event === 'ExemptWalletRemoved'); + assert.equal(logs.length, wallets.length, "Batch Exempt wallets not removed"); + + for (let i = 0; i < logs.length; i++) { + assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); + } + + errorThrown = false; + try { + tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([], tokenLimits, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "wallets cannot be empty"); + + errorThrown = false; + try { + tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([accounts[0]], tokenLimits, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "wallet array length dont match"); + + tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { + from: token_owner + }); + logs = tx.logs.filter(log => log.event == 'TransferLimitInTokensSet'); + assert.equal(wallets.length, logs.length, "Transfer limit not set"); + for (let i = 0; i < wallets.length; i++) { + assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not set for wallet"); + assert.equal(logs[i].args._amount.toNumber(), tokenLimits[i]); + } + errorThrown = false + try { + await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti([], { + from: token_owner + }); + } catch (e) { + ensureException(e); + errorThrown = true; + } + assert.ok(errorThrown, "Wallets cannot be empty"); + tx = await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, { + from: token_owner + }); + logs = tx.logs.filter(log => log.event === 'TransferLimitInTokensRemoved'); + assert.equal(logs.length, wallets.length, "Transfer limit not removed"); + for (let i = 0; i < wallets.length; i++) { + assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not removed for wallet"); + } + + errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti([], percentageLimits, { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "wallets cannot be empty"); + + errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, [], { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "wallets and amounts dont match be empty"); + tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { + from: token_owner + }); + logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageSet'); + assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); + + for (let i = 0; i < wallets.length; i++) { + assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); + assert.equal(logs[i].args._percentage.toNumber(), percentageLimits[i]); + } + + errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti([], { + from: token_owner + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Wallets cannot be empty"); + + tx = await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { + from: token_owner + }); + logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageRemoved'); + assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); + + for (let i = 0; i < wallets.length; i++) { + assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); + } + + errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentage(wallets[0], { + from: token_owner + }); + } catch (e) { + ensureException(e) + errorThrown = true; + } + assert.ok(errorThrown, "Wallet should not be removed"); + }) + + it('should be able to transfer tokens SingleTradeVolumeRestriction', async () => { + await I_SingleTradeVolumeRestrictionManager.unpause({ + from: token_owner + }) + await I_SingleTradeVolumeRestrictionPercentageManager.pause({ + from: token_owner + }) + await P_SingleTradeVolumeRestrictionManager.pause({ + from: token_owner + }); + + await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, { + from: account_issuer + } + ); + + await I_GeneralTransferManager.modifyWhitelist( + account_investor4, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, { + from: account_issuer + } + ); + + await I_GeneralTransferManager.modifyWhitelist( + account_investor5, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, { + from: account_issuer + } + ); + + + //setting a max of 5 tokens + await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(web3.utils.toWei('5', 'ether'), { + from: token_owner + }) + + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('6', 'ether'), { + from: account_investor1 + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Transfer should have not happened"); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('4', 'ether'), { + from: account_investor1 + }); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('4', 'ether')); + + // exempt wallet + await I_SingleTradeVolumeRestrictionManager.addExemptWallet(account_investor1, { + from: token_owner + }); + await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('7', 'ether'), { + from: account_investor1 + }); + assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toNumber(), web3.utils.toWei('7', 'ether')); + + //special limits wallet + await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(account_investor5, web3.utils.toWei('5', 'ether'), { + from: token_owner + }); + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('7', 'ether'), { + from: account_investor5 + }); + } catch (e) { + errorThrown = true; + ensureException(e); + } + assert.ok(errorThrown, "Transfer should have not happened"); + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('4', 'ether'), { + from: account_investor5 + }) + assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei('4', 'ether')) + }) + + it('should be able to transfer tokens (percentage transfer limit)', async () => { + await I_SingleTradeVolumeRestrictionManager.pause({ + from: token_owner + }); + let balance = (await I_SecurityToken.balanceOf(account_investor2)).toNumber(); + await I_SecurityToken.transfer(account_investor1, balance, { + from: account_investor2 + }); + + + balance = (await I_SecurityToken.balanceOf(account_investor3)).toNumber(); + + await I_SecurityToken.transfer(account_investor1, balance, { + from: account_investor3 + }); + + + balance = (await I_SecurityToken.balanceOf(account_investor4)).toNumber(); + await I_SecurityToken.transfer(account_investor1, balance, { + from: account_investor4 + }); + + balance = (await I_SecurityToken.balanceOf(account_investor5)).toNumber(); + await I_SecurityToken.transfer(account_investor1, balance, { + from: account_investor5 + }); + + await I_SingleTradeVolumeRestrictionPercentageManager.unpause({ + from: token_owner + }); + // // + await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(49 * 10 ** 16, { + from: token_owner + }); + + let errorThrown = false; + try { + // more than the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('90', 'ether'), { + from: account_investor1 + }); + } catch (e) { + ensureException(e); + errorThrown = true; + } + assert.ok(errorThrown, "Transfer above limit happened"); + + + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('20', 'ether'), { + from: account_investor1 + }); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei('20', 'ether')) + + await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(account_investor1, 5 * 10 ** 16, { + from: token_owner + }); + errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('35', 'ether'), { + from: account_investor1 + }); + } catch (e) { + ensureException(e); + errorThrown = true; + } + assert.ok(errorThrown, "transfer happened above limit"); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { + from: account_investor1 + }); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('1', 'ether')); + }); + + it('should change transfer limits to tokens', async () => { + let errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { + from: token_owner + }); + } catch (e) { + + ensureException(e); + errorThrown = true; + } + assert.equal(errorThrown, true, "Should not change to percentage again"); + + + let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { + from: token_owner + }); + assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); + assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); + }) + + it('should change transfer limits to percentage', async () => { + let errorThrown = false; + try { + await I_SingleTradeVolumeRestrictionManager.changeTransferLimitToTokens(1, { + from: token_owner + }); + } catch (e) { + ensureException(e); + errorThrown = true; + } + assert.equal(errorThrown, true, "Should not change to tokens again"); + + let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { + from: token_owner + }); + assert.ok(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), "Error Changing"); + assert.equal(tx.logs[0].args._percentage.toNumber(), 1, "Transfer limit not changed"); + }) + + + + }); + + describe("SingleTradeVolumeRestrictionManager Factory test cases", async () => { + + it("Should get the exact details of the factory", async () => { + assert.equal(await I_SingleTradeVolumeRestrictionManagerFactory.setupCost.call(), 0); + assert.equal((await I_SingleTradeVolumeRestrictionManagerFactory.getTypes.call())[0], 2); + let name = web3.utils.toUtf8(await I_SingleTradeVolumeRestrictionManagerFactory.getName.call()); + assert.equal(name, "SingleTradeVolumeRestriction", "Wrong Module added"); + let desc = await I_SingleTradeVolumeRestrictionManagerFactory.getDescription.call(); + assert.equal(desc, "Imposes volume restriction on a single trade", "Wrong Module added"); + let title = await I_SingleTradeVolumeRestrictionManagerFactory.getTitle.call(); + assert.equal(title, "Single Trade Volume Restriction Manager", "Wrong Module added"); + let inst = await I_SingleTradeVolumeRestrictionManagerFactory.getInstructions.call(); + assert.equal(inst, "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens", "Wrong Module added"); + let version = await I_SingleTradeVolumeRestrictionManagerFactory.getVersion.call(); + assert.equal(version, "1.0.0", "Version not correct"); + }); + + it("Should get the tags of the factory", async () => { + let tags = await I_SingleTradeVolumeRestrictionManagerFactory.getTags.call(); + assert.equal(web3.utils.toUtf8(tags[0]), "Single Trade"); + assert.equal(web3.utils.toUtf8(tags[1]), "Transfer"); + assert.equal(web3.utils.toUtf8(tags[2]), "Volume"); + }); + + + }); +}); diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index adbce48e3..ddb350499 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -290,7 +290,7 @@ contract('BlacklistTransferManager', accounts => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); const tx = await I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type[0].toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), @@ -303,7 +303,7 @@ contract('BlacklistTransferManager', accounts => { it("Should successfully attach the BlacklistTransferManager with the security token", async () => { const tx = await I_SecurityToken.addModule(I_BlacklistTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type[0].toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -335,11 +335,11 @@ contract('BlacklistTransferManager', accounts => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('3', 'ether'), { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('1', 'ether') + web3.utils.toWei('3', 'ether') ); }); @@ -584,7 +584,7 @@ contract('BlacklistTransferManager', accounts => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); } catch(error){ - console.log(` tx revert -> Trying to send token to the blacklisted address`.grey); + console.log(` tx revert -> Trying to send token by the blacklisted address`.grey); errorThrown = true; ensureException(error); } @@ -603,197 +603,197 @@ contract('BlacklistTransferManager', accounts => { ); }); - it("Should delete the blacklist type", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "b_blacklist", "Failed in deleting the blacklist"); - - }); - - it("Should fail in deleting the blacklist type", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to delete the blacklist type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in deleting the blacklist type", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteBlacklistType("a_blacklist", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Not able to delete the blacklist as blacklist has associated addresses.`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in deleting the blacklist type", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteBlacklistType("c_blacklist", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Not able to delete the blacklist as blacklist type doesnot exist.`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should delete the investor from all the associated blacklist", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "g_blacklist", 20, { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "g_blacklist", { from: token_owner }); - let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: token_owner }); - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); - - }); - - it("Should fail in deleting the investor from the blacklist type", async() => { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in deleting the investor from the blacklist type", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(0x0, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Invalid investor address`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in deleting the investor from the blacklist type", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor2, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Investor is not associated to blacklist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should delete the investor from the blacklist type", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); - - }); - - it("Should fail in deleting the investor from the blacklist type", async() => { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should add investor and new blacklist type", async() => { - let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "c_blacklist", "Failed in adding the blacklist"); - assert.equal(tx.logs[1].args._investor, account_investor3, "Failed in adding the investor to blacklist"); - - }); - - it("Should fail in adding the investor and new blacklist type", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to add the investor to blacklist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should add mutiple investor to blacklist", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "d_blacklist", 20, { from: token_owner }); - let investor = [account_investor4,account_investor5]; - let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "d_blacklist", { from: token_owner }); + // it("Should delete the blacklist type", async() => { + // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); + // let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); + // assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "b_blacklist", "Failed in deleting the blacklist"); + + // }); + + // it("Should fail in deleting the blacklist type", async() => { + // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); + // let errorThrown = false; + // try { + // let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: account_investor1 }); + // } catch(error) { + // console.log(` tx revert -> Only owner have the permission to delete the blacklist type`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // }); + + // it("Should fail in deleting the blacklist type", async() => { + // let errorThrown = false; + // try { + // let tx = await I_BlacklistTransferManager.deleteBlacklistType("a_blacklist", { from: token_owner }); + // } catch(error) { + // console.log(` tx revert -> Not able to delete the blacklist as blacklist has associated addresses.`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // }); + + // it("Should fail in deleting the blacklist type", async() => { + // let errorThrown = false; + // try { + // let tx = await I_BlacklistTransferManager.deleteBlacklistType("c_blacklist", { from: token_owner }); + // } catch(error) { + // console.log(` tx revert -> Not able to delete the blacklist as blacklist type doesnot exist.`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // }); + + // it("Should delete the investor from all the associated blacklist", async() => { + // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "g_blacklist", 20, { from: token_owner }); + // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "g_blacklist", { from: token_owner }); + // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: token_owner }); + // assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); + + // }); + + // it("Should fail in deleting the investor from the blacklist type", async() => { + // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); + // let errorThrown = false; + // try { + // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: account_investor2 }); + // } catch(error) { + // console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // }); + + // it("Should fail in deleting the investor from the blacklist type", async() => { + // let errorThrown = false; + // try { + // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(0x0, { from: token_owner }); + // } catch(error) { + // console.log(` tx revert -> Invalid investor address`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // }); + + // it("Should fail in deleting the investor from the blacklist type", async() => { + // let errorThrown = false; + // try { + // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor2, { from: token_owner }); + // } catch(error) { + // console.log(` tx revert -> Investor is not associated to blacklist`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // }); + + // it("Should delete the investor from the blacklist type", async() => { + // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); + // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + // let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + // assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); + + // }); + + // it("Should fail in deleting the investor from the blacklist type", async() => { + // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + // let errorThrown = false; + // try { + // let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: account_investor2 }); + // } catch(error) { + // console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // }); + + // it("Should add investor and new blacklist type", async() => { + // let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: token_owner }); + // assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "c_blacklist", "Failed in adding the blacklist"); + // assert.equal(tx.logs[1].args._investor, account_investor3, "Failed in adding the investor to blacklist"); + + // }); + + // it("Should fail in adding the investor and new blacklist type", async() => { + // let errorThrown = false; + // try { + // let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: account_investor2 }); + // } catch(error) { + // console.log(` tx revert -> Only owner have the permission to add the investor to blacklist`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // }); + + // it("Should add mutiple investor to blacklist", async() => { + // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "d_blacklist", 20, { from: token_owner }); + // let investor = [account_investor4,account_investor5]; + // let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "d_blacklist", { from: token_owner }); - let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let user = event_data[i].args._investor; - assert.equal(user, investor[i], "Failed in adding the investor to blacklist"); - } + // let event_data = tx.logs; + // for (var i = 0; i < event_data.length; i++) { + // let user = event_data[i].args._investor; + // assert.equal(user, investor[i], "Failed in adding the investor to blacklist"); + // } - }); - - it("Should fail in adding the mutiple investor to the blacklist", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "b_blacklist", { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to add the investors to blacklist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should get the init function", async() => { - let byte = await I_BlacklistTransferManager.getInitFunction.call(); - assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); - }); - - it("Should get the permission", async() => { - let perm = await I_BlacklistTransferManager.getPermissions.call(); - assert.equal(perm.length, 1); - }); + // }); + + // it("Should fail in adding the mutiple investor to the blacklist", async() => { + // let errorThrown = false; + // try { + // let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "b_blacklist", { from: account_investor1 }); + // } catch(error) { + // console.log(` tx revert -> Only owner have the permission to add the investors to blacklist`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // }); + + // it("Should get the init function", async() => { + // let byte = await I_BlacklistTransferManager.getInitFunction.call(); + // assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); + // }); + + // it("Should get the permission", async() => { + // let perm = await I_BlacklistTransferManager.getPermissions.call(); + // assert.equal(perm.length, 1); + // }); }); - describe("Test cases for the factory", async() => { - it("Should get the exact details of the factory", async() => { - assert.equal(await I_BlacklistTransferManagerFactory.setupCost.call(),0); - assert.equal(await I_BlacklistTransferManagerFactory.getType.call(),2); - assert.equal(web3.utils.toAscii(await I_BlacklistTransferManagerFactory.getName.call()) - .replace(/\u0000/g, ''), - "BlacklistTransferManager", - "Wrong Module added"); - assert.equal(await I_BlacklistTransferManagerFactory.getDescription.call(), - "Automate blacklist to restrict selling", - "Wrong Module added"); - assert.equal(await I_BlacklistTransferManagerFactory.getTitle.call(), - "Blacklist Transfer Manager", - "Wrong Module added"); - assert.equal(await I_BlacklistTransferManagerFactory.getInstructions.call(), - "Allows an issuer to blacklist the addresses.", - "Wrong Module added"); + // describe("Test cases for the factory", async() => { + // it("Should get the exact details of the factory", async() => { + // assert.equal(await I_BlacklistTransferManagerFactory.setupCost.call(),0); + // assert.equal((await I_CountTransferManagerFactory.getTypes.call())[0],2); + // assert.equal(web3.utils.toAscii(await I_BlacklistTransferManagerFactory.getName.call()) + // .replace(/\u0000/g, ''), + // "BlacklistTransferManager", + // "Wrong Module added"); + // assert.equal(await I_BlacklistTransferManagerFactory.getDescription.call(), + // "Automate blacklist to restrict selling", + // "Wrong Module added"); + // assert.equal(await I_BlacklistTransferManagerFactory.getTitle.call(), + // "Blacklist Transfer Manager", + // "Wrong Module added"); + // assert.equal(await I_BlacklistTransferManagerFactory.getInstructions.call(), + // "Allows an issuer to blacklist the addresses.", + // "Wrong Module added"); - }); + // }); - it("Should get the tags of the factory", async() => { - let tags = await I_BlacklistTransferManagerFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Blacklist"); - }); - }); + // it("Should get the tags of the factory", async() => { + // let tags = await I_BlacklistTransferManagerFactory.getTags.call(); + // assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Blacklist"); + // }); + // }); }); From aa2e39e82680fe39d0eadd14255b8981b8e514fd Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Sun, 7 Oct 2018 15:02:58 +0530 Subject: [PATCH 013/582] changes in test cases --- .../BlacklistTransferManager.sol | 4 ++ test/y_blacklist_transfer_manager.js | 53 ++++++++----------- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 140a79131..c2d8a0d0a 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -222,9 +222,13 @@ contract BlacklistTransferManager is ITransferManager { require(_investor != address(0), "Invalid investor address"); require(_blacklistName != bytes32(0),"Invalid blacklist name"); require(investorToBlacklist[_investor][investorToIndex[_investor][_blacklistName]] != bytes32(0), "Investor is not associated to blacklist type"); + // delete the investor from the blacklist type delete(blacklistToInvestor[_blacklistName][blacklistToIndex[_blacklistName][_investor]]); + // delete the investor index from the blacklist delete(blacklistToIndex[_blacklistName][_investor]); + // delete the blacklist from the investor delete(investorToBlacklist[_investor][investorToIndex[_investor][_blacklistName]]); + // delete the blacklist index from the invetsor delete(investorToIndex[_investor][_blacklistName]); emit DeleteInvestorFromBlacklist(_investor, investorToBlacklist[_investor][investorToIndex[_investor][_blacklistName]]); } diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index ddb350499..33319d2e3 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -374,7 +374,7 @@ contract('BlacklistTransferManager', accounts => { assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in adding the type in blacklist"); }); - it("Should fail in adding the blacklist", async() => { + it("Should fail in adding the blacklist as blacklist type already exist", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); @@ -386,7 +386,7 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in adding the blacklist", async() => { + it("Should fail in adding the blacklist as the blacklist name is invalid", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "", 20, { from: token_owner }); @@ -398,7 +398,7 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in adding the blacklist", async() => { + it("Should fail in adding the blacklist as the dates are invalid", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.addBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); @@ -410,7 +410,7 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in adding the blacklist", async() => { + it("Should fail in adding the blacklist as repeat in days is invalid", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 0, { from: token_owner }); @@ -422,7 +422,7 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in adding the blacklist", async() => { + it("Should fail in adding the blacklist because only owner can add the blacklist", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: account_investor1 }); @@ -434,17 +434,6 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in adding the existing blacklist", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Blacklist type already exist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }) it("Should modify the blacklist", async() => { //Modify the existing blacklist @@ -453,7 +442,7 @@ contract('BlacklistTransferManager', accounts => { }); - it("Should fail in modifying the blacklist", async() => { + it("Should fail in modifying the blacklist as the name is invalid", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "", 20, { from: token_owner }); @@ -465,7 +454,7 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in modifying the blacklist", async() => { + it("Should fail in modifying the blacklist as the dates are invalid", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); @@ -477,7 +466,7 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in modifying the blacklist", async() => { + it("Should fail in modifying the blacklist as the repeat in days is invalid", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "b_blacklist", 0, { from: token_owner }); @@ -490,7 +479,7 @@ contract('BlacklistTransferManager', accounts => { }); - it("Should fail in modifying the blacklist", async() => { + it("Should fail in modifying the blacklist as only owner can modify the blacklist", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: account_investor1 }); @@ -502,7 +491,7 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in modifying the blacklist", async() => { + it("Should fail in modifying the blacklist as blacklist type doesnot exist", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); @@ -521,7 +510,7 @@ contract('BlacklistTransferManager', accounts => { }); - it("Should fail in adding the investor to the blacklist", async() => { + it("Should fail in adding the investor to the blacklist because only owner can add the investor", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "a_blacklist", { from: account_investor1 }); @@ -533,7 +522,7 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should fail in adding the investor to the blacklist", async() => { + it("Should fail in adding the investor to the blacklist as investor address is invalid", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.addInvestorToBlacklist(0x0, "a_blacklist", { from: token_owner }); @@ -546,7 +535,7 @@ contract('BlacklistTransferManager', accounts => { }); - it("Should fail in adding the investor to the blacklist", async() => { + it("Should fail in adding the investor to the non existing blacklist", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "b_blacklist", { from: token_owner }); @@ -563,7 +552,7 @@ contract('BlacklistTransferManager', accounts => { assert.equal(perm.length, 1); }); - it("Should fail in getting the list of investors associated to blacklist", async() => { + it("Should fail in getting the list of investors from the non existing blacklist", async() => { let errorThrown = false; try{ let perm = await I_BlacklistTransferManager.getListOfAddresses.call("b_blacklist"); @@ -610,7 +599,7 @@ contract('BlacklistTransferManager', accounts => { // }); - // it("Should fail in deleting the blacklist type", async() => { + // it("Only owner have the permission to delete thr blacklist type", async() => { // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); // let errorThrown = false; // try { @@ -623,7 +612,7 @@ contract('BlacklistTransferManager', accounts => { // assert.ok(errorThrown, message); // }); - // it("Should fail in deleting the blacklist type", async() => { + // it("Should fail in deleting the blacklist type as the blacklist has associated addresses", async() => { // let errorThrown = false; // try { // let tx = await I_BlacklistTransferManager.deleteBlacklistType("a_blacklist", { from: token_owner }); @@ -635,7 +624,7 @@ contract('BlacklistTransferManager', accounts => { // assert.ok(errorThrown, message); // }); - // it("Should fail in deleting the blacklist type", async() => { + // it("Should fail in deleting the blacklist type as the blacklist doesnot exist", async() => { // let errorThrown = false; // try { // let tx = await I_BlacklistTransferManager.deleteBlacklistType("c_blacklist", { from: token_owner }); @@ -655,7 +644,7 @@ contract('BlacklistTransferManager', accounts => { // }); - // it("Should fail in deleting the investor from the blacklist type", async() => { + // it("Only owner has the permission to delete the investor from all the blacklist type", async() => { // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); // let errorThrown = false; // try { @@ -668,7 +657,7 @@ contract('BlacklistTransferManager', accounts => { // assert.ok(errorThrown, message); // }); - // it("Should fail in deleting the investor from the blacklist type", async() => { + // it("Should fail in deleting the investor from all the associated blacklist as th address is invalid", async() => { // let errorThrown = false; // try { // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(0x0, { from: token_owner }); @@ -680,7 +669,7 @@ contract('BlacklistTransferManager', accounts => { // assert.ok(errorThrown, message); // }); - // it("Should fail in deleting the investor from the blacklist type", async() => { + // it("Should fail in deleting the investor which is not associated to blacklist", async() => { // let errorThrown = false; // try { // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor2, { from: token_owner }); @@ -700,7 +689,7 @@ contract('BlacklistTransferManager', accounts => { // }); - // it("Should fail in deleting the investor from the blacklist type", async() => { + // it("Only owner can delete the investor from the blacklist type", async() => { // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); // let errorThrown = false; // try { From 7da623a99de7cd3be9824c0a055dfcc3b90a7863 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Sun, 7 Oct 2018 20:35:52 +0530 Subject: [PATCH 014/582] changes in test cases --- .../BlacklistTransferManager.sol | 2 - test/y_blacklist_transfer_manager.js | 396 +++++++++--------- 2 files changed, 199 insertions(+), 199 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index c2d8a0d0a..8b278de8a 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -118,10 +118,8 @@ contract BlacklistTransferManager is ITransferManager { // based on the new current time value uint256 repeater = now.div(endTimeTemp.add(repeatPeriodTimeTemp)); if (startTimeTemp.add(blacklistTime.mul(repeater)) <= now && endTimeTemp.add(blacklistTime.mul(repeater)) >= now) { - emit LogTransfer(endTimeTemp,startTimeTemp,repeatPeriodTimeTemp,blacklistTime,repeater,now); return Result.INVALID; } - emit LogTransfer(endTimeTemp,startTimeTemp,repeatPeriodTimeTemp,blacklistTime,repeater,now); return Result.NA; } return Result.NA; diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index 33319d2e3..0e526233a 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -324,7 +324,7 @@ contract('BlacklistTransferManager', accounts => { account_investor1, latestTime(), latestTime(), - latestTime() + duration.days(10), + latestTime() + duration.days(50), true, { from: account_issuer @@ -351,7 +351,7 @@ contract('BlacklistTransferManager', accounts => { account_investor2, latestTime(), latestTime(), - latestTime() + duration.days(10), + latestTime() + duration.days(50), true, { from: account_issuer @@ -565,10 +565,22 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); + it("Should investor be able to transfer token as it is not in blacklist time period", async() => { + // Jump time + await increaseTime(4000); + + //Trasfer tokens + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('3', 'ether') + ); + }); + it("Should fail in transfer the tokens as the investor in blacklist", async() => { let errorThrown = false; // Jump time - await increaseTime(1731500); + await increaseTime(1727500); try{ await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); } @@ -580,209 +592,199 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); - it("Should investor be able to transfer token as it is not in blacklist time period", async() => { - // Jump time - await increaseTime(3000); - - //Trasfer tokens - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('1', 'ether') - ); + + + it("Should delete the blacklist type", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "b_blacklist", "Failed in deleting the blacklist"); + + }); + + it("Only owner have the permission to delete thr blacklist type", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to delete the blacklist type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in deleting the blacklist type as the blacklist has associated addresses", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteBlacklistType("a_blacklist", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Not able to delete the blacklist as blacklist has associated addresses.`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in deleting the blacklist type as the blacklist doesnot exist", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteBlacklistType("c_blacklist", { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Not able to delete the blacklist as blacklist type doesnot exist.`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); }); - // it("Should delete the blacklist type", async() => { - // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - // let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); - // assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "b_blacklist", "Failed in deleting the blacklist"); - - // }); - - // it("Only owner have the permission to delete thr blacklist type", async() => { - // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - // let errorThrown = false; - // try { - // let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: account_investor1 }); - // } catch(error) { - // console.log(` tx revert -> Only owner have the permission to delete the blacklist type`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should fail in deleting the blacklist type as the blacklist has associated addresses", async() => { - // let errorThrown = false; - // try { - // let tx = await I_BlacklistTransferManager.deleteBlacklistType("a_blacklist", { from: token_owner }); - // } catch(error) { - // console.log(` tx revert -> Not able to delete the blacklist as blacklist has associated addresses.`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should fail in deleting the blacklist type as the blacklist doesnot exist", async() => { - // let errorThrown = false; - // try { - // let tx = await I_BlacklistTransferManager.deleteBlacklistType("c_blacklist", { from: token_owner }); - // } catch(error) { - // console.log(` tx revert -> Not able to delete the blacklist as blacklist type doesnot exist.`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should delete the investor from all the associated blacklist", async() => { - // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "g_blacklist", 20, { from: token_owner }); - // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "g_blacklist", { from: token_owner }); - // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: token_owner }); - // assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); - - // }); - - // it("Only owner has the permission to delete the investor from all the blacklist type", async() => { - // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); - // let errorThrown = false; - // try { - // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: account_investor2 }); - // } catch(error) { - // console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should fail in deleting the investor from all the associated blacklist as th address is invalid", async() => { - // let errorThrown = false; - // try { - // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(0x0, { from: token_owner }); - // } catch(error) { - // console.log(` tx revert -> Invalid investor address`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should fail in deleting the investor which is not associated to blacklist", async() => { - // let errorThrown = false; - // try { - // let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor2, { from: token_owner }); - // } catch(error) { - // console.log(` tx revert -> Investor is not associated to blacklist`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should delete the investor from the blacklist type", async() => { - // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); - // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - // let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - // assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); - - // }); - - // it("Only owner can delete the investor from the blacklist type", async() => { - // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - // let errorThrown = false; - // try { - // let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: account_investor2 }); - // } catch(error) { - // console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should add investor and new blacklist type", async() => { - // let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: token_owner }); - // assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "c_blacklist", "Failed in adding the blacklist"); - // assert.equal(tx.logs[1].args._investor, account_investor3, "Failed in adding the investor to blacklist"); - - // }); - - // it("Should fail in adding the investor and new blacklist type", async() => { - // let errorThrown = false; - // try { - // let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: account_investor2 }); - // } catch(error) { - // console.log(` tx revert -> Only owner have the permission to add the investor to blacklist`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should add mutiple investor to blacklist", async() => { - // await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "d_blacklist", 20, { from: token_owner }); - // let investor = [account_investor4,account_investor5]; - // let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "d_blacklist", { from: token_owner }); + it("Should delete the investor from all the associated blacklist", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "g_blacklist", 20, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "g_blacklist", { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: token_owner }); + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); + + }); + + it("Only owner has the permission to delete the investor from all the blacklist type", async() => { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in deleting the investor from all the associated blacklist as th address is invalid", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(0x0, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid investor address`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in deleting the investor which is not associated to blacklist", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor2, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Investor is not associated to blacklist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should delete the investor from the blacklist type", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); + + }); + + it("Only owner can delete the investor from the blacklist type", async() => { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should add investor and new blacklist type", async() => { + let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: token_owner }); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "c_blacklist", "Failed in adding the blacklist"); + assert.equal(tx.logs[1].args._investor, account_investor3, "Failed in adding the investor to blacklist"); + + }); + + it("Should fail in adding the investor and new blacklist type", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: account_investor2 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to add the investor to blacklist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should add mutiple investor to blacklist", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "d_blacklist", 20, { from: token_owner }); + let investor = [account_investor4,account_investor5]; + let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "d_blacklist", { from: token_owner }); - // let event_data = tx.logs; - // for (var i = 0; i < event_data.length; i++) { - // let user = event_data[i].args._investor; - // assert.equal(user, investor[i], "Failed in adding the investor to blacklist"); - // } + let event_data = tx.logs; + for (var i = 0; i < event_data.length; i++) { + let user = event_data[i].args._investor; + assert.equal(user, investor[i], "Failed in adding the investor to blacklist"); + } - // }); - - // it("Should fail in adding the mutiple investor to the blacklist", async() => { - // let errorThrown = false; - // try { - // let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "b_blacklist", { from: account_investor1 }); - // } catch(error) { - // console.log(` tx revert -> Only owner have the permission to add the investors to blacklist`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should get the init function", async() => { - // let byte = await I_BlacklistTransferManager.getInitFunction.call(); - // assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); - // }); - - // it("Should get the permission", async() => { - // let perm = await I_BlacklistTransferManager.getPermissions.call(); - // assert.equal(perm.length, 1); - // }); + }); + + it("Should fail in adding the mutiple investor to the blacklist", async() => { + let errorThrown = false; + try { + let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "b_blacklist", { from: account_investor1 }); + } catch(error) { + console.log(` tx revert -> Only owner have the permission to add the investors to blacklist`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should get the init function", async() => { + let byte = await I_BlacklistTransferManager.getInitFunction.call(); + assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); + }); + + it("Should get the permission", async() => { + let perm = await I_BlacklistTransferManager.getPermissions.call(); + assert.equal(perm.length, 1); + }); }); - // describe("Test cases for the factory", async() => { - // it("Should get the exact details of the factory", async() => { - // assert.equal(await I_BlacklistTransferManagerFactory.setupCost.call(),0); - // assert.equal((await I_CountTransferManagerFactory.getTypes.call())[0],2); - // assert.equal(web3.utils.toAscii(await I_BlacklistTransferManagerFactory.getName.call()) - // .replace(/\u0000/g, ''), - // "BlacklistTransferManager", - // "Wrong Module added"); - // assert.equal(await I_BlacklistTransferManagerFactory.getDescription.call(), - // "Automate blacklist to restrict selling", - // "Wrong Module added"); - // assert.equal(await I_BlacklistTransferManagerFactory.getTitle.call(), - // "Blacklist Transfer Manager", - // "Wrong Module added"); - // assert.equal(await I_BlacklistTransferManagerFactory.getInstructions.call(), - // "Allows an issuer to blacklist the addresses.", - // "Wrong Module added"); + describe("Test cases for the factory", async() => { + it("Should get the exact details of the factory", async() => { + assert.equal(await I_BlacklistTransferManagerFactory.setupCost.call(),0); + assert.equal((await I_BlacklistTransferManagerFactory.getTypes.call())[0],2); + assert.equal(web3.utils.toAscii(await I_BlacklistTransferManagerFactory.getName.call()) + .replace(/\u0000/g, ''), + "BlacklistTransferManager", + "Wrong Module added"); + assert.equal(await I_BlacklistTransferManagerFactory.getDescription.call(), + "Automate blacklist to restrict selling", + "Wrong Module added"); + assert.equal(await I_BlacklistTransferManagerFactory.getTitle.call(), + "Blacklist Transfer Manager", + "Wrong Module added"); + assert.equal(await I_BlacklistTransferManagerFactory.getInstructions.call(), + "Allows an issuer to blacklist the addresses.", + "Wrong Module added"); - // }); + }); - // it("Should get the tags of the factory", async() => { - // let tags = await I_BlacklistTransferManagerFactory.getTags.call(); - // assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Blacklist"); - // }); - // }); + it("Should get the tags of the factory", async() => { + let tags = await I_BlacklistTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Blacklist"); + }); + }); }); From e2bdc99abd2b7f95141bcfb57ba818a6994743ba Mon Sep 17 00:00:00 2001 From: Vikas Panwar Date: Tue, 9 Oct 2018 14:42:11 +0530 Subject: [PATCH 015/582] change in repeatar calculation --- .../TransferManager/BlacklistTransferManager.sol | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 8b278de8a..f2877480e 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -65,17 +65,7 @@ contract BlacklistTransferManager is ITransferManager { bytes32 _blacklist ); - // Emit when investor is deleted from the blacklist type - event LogTransfer( - uint256 _endTime, - uint256 _startTime, - uint256 _repeat, - uint256 _blacklist, - uint256 _repeatar, - uint256 _now - - ); - + /** * @notice Constructor * @param _securityToken Address of the security token @@ -116,7 +106,7 @@ contract BlacklistTransferManager is ITransferManager { uint256 blacklistTime = (endTimeTemp.sub(startTimeTemp)).add(repeatPeriodTimeTemp); // Find the repeating parameter that will be used to calculate the new startTime and endTime // based on the new current time value - uint256 repeater = now.div(endTimeTemp.add(repeatPeriodTimeTemp)); + uint256 repeater = (now.sub(startTimeTemp)).div(blacklistTime); if (startTimeTemp.add(blacklistTime.mul(repeater)) <= now && endTimeTemp.add(blacklistTime.mul(repeater)) >= now) { return Result.INVALID; } From f1f33b0690922a909885f1104e3f4db3f2ed4a49 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 9 Oct 2018 18:18:09 +0530 Subject: [PATCH 016/582] Delete .node-xmlhttprequest-sync-35460 --- .node-xmlhttprequest-sync-35460 | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .node-xmlhttprequest-sync-35460 diff --git a/.node-xmlhttprequest-sync-35460 b/.node-xmlhttprequest-sync-35460 deleted file mode 100644 index e69de29bb..000000000 From cd824b44586ed528d3818898ff8dd8ed4c9cdcef Mon Sep 17 00:00:00 2001 From: Vikas Panwar Date: Wed, 10 Oct 2018 09:51:45 +0530 Subject: [PATCH 017/582] minor change in start date check --- .../TransferManager/BlacklistTransferManager.sol | 2 +- test/y_blacklist_transfer_manager.js | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index f2877480e..76a5d0d44 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -140,7 +140,7 @@ contract BlacklistTransferManager is ITransferManager { */ function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) internal view { require(_name != bytes32(0), "Invalid blacklist name"); - require(_startTime > now && _startTime < _endTime, "Invalid start or end date"); + require(_startTime != 0 && _startTime < _endTime, "Invalid start or end date"); require(_repeatPeriodTime != 0, "Invalid repeat days"); } diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index 0e526233a..9c4ca6142 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -398,12 +398,24 @@ contract('BlacklistTransferManager', accounts => { assert.ok(errorThrown, message); }); + it("Should fail in adding the blacklist as the start date is invalid", async() => { + let errorThrown = false; + try { + await I_BlacklistTransferManager.addBlacklistType(0, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); + } catch(error) { + console.log(` tx revert -> Invalid start date`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + it("Should fail in adding the blacklist as the dates are invalid", async() => { let errorThrown = false; try { await I_BlacklistTransferManager.addBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); } catch(error) { - console.log(` tx revert -> Invalid start or end date`.grey); + console.log(` tx revert -> Start date is less than end date`.grey); errorThrown = true; ensureException(error); } From 183a138ddd3caae20e4b32270ac55e957017fbb8 Mon Sep 17 00:00:00 2001 From: Vikas Panwar Date: Thu, 11 Oct 2018 17:27:16 +0530 Subject: [PATCH 018/582] changes in test cases --- test/helpers/createInstances.js | 14 ++ test/y_blacklist_transfer_manager.js | 183 ++++++--------------------- 2 files changed, 53 insertions(+), 144 deletions(-) diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index ff2a66f4b..c60292e97 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -14,6 +14,7 @@ const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApproval const SingleTradeVolumeRestrictionManagerFactory = artifacts.require('./SingleTradeVolumeRestrictionManagerFactory.sol'); const TrackedRedemptionFactory = artifacts.require("./TrackedRedemptionFactory.sol"); const PercentageTransferManagerFactory = artifacts.require("./PercentageTransferManagerFactory.sol"); +const BlacklistTransferManagerFactory = artifacts.require("./BlacklistTransferManagerFactory.sol"); const USDTieredSTOFactory = artifacts.require("./USDTieredSTOFactory.sol"); const USDTieredSTOProxyFactory = artifacts.require("./USDTieredSTOProxyFactory"); const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); @@ -39,6 +40,7 @@ let I_SingleTradeVolumeRestrictionManagerFactory; let I_ManualApprovalTransferManagerFactory; let I_VolumeRestrictionTransferManagerFactory; let I_PercentageTransferManagerFactory; +let I_BlacklistTransferManagerFactory; let I_EtherDividendCheckpointFactory; let I_CountTransferManagerFactory; let I_ERC20DividendCheckpointFactory; @@ -237,6 +239,18 @@ export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInst return new Array(I_PercentageTransferManagerFactory); } +export async function deployBlacklistTMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { + I_BlacklistTransferManagerFactory = await BlacklistTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + assert.notEqual( + I_BlacklistTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "BlacklistTransferManagerFactory contract was not deployed" + ); + + await registerAndVerifyByMR(I_BlacklistTransferManagerFactory.address, accountPolymath, MRProxyInstance); + return new Array(I_BlacklistTransferManagerFactory); +} + export async function deployVolumeRTMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index 9c4ca6142..8de367f1a 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -2,22 +2,12 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; +import { setUpPolymathNetwork, deployGPMAndVerifyed, deployBlacklistTMAndVerified } from "./helpers/createInstances"; -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); -const STFactory = artifacts.require('./STFactory.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const BlacklistTransferManagerFactory = artifacts.require('./BlacklistTransferManagerFactory.sol'); -const BlacklistTransferManager = artifacts.require('./BlacklistTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); + +const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); +const BlacklistTransferManager = artifacts.require("./BlacklistTransferManager"); +const SecurityToken = artifacts.require("./SecurityToken.sol"); const Web3 = require('web3'); const BigNumber = require('bignumber.js'); @@ -98,140 +88,45 @@ contract('BlacklistTransferManager', accounts => { account_investor4 = accounts[5]; account_investor5 = accounts[6]; + let instances = await setUpPolymathNetwork(account_polymath, token_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; + + // STEP 2: Deploy the GeneralDelegateManagerFactory + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + // STEP 3(a): Deploy the PercentageTransferManager + [I_BlacklistTransferManagerFactory] = await deployBlacklistTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + // STEP 4(b): Deploy the PercentageTransferManager + [P_BlacklistTransferManagerFactory] = await deployBlacklistTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); // ----------- POLYMATH NETWORK Configuration ------------ - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - - // Step 2: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // STEP 3: Deploy the ModuleRegistry - - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - // Step 3 (b): Deploy the proxy and attach the implementation contract to it - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); - await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); - I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - - - // STEP 4: Deploy the GeneralTransferManagerFactory - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 6: Deploy the BlacklistTransferManager - I_BlacklistTransferManagerFactory = await BlacklistTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - assert.notEqual( - I_BlacklistTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "BlacklistTransferManagerFactory contract was not deployed" - ); - - // STEP 7: Deploy Paid the CountTransferManager - P_BlacklistTransferManagerFactory = await BlacklistTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); - assert.notEqual( - P_BlacklistTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "BlacklistTransferManagerFactory contract was not deployed" - ); - - // Step 9: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 10: Deploy the SecurityTokenRegistry - - // Deploy the SecurityTokenregistry - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 11: Deploy the proxy and attach the implementation contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 12: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_MRProxied.updateFromRegistry({from: account_polymath}); - - // STEP 8: Register the Modules with the ModuleRegistry contract - - // (A) : Register the GeneralTransferManagerFactory - await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - - // (B) : Register the GeneralDelegateManagerFactory - await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the BlacklistTransferManagerFactory - await I_MRProxied.registerModule(I_BlacklistTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_BlacklistTransferManagerFactory.address, true, { from: account_polymath }); - - // (C) : Register the Paid BlacklistTransferManagerFactory - await I_MRProxied.registerModule(P_BlacklistTransferManagerFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(P_BlacklistTransferManagerFactory.address, true, { from: account_polymath }); - // Printing all the contract addresses console.log(` --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + PolymathRegistry: ${I_PolymathRegistry.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistry: ${I_ModuleRegistry.address} + ModuleRegistryProxy: ${I_ModuleRegistryProxy.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + STFactory: ${I_STFactory.address} + GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${I_GeneralPermissionManagerFactory.address} BlacklistTransferManagerFactory: ${I_BlacklistTransferManagerFactory.address} ----------------------------------------------------------------------------- From 76133678e543d02dc05c2b28e7ae954e5ba3be2c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 16 Oct 2018 09:53:07 +0530 Subject: [PATCH 019/582] Update createInstances.js --- test/helpers/createInstances.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 73cf1db40..84844d22f 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -251,7 +251,7 @@ export async function deployBlacklistTMAndVerified(accountPolymath, MRProxyInsta return new Array(I_BlacklistTransferManagerFactory); } -export async function deployVolumeRTMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { +export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_VolumeRestrictionTransferManagerFactory.address.valueOf(), @@ -405,4 +405,4 @@ function mergeReturn(returnData) { } } return returnArray; -} \ No newline at end of file +} From 5f80bad413e19a5ba76ac2faa52ca9fe993a1757 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Thu, 18 Oct 2018 19:57:23 -0300 Subject: [PATCH 020/582] CLI transfer manager for GTM --- CLI/commands/transfer_manager.js | 330 ++++++++++++++++++++++++------- CLI/package.json | 1 + CLI/yarn.lock | 21 ++ 3 files changed, 276 insertions(+), 76 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index df06c68f4..6a03ec1dd 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1,17 +1,27 @@ -var readlineSync = require('readline-sync'); -var chalk = require('chalk'); -var moment = require('moment'); -var common = require('./common/common_functions'); -var global = require('./common/global'); -var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis'); +const readlineSync = require('readline-sync'); +const chalk = require('chalk'); +const ethers = require('ethers'); +const common = require('./common/common_functions'); +const global = require('./common/global'); +const contracts = require('./helpers/contract_addresses'); +const abis = require('./helpers/contract_abis'); + +const MODULES_TYPES = { + PERMISSION: 1, + TRANSFER: 2, + STO: 3, + DIVIDEND: 4, + BURN: 5 +} // App flow let tokenSymbol; let securityToken; let securityTokenRegistry; +let network; async function executeApp(remoteNetwork) { + network = remoteNetwork; await global.initialize(remoteNetwork); common.logAsciiBull(); @@ -55,87 +65,255 @@ async function start_explorer() { } else { let securityTokenABI = abis.securityToken(); securityToken = new web3.eth.Contract(securityTokenABI,result); + + let tmModules = securityToken.methods.getModulesByType(MODULES_TYPES.TRANSFER).call(); + let options = []; let forcedTransferDisabled = await securityToken.methods.controllerDisabled().call(); - if (!forcedTransferDisabled) { - let options = ['Disable controller', 'Set controller']; - let controller = await securityToken.methods.controller().call(); - if (controller == Issuer.address) { - options.push('Force Transfer') - } - let index = readlineSync.keyInSelect(options, 'What do you want to do?'); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); - switch (optionSelected) { - case 'Disable controller': - if (readlineSync.keyInYNStrict()) { - let disableControllerAction = securityToken.methods.disableController(); - await common.sendTransaction(Issuer, disableControllerAction, defaultGasPrice); - console.log(chalk.green(`Forced transfers have been disabled permanently`)); - } + options.push('Forced Transfers'); + } + + options.push('GeneralTransferManager', 'ManualApprovalTransferManager', 'PercentageTransferManager', 'CountTransferManager', + 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM'); + + let index = readlineSync.keyInSelect(options, 'Choose one:'); + let optionSelected = options[index]; + console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); + switch (optionSelected) { + case 'Forced Transfers': + await forcedTransfers(); + break; + case 'GeneralTransferManager': + await generalTransferManager(); break; - case 'Set controller': - let controllerAddress = readlineSync.question(`Enter the address for the controller (${Issuer.address}): `, { - limit: function(input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - defaultInput: Issuer.address - }); - let setControllerAction = securityToken.methods.setController(controllerAddress); - let setControllerReceipt = await common.sendTransaction(Issuer, setControllerAction, defaultGasPrice); - let setControllerEvent = common.getEventFromLogs(securityToken._jsonInterface, setControllerReceipt.logs, 'SetController'); - console.log(chalk.green(`New controller is ${setControllerEvent._newController}`)); + case 'ManualApprovalTransferManager': + await manualApprovalTransferManager(); break; - case 'Force Transfer': - let from = readlineSync.question('Enter the address from which to take tokens: ', { - limit: function(input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - }); - let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(from).call()); - console.log(chalk.yellow(`Balance of ${from}: ${fromBalance} ${tokenSymbol}`)); - let to = readlineSync.question('Enter address where to send tokens: ', { - limit: function(input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - }); - let toBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(to).call()); - console.log(chalk.yellow(`Balance of ${to}: ${toBalance} ${tokenSymbol}`)); - let amount = readlineSync.question('Enter amount of tokens to transfer: ', { - limit: function(input) { - return parseInt(input) <= parseInt(fromBalance); - }, - limitMessage: `Amount must be less or equal than ${fromBalance} ${tokenSymbol}`, - }); - let data = readlineSync.question('Enter the data to indicate validation: '); - let log = readlineSync.question('Enter the data attached to the transfer by controller to emit in event: '); - let forceTransferAction = securityToken.methods.forceTransfer(from, to, web3.utils.toWei(amount), web3.utils.asciiToHex(data), web3.utils.asciiToHex(log)); - let forceTransferReceipt = await common.sendTransaction(Issuer, forceTransferAction, defaultGasPrice, 0, 1.5); - let forceTransferEvent = common.getEventFromLogs(securityToken._jsonInterface, forceTransferReceipt.logs, 'ForceTransfer'); - console.log(chalk.green(` ${forceTransferEvent._controller} has successfully forced a transfer of ${web3.utils.fromWei(forceTransferEvent._value)} ${tokenSymbol} + case 'PercentageTransferManager': + await percentageTransferManager(); + break; + case 'CountTransferManager': + await countTransferManager(); + break; + case 'SingleTradeVolumeRestrictionTM': + await singleTradeVolumeRestrictionTM(); + break; + case 'LookupVolumeRestrictionTM': + await lookupVolumeRestrictionTM(); + break; + } + } + + //Restart + await start_explorer(); +} + +async function forcedTransfers() { + let options = ['Disable controller', 'Set controller']; + let controller = await securityToken.methods.controller().call(); + if (controller == Issuer.address) { + options.push('Force Transfer'); + } + let index = readlineSync.keyInSelect(options, 'What do you want to do?'); + let optionSelected = options[index]; + console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); + switch (optionSelected) { + case 'Disable controller': + if (readlineSync.keyInYNStrict()) { + let disableControllerAction = securityToken.methods.disableController(); + await common.sendTransaction(Issuer, disableControllerAction, defaultGasPrice); + console.log(chalk.green(`Forced transfers have been disabled permanently`)); + } + break; + case 'Set controller': + let controllerAddress = readlineSync.question(`Enter the address for the controller (${Issuer.address}): `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: Issuer.address + }); + let setControllerAction = securityToken.methods.setController(controllerAddress); + let setControllerReceipt = await common.sendTransaction(Issuer, setControllerAction, defaultGasPrice); + let setControllerEvent = common.getEventFromLogs(securityToken._jsonInterface, setControllerReceipt.logs, 'SetController'); + console.log(chalk.green(`New controller is ${setControllerEvent._newController}`)); + break; + case 'Force Transfer': + let from = readlineSync.question('Enter the address from which to take tokens: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + }); + let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(from).call()); + console.log(chalk.yellow(`Balance of ${from}: ${fromBalance} ${tokenSymbol}`)); + let to = readlineSync.question('Enter address where to send tokens: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + }); + let toBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(to).call()); + console.log(chalk.yellow(`Balance of ${to}: ${toBalance} ${tokenSymbol}`)); + let amount = readlineSync.question('Enter amount of tokens to transfer: ', { + limit: function (input) { + return parseInt(input) <= parseInt(fromBalance); + }, + limitMessage: `Amount must be less or equal than ${fromBalance} ${tokenSymbol}`, + }); + let data = readlineSync.question('Enter the data to indicate validation: '); + let log = readlineSync.question('Enter the data attached to the transfer by controller to emit in event: '); + let forceTransferAction = securityToken.methods.forceTransfer(from, to, web3.utils.toWei(amount), web3.utils.asciiToHex(data), web3.utils.asciiToHex(log)); + let forceTransferReceipt = await common.sendTransaction(Issuer, forceTransferAction, defaultGasPrice, 0, 1.5); + let forceTransferEvent = common.getEventFromLogs(securityToken._jsonInterface, forceTransferReceipt.logs, 'ForceTransfer'); + console.log(chalk.green(` ${forceTransferEvent._controller} has successfully forced a transfer of ${web3.utils.fromWei(forceTransferEvent._value)} ${tokenSymbol} from ${forceTransferEvent._from} to ${forceTransferEvent._to} Verified transfer: ${forceTransferEvent._verifyTransfer} Data: ${web3.utils.hexToAscii(forceTransferEvent._data)} - `)); - console.log(`Balance of ${from} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(from).call())} ${tokenSymbol}`); - console.log(`Balance of ${to} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(to).call())} ${tokenSymbol}`); - break; - default: - process.exit(0); + `)); + console.log(`Balance of ${from} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(from).call())} ${tokenSymbol}`); + console.log(`Balance of ${to} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(to).call())} ${tokenSymbol}`); + break; + } +} + +async function generalTransferManager() { + let options = ['Change Issuance Address', 'Change Signing Address', 'Change Allow All Transfers', 'Change Allow All Whitelist Transfers', + 'Change Allow All Whitelist Issuances', 'Change Allow All Burn Transfers', 'Modify Whitelist', 'Modify Whitelist from CSV', + 'Modify Whitelist Signed']; + let index = readlineSync.keyInSelect(options, 'What do you want to do?'); + let optionSelected = options[index]; + console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); + switch (optionSelected) { + case 'Change Issuance Address': + let issuanceAddress = readlineSync.question('Enter the new issuance address: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let changeIssuanceAddressAction = currentTransferManager.methods.changeIssuanceAddress(issuanceAddress); + let changeIssuanceAddressReceipt = await common.sendTransaction(Issuer.address, changeIssuanceAddressAction, defaultGasPrice); + let changeIssuanceAddressEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeIssuanceAddressReceipt.logs, 'ChangeIssuanceAddress'); + console.log(chalk.green(`${changeIssuanceAddressEvent._issuanceAddress} is the new address for the issuance!`)); + break; + case 'Change Signing Address': + let signingAddress = readlineSync.question('Enter the new signing address: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let changeSigningAddressAction = currentTransferManager.methods.changeSigningAddress(signingAddress); + let changeSigningAddressReceipt = await common.sendTransaction(Issuer.address, changeSigningAddressAction, defaultGasPrice); + let changeSigningAddressEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeSigningAddressReceipt.logs, 'ChangeSigningAddress'); + console.log(chalk.green(`${changeSigningAddressEvent._signingAddress} is the new address for the signing!`)); + break; + case 'Change Allow All Transfers': + let allowAllTransfers = readlineSync.keyInYNStrict('Do you want to remove all restrictions for any addresses?'); + let changeAllowAllTransfersAction = currentTransferManager.methods.changeAllowAllTransfers(allowAllTransfers); + let changeAllowAllTransfersReceipt = await common.sendTransaction(Issuer.address, changeAllowAllTransfersAction, defaultGasPrice); + let changeAllowAllTransfersEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllTransfersReceipt.logs, 'AllowAllTransfers'); + if (changeAllowAllTransfersEvent._allowAllTransfers) { + console.log(chalk.green(`All transfers are allowed!`)); + } else { + console.log(chalk.green(`Transfers are restricted!`)); } - } else { - console.log(chalk.red(`Controller featueres are permanently disabled for this token.`)) - tokenSymbol = undefined; - } + break; + case 'Change Allow All Whitelist Transfers': + let allowAllWhitelistTransfers = readlineSync.keyInYNStrict('Do you want to ignore time locks from whitelist (address must still be whitelisted)?'); + let changeAllowAllWhitelistTransfersAction = currentTransferManager.methods.changeAllowAllWhitelistTransfers(allowAllWhitelistTransfers); + let changeAllowAllWhitelistTransfersReceipt = await common.sendTransaction(Issuer.address, changeAllowAllWhitelistTransfersAction, defaultGasPrice); + let changeAllowAllWhitelistTransfersEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllWhitelistTransfersReceipt.logs, 'AllowAllWhitelistTransfers'); + if (changeAllowAllWhitelistTransfersEvent._allowAllWhitelistTransfers) { + console.log(chalk.green(`Time locks from whitelist are ignored for transfers!`)); + } else { + console.log(chalk.green(`Transfers are restricted by time locks from whitelist!`)); + } + break; + case 'Change Allow All Whitelist Issuances': + let allowAllWhitelistIssuances = readlineSync.keyInYNStrict('Do you want to ignore time locks from whitelist (address must still be whitelisted)?'); + let changeAllowAllWhitelistIssuancesAction = currentTransferManager.methods.changeAllowAllIssuancesTransfers(allowAllWhitelistIssuances); + let changeAllowAllWhitelistIssuancesReceipt = await common.sendTransaction(Issuer.address, changeAllowAllWhitelistIssuancesAction, defaultGasPrice); + let changeAllowAllWhitelistIssuancesEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllWhitelistIssuancesReceipt.logs, 'AllowAllWhitelistIssuances'); + if (changeAllowAllWhitelistIssuancesEvent._allowAllWhitelistIssuances) { + console.log(chalk.green(`Time locks from whitelist are ignored for issuances!`)); + } else { + console.log(chalk.green(`Issuances are restricted by time locks from whitelist!`)); + } + break; + case 'Change Allow All Burn Transfers': + let allowAllBurnTransfers = readlineSync.keyInYNStrict('Do you want to ignore time locks from whitelist (address must still be whitelisted)?'); + let changeAllowAllBurnTransfersAction = currentTransferManager.methods.allowAllBurnTransfers(allowAllBurnTransfers); + let changeAllowAllBurnTransfersReceipt = await common.sendTransaction(Issuer.address, changeAllowAllBurnTransfersAction, defaultGasPrice); + let changeAllowAllBurnTransfersEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllBurnTransfersReceipt.logs, 'AllowAllBurnTransfers'); + if (changeAllowAllBurnTransfersEvent._allowAllWhitelistTransfers) { + console.log(chalk.green(`To burn tokens is allowed!`)); + } else { + console.log(chalk.green(`The burning mechanism is deactivated!`)); + } + break; + case 'Modify Whitelist': + let investor = readlineSync.question('Enter the address to whitelist: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let fromTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); + let toTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); + let expiryTime = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); + let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); + let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); + let modifyWhitelistReceipt = await common.sendTransaction(Issuer.address, modifyWhitelistAction, defaultGasPrice); + let modifyWhitelistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); + console.log(chalk.green(`${modifyWhitelistEvent._investor} has been whitelisted sucessfully!`)); + case 'Modify Whitelist from CSV': + console.log(chalk.yellow(`Data is going to be read from 'data/whitelist_data.csv'. Be sure this file is updated!`)); + if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { + shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${network}`); + } + break; + /* + case 'Modify Whitelist Signed': + let investorSigned = readlineSync.question('Enter the address to whitelist: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let fromTimeSigned = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); + let toTimeSigned = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); + let expiryTimeSigned = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); + let vSigned = readlineSync.questionInt('Enter v: '); + let rSigned = readlineSync.question('Enter r: '); + let sSigned = readlineSync.question('Enter s: '); + let canBuyFromSTOSigned = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); + let modifyWhitelistSignedAction = currentTransferManager.methods.modifyWhitelistSigned(investorSigned, fromTimeSigned, toTimeSigned, expiryTimeSigned, canBuyFromSTOSigned); + let modifyWhitelistSignedReceipt = await common.sendTransaction(Issuer.address, modifyWhitelistSignedAction, defaultGasPrice); + let modifyWhitelistSignedEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistSignedReceipt.logs, 'ModifyWhitelist'); + console.log(chalk.green(`${modifyWhitelistSignedEvent._investor} has been whitelisted sucessfully!`)); + break; + */ } +} - //Restart - await start_explorer(); +/* +// Copied from tests +function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, pk) { + let packedData = ethers.utils + .solidityKeccak256( + ["address", "address", "uint256", "uint256", "uint256", "bool", "uint256", "uint256"], + [tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo] + ) + .slice(2); + packedData = new Buffer(packedData, "hex"); + packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message:\n${packedData.length.toString()}`), packedData]); + packedData = web3.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); + return ethUtil.ecsign(new Buffer(packedData.slice(2), "hex"), new Buffer(pk, "hex")); } +*/ module.exports = { executeApp: async function(type, remoteNetwork) { diff --git a/CLI/package.json b/CLI/package.json index 92430ac59..d035e7cca 100644 --- a/CLI/package.json +++ b/CLI/package.json @@ -11,6 +11,7 @@ "dependencies": { "chalk": "^2.4.1", "commander": "^2.16.0", + "ethers": "^4.0.7", "moment": "^2.22.2", "readline-sync": "^1.4.9", "request": "^2.88.0", diff --git a/CLI/yarn.lock b/CLI/yarn.lock index 4a06bda2e..0fd77a236 100644 --- a/CLI/yarn.lock +++ b/CLI/yarn.lock @@ -674,6 +674,22 @@ ethers@4.0.0-beta.1: uuid "2.0.1" xmlhttprequest "1.8.0" +ethers@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.7.tgz#8c653618077a1fc60c5c1b2575da03561f0039f4" + integrity sha512-HGR2FcyeiRjg6qZUjtK5gkTp7puB+KPhBDa0s2zG4IMVcfU33rkhl9yBIqZBzpD5J0fE33gQ57+epZh90nBaeA== + dependencies: + "@types/node" "^10.3.2" + aes-js "3.0.0" + bn.js "^4.4.0" + elliptic "6.3.3" + hash.js "1.1.3" + js-sha3 "0.5.7" + scrypt-js "2.0.4" + setimmediate "1.0.4" + uuid "2.0.1" + xmlhttprequest "1.8.0" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -1658,6 +1674,11 @@ scrypt-js@2.0.3: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" integrity sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q= +scrypt-js@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" + integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== + scrypt.js@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" From 3a96716ae68dc7fd8d38aa627de83d3c7abf26bb Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Fri, 19 Oct 2018 11:58:50 +0530 Subject: [PATCH 021/582] added changes in test cases --- .../BlacklistTransferManager.sol | 47 +- test/y_blacklist_transfer_manager.js | 408 ++++++++---------- 2 files changed, 187 insertions(+), 268 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index cac49a779..863d64cc5 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -32,6 +32,7 @@ contract BlacklistTransferManager is ITransferManager { //store the index of the blacklist to investor mapping(bytes32 => mapping(address => uint256)) blacklistToIndex; + // Emit when new blacklist type is added event AddBlacklistType( uint256 _startTime, @@ -96,31 +97,23 @@ contract BlacklistTransferManager is ITransferManager { if (!paused) { if (investorToBlacklist[_from].length != 0) { for (uint256 i = 0; i < investorToBlacklist[_from].length; i++) { - if (investorToBlacklist[_from][i] != bytes32(0)) { - uint256 endTimeTemp = blacklists[investorToBlacklist[_from][i]].endTime; - uint256 startTimeTemp = blacklists[investorToBlacklist[_from][i]].startTime; - uint256 repeatPeriodTimeTemp = blacklists[investorToBlacklist[_from][i]].repeatPeriodTime * 1 days; - // blacklistTime time is used to find the new startTime and endTime - // suppose startTime=500,endTime=1500,repeatPeriodTime=500 then blacklistTime =1500 - // if you add blacklistTime to startTime and endTime i.e startTime = 2000 and endTime = 3000 - uint256 blacklistTime = (endTimeTemp.sub(startTimeTemp)).add(repeatPeriodTimeTemp); - if (now > startTimeTemp) { - // Find the repeating parameter that will be used to calculate the new startTime and endTime - // based on the new current time value - uint256 repeater = (now.sub(startTimeTemp)).div(blacklistTime); - if (startTimeTemp.add(blacklistTime.mul(repeater)) <= now && endTimeTemp.add(blacklistTime.mul(repeater)) >= now) { - return Result.INVALID; - } - return Result.NA; - } else - // BlackList time period is not yet started - return Result.NA; - } - return Result.NA; - } - - } - return Result.NA; + uint256 endTimeTemp = blacklists[investorToBlacklist[_from][i]].endTime; + uint256 startTimeTemp = blacklists[investorToBlacklist[_from][i]].startTime; + uint256 repeatPeriodTimeTemp = blacklists[investorToBlacklist[_from][i]].repeatPeriodTime * 1 days; + // blacklistTime time is used to find the new startTime and endTime + // suppose startTime=500,endTime=1500,repeatPeriodTime=500 then blacklistTime =1500 + // if you add blacklistTime to startTime and endTime i.e startTime = 2000 and endTime = 3000 + uint256 blacklistTime = (endTimeTemp.sub(startTimeTemp)).add(repeatPeriodTimeTemp); + if (now > startTimeTemp) { + // Find the repeating parameter that will be used to calculate the new startTime and endTime + // based on the new current time value + uint256 repeater = (now.sub(startTimeTemp)).div(blacklistTime); + if (startTimeTemp.add(blacklistTime.mul(repeater)) <= now && endTimeTemp.add(blacklistTime.mul(repeater)) >= now) { + return Result.INVALID; + } + } + } + } } return Result.NA; } @@ -142,7 +135,7 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Internal function */ - function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) internal view { + function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) internal pure { require(_name != bytes32(0), "Invalid blacklist name"); require(_startTime != 0 && _startTime < _endTime, "Invalid start or end date"); require(_repeatPeriodTime != 0, "Invalid repeat days"); @@ -213,7 +206,6 @@ contract BlacklistTransferManager is ITransferManager { function deleteInvestorFromBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { require(_investor != address(0), "Invalid investor address"); require(_blacklistName != bytes32(0),"Invalid blacklist name"); - require(investorToBlacklist[_investor][investorToIndex[_investor][_blacklistName]] != bytes32(0), "Investor is not associated to blacklist type"); // delete the investor from the blacklist type uint256 _blacklistIndex = blacklistToIndex[_blacklistName][_investor]; uint256 _len = blacklistToInvestor[_blacklistName].length; @@ -267,7 +259,6 @@ contract BlacklistTransferManager is ITransferManager { */ function getListOfAddresses(bytes32 _blacklistName) public view returns(address[]) { require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); - require(blacklistToInvestor[_blacklistName].length != 0, "Blacklist doesnot have any associated address"); return blacklistToInvestor[_blacklistName]; } diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index 8de367f1a..49d9f6dc1 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -3,7 +3,7 @@ import { duration, ensureException, promisifyLogWatch, latestBlock } from './hel import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; import { setUpPolymathNetwork, deployGPMAndVerifyed, deployBlacklistTMAndVerified } from "./helpers/createInstances"; - +import { catchRevert } from "./helpers/exceptions"; const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const BlacklistTransferManager = artifacts.require("./BlacklistTransferManager"); @@ -169,16 +169,12 @@ contract('BlacklistTransferManager', accounts => { }); it("Should successfully attach the BlacklistTransferManager factory with the security token", async () => { - let errorThrown = false; await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - try { - const tx = await I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - } catch(error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); + await catchRevert ( + I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + from: token_owner + }) + ); }); it("Should successfully attach the BlacklistTransferManager factory with the security token", async () => { @@ -230,11 +226,11 @@ contract('BlacklistTransferManager', accounts => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('3', 'ether'), { from: token_owner }); + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('5', 'ether'), { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('3', 'ether') + web3.utils.toWei('5', 'ether') ); }); @@ -270,75 +266,51 @@ contract('BlacklistTransferManager', accounts => { }); it("Should fail in adding the blacklist as blacklist type already exist", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Blacklist type already exist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { + from: token_owner + }) + ); }); it("Should fail in adding the blacklist as the blacklist name is invalid", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "", 20, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Invalid blacklist name`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "", 20, { + from: token_owner + }) + ); }); it("Should fail in adding the blacklist as the start date is invalid", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addBlacklistType(0, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Invalid start date`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(0, latestTime()+3000, "b_blacklist", 20, { + from: token_owner + }) + ); }); it("Should fail in adding the blacklist as the dates are invalid", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Start date is less than end date`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { + from: token_owner + }) + ); }); it("Should fail in adding the blacklist as repeat in days is invalid", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 0, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Invalid repeat in days`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 0, { + from: token_owner + }) + ); }); it("Should fail in adding the blacklist because only owner can add the blacklist", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to add the blacklist type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { + from: account_investor1 + }) + ); }); @@ -350,64 +322,44 @@ contract('BlacklistTransferManager', accounts => { }); it("Should fail in modifying the blacklist as the name is invalid", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "", 20, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Invalid blacklist name`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "", 20, { + from: token_owner + }) + ); }); it("Should fail in modifying the blacklist as the dates are invalid", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Invalid start or end date`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.modifyBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { + from: token_owner + }) + ); }); it("Should fail in modifying the blacklist as the repeat in days is invalid", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "b_blacklist", 0, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Invalid repeat in days`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "b_blacklist", 0, { + from: token_owner + }) + ); }); it("Should fail in modifying the blacklist as only owner can modify the blacklist", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to modify the blacklist type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { + from: account_investor1 + }) + ); }); it("Should fail in modifying the blacklist as blacklist type doesnot exist", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Blacklist type doesnot exist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { + from: token_owner + }) + ); }); it("Should add investor to the blacklist", async() => { @@ -418,40 +370,28 @@ contract('BlacklistTransferManager', accounts => { }); it("Should fail in adding the investor to the blacklist because only owner can add the investor", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "a_blacklist", { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to add the investor to the blacklist type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "a_blacklist", { + from: account_investor1 + }) + ); }); it("Should fail in adding the investor to the blacklist as investor address is invalid", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addInvestorToBlacklist(0x0, "a_blacklist", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Invalid investor address`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addInvestorToBlacklist(0x0, "a_blacklist", { + from: token_owner + }) + ); }); it("Should fail in adding the investor to the non existing blacklist", async() => { - let errorThrown = false; - try { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "b_blacklist", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Trying to add the investor in non existing blacklist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "b_blacklist", { + from: token_owner + }) + ); }); it("Should get the list of investors associated to blacklist", async() => { @@ -460,16 +400,18 @@ contract('BlacklistTransferManager', accounts => { }); it("Should fail in getting the list of investors from the non existing blacklist", async() => { - let errorThrown = false; - try{ - let perm = await I_BlacklistTransferManager.getListOfAddresses.call("b_blacklist"); - } - catch(error){ - console.log(` tx revert -> Trying to get the list of investors of non existing blacklist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.getListOfAddresses.call("b_blacklist") + ); + }); + + it("Should investor be able to transfer token because current time is less than the blacklist start time", async() => { + //Trasfer tokens + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('3', 'ether') + ); }); it("Should investor be able to transfer token as it is not in blacklist time period", async() => { @@ -480,28 +422,34 @@ contract('BlacklistTransferManager', accounts => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); assert.equal( (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('3', 'ether') + web3.utils.toWei('4', 'ether') ); }); it("Should fail in transfer the tokens as the investor in blacklist", async() => { - let errorThrown = false; // Jump time await increaseTime(1727500); - try{ - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - } - catch(error){ - console.log(` tx revert -> Trying to send token by the blacklisted address`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { + from: account_investor1 + }) + ); + }); + + it("Should investor is able transfer the tokens- because BlacklistTransferManager is paused", async() => { + await I_BlacklistTransferManager.pause({from:token_owner}); + //Trasfer tokens + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('5', 'ether') + ); }); it("Should delete the blacklist type", async() => { + await I_BlacklistTransferManager.unpause({from:token_owner}); await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "b_blacklist", "Failed in deleting the blacklist"); @@ -510,39 +458,27 @@ contract('BlacklistTransferManager', accounts => { it("Only owner have the permission to delete thr blacklist type", async() => { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to delete the blacklist type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { + from: account_investor1 + }) + ); }); it("Should fail in deleting the blacklist type as the blacklist has associated addresses", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteBlacklistType("a_blacklist", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Not able to delete the blacklist as blacklist has associated addresses.`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.deleteBlacklistType("a_blacklist", { + from: token_owner + }) + ); }); it("Should fail in deleting the blacklist type as the blacklist doesnot exist", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteBlacklistType("c_blacklist", { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Not able to delete the blacklist as blacklist type doesnot exist.`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.deleteBlacklistType("c_blacklist", { + from: token_owner + }) + ); }); it("Should delete the investor from all the associated blacklist", async() => { @@ -555,39 +491,27 @@ contract('BlacklistTransferManager', accounts => { it("Only owner has the permission to delete the investor from all the blacklist type", async() => { await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { + from: account_investor2 + }) + ) }); it("Should fail in deleting the investor from all the associated blacklist as th address is invalid", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(0x0, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Invalid investor address`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(0x0, { + from: token_owner + }) + ); }); it("Should fail in deleting the investor which is not associated to blacklist", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor2, { from: token_owner }); - } catch(error) { - console.log(` tx revert -> Investor is not associated to blacklist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor2, { + from: token_owner + }) + ); }); it("Should delete the investor from the blacklist type", async() => { @@ -600,15 +524,27 @@ contract('BlacklistTransferManager', accounts => { it("Only owner can delete the investor from the blacklist type", async() => { await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to delete the investor from blacklist type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { + from: account_investor2 + }) + ); + }); + + it("Should fail in deleting the investor because the investor address is invalid", async() => { + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromBlacklist(0x0, "f_blacklist", { + from: token_owner + }) + ); + }); + + it("Should fail in deleting the investor because the blacklist name is invalid", async() => { + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "", { + from: token_owner + }) + ); }); it("Should add investor and new blacklist type", async() => { @@ -619,15 +555,11 @@ contract('BlacklistTransferManager', accounts => { }); it("Should fail in adding the investor and new blacklist type", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: account_investor2 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to add the investor to blacklist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { + from: account_investor2 + }) + ); }); it("Should add mutiple investor to blacklist", async() => { @@ -644,15 +576,11 @@ contract('BlacklistTransferManager', accounts => { }); it("Should fail in adding the mutiple investor to the blacklist", async() => { - let errorThrown = false; - try { - let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "b_blacklist", { from: account_investor1 }); - } catch(error) { - console.log(` tx revert -> Only owner have the permission to add the investors to blacklist`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "b_blacklist", { + from: account_investor1 + }) + ); }); it("Should get the init function", async() => { From 7e75b3a575c297b08ba4008af1f8b7932cb7d39b Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Fri, 19 Oct 2018 15:54:18 +0530 Subject: [PATCH 022/582] added test cases --- test/y_blacklist_transfer_manager.js | 140 +++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 10 deletions(-) diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index 49d9f6dc1..cacb2f8a8 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -259,6 +259,55 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should Buy some more tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(50), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should Buy some more tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor4, + latestTime(), + latestTime(), + latestTime() + duration.days(50), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor4.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor4, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should add the blacklist", async() => { //Add the new blacklist let tx = await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); @@ -446,10 +495,89 @@ contract('BlacklistTransferManager', accounts => { ); }); - + it("Should investor fail in transfer token as it is in blacklist time period", async() => { + await I_BlacklistTransferManager.unpause({from:token_owner}); + await I_BlacklistTransferManager.addBlacklistType(latestTime()+500, latestTime()+4000, "k_blacklist", 8, { from: token_owner }); + + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "k_blacklist", { from: token_owner }); + // Jump time + await increaseTime(3500); + + //Trasfer tokens + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { + from: account_investor2 + }) + ) + }); + + it("Should investor be able to transfer token as it is not in blacklist time period", async() => { + // Jump time + await increaseTime(1000); + + //Trasfer tokens + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('3', 'ether') + ); + }); + + it("Should investor fail in transfer token as it is in blacklist time period", async() => { + + // Jump time + await increaseTime(690800); + + //Trasfer tokens + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { + from: account_investor2 + }) + ); + }); + + it("Should investor fail in transfer token as it is in blacklist time period", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+5000, latestTime()+8000, "l_blacklist", 5, { from: token_owner }); + + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor3, "l_blacklist", { from: token_owner }); + // Jump time + await increaseTime(5500); + + //Trasfer tokens + await catchRevert( + I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { + from: account_investor3 + }) + ); + }); + + it("Should investor be able to transfer token as it is not in blacklist time period", async() => { + // Jump time + await increaseTime(3000); + + //Trasfer tokens + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor3 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), + web3.utils.toWei('3', 'ether') + ); + }); + + it("Should investor fail in transfer token as it is in blacklist time period", async() => { + + // Jump time + await increaseTime(431600); + + //Trasfer tokens + await catchRevert( + I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { + from: account_investor3 + }) + ); + }); + it("Should delete the blacklist type", async() => { - await I_BlacklistTransferManager.unpause({from:token_owner}); await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "b_blacklist", "Failed in deleting the blacklist"); @@ -506,14 +634,6 @@ contract('BlacklistTransferManager', accounts => { ); }); - it("Should fail in deleting the investor which is not associated to blacklist", async() => { - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor2, { - from: token_owner - }) - ); - }); - it("Should delete the investor from the blacklist type", async() => { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); From 621cd6aafe01850a024d8d8331a2be7ef16660be Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Fri, 19 Oct 2018 18:51:52 +0530 Subject: [PATCH 023/582] changed title --- contracts/modules/TransferManager/BlacklistTransferManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 863d64cc5..176d42dd8 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -4,7 +4,7 @@ import "./ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** - * @title Transfer Manager module for manually approving or blocking transactions between accounts + * @title Transfer Manager module to automate blacklist to restrict transfer */ contract BlacklistTransferManager is ITransferManager { using SafeMath for uint256; From f6d1323ce22fc3340c9b1da9f58bca16c50dab7f Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Fri, 19 Oct 2018 20:24:48 +0530 Subject: [PATCH 024/582] added test cases --- test/y_blacklist_transfer_manager.js | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index cacb2f8a8..a5d0a445c 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -307,6 +307,30 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should Buy some more tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor5, + latestTime(), + latestTime(), + latestTime() + duration.days(50), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor5.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor5, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor5)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + it("Should add the blacklist", async() => { //Add the new blacklist @@ -634,9 +658,19 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should fail in deleting the investor because investor is not associated to any blacklist", async() => { + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor5, { + from: token_owner + }) + ); + }); + it("Should delete the investor from the blacklist type", async() => { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + await I_BlacklistTransferManager.addBlacklistType(latestTime()+500, latestTime()+8000, "q_blacklist", 10, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "q_blacklist", { from: token_owner }); let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); From d9bcf92c33a4ed9f1853b937a4c811954b13f109 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Fri, 19 Oct 2018 23:39:32 +0530 Subject: [PATCH 025/582] added check for add and delete investor --- .../BlacklistTransferManager.sol | 6 ++++++ test/y_blacklist_transfer_manager.js | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 176d42dd8..bbdd5a693 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -32,6 +32,8 @@ contract BlacklistTransferManager is ITransferManager { //store the index of the blacklist to investor mapping(bytes32 => mapping(address => uint256)) blacklistToIndex; + //store the investor to blacklist status + mapping(address => mapping(bytes32 => bool)) investorBlacklistStatus; // Emit when new blacklist type is added event AddBlacklistType( @@ -175,6 +177,7 @@ contract BlacklistTransferManager is ITransferManager { function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); + require(!investorBlacklistStatus[_investor][_blacklistName],"Investor already associated to the same blacklist"); uint256 investorIndex = investorToBlacklist[_investor].length; // Add blacklist index to the investor investorToIndex[_investor][_blacklistName] = investorIndex; @@ -183,6 +186,7 @@ contract BlacklistTransferManager is ITransferManager { blacklistToIndex[_blacklistName][_investor] = blacklistIndex; investorToBlacklist[_investor].push(_blacklistName); blacklistToInvestor[_blacklistName].push(_investor); + investorBlacklistStatus[_investor][_blacklistName] = true; emit AddInvestorToBlacklist(_investor, _blacklistName); } @@ -206,6 +210,7 @@ contract BlacklistTransferManager is ITransferManager { function deleteInvestorFromBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { require(_investor != address(0), "Invalid investor address"); require(_blacklistName != bytes32(0),"Invalid blacklist name"); + require(investorBlacklistStatus[_investor][_blacklistName],"Investor not associated to the blacklist"); // delete the investor from the blacklist type uint256 _blacklistIndex = blacklistToIndex[_blacklistName][_investor]; uint256 _len = blacklistToInvestor[_blacklistName].length; @@ -225,6 +230,7 @@ contract BlacklistTransferManager is ITransferManager { } investorToBlacklist[_investor].length--; // delete the blacklist index from the invetsor + investorBlacklistStatus[_investor][_blacklistName] = false; delete(investorToIndex[_investor][_blacklistName]); emit DeleteInvestorFromBlacklist(_investor, _blacklistName); } diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index a5d0a445c..5f771e469 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -450,6 +450,14 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should fail in adding the investor to the same blacklist", async() => { + await catchRevert( + I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { + from: account_investor1 + }) + ); + }); + it("Should fail in adding the investor to the blacklist as investor address is invalid", async() => { await catchRevert( I_BlacklistTransferManager.addInvestorToBlacklist(0x0, "a_blacklist", { @@ -669,6 +677,7 @@ contract('BlacklistTransferManager', accounts => { it("Should delete the investor from the blacklist type", async() => { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "f_blacklist", { from: token_owner }); await I_BlacklistTransferManager.addBlacklistType(latestTime()+500, latestTime()+8000, "q_blacklist", 10, { from: token_owner }); await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "q_blacklist", { from: token_owner }); let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); @@ -693,6 +702,15 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should fail in deleting the investor because the investor is not associated to blacklist", async() => { + await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { + from: token_owner + }) + ); + }); + it("Should fail in deleting the investor because the blacklist name is invalid", async() => { await catchRevert( I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "", { From 44c83b4e7fff51ee78e112aafdafdc64bc6b213f Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Sat, 20 Oct 2018 01:26:39 -0300 Subject: [PATCH 026/582] CLI transfer manager for STVR TM --- CLI/commands/transfer_manager.js | 163 +++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 6a03ec1dd..9d4917117 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -299,6 +299,169 @@ async function generalTransferManager() { } } +async function singleTradeVolumeRestrictionTM() { + let primaryIssuanceAllowed = await currentTransferManager.methods.allowPrimaryIssuance().call(); + let allowPrimeryIssuanceOption = primaryIssuanceAllowed ? 'Allow Primary Issuance' : 'Disallow Primary Issuance'; + + let options = [allowPrimeryIssuanceOption, 'Add exempted wallet', 'Remove exempted wallet']; + + let isTransferLimitInPercentage = await currentTransferManager.methods.isTransferLimitInPercentage().call(); + if (isTransferLimitInPercentage) { + options.push('Change transfer limit to tokens', 'Change default percentage limit', + 'Set percentage transfer limit per account', 'Remove percentage transfer limit per account'); + } else { + options.push('Change transfer limit to percentage', 'Change default tokens limit', + 'Set tokens transfer limit per account', 'Remove tokens transfer limit per account'); + } + + let index = readlineSync.keyInSelect(options, 'What do you want to do?'); + let optionSelected = options[index]; + console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); + switch (optionSelected) { + case 'Allow Primary Issuance': + let allowPrimaryIssuanceAction = currentTransferManager.methods.setAllowPrimaryIssuance(true); + await common.sendTransaction(Issuer.address, allowPrimaryIssuanceAction, defaultGasPrice); + break; + case 'Disallow Primary Issuance': + let disallowPrimaryIssuanceAction = currentTransferManager.methods.setAllowPrimaryIssuance(false); + await common.sendTransaction(Issuer.address, disallowPrimaryIssuanceAction, defaultGasPrice); + break; + case 'Add exempted wallet': + let walletToExempt = readlineSync.question('Enter the wallet to exempt', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let addExemptWalletAction = currentTransferManager.methods.addExemptWallet(walletToExempt); + let addExemptWalletReceipt = await common.sendTransaction(Issuer.address, addExemptWalletAction, defaultGasPrice); + let addExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addExemptWalletReceipt.logs, 'ExemptWalletAdded'); + console.log(chalk.green(`${addExemptWalletEvent._wallet} has been exempted sucessfully!`)); + break; + case 'Remove exempted wallet': + let exemptedWallet = readlineSync.question('Enter the wallet to remove from exempt', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let removeExemptWalletAction = currentTransferManager.methods.removeExemptWallet(exemptedWallet); + let removeExemptWalletReceipt = await common.sendTransaction(Issuer.address, removeExemptWalletAction, defaultGasPrice); + let removeExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeExemptWalletReceipt.logs, 'ExemptWalletRemoved'); + console.log(chalk.green(`${removeExemptWalletEvent._wallet} has been removed from exempt wallets sucessfully!`)); + break; + case 'Change transfer limit to tokens': + let newDefaultLimitInTokens = readlineSync.questionInt('Enter the amount of tokens for default limit: ', { + limit: function(input) { + return input > 0; + }, + limitMessage: "Must be greater than zero" + }); + let changeTransferLimitToTokensAction = currentTransferManager.methods.changeTransferLimitToTokens(web3.utils.toWei(newDefaultLimitInTokens)); + let changeTransferLimitToTokensReceipt = await common.sendTransaction(Issuer.address, changeTransferLimitToTokensAction, defaultGasPrice); + let changeTransferLimitToTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); + console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); + console.log(chalk.green(`The default transfer limit is ${changeTransferLimitToTokensEvent._amount} ${tokenSymbol}`)); + break; + case 'Change transfer limit to percentage': + let newDefaultLimitInPercentage = readlineSync.questionInt('Enter the percentage for default limit: ', { + limit: function(input) { + return 0 < input <= 100; + }, + limitMessage: "Must be greater than 0 and less than 100" + }); + let changeTransferLimitToPercentageAction = currentTransferManager.methods.changeTransferLimitToPercentage(newDefaultLimitInPercentage); + let changeTransferLimitToPercentageReceipt = await common.sendTransaction(Issuer.address, changeTransferLimitToPercentageAction, defaultGasPrice); + let changeTransferLimitToPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); + console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); + console.log(chalk.green(`The default transfer limit is ${changeTransferLimitToPercentageEvent._percentage}%`)); + break; + case 'Change default percentage limit': + let defaultLimitInPercentage = readlineSync.questionInt('Enter the percentage for default limit: ', { + limit: function(input) { + return 0 < input <= 100; + }, + limitMessage: "Must be greater than 0 and less than 100" + }); + let changeGlobalLimitInPercentageAction = currentTransferManager.methods.changeGlobalLimitInPercentage(defaultLimitInPercentage); + let changeGlobalLimitInPercentageReceipt = await common.sendTransaction(Issuer.address, changeGlobalLimitInPercentageAction, defaultGasPrice); + let changeGlobalLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); + console.log(chalk.green(`The default transfer limit is ${changeGlobalLimitInPercentageEvent._percentage}%`)); + break; + case 'Change default tokens limit': + let defaultLimitInTokens = readlineSync.questionInt('Enter the amount of tokens for default limit: ', { + limit: function(input) { + return input > 0; + }, + limitMessage: "Must be greater than zero" + }); + let changeGlobalLimitInTokensAction = currentTransferManager.methods.changeGlobalLimitInTokens(web3.utils.toWei(defaultLimitInTokens)); + let changeGlobalLimitInTokensReceipt = await common.sendTransaction(Issuer.address, changeGlobalLimitInTokensAction, defaultGasPrice); + let changeGlobalLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); + console.log(chalk.green(`The default transfer limit is ${changeGlobalLimitInTokensEvent._amount} ${tokenSymbol}`)); + break; + case 'Set percentage transfer limit per account': + let percentageAccount = readlineSync.question('Enter the wallet: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let accountLimitInPercentage = readlineSync.questionInt(`Enter the transfer limit for ${percentageAccount} in percentage: `, { + limit: function(input) { + return 0 < input <= 100; + }, + limitMessage: "Must be greater than 0 and less than 100" + }); + let setTransferLimitInPercentageAction = currentTransferManager.methods.setTransferLimitInPercentage(percentageAccount, web3.utils.toWei(accountLimitInPercentage)); + let setTransferLimitInPercentageReceipt = await common.sendTransaction(Issuer.address, setTransferLimitInPercentageAction, defaultGasPrice); + let setTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageSet'); + console.log(chalk.green(`The transfer limit for ${setTransferLimitInPercentageEvent._wallet} is ${setTransferLimitInPercentageEvent._percentage}%`)); + break; + case 'Set tokens transfer limit per account': + let tokensAccount = readlineSync.question('Enter the wallet: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let accountLimitInTokens = readlineSync.questionInt(`Enter the transfer limit for ${tokensAccount} in amount of tokens: `, { + limit: function(input) { + return input > 0; + }, + limitMessage: "Must be greater than zero" + }); + let setTransferLimitInTokensAction = currentTransferManager.methods.setTransferLimitInTokens(tokensAccount, web3.utils.toWei(accountLimitInTokens)); + let setTransferLimitInTokensReceipt = await common.sendTransaction(Issuer.address, setTransferLimitInTokensAction, defaultGasPrice); + let setTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensSet'); + console.log(chalk.green(`The transfer limit for ${setTransferLimitInTokensEvent._wallet} is ${setTransferLimitInTokensEvent._percentage} ${tokenSymbol}`)); + break; + case 'Remove percentage transfer limit per account': + let percentageAccountToRemove = readlineSync.question('Enter the wallet to remove: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let removeTransferLimitInPercentageAction = currentTransferManager.methods.removeTransferLimitInPercentage(percentageAccountToRemove); + let removeTransferLimitInPercentageReceipt = await common.sendTransaction(Issuer.address, removeTransferLimitInPercentageAction, defaultGasPrice); + let removeTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageRemoved'); + console.log(chalk.green(`The transfer limit for ${removeTransferLimitInPercentageEvent._wallet} is the default limit`)); + break; + case 'Remove tokens transfer limit per account': + let tokensAccountToRemove = readlineSync.question('Enter the wallet to remove: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let removeTransferLimitInTokensAction = currentTransferManager.methods.removeTransferLimitInTokens(tokensAccountToRemove); + let removeTransferLimitInTokensReceipt = await common.sendTransaction(Issuer.address, removeTransferLimitInTokensAction, defaultGasPrice); + let removeTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensRemoved'); + console.log(chalk.green(`The transfer limit for ${removeTransferLimitInTokensEvent._wallet} is the default limit`)); + break; + } +} /* // Copied from tests function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, pk) { From a3bbbc1b385735181f374de9de0c2f6874372141 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Sun, 21 Oct 2018 19:46:20 +0530 Subject: [PATCH 027/582] minor change in test cases --- test/y_blacklist_transfer_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index 5f771e469..edbf7a221 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -453,7 +453,7 @@ contract('BlacklistTransferManager', accounts => { it("Should fail in adding the investor to the same blacklist", async() => { await catchRevert( I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { - from: account_investor1 + from: token_owner }) ); }); From f8d73b92569b780d6f83d3260e05ad2e92dbd1fa Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Tue, 23 Oct 2018 11:37:47 -0300 Subject: [PATCH 028/582] Minor changes --- CLI/commands/common/common_functions.js | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index dbf3aa8dd..aa553b18e 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -1,5 +1,30 @@ const chalk = require('chalk'); const Tx = require('ethereumjs-tx'); +const permissionsList = require('./permissions_list'); +const abis = require('../helpers/contract_abis'); + +async function connect(abi, address) { + contractRegistry = new web3.eth.Contract(abi, address); + contractRegistry.setProvider(web3.currentProvider); + return contractRegistry +}; + +async function checkPermission(contractName, functionName, contractRegistry) { + let permission = permissionsList.verifyPermission(contractName, functionName); + if (permission === undefined) { + return true + } else { + let stAddress = await contractRegistry.methods.securityToken().call(); + let securityToken = await connect(abis.securityToken(), stAddress); + let stOwner = await securityToken.methods.owner().call(); + if (stOwner == Issuer.address) { + return true + } else { + let result = await securityToken.methods.checkPermission(Issuer.address, contractRegistry.options.address, web3.utils.asciiToHex(permission)).call(); + return result + } + } +}; module.exports = { convertToDaysRemaining: function (timeRemaining) { @@ -48,6 +73,20 @@ module.exports = { `); }, sendTransaction: async function (from, action, gasPrice, value, factor) { + let contractRegistry = await connect(action._parent.options.jsonInterface, action._parent._address); + + //NOTE this is a condition to verify if the transaction comes from a module or not. + if (contractRegistry.methods.hasOwnProperty('factory')) { + let moduleAddress = await contractRegistry.methods.factory().call(); + let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress) + let parentModule = await moduleRegistry.methods.getName().call(); + let result = await checkPermission(web3.utils.hexToUtf8(parentModule), action._method.name, contractRegistry); + if (!result) { + console.log(chalk.red(`\nYou have not the right permissions to execute this method on this module!\n`)); + process.exit(0); + } + } + if (typeof factor === 'undefined') factor = 1.2; let block = await web3.eth.getBlock("latest"); From 40d49a18c8769908cf8ce6c1be86fc35a35673ab Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Tue, 23 Oct 2018 11:53:57 -0300 Subject: [PATCH 029/582] Dependencies fix for CLI --- CLI/package.json | 2 +- CLI/yarn.lock | 394 ++++++++++++++++++++--------------------------- 2 files changed, 167 insertions(+), 229 deletions(-) diff --git a/CLI/package.json b/CLI/package.json index d035e7cca..95a391b45 100644 --- a/CLI/package.json +++ b/CLI/package.json @@ -16,6 +16,6 @@ "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", - "web3": "^1.0.0-beta.35" + "web3": "1.0.0-beta.35" } } diff --git a/CLI/yarn.lock b/CLI/yarn.lock index 0fd77a236..4d20bee11 100644 --- a/CLI/yarn.lock +++ b/CLI/yarn.lock @@ -3,9 +3,9 @@ "@types/node@^10.3.2": - version "10.11.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.11.7.tgz#0e75ca9357d646ca754016ca1d68a127ad7e7300" - integrity sha512-yOxFfkN9xUFLyvWaeYj90mlqTJ41CsQzWKS3gXdOMOyPVacUsymejKxJ4/pMW7exouubuEeZLJawGgcNGYlTeg== + version "10.12.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.0.tgz#ea6dcbddbc5b584c83f06c60e82736d8fbb0c235" + integrity sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ== accepts@~1.3.5: version "1.3.5" @@ -327,14 +327,7 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -combined-stream@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= - dependencies: - delayed-stream "~1.0.0" - -combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== @@ -628,14 +621,6 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -eth-ens-namehash@2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" - integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= - dependencies: - idna-uts46-hx "^2.3.1" - js-sha3 "^0.5.7" - eth-lib@0.1.27, eth-lib@^0.1.26: version "0.1.27" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" @@ -658,22 +643,6 @@ eth-lib@0.2.7: elliptic "^6.4.0" xhr-request-promise "^0.1.2" -ethers@4.0.0-beta.1: - version "4.0.0-beta.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.1.tgz#0648268b83e0e91a961b1af971c662cdf8cbab6d" - integrity sha512-SoYhktEbLxf+fiux5SfCEwdzWENMvgIbMZD90I62s4GZD9nEjgEWy8ZboI3hck193Vs0bDoTohDISx84f2H2tw== - dependencies: - "@types/node" "^10.3.2" - aes-js "3.0.0" - bn.js "^4.4.0" - elliptic "6.3.3" - hash.js "1.1.3" - js-sha3 "0.5.7" - scrypt-js "2.0.3" - setimmediate "1.0.4" - uuid "2.0.1" - xmlhttprequest "1.8.0" - ethers@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.7.tgz#8c653618077a1fc60c5c1b2575da03561f0039f4" @@ -820,12 +789,12 @@ forever-agent@~0.6.1: integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" - combined-stream "1.0.6" + combined-stream "^1.0.6" mime-types "^2.1.12" forwarded@~0.1.2: @@ -1040,13 +1009,6 @@ iconv-lite@0.4.23: dependencies: safer-buffer ">= 2.1.2 < 3" -idna-uts46-hx@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" - integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== - dependencies: - punycode "2.1.0" - ieee754@^1.1.4: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" @@ -1133,7 +1095,7 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -js-sha3@0.5.7, js-sha3@^0.5.7: +js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= @@ -1237,17 +1199,17 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" - integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw== +mime-db@~1.37.0: + version "1.37.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" + integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: - version "2.1.20" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" - integrity sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A== + version "2.1.21" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" + integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== dependencies: - mime-db "~1.36.0" + mime-db "~1.37.0" mime@1.4.1: version "1.4.1" @@ -1524,11 +1486,6 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" -punycode@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= - punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -1669,11 +1626,6 @@ safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, s resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -scrypt-js@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" - integrity sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q= - scrypt-js@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" @@ -2055,86 +2007,87 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -web3-bzz@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.36.tgz#adb3fe7a70053eb7843e32b106792b01b482ef41" - integrity sha512-clDRS/ziboJ5ytnrfxq80YSu9HQsT0vggnT3BkoXadrauyEE/9JNLxRu016jjUxqdkfdv4MgIPDdOS3Bv2ghiw== +web3-bzz@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.35.tgz#9d5e1362b3db2afd77d65619b7cd46dd5845c192" + integrity sha512-BhAU0qhlr8zltm4gs/+P1gki2VkxHJaM2Rrh4DGesDW0lzwufRoNvWFlwx1bKHoFPWNbSmm9PRkHOYOINL/Tgw== dependencies: got "7.1.0" swarm-js "0.1.37" underscore "1.8.3" -web3-core-helpers@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz#6f618e80f1a6588d846efbfdc28f92ae0477f8d2" - integrity sha512-gu74l0htiGWuxLQuMnZqKToFvkSM+UFPE7qUuy1ZosH/h2Jd+VBWg6k4CyNYVYfP0hL5x3CN8SBmB+HMowo55A== +web3-core-helpers@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.35.tgz#d681d218a0c6e3283ee1f99a078ab9d3eef037f1" + integrity sha512-APOu3sEsamyqWt//8o4yq9KF25/uqGm+pQShson/sC4gKzmfJB07fLo2ond0X30E8fIqAPeVCotPXQxGciGUmA== dependencies: underscore "1.8.3" - web3-eth-iban "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" + web3-eth-iban "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -web3-core-method@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz#855c0365ae7d0ead394d973ea9e28828602900e0" - integrity sha512-dJsP3KkGaqBBSdxfzvLsYPOmVaSs1lR/3oKob/gtUYG7UyTnwquwliAc7OXj+gqRA2E/FHZcM83cWdl31ltdSA== +web3-core-method@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.35.tgz#fc10e2d546cf4886038e6130bd5726b0952a4e5f" + integrity sha512-jidImCide8q0GpfsO4L73qoHrbkeWgwU3uOH5DKtJtv0ccmG086knNMRgryb/o9ZgetDWLmDEsJnHjBSoIwcbA== dependencies: underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - web3-core-promievent "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" + web3-core-helpers "1.0.0-beta.35" + web3-core-promievent "1.0.0-beta.35" + web3-core-subscriptions "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -web3-core-promievent@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz#3a5127787fff751be6de272722cbc77dc9523fd5" - integrity sha512-RGIL6TjcOeJTullFLMurChPTsg94cPF6LI763y/sPYtXTDol1vVa+J5aGLp/4WW8v+s+1bSQO6zYq2ZtkbmtEQ== +web3-core-promievent@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.35.tgz#4f1b24737520fa423fee3afee110fbe82bcb8691" + integrity sha512-GvqXqKq07OmHuVi5uNRg6k79a1/CI0ViCC+EtNv4CORHtDRmYEt5Bvdv6z6FJEiaaQkD0lKbFwNhLxutx7HItw== dependencies: any-promise "1.3.0" eventemitter3 "1.1.1" -web3-core-requestmanager@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz#70c8eead84da9ed1cf258e6dde3f137116d0691b" - integrity sha512-/CHuaMbiMDu1v8ANGYI7yFCnh1GaCWx5pKnUPJf+QTk2xAAw+Bvd97yZJIWPOK5AOPUIzxgwx9Ob/5ln6mTmYA== +web3-core-requestmanager@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.35.tgz#2b77cbf6303720ad68899b39fa7f584dc03dbc8f" + integrity sha512-S+zW2h17ZZQU9oe3yaCJE0E7aJS4C3Kf4kGPDv+nXjW0gKhQQhgVhw1Doq/aYQGqNSWJp7f1VHkz5gQWwg6RRg== dependencies: underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - web3-providers-http "1.0.0-beta.36" - web3-providers-ipc "1.0.0-beta.36" - web3-providers-ws "1.0.0-beta.36" + web3-core-helpers "1.0.0-beta.35" + web3-providers-http "1.0.0-beta.35" + web3-providers-ipc "1.0.0-beta.35" + web3-providers-ws "1.0.0-beta.35" -web3-core-subscriptions@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz#20f1f20c85d5b40f1e5a49b070ba977a142621f3" - integrity sha512-/evyLQ8CMEYXC5aUCodDpmEnmGVYQxaIjiEIfA/85f9ifHkfzP1aOwCAjcsLsJWnwrWDagxSpjCYrDtnNabdEw== +web3-core-subscriptions@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.35.tgz#c1b76a2ad3c6e80f5d40b8ba560f01e0f4628758" + integrity sha512-gXzLrWvcGkGiWq1y33Z4Y80XI8XMrwowiQJkrPSjQ81K5PBKquOGwcMffLaKcwdmEy/NpsOXDeFo3eLE1Ghvvw== dependencies: eventemitter3 "1.1.1" underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" + web3-core-helpers "1.0.0-beta.35" -web3-core@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.36.tgz#86182f2456c2cf1cd6e7654d314e195eac211917" - integrity sha512-C2QW9CMMRZdYAiKiLkMrKRSp+gekSqTDgZTNvlxAdN1hXn4d9UmcmWSJXOmIHqr5N2ISbRod+bW+qChODxVE3Q== +web3-core@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.35.tgz#0c44d3c50d23219b0b1531d145607a9bc7cd4b4f" + integrity sha512-ayGavbgVk4KL9Y88Uv411fBJ0SVgVfKhKEBweKYzmP0zOqneMzWt6YsyD1n6kRvjAbqA0AfUPEOKyMNjcx2tjw== dependencies: - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-requestmanager "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-core-requestmanager "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -web3-eth-abi@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.36.tgz#21c0f222701db827a8a269accb9cd18bbd8f70f9" - integrity sha512-fBfW+7hvA0rxEMV45fO7JU+0R32ayT7aRwG9Cl6NW2/QvhFeME2qVbMIWw0q5MryPZGIN8A6366hKNuWvVidDg== +web3-eth-abi@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.35.tgz#2eb9c1c7c7233db04010defcb192293e0db250e6" + integrity sha512-KUDC+EtFFYG8z01ZleKrASdjj327/rtWHzEt6RWsEj7bBa0bGp9nEh+nqdZx/Sdgz1O8tnfFzJlrRcXpfr1vGg== dependencies: - ethers "4.0.0-beta.1" + bn.js "4.11.6" underscore "1.8.3" - web3-utils "1.0.0-beta.36" + web3-core-helpers "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -web3-eth-accounts@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.36.tgz#8aea37df9b038ef2c6cda608856ffd861b39eeef" - integrity sha512-MmgIlBEZ0ILLWV4+wfMrbeVVMU/VmQnCpgSDcw7wHKOKu47bKncJ6rVqVsUbC6d9F613Rios+Yj2Ua6SCHtmrg== +web3-eth-accounts@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.35.tgz#7d0e5a69f510dc93874471599eb7abfa9ddf3e63" + integrity sha512-duIgRsfht/0kAW/eQ0X9lKtVIykbETrnM2H7EnvplCzPHtQLodpib4o9JXfh9n6ZDgdDC7cuJoiVB9QJg089ew== dependencies: any-promise "1.3.0" crypto-browserify "3.12.0" @@ -2142,126 +2095,111 @@ web3-eth-accounts@1.0.0-beta.36: scrypt.js "0.2.0" underscore "1.8.3" uuid "2.0.1" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" + web3-core "1.0.0-beta.35" + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -web3-eth-contract@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.36.tgz#c0c366c4e4016896142208cee758a2ff2a31be2a" - integrity sha512-cywqcIrUsCW4fyqsHdOb24OCC8AnBol8kNiptI+IHRylyCjTNgr53bUbjrXWjmEnear90rO0QhAVjLB1a4iEbQ== +web3-eth-contract@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.35.tgz#5276242d8a3358d9f1ce92b71575c74f9015935c" + integrity sha512-foPohOg5O1UCGKGZOIs+kQK5IZdV2QQ7pAWwNxH8WHplUA+fre1MurXNpoxknUmH6mYplFhXjqgYq2MsrBpHrA== dependencies: underscore "1.8.3" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-promievent "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-eth-abi "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth-ens@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.36.tgz#c7440b42b597fd74f64bc402f03ad2e832f423d8" - integrity sha512-8ZdD7XoJfSX3jNlZHSLe4G837xQ0v5a8cHCcDcd1IoqoY855X9SrIQ0Xdqia9p4mR1YcH1vgmkXY9/3hsvxS7g== - dependencies: - eth-ens-namehash "2.0.8" - underscore "1.8.3" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-promievent "1.0.0-beta.36" - web3-eth-abi "1.0.0-beta.36" - web3-eth-contract "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth-iban@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz#00cb3aba7a5aeb15d02b07421042e263d7b2e01b" - integrity sha512-b5AEDjjhOLR4q47Hbzf65zYE+7U7JgCgrUb13RU4HMIGoMb1q4DXaJw1UH8VVHCZulevl2QBjpCyrntecMqqCQ== + web3-core "1.0.0-beta.35" + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-core-promievent "1.0.0-beta.35" + web3-core-subscriptions "1.0.0-beta.35" + web3-eth-abi "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-eth-iban@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.35.tgz#5aa10327a9abb26bcfc4ba79d7bad18a002b332c" + integrity sha512-H5wkcNcAIc+h/WoDIKv7ZYmrM2Xqu3O7jBQl1IWo73EDVQji+AoB2i3J8tuwI1yZRInRwrfpI3Zuwuf54hXHmQ== dependencies: bn.js "4.11.6" - web3-utils "1.0.0-beta.36" + web3-utils "1.0.0-beta.35" -web3-eth-personal@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.36.tgz#95545998a8ee377e3bb71e27c8d1a5dc1d7d5a21" - integrity sha512-+oxvhojeWh4C/XtnlYURWRR3F5Cg7bQQNjtN1ZGnouKAZyBLoYDVVJ6OaPiveNtfC9RKnzLikn9/Uqc0xz410A== +web3-eth-personal@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.35.tgz#ecac95b7a53d04a567447062d5cae5f49879e89f" + integrity sha512-AcM9nnlxu7ZRRxPvkrFB9eLxMM4A2cPfj2aCg21Wb2EpMnhR+b/O1cT33k7ApRowoMpM+T9M8vx2oPNwXfaCOQ== dependencies: - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" + web3-core "1.0.0-beta.35" + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-net "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -web3-eth@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.36.tgz#04a8c748d344c1accaa26d7d5d0eac0da7127f14" - integrity sha512-uEa0UnbnNHUB4N2O1U+LsvxzSPJ/w3azy5115IseaUdDaiz6IFFgFfFP3ssauayQNCf7v2F44GXLfPhrNeb/Sw== +web3-eth@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.35.tgz#c52c804afb95e6624b6f5e72a9af90fbf5005b68" + integrity sha512-04mcb2nGPXThawuuYICPOxv0xOHofvQKsjZeIq+89nyOC8DQMGTAErDkGyMHQYtjpth5XDhic0wuEsA80AmFZA== dependencies: underscore "1.8.3" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-eth-abi "1.0.0-beta.36" - web3-eth-accounts "1.0.0-beta.36" - web3-eth-contract "1.0.0-beta.36" - web3-eth-ens "1.0.0-beta.36" - web3-eth-iban "1.0.0-beta.36" - web3-eth-personal "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-net@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.36.tgz#396cd35cb40934ed022a1f44a8a642d3908c41eb" - integrity sha512-BriXK0Pjr6Hc/VDq1Vn8vyOum4JB//wpCjgeGziFD6jC7Of8YaWC7AJYXje89OckzfcqX1aJyJlBwDpasNkAzQ== - dependencies: - web3-core "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-providers-http@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz#c1937a2e64f8db7cd30f166794e37cf0fcca1131" - integrity sha512-KLSqMS59nRdpet9B0B64MKgtM3n9wAHTcAHJ03hv79avQNTjHxtjZm0ttcjcFUPpWDgTCtcYCa7tqaYo9Pbeog== - dependencies: - web3-core-helpers "1.0.0-beta.36" + web3-core "1.0.0-beta.35" + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-core-subscriptions "1.0.0-beta.35" + web3-eth-abi "1.0.0-beta.35" + web3-eth-accounts "1.0.0-beta.35" + web3-eth-contract "1.0.0-beta.35" + web3-eth-iban "1.0.0-beta.35" + web3-eth-personal "1.0.0-beta.35" + web3-net "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-net@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.35.tgz#5c6688e0dea71fcd910ee9dc5437b94b7f6b3354" + integrity sha512-bbwaQ/KohGjIJ6HAKbZ6KrklCAaG6/B7hIbAbVLSFLxF+Yz9lmAgQYaDInpidpC/NLb3WOmcbRF+P77J4qMVIA== + dependencies: + web3-core "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-providers-http@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.35.tgz#92059d9d6de6e9f82f4fae30b743efd841afc1e1" + integrity sha512-DcIMFq52Fb08UpWyZ3ZlES6NsNqJnco4hBS/Ej6eOcASfuUayPI+GLkYVZsnF3cBYqlH+DOKuArcKSuIxK7jIA== + dependencies: + web3-core-helpers "1.0.0-beta.35" xhr2-cookies "1.1.0" -web3-providers-ipc@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz#0c78efb4ed6b0305ec830e1e0b785e61217ee605" - integrity sha512-iEUrmdd2CzoWgp+75/ydom/1IaoLw95qkAzsgwjjZp1waDncHP/cvVGX74+fbUx4hRaPdchyzxCQfNpgLDmNjQ== +web3-providers-ipc@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.35.tgz#031afeb10fade2ebb0ef2fb82f5e58c04be842d9" + integrity sha512-iB0FG0HcpUnayfa8pn4guqEQ4Y1nrroi/jffdtQgFkrNt0sD3fMSwwC0AbmECqj3tDLl0e1slBR0RENll+ZF0g== dependencies: oboe "2.1.3" underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" + web3-core-helpers "1.0.0-beta.35" -web3-providers-ws@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz#27b74082c7adfa0cb5a65535eb312e49008c97c3" - integrity sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw== +web3-providers-ws@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.35.tgz#5d38603fd450243a26aae0ff7f680644e77fa240" + integrity sha512-Cx64NgDStynKaUGDIIOfaCd0fZusL8h5avKTkdTjUu2aHhFJhZoVBGVLhoDtUaqZGWIZGcBJOoVf2JkGUOjDRQ== dependencies: underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" + web3-core-helpers "1.0.0-beta.35" websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" -web3-shh@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.36.tgz#6ff297594480edefc710d9d287765a0c4a5d5af1" - integrity sha512-bREGHS/WprYFSvGUhyIk8RSpT2Z5SvJOKGBrsUW2nDIMWO6z0Op8E7fzC6GXY2HZfZliAqq6LirbXLgcLRWuPw== +web3-shh@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.35.tgz#7e4a585f8beee0c1927390937c6537748a5d1a58" + integrity sha512-8qSonk/x0xabERS9Sr6AIADN/Ty+5KwARkkGIfSYHKqFpdMDz+76F7cUCxtoCZoS8K04xgZlDKYe0TJXLYA0Fw== dependencies: - web3-core "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-net "1.0.0-beta.36" + web3-core "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-core-subscriptions "1.0.0-beta.35" + web3-net "1.0.0-beta.35" -web3-utils@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.36.tgz#dc19c9aeec009b1816cc91ef64d7fe9f8ee344c9" - integrity sha512-7ri74lG5fS2Th0fhYvTtiEHMB1Pmf2p7dQx1COQ3OHNI/CHNEMjzoNMEbBU6FAENrywfoFur40K4m0AOmEUq5A== +web3-utils@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.35.tgz#ced9e1df47c65581c441c5f2af76b05a37a273d7" + integrity sha512-Dq6f0SOKj3BDFRgOPnE6ALbzBDCKVIW8mKWVf7tGVhTDHf+wQaWwQSC3aArFSqdExB75BPBPyDpuMTNszhljpA== dependencies: bn.js "4.11.6" eth-lib "0.1.27" @@ -2271,18 +2209,18 @@ web3-utils@1.0.0-beta.36: underscore "1.8.3" utf8 "2.1.1" -web3@^1.0.0-beta.35: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.36.tgz#2954da9e431124c88396025510d840ba731c8373" - integrity sha512-fZDunw1V0AQS27r5pUN3eOVP7u8YAvyo6vOapdgVRolAu5LgaweP7jncYyLINqIX9ZgWdS5A090bt+ymgaYHsw== - dependencies: - web3-bzz "1.0.0-beta.36" - web3-core "1.0.0-beta.36" - web3-eth "1.0.0-beta.36" - web3-eth-personal "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - web3-shh "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" +web3@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.35.tgz#6475095bd451a96e50a32b997ddee82279292f11" + integrity sha512-xwDmUhvTcHQvvNnOPcPZZgCxKUsI2e+GbHy7JkTK3/Rmnutazy8x7fsAXT9myw7V1qpi3GgLoZ3fkglSUbg1Mg== + dependencies: + web3-bzz "1.0.0-beta.35" + web3-core "1.0.0-beta.35" + web3-eth "1.0.0-beta.35" + web3-eth-personal "1.0.0-beta.35" + web3-net "1.0.0-beta.35" + web3-shh "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" "websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": version "1.0.26" From fe06853ba783c2a1b8ae0a3738a45b3efff59ffd Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Tue, 23 Oct 2018 23:29:26 +0530 Subject: [PATCH 030/582] added batch version of each function --- .../BlacklistTransferManager.sol | 115 +++++++--- test/y_blacklist_transfer_manager.js | 197 +++++++++++++++++- 2 files changed, 280 insertions(+), 32 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index bbdd5a693..cdc7fe8d7 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -31,9 +31,6 @@ contract BlacklistTransferManager is ITransferManager { //store the index of the blacklist to investor mapping(bytes32 => mapping(address => uint256)) blacklistToIndex; - - //store the investor to blacklist status - mapping(address => mapping(bytes32 => bool)) investorBlacklistStatus; // Emit when new blacklist type is added event AddBlacklistType( @@ -134,6 +131,20 @@ contract BlacklistTransferManager is ITransferManager { emit AddBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); } + /** + * @notice Used to add the multiple blacklist type + * @param _startTime start date of the blacklist type + * @param _endTime end date of the blacklist type + * @param _name name of the blacklist type + * @param _repeatPeriodTime repeat period of the blacklist type + */ + function addBlacklistTypeMulti(uint256[] _startTime, uint256[] _endTime, bytes32[] _name, uint256[] _repeatPeriodTime) public withPerm(ADMIN) { + require (_startTime.length == _endTime.length && _endTime.length == _name.length && _name.length == _repeatPeriodTime.length, "Input array's length mismatch"); + for (uint256 i = 0; i < _startTime.length; i++){ + addBlacklistType(_startTime[i], _endTime[i], _name[i], _repeatPeriodTime[i]); + } + } + /** * @notice Internal function */ @@ -157,6 +168,20 @@ contract BlacklistTransferManager is ITransferManager { emit ModifyBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); } + /** + * @notice Used to edit the mutiple blacklist type + * @param _startTime start date of the blacklist type + * @param _endTime end date of the blacklist type + * @param _name name of the blacklist type + * @param _repeatPeriodTime repeat period of the blacklist type + */ + function modifyBlacklistTypeMulti(uint256[] _startTime, uint256[] _endTime, bytes32[] _name, uint256[] _repeatPeriodTime) public withPerm(ADMIN) { + require (_startTime.length == _endTime.length && _endTime.length == _name.length && _name.length == _repeatPeriodTime.length, "Input array's length mismatch"); + for (uint256 i = 0; i < _startTime.length; i++){ + modifyBlacklistType(_startTime[i], _endTime[i], _name[i], _repeatPeriodTime[i]); + } + } + /** * @notice Used to delete the blacklist type * @param _name name of the blacklist type @@ -169,6 +194,16 @@ contract BlacklistTransferManager is ITransferManager { emit DeleteBlacklistType(_name); } + /** + * @notice Used to delete the mutiple blacklist type + * @param _name name of the blacklist type + */ + function deleteBlacklistTypeMulti(bytes32[] _name) public withPerm(ADMIN) { + for(uint256 i = 0; i < _name.length; i++){ + deleteBlacklistType(_name[i]); + } + } + /** * @notice Used to assign the blacklist type to the investor * @param _investor address of the investor @@ -177,7 +212,6 @@ contract BlacklistTransferManager is ITransferManager { function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); - require(!investorBlacklistStatus[_investor][_blacklistName],"Investor already associated to the same blacklist"); uint256 investorIndex = investorToBlacklist[_investor].length; // Add blacklist index to the investor investorToIndex[_investor][_blacklistName] = investorIndex; @@ -186,10 +220,45 @@ contract BlacklistTransferManager is ITransferManager { blacklistToIndex[_blacklistName][_investor] = blacklistIndex; investorToBlacklist[_investor].push(_blacklistName); blacklistToInvestor[_blacklistName].push(_investor); - investorBlacklistStatus[_investor][_blacklistName] = true; emit AddInvestorToBlacklist(_investor, _blacklistName); } + /** + * @notice Used to assign the blacklist type to the multiple investor + * @param _investor address of the investor + * @param _blacklistName name of the blacklist + */ + function addInvestorToBlacklistMulti(address[] _investor, bytes32 _blacklistName) public withPerm(ADMIN){ + for(uint256 i = 0; i < _investor.length; i++){ + addInvestorToBlacklist(_investor[i], _blacklistName); + } + } + + /** + * @notice Used to assign the mutiple blacklist type to the multiple investor + * @param _investor address of the investor + * @param _blacklistName name of the blacklist + */ + function addMultiInvestorToBlacklistMulti(address[] _investor, bytes32[] _blacklistName) public withPerm(ADMIN){ + require (_investor.length == _blacklistName.length, "Input array's length mismatch"); + for(uint256 i = 0; i < _investor.length; i++){ + addInvestorToBlacklist(_investor[i], _blacklistName[i]); + } + } + + /** + * @notice Used to assign the new blacklist type to the investor + * @param _startTime start date of the blacklist type + * @param _endTime end date of the blacklist type + * @param _name name of the blacklist type + * @param _repeatPeriodTime repeat period of the blacklist type + * @param _investor address of the investor + */ + function addInvestorToNewBlacklist(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime, address _investor) public withPerm(ADMIN){ + addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); + addInvestorToBlacklist(_investor, _name); + } + /** * @notice Used to delete the investor from the all associated blacklists * @param _investor address of the investor @@ -202,6 +271,16 @@ contract BlacklistTransferManager is ITransferManager { } } + /** + * @notice Used to delete the mutiple investor from the all associated blacklists + * @param _investor address of the investor + */ + function deleteInvestorFromAllBlacklistMulti(address[] _investor) public withPerm(ADMIN) { + for(uint256 i = 0; i < _investor.length; i++){ + deleteInvestorFromAllBlacklist(_investor[i]); + } + } + /** * @notice Used to delete the investor from the blacklist * @param _investor address of the investor @@ -210,7 +289,7 @@ contract BlacklistTransferManager is ITransferManager { function deleteInvestorFromBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { require(_investor != address(0), "Invalid investor address"); require(_blacklistName != bytes32(0),"Invalid blacklist name"); - require(investorBlacklistStatus[_investor][_blacklistName],"Investor not associated to the blacklist"); + require(investorToBlacklist[_investor][investorToIndex[_investor][_blacklistName]] == _blacklistName, "Investor not associated to the blacklist"); // delete the investor from the blacklist type uint256 _blacklistIndex = blacklistToIndex[_blacklistName][_investor]; uint256 _len = blacklistToInvestor[_blacklistName].length; @@ -230,35 +309,23 @@ contract BlacklistTransferManager is ITransferManager { } investorToBlacklist[_investor].length--; // delete the blacklist index from the invetsor - investorBlacklistStatus[_investor][_blacklistName] = false; delete(investorToIndex[_investor][_blacklistName]); emit DeleteInvestorFromBlacklist(_investor, _blacklistName); } - /** - * @notice Used to assign the blacklist type to the multiple investor + /** + * @notice Used to delete the mutiple investor from the blacklist * @param _investor address of the investor * @param _blacklistName name of the blacklist */ - function addInvestorToBlacklistMulti(address[] _investor, bytes32 _blacklistName) public withPerm(ADMIN){ + function deleteInvestorFromBlacklistMulti(address[] _investor, bytes32[] _blacklistName) public withPerm(ADMIN) { + require (_investor.length == _blacklistName.length, "Input array's length mismatch"); for(uint256 i = 0; i < _investor.length; i++){ - addInvestorToBlacklist(_investor[i], _blacklistName); + deleteInvestorFromBlacklist(_investor[i], _blacklistName[i]); } } - /** - * @notice Used to assign the new blacklist type to the investor - * @param _startTime start date of the blacklist type - * @param _endTime end date of the blacklist type - * @param _name name of the blacklist type - * @param _repeatPeriodTime repeat period of the blacklist type - * @param _investor address of the investor - */ - function addInvestorToNewBlacklist(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime, address _investor) public withPerm(ADMIN){ - addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); - addInvestorToBlacklist(_investor, _name); - } - + /** * @notice get the list of the investors of a blacklist type * @param _blacklistName name of the blacklist type diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index edbf7a221..2ecd506f8 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -386,6 +386,46 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should add the mutiple blacklist", async() => { + //Add the new blacklist + let startTime = [latestTime()+2000,latestTime()+3000]; + let endTime = [latestTime()+5000,latestTime()+8000]; + let name = ["y_blacklist","z_blacklist"]; + let repeatTime = [15,30]; + let tx = await I_BlacklistTransferManager.addBlacklistTypeMulti(startTime, endTime, name, repeatTime, { from: token_owner }); + + let event_data = tx.logs; + for (var i = 0; i < event_data.length; i++) { + let blacklistName = event_data[i].args._name; + assert.equal(web3.utils.hexToUtf8(blacklistName), name[i], "Failed in adding the blacklist"); + } + }); + + it("Should fail in adding the mutiple blacklist because only owner can add it", async() => { + //Add the new blacklist + let startTime = [latestTime()+2000,latestTime()+3000]; + let endTime = [latestTime()+5000,latestTime()+8000]; + let name = ["y_blacklist","z_blacklist"]; + let repeatTime = [15,30]; + await catchRevert( + I_BlacklistTransferManager.addBlacklistTypeMulti(startTime, endTime, name, repeatTime, { + from: account_investor1 + }) + ); + }); + + it("Should fail in adding the mutiple blacklist because array lenth are different", async() => { + //Add the new blacklist + let startTime = [latestTime()+2000,latestTime()+3000]; + let endTime = [latestTime()+5000,latestTime()+8000]; + let name = ["y_blacklist","z_blacklist","w_blacklist"]; + let repeatTime = [15,30]; + await catchRevert( + I_BlacklistTransferManager.addBlacklistTypeMulti(startTime, endTime, name, repeatTime, { + from: token_owner + }) + ); + }); it("Should modify the blacklist", async() => { //Modify the existing blacklist @@ -435,6 +475,47 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should modify the mutiple blacklist", async() => { + //Add the new blacklist + let startTime = [latestTime()+3000,latestTime()+3000]; + let endTime = [latestTime()+5000,latestTime()+7000]; + let name = ["y_blacklist","z_blacklist"]; + let repeatTime = [15,30]; + let tx = await I_BlacklistTransferManager.modifyBlacklistTypeMulti(startTime, endTime, name, repeatTime, { from: token_owner }); + + let event_data = tx.logs; + for (var i = 0; i < event_data.length; i++) { + let blacklistName = event_data[i].args._name; + assert.equal(web3.utils.hexToUtf8(blacklistName), name[i], "Failed in adding the blacklist"); + } + }); + + it("Should fail in modifying the mutiple blacklist because only owner can add it", async() => { + //Add the new blacklist + let startTime = [latestTime()+3000,latestTime()+3000]; + let endTime = [latestTime()+5000,latestTime()+7000]; + let name = ["y_blacklist","z_blacklist"]; + let repeatTime = [15,30]; + await catchRevert( + I_BlacklistTransferManager.modifyBlacklistTypeMulti(startTime, endTime, name, repeatTime, { + from: account_investor1 + }) + ); + }); + + it("Should fail in modifying the mutiple blacklist because array length are different", async() => { + //Add the new blacklist + let startTime = [latestTime()+3000,latestTime()+3000]; + let endTime = [latestTime()+5000,latestTime()+7000]; + let name = ["y_blacklist","z_blacklist","w_blacklist"]; + let repeatTime = [15,30]; + await catchRevert( + I_BlacklistTransferManager.modifyBlacklistTypeMulti(startTime, endTime, name, repeatTime, { + from: token_owner + }) + ); + }); + it("Should add investor to the blacklist", async() => { //Add investor to the existing blacklist let tx = await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); @@ -450,14 +531,6 @@ contract('BlacklistTransferManager', accounts => { ); }); - it("Should fail in adding the investor to the same blacklist", async() => { - await catchRevert( - I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { - from: token_owner - }) - ); - }); - it("Should fail in adding the investor to the blacklist as investor address is invalid", async() => { await catchRevert( I_BlacklistTransferManager.addInvestorToBlacklist(0x0, "a_blacklist", { @@ -641,6 +714,27 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should delete the mutiple blacklist type", async() => { + let name = ["y_blacklist","z_blacklist"]; + let tx = await I_BlacklistTransferManager.deleteBlacklistTypeMulti(name, { from: token_owner }); + + let event_data = tx.logs; + for (var i = 0; i < event_data.length; i++) { + let blacklistName = event_data[i].args._name; + assert.equal(web3.utils.hexToUtf8(blacklistName), name[i], "Failed in deleting the blacklist"); + } + + }); + + it("Should fail in deleting multiple blacklist type because only owner can do it.", async() => { + let name = ["b_blacklist","a_blacklist"]; + await catchRevert( + I_BlacklistTransferManager.deleteBlacklistTypeMulti(name, { + from: account_investor1 + }) + ); + }); + it("Should delete the investor from all the associated blacklist", async() => { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "g_blacklist", 20, { from: token_owner }); await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "g_blacklist", { from: token_owner }); @@ -674,6 +768,55 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should delete the mutiple investor from all the associated blacklist", async() => { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "g_blacklist", { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); + let investor = [account_investor5,account_investor2]; + let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklistMulti(investor, { from: token_owner }); + let event_data = tx.logs; + for (var i = 0; i < event_data.length; i++) { + let investorName = event_data[i].args._investor; + assert.equal(investorName.toLowerCase(), investor[i].toLowerCase(), "Failed in deleting the blacklist"); + } + }); + + it("Should fail in deleting the mutiple investor from all the associated blacklist because only owner can do it.", async() => { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "g_blacklist", { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); + let investor = [account_investor5,account_investor2]; + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromAllBlacklistMulti(investor, { + from: account_investor1 + }) + ); + }); + + it("Should delete the mutiple investor from particular associated blacklists", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "s_blacklist", 20, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "s_blacklist", { from: token_owner }); + // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); + let investor = [account_investor5,account_investor2]; + let blacklistName = ["s_blacklist","g_blacklist"]; + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { from: token_owner }); + let event_data = tx.logs; + for (var i = 0; i < event_data.length; i++) { + let investorName = event_data[i].args._investor; + assert.equal(investorName.toLowerCase(), investor[i].toLowerCase(), "Failed in deleting the blacklist"); + } + }); + + it("Should fail in deleting the mutiple investor from particular associated blacklist because only owner can do it.", async() => { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "s_blacklist", { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); + let investor = [account_investor5,account_investor2]; + let blacklistName = ["s_blacklist","g_blacklist"]; + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { + from: account_investor1 + }) + ); + }); + it("Should delete the investor from the blacklist type", async() => { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); @@ -755,6 +898,44 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should add mutiple investor to the mutiple blacklist", async() => { + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "m_blacklist", 20, { from: token_owner }); + await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "n_blacklist", 20, { from: token_owner }); + let investor = [account_investor4,account_investor5]; + let blacklistName =["m_blacklist","n_blacklist"]; + let tx = await I_BlacklistTransferManager.addMultiInvestorToBlacklistMulti(investor, blacklistName, { from: token_owner }); + + let event_data = tx.logs; + for (var i = 0; i < event_data.length; i++) { + let user = event_data[i].args._investor; + let blacklist = event_data[i].args._blacklistName; + assert.equal(user, investor[i], "Failed in adding the investor to blacklist"); + assert.equal(web3.utils.hexToUtf8(blacklist), blacklistName[i], "Failed in adding the investor to blacklist"); + } + + }); + + it("Should fail in adding the mutiple investor to the mutiple blacklist because only owner can do it.", async() => { + let investor = [account_investor4,account_investor5]; + let blacklistName = ["m_blacklist","n_blacklist"]; + await I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { from: token_owner }); + await catchRevert( + I_BlacklistTransferManager.addMultiInvestorToBlacklistMulti(investor, blacklistName, { + from: account_investor1 + }) + ); + }); + + it("Should fail in adding mutiple investor to the mutiple blacklist because array length is not same", async() => { + let investor = [account_investor4,account_investor5]; + let blacklistName =["m_blacklist"]; + await catchRevert( + I_BlacklistTransferManager.addMultiInvestorToBlacklistMulti(investor, blacklistName, { + from: token_owner + }) + ); + }); + it("Should get the init function", async() => { let byte = await I_BlacklistTransferManager.getInitFunction.call(); assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); From d7e97bbaec22a7af6f99f5dbe6449d28fd742917 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Tue, 23 Oct 2018 16:30:50 -0300 Subject: [PATCH 031/582] STRV TM added to migration script --- migrations/2_deploy_contracts.js | 51 +++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 0994e249e..70ba2e8fe 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -2,6 +2,7 @@ const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') +const SingleTradeVolumeRestrictionTMFactory = artifacts.require('./SingleTradeVolumeRestrictionTMFactory.sol') const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') @@ -157,6 +158,10 @@ module.exports = function (deployer, network, accounts) { // D) Deploy the CountTransferManagerFactory Contract (Factory used to generate the CountTransferManager contract use // to track the counts of the investors of the security token) return deployer.deploy(CountTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // D) Deploy the SingleTradeVolumeRestrictionTMFactory Contract (Factory used to generate the SingleTradeVolumeRestrictionTM contract use + // to impose volume restriction on a single trade that the investors could do for a particular security token) + return deployer.deploy(SingleTradeVolumeRestrictionTMFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // D) Deploy the PercentageTransferManagerFactory Contract (Factory used to generate the PercentageTransferManager contract use // to track the percentage of investment the investors could do for a particular security token) @@ -196,6 +201,10 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // Update all addresses into the registry contract by calling the function updateFromregistry return moduleRegistry.updateFromRegistry({from: PolymathAccount}); + }).then(() => { + // D) Register the SingleTradeVolumeRestrictionTMFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the SingleTradeVolumeRestrictionTM contract. + return moduleRegistry.registerModule(SingleTradeVolumeRestrictionTMFactory.address, {from: PolymathAccount}); }).then(() => { // D) Register the PercentageTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the PercentageTransferManager contract. @@ -239,6 +248,11 @@ module.exports = function (deployer, network, accounts) { // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(PercentageTransferManagerFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // G) Once the SingleTradeVolumeRestrictionTMFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(SingleTradeVolumeRestrictionTMFactory.address, true, {from: PolymathAccount}); }).then(() => { // G) Once the GeneralPermissionManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. @@ -294,27 +308,28 @@ module.exports = function (deployer, network, accounts) { console.log('\n'); console.log(` ----------------------- Polymath Network Smart Contracts: ----------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistry (Proxy): ${SecurityTokenRegistryProxy.address} - ModuleRegistry (Proxy): ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} - - ETHOracle: ${ETHOracle} - POLYOracle: ${POLYOracle} + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistry (Proxy): ${SecurityTokenRegistryProxy.address} + ModuleRegistry (Proxy): ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + ETHOracle: ${ETHOracle} + POLYOracle: ${POLYOracle} - CappedSTOFactory: ${CappedSTOFactory.address} - USDTieredSTOFactory: ${USDTieredSTOFactory.address} - USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + + CappedSTOFactory: ${CappedSTOFactory.address} + USDTieredSTOFactory: ${USDTieredSTOFactory.address} + USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} - CountTransferManagerFactory: ${CountTransferManagerFactory.address} - PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} - ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} - EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} - ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} + CountTransferManagerFactory: ${CountTransferManagerFactory.address} + PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} + ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} + SingleTradeVolumeRestrictionTMFactory: ${SingleTradeVolumeRestrictionTMFactory.address} + EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} + ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} --------------------------------------------------------------------------------- `); console.log('\n'); From 0ecec66d2b1f215f3553ef748aa549deaa3253e6 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Wed, 24 Oct 2018 08:28:49 -0300 Subject: [PATCH 032/582] STVR TM support --- CLI/commands/helpers/contract_abis.js | 5 + CLI/commands/transfer_manager.js | 534 +++++++++++++++++++------- 2 files changed, 397 insertions(+), 142 deletions(-) diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index b6c58cc38..38f063aec 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -7,6 +7,7 @@ let stoInterfaceABI; let cappedSTOABI; let usdTieredSTOABI; let generalTransferManagerABI; +let stvrTransferManagerABI; let generalPermissionManagerABI; let polyTokenABI; let cappedSTOFactoryABI; @@ -27,6 +28,7 @@ try { cappedSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTO.json').toString()).abi; usdTieredSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTO.json').toString()).abi; generalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralTransferManager.json').toString()).abi; + stvrTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/SingleTradeVolumeRestrictionTM.json').toString()).abi; generalPermissionManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralPermissionManager.json').toString()).abi; polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; @@ -69,6 +71,9 @@ module.exports = { generalTransferManager: function () { return generalTransferManagerABI; }, + singleTradeVolumeRestrictionTM: function() { + return stvrTransferManagerABI; + }, generalPermissionManager: function () { return generalPermissionManagerABI; }, diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 9d4917117..c17ba918c 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1,6 +1,7 @@ const readlineSync = require('readline-sync'); const chalk = require('chalk'); const ethers = require('ethers'); +const shell = require('shelljs'); const common = require('./common/common_functions'); const global = require('./common/global'); const contracts = require('./helpers/contract_addresses'); @@ -19,6 +20,7 @@ let tokenSymbol; let securityToken; let securityTokenRegistry; let network; +let currentTransferManager; async function executeApp(remoteNetwork) { network = remoteNetwork; @@ -66,42 +68,89 @@ async function start_explorer() { let securityTokenABI = abis.securityToken(); securityToken = new web3.eth.Contract(securityTokenABI,result); - let tmModules = securityToken.methods.getModulesByType(MODULES_TYPES.TRANSFER).call(); + let tmModules = []; + let tmModuleAddresses = await securityToken.methods.getModulesByType(MODULES_TYPES.TRANSFER).call(); + for (const address of tmModuleAddresses) { + tmModules.push(await securityToken.methods.getModule(address).call()); + } + + // Show non-archived attached TM modules + console.log(); + console.log(`Transfer Manager modules attached:`); + tmModules.filter(m => m[3] == false).map(m => console.log(` - ${web3.utils.hexToAscii(m[0])} at ${m[1]}`)) - let options = []; + let options = ['Verify transfer', 'Transfer']; let forcedTransferDisabled = await securityToken.methods.controllerDisabled().call(); if (!forcedTransferDisabled) { - options.push('Forced Transfers'); + options.push('Forced transfers'); } - - options.push('GeneralTransferManager', 'ManualApprovalTransferManager', 'PercentageTransferManager', 'CountTransferManager', - 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM'); + options.push('Config existing modules', 'Add new Transfer Manager module'); let index = readlineSync.keyInSelect(options, 'Choose one:'); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); + let optionSelected = index != -1 ? options[index] : 'Cancel'; + console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { - case 'Forced Transfers': - await forcedTransfers(); + case 'Verify transfer': + let verifyTransferFrom = readlineSync.question(`Enter the sender account (${Issuer.address}): `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: Issuer.address + }); + let verifyFromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferFrom).call()); + console.log(chalk.yellow(`Balance of ${verifyTransferFrom}: ${verifyFromBalance} ${tokenSymbol}`)); + let verifyTransferTo = readlineSync.question('Enter the receiver account: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + }); + let verifyToBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferTo).call()); + console.log(chalk.yellow(`Balance of ${verifyTransferTo}: ${verifyToBalance} ${tokenSymbol}`)); + let verifyTransferAmount = readlineSync.question('Enter amount of tokens to verify: '); + let isVerified = await securityToken.methods.verifyTransfer(verifyTransferFrom, verifyTransferTo, web3.utils.toWei(verifyTransferAmount), web3.utils.fromAscii("")).call(); + if (isVerified) { + console.log(chalk.green(`\n${verifyTransferAmount} ${tokenSymbol} can be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); + } else { + console.log(chalk.red(`\n${verifyTransferAmount} ${tokenSymbol} can't be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); + } break; - case 'GeneralTransferManager': - await generalTransferManager(); + case 'Transfer': + let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call()); + console.log(chalk.yellow(`Balance of ${Issuer.address}: ${fromBalance} ${tokenSymbol}`)); + let transferTo = readlineSync.question('Enter beneficiary of tranfer: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let toBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call()); + console.log(chalk.yellow(`Balance of ${transferTo}: ${toBalance} ${tokenSymbol}`)); + let transferAmount = readlineSync.question('Enter amount of tokens to transfer: '); + let isTranferVerified = await securityToken.methods.verifyTransfer(Issuer.address, transferTo, web3.utils.toWei(transferAmount), web3.utils.fromAscii("")).call(); + if (isTranferVerified) { + let transferAction = securityToken.methods.transfer(transferTo, web3.utils.toWei(transferAmount)); + let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); + console.log(chalk.green(`${event.from} transferred ${web3.utils.fromWei(event.value)} ${tokenSymbol} to ${event.to} successfully!`)); + console.log(`Balance of ${Issuer.address} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call())} ${tokenSymbol}`); + console.log(`Balance of ${transferTo} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call())} ${tokenSymbol}`); + } else { + console.log(chalk.red(`Transfer failed at verification. Please review the transfer restrictions.`)); + } break; - case 'ManualApprovalTransferManager': - await manualApprovalTransferManager(); - break; - case 'PercentageTransferManager': - await percentageTransferManager(); - break; - case 'CountTransferManager': - await countTransferManager(); + case 'Forced transfers': + await forcedTransfers(); break; - case 'SingleTradeVolumeRestrictionTM': - await singleTradeVolumeRestrictionTM(); + case 'Config existing modules': + await configExistingModules(tmModules); break; - case 'LookupVolumeRestrictionTM': - await lookupVolumeRestrictionTM(); + case 'Add new Transfer Manager module': + await addTransferManagerModule(); break; + case 'Cancel': + process.exit(0); } } @@ -178,15 +227,234 @@ async function forcedTransfers() { } } +async function configExistingModules(tmModules) { + let nonArchivedModules = tmModules.filter(m => m[3] == false); + + let options = nonArchivedModules.map(m => `${web3.utils.hexToAscii(m[0])} at ${m[1]}`); + let index = readlineSync.keyInSelect(options, 'Which module do you want to config? '); + console.log('Selected:', index != -1 ? options[index] : 'Cancel', '\n'); + let moduleNameSelected = web3.utils.hexToUtf8(nonArchivedModules[index][0]); + + switch (moduleNameSelected) { + case 'GeneralTransferManager': + currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), nonArchivedModules[index][1]); + currentTransferManager.setProvider(web3.currentProvider); + await generalTransferManager(); + break; + case 'ManualApprovalTransferManager': + //await manualApprovalTransferManager(); + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************` + )); + break; + case 'PercentageTransferManager': + //await percentageTransferManager(); + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************` + )); + break; + case 'CountTransferManager': + //await countTransferManager(); + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************` + )); + break; + case 'SingleTradeVolumeRestrictionTM': + currentTransferManager = new web3.eth.Contract(abis.singleTradeVolumeRestrictionTM(), nonArchivedModules[index][1]); + currentTransferManager.setProvider(web3.currentProvider); + await singleTradeVolumeRestrictionTM(); + break; + case 'LookupVolumeRestrictionTM': + //await lookupVolumeRestrictionTM(); + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************` + )); + break; + } +} + +async function addTransferManagerModule() { + let options = ['GeneralTransferManager', 'ManualApprovalTransferManager', 'PercentageTransferManager', + 'CountTransferManager', 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM']; + + let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? '); + if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { + let bytes; + switch (options[index]) { + case 'ManualApprovalTransferManager': + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************` + )); + break; + case 'PercentageTransferManager': + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************` + )); + break; + case 'CountTransferManager': + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************` + )); + break; + case 'SingleTradeVolumeRestrictionTM': + let isTransferLimitInPercentage = !!readlineSync.keyInSelect(['In tokens', 'In percentage'], 'How do you want to set the transfer limit? ', {cancel: false}); + let globalTransferLimitInPercentageOrToken; + if (isTransferLimitInPercentage) { + globalTransferLimitInPercentageOrToken = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { + limit: function(input) { + return (parseInt(input) > 0 && parseInt(input) <= 100); + }, + limitMessage: "Must be greater than 0 and less than 100" + })); + } else { + globalTransferLimitInPercentageOrToken = web3.utils.toWei(readlineSync.question('Enter the amount of tokens for default limit: ', { + limit: function(input) { + return parseInt(input) > 0; + }, + limitMessage: "Must be greater than zero" + })); + } + let allowPrimaryIssuance = readlineSync.keyInYNStrict(`Do you want to allow all primary issuance transfers? `); + bytes = web3.eth.abi.encodeFunctionCall( { + name: 'configure', + type: 'function', + inputs: [ + { + type: 'bool', + name: '_isTransferLimitInPercentage' + },{ + type: 'uint256', + name: '_globalTransferLimitInPercentageOrToken' + },{ + type: 'bool', + name: '_isTransferLimitInPercentage' + } + ] + }, [isTransferLimitInPercentage, globalTransferLimitInPercentageOrToken, allowPrimaryIssuance]); + break; + case 'LookupVolumeRestrictionTM': + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************` + )); + break; + default: + bytes = web3.utils.fromAscii('', 16); + } + let selectedTMFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.TRANSFER, options[index]); + let addModuleAction = securityToken.methods.addModule(selectedTMFactoryAddress, bytes, 0, 0); + let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); + console.log(`Module deployed at address: ${event._module}`); + } +} + async function generalTransferManager() { - let options = ['Change Issuance Address', 'Change Signing Address', 'Change Allow All Transfers', 'Change Allow All Whitelist Transfers', - 'Change Allow All Whitelist Issuances', 'Change Allow All Burn Transfers', 'Modify Whitelist', 'Modify Whitelist from CSV', - 'Modify Whitelist Signed']; + console.log(chalk.blue(`General Transfer Manager at ${currentTransferManager.options.address}`)); + console.log(); + + // Show current data + let displayIssuanceAddress = await currentTransferManager.methods.issuanceAddress().call(); + let displaySigningAddress = await currentTransferManager.methods.signingAddress().call(); + let displayAllowAllTransfers = await currentTransferManager.methods.allowAllTransfers().call(); + let displayAllowAllWhitelistTransfers = await currentTransferManager.methods.allowAllWhitelistTransfers().call(); + let displayAllowAllWhitelistIssuances = await currentTransferManager.methods.allowAllWhitelistIssuances().call(); + let displayAllowAllBurnTransfers = await currentTransferManager.methods.allowAllBurnTransfers().call(); + + console.log(`- Issuance address: ${displayIssuanceAddress}`); + console.log(`- Signing address: ${displaySigningAddress}`); + console.log(`- Allow all transfers: ${displayAllowAllTransfers ? `YES` : `NO`}`); + console.log(`- Allow all whitelist transfers: ${displayAllowAllWhitelistTransfers ? `YES` : `NO`}`); + console.log(`- Allow all whitelist issuances: ${displayAllowAllWhitelistIssuances ? `YES` : `NO`}`); + console.log(`- Allow all burn transfers: ${displayAllowAllBurnTransfers ? `YES` : `NO`}`); + // ------------------ + + let options = ['Modify whitelist', 'Modify whitelist from CSV', /*'Modify Whitelist Signed',*/ + `Change issuance address`, 'Change signing address']; + if (displayAllowAllTransfers) { + options.push('Disallow all transfers'); + } else { + options.push('Allow all transfers'); + } + if (displayAllowAllWhitelistTransfers) { + options.push('Disallow all whitelist transfers'); + } else { + options.push('Allow all whitelist transfers'); + } + if (displayAllowAllWhitelistIssuances) { + options.push('Disallow all whitelist issuances'); + } else { + options.push('Allow all whitelist issuances'); + } + if (displayAllowAllBurnTransfers) { + options.push('Disallow all burn transfers'); + } else { + options.push('Allow all burn transfers'); + } + let index = readlineSync.keyInSelect(options, 'What do you want to do?'); let optionSelected = options[index]; console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); switch (optionSelected) { - case 'Change Issuance Address': + case 'Modify whitelist': + let investor = readlineSync.question('Enter the address to whitelist: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let fromTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); + let toTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); + let expiryTime = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); + let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); + let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); + let modifyWhitelistReceipt = await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); + let modifyWhitelistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); + console.log(chalk.green(`${modifyWhitelistEvent._investor} has been whitelisted sucessfully!`)); + break; + case 'Modify whitelist from CSV': + console.log(chalk.yellow(`Data is going to be read from 'data/whitelist_data.csv'. Be sure this file is updated!`)); + if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { + shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${network}`); + } + break; + /* + case 'Modify Whitelist Signed': + let investorSigned = readlineSync.question('Enter the address to whitelist: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let fromTimeSigned = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); + let toTimeSigned = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); + let expiryTimeSigned = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); + let vSigned = readlineSync.questionInt('Enter v: '); + let rSigned = readlineSync.question('Enter r: '); + let sSigned = readlineSync.question('Enter s: '); + let canBuyFromSTOSigned = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); + let modifyWhitelistSignedAction = currentTransferManager.methods.modifyWhitelistSigned(investorSigned, fromTimeSigned, toTimeSigned, expiryTimeSigned, canBuyFromSTOSigned); + let modifyWhitelistSignedReceipt = await common.sendTransaction(Issuer, modifyWhitelistSignedAction, defaultGasPrice); + let modifyWhitelistSignedEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistSignedReceipt.logs, 'ModifyWhitelist'); + console.log(chalk.green(`${modifyWhitelistSignedEvent._investor} has been whitelisted sucessfully!`)); + break; + */ + case 'Change issuance address': let issuanceAddress = readlineSync.question('Enter the new issuance address: ', { limit: function(input) { return web3.utils.isAddress(input); @@ -194,11 +462,11 @@ async function generalTransferManager() { limitMessage: "Must be a valid address" }); let changeIssuanceAddressAction = currentTransferManager.methods.changeIssuanceAddress(issuanceAddress); - let changeIssuanceAddressReceipt = await common.sendTransaction(Issuer.address, changeIssuanceAddressAction, defaultGasPrice); + let changeIssuanceAddressReceipt = await common.sendTransaction(Issuer, changeIssuanceAddressAction, defaultGasPrice); let changeIssuanceAddressEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeIssuanceAddressReceipt.logs, 'ChangeIssuanceAddress'); console.log(chalk.green(`${changeIssuanceAddressEvent._issuanceAddress} is the new address for the issuance!`)); break; - case 'Change Signing Address': + case 'Change signing address': let signingAddress = readlineSync.question('Enter the new signing address: ', { limit: function(input) { return web3.utils.isAddress(input); @@ -206,14 +474,14 @@ async function generalTransferManager() { limitMessage: "Must be a valid address" }); let changeSigningAddressAction = currentTransferManager.methods.changeSigningAddress(signingAddress); - let changeSigningAddressReceipt = await common.sendTransaction(Issuer.address, changeSigningAddressAction, defaultGasPrice); + let changeSigningAddressReceipt = await common.sendTransaction(Issuer, changeSigningAddressAction, defaultGasPrice); let changeSigningAddressEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeSigningAddressReceipt.logs, 'ChangeSigningAddress'); console.log(chalk.green(`${changeSigningAddressEvent._signingAddress} is the new address for the signing!`)); break; - case 'Change Allow All Transfers': - let allowAllTransfers = readlineSync.keyInYNStrict('Do you want to remove all restrictions for any addresses?'); - let changeAllowAllTransfersAction = currentTransferManager.methods.changeAllowAllTransfers(allowAllTransfers); - let changeAllowAllTransfersReceipt = await common.sendTransaction(Issuer.address, changeAllowAllTransfersAction, defaultGasPrice); + case 'Allow all transfers': + case 'Disallow all transfers': + let changeAllowAllTransfersAction = currentTransferManager.methods.changeAllowAllTransfers(!displayAllowAllTransfers); + let changeAllowAllTransfersReceipt = await common.sendTransaction(Issuer, changeAllowAllTransfersAction, defaultGasPrice); let changeAllowAllTransfersEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllTransfersReceipt.logs, 'AllowAllTransfers'); if (changeAllowAllTransfersEvent._allowAllTransfers) { console.log(chalk.green(`All transfers are allowed!`)); @@ -221,10 +489,10 @@ async function generalTransferManager() { console.log(chalk.green(`Transfers are restricted!`)); } break; - case 'Change Allow All Whitelist Transfers': - let allowAllWhitelistTransfers = readlineSync.keyInYNStrict('Do you want to ignore time locks from whitelist (address must still be whitelisted)?'); - let changeAllowAllWhitelistTransfersAction = currentTransferManager.methods.changeAllowAllWhitelistTransfers(allowAllWhitelistTransfers); - let changeAllowAllWhitelistTransfersReceipt = await common.sendTransaction(Issuer.address, changeAllowAllWhitelistTransfersAction, defaultGasPrice); + case 'Allow all whitelist transfers': + case 'Disallow all whitelist transfers': + let changeAllowAllWhitelistTransfersAction = currentTransferManager.methods.changeAllowAllWhitelistTransfers(!displayAllowAllWhitelistTransfers); + let changeAllowAllWhitelistTransfersReceipt = await common.sendTransaction(Issuer, changeAllowAllWhitelistTransfersAction, defaultGasPrice); let changeAllowAllWhitelistTransfersEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllWhitelistTransfersReceipt.logs, 'AllowAllWhitelistTransfers'); if (changeAllowAllWhitelistTransfersEvent._allowAllWhitelistTransfers) { console.log(chalk.green(`Time locks from whitelist are ignored for transfers!`)); @@ -232,10 +500,10 @@ async function generalTransferManager() { console.log(chalk.green(`Transfers are restricted by time locks from whitelist!`)); } break; - case 'Change Allow All Whitelist Issuances': - let allowAllWhitelistIssuances = readlineSync.keyInYNStrict('Do you want to ignore time locks from whitelist (address must still be whitelisted)?'); - let changeAllowAllWhitelistIssuancesAction = currentTransferManager.methods.changeAllowAllIssuancesTransfers(allowAllWhitelistIssuances); - let changeAllowAllWhitelistIssuancesReceipt = await common.sendTransaction(Issuer.address, changeAllowAllWhitelistIssuancesAction, defaultGasPrice); + case 'Allow all whitelist issuances': + case 'Disallow all whitelist issuances': + let changeAllowAllWhitelistIssuancesAction = currentTransferManager.methods.changeAllowAllWhitelistIssuances(!displayAllowAllWhitelistIssuances); + let changeAllowAllWhitelistIssuancesReceipt = await common.sendTransaction(Issuer, changeAllowAllWhitelistIssuancesAction, defaultGasPrice); let changeAllowAllWhitelistIssuancesEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllWhitelistIssuancesReceipt.logs, 'AllowAllWhitelistIssuances'); if (changeAllowAllWhitelistIssuancesEvent._allowAllWhitelistIssuances) { console.log(chalk.green(`Time locks from whitelist are ignored for issuances!`)); @@ -243,10 +511,10 @@ async function generalTransferManager() { console.log(chalk.green(`Issuances are restricted by time locks from whitelist!`)); } break; - case 'Change Allow All Burn Transfers': - let allowAllBurnTransfers = readlineSync.keyInYNStrict('Do you want to ignore time locks from whitelist (address must still be whitelisted)?'); - let changeAllowAllBurnTransfersAction = currentTransferManager.methods.allowAllBurnTransfers(allowAllBurnTransfers); - let changeAllowAllBurnTransfersReceipt = await common.sendTransaction(Issuer.address, changeAllowAllBurnTransfersAction, defaultGasPrice); + case 'Allow all burn transfers': + case 'Disallow all burn transfers': + let changeAllowAllBurnTransfersAction = currentTransferManager.methods.changeAllowAllBurnTransfers(!displayAllowAllBurnTransfers); + let changeAllowAllBurnTransfersReceipt = await common.sendTransaction(Issuer, changeAllowAllBurnTransfersAction, defaultGasPrice); let changeAllowAllBurnTransfersEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllBurnTransfersReceipt.logs, 'AllowAllBurnTransfers'); if (changeAllowAllBurnTransfersEvent._allowAllWhitelistTransfers) { console.log(chalk.green(`To burn tokens is allowed!`)); @@ -254,59 +522,36 @@ async function generalTransferManager() { console.log(chalk.green(`The burning mechanism is deactivated!`)); } break; - case 'Modify Whitelist': - let investor = readlineSync.question('Enter the address to whitelist: ', { - limit: function(input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let fromTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); - let toTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); - let expiryTime = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); - let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); - let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); - let modifyWhitelistReceipt = await common.sendTransaction(Issuer.address, modifyWhitelistAction, defaultGasPrice); - let modifyWhitelistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); - console.log(chalk.green(`${modifyWhitelistEvent._investor} has been whitelisted sucessfully!`)); - case 'Modify Whitelist from CSV': - console.log(chalk.yellow(`Data is going to be read from 'data/whitelist_data.csv'. Be sure this file is updated!`)); - if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { - shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${network}`); - } - break; - /* - case 'Modify Whitelist Signed': - let investorSigned = readlineSync.question('Enter the address to whitelist: ', { - limit: function(input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let fromTimeSigned = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); - let toTimeSigned = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); - let expiryTimeSigned = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); - let vSigned = readlineSync.questionInt('Enter v: '); - let rSigned = readlineSync.question('Enter r: '); - let sSigned = readlineSync.question('Enter s: '); - let canBuyFromSTOSigned = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); - let modifyWhitelistSignedAction = currentTransferManager.methods.modifyWhitelistSigned(investorSigned, fromTimeSigned, toTimeSigned, expiryTimeSigned, canBuyFromSTOSigned); - let modifyWhitelistSignedReceipt = await common.sendTransaction(Issuer.address, modifyWhitelistSignedAction, defaultGasPrice); - let modifyWhitelistSignedEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistSignedReceipt.logs, 'ModifyWhitelist'); - console.log(chalk.green(`${modifyWhitelistSignedEvent._investor} has been whitelisted sucessfully!`)); - break; - */ } } async function singleTradeVolumeRestrictionTM() { - let primaryIssuanceAllowed = await currentTransferManager.methods.allowPrimaryIssuance().call(); - let allowPrimeryIssuanceOption = primaryIssuanceAllowed ? 'Allow Primary Issuance' : 'Disallow Primary Issuance'; - - let options = [allowPrimeryIssuanceOption, 'Add exempted wallet', 'Remove exempted wallet']; + console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address}`)); + console.log(); - let isTransferLimitInPercentage = await currentTransferManager.methods.isTransferLimitInPercentage().call(); - if (isTransferLimitInPercentage) { + // Show current data + let displayIsInPercentage = await currentTransferManager.methods.isTransferLimitInPercentage().call(); + let displayGlobalTransferLimit; + if (displayIsInPercentage) { + displayGlobalTransferLimit = fromWeiPercentage(await currentTransferManager.methods.globalTransferLimitInPercentage().call()); + } else { + displayGlobalTransferLimit = web3.utils.fromWei(await currentTransferManager.methods.globalTransferLimitInTokens().call()); + } + let displayAllowPrimaryIssuance = await currentTransferManager.methods.allowPrimaryIssuance().call(); + + console.log(`- Limit type: ${displayIsInPercentage ? `Percentage` : `Tokens`}`); + console.log(`- Default transfer limit: ${displayGlobalTransferLimit} ${displayIsInPercentage ? `%` : `${tokenSymbol}`}`); + console.log(`- Allow primary issuance: ${displayAllowPrimaryIssuance ? `YES` : `NO`}`); + // ------------------ + + let options = []; + if (displayAllowPrimaryIssuance) { + options.push('Disallow primary issuance'); + } else { + options.push('Allow primary issuance'); + } + options.push('Add exempted wallet', 'Remove exempted wallet'); + if (displayIsInPercentage) { options.push('Change transfer limit to tokens', 'Change default percentage limit', 'Set percentage transfer limit per account', 'Remove percentage transfer limit per account'); } else { @@ -318,87 +563,84 @@ async function singleTradeVolumeRestrictionTM() { let optionSelected = options[index]; console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); switch (optionSelected) { - case 'Allow Primary Issuance': - let allowPrimaryIssuanceAction = currentTransferManager.methods.setAllowPrimaryIssuance(true); - await common.sendTransaction(Issuer.address, allowPrimaryIssuanceAction, defaultGasPrice); - break; - case 'Disallow Primary Issuance': - let disallowPrimaryIssuanceAction = currentTransferManager.methods.setAllowPrimaryIssuance(false); - await common.sendTransaction(Issuer.address, disallowPrimaryIssuanceAction, defaultGasPrice); + case 'Allow primary issuance': + case 'Disallow primary issuance': + let disallowPrimaryIssuanceAction = currentTransferManager.methods.setAllowPrimaryIssuance(!displayAllowPrimaryIssuance); + await common.sendTransaction(Issuer, disallowPrimaryIssuanceAction, defaultGasPrice); break; case 'Add exempted wallet': - let walletToExempt = readlineSync.question('Enter the wallet to exempt', { + let walletToExempt = readlineSync.question('Enter the wallet to exempt: ', { limit: function(input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" }); let addExemptWalletAction = currentTransferManager.methods.addExemptWallet(walletToExempt); - let addExemptWalletReceipt = await common.sendTransaction(Issuer.address, addExemptWalletAction, defaultGasPrice); + let addExemptWalletReceipt = await common.sendTransaction(Issuer, addExemptWalletAction, defaultGasPrice); let addExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addExemptWalletReceipt.logs, 'ExemptWalletAdded'); console.log(chalk.green(`${addExemptWalletEvent._wallet} has been exempted sucessfully!`)); break; case 'Remove exempted wallet': - let exemptedWallet = readlineSync.question('Enter the wallet to remove from exempt', { + let exemptedWallet = readlineSync.question('Enter the wallet to remove from exempt: ', { limit: function(input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" }); let removeExemptWalletAction = currentTransferManager.methods.removeExemptWallet(exemptedWallet); - let removeExemptWalletReceipt = await common.sendTransaction(Issuer.address, removeExemptWalletAction, defaultGasPrice); + let removeExemptWalletReceipt = await common.sendTransaction(Issuer, removeExemptWalletAction, defaultGasPrice); let removeExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeExemptWalletReceipt.logs, 'ExemptWalletRemoved'); console.log(chalk.green(`${removeExemptWalletEvent._wallet} has been removed from exempt wallets sucessfully!`)); break; case 'Change transfer limit to tokens': - let newDefaultLimitInTokens = readlineSync.questionInt('Enter the amount of tokens for default limit: ', { + let newDefaultLimitInTokens = web3.utils.toWei(readlineSync.question('Enter the amount of tokens for default limit: ', { limit: function(input) { - return input > 0; + return parseInt(input) > 0; }, limitMessage: "Must be greater than zero" - }); - let changeTransferLimitToTokensAction = currentTransferManager.methods.changeTransferLimitToTokens(web3.utils.toWei(newDefaultLimitInTokens)); - let changeTransferLimitToTokensReceipt = await common.sendTransaction(Issuer.address, changeTransferLimitToTokensAction, defaultGasPrice); + })); + let changeTransferLimitToTokensAction = currentTransferManager.methods.changeTransferLimitToTokens(newDefaultLimitInTokens); + let changeTransferLimitToTokensReceipt = await common.sendTransaction(Issuer, changeTransferLimitToTokensAction, defaultGasPrice); let changeTransferLimitToTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); - console.log(chalk.green(`The default transfer limit is ${changeTransferLimitToTokensEvent._amount} ${tokenSymbol}`)); + console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeTransferLimitToTokensEvent._amount)} ${tokenSymbol}`)); break; case 'Change transfer limit to percentage': - let newDefaultLimitInPercentage = readlineSync.questionInt('Enter the percentage for default limit: ', { + let newDefaultLimitInPercentage = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { limit: function(input) { - return 0 < input <= 100; + return (parseInt(input) > 0 && parseInt(input) <= 100); }, limitMessage: "Must be greater than 0 and less than 100" - }); + })); let changeTransferLimitToPercentageAction = currentTransferManager.methods.changeTransferLimitToPercentage(newDefaultLimitInPercentage); - let changeTransferLimitToPercentageReceipt = await common.sendTransaction(Issuer.address, changeTransferLimitToPercentageAction, defaultGasPrice); + let changeTransferLimitToPercentageReceipt = await common.sendTransaction(Issuer, changeTransferLimitToPercentageAction, defaultGasPrice); let changeTransferLimitToPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); - console.log(chalk.green(`The default transfer limit is ${changeTransferLimitToPercentageEvent._percentage}%`)); + console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeTransferLimitToPercentageEvent._percentage)} %`)); break; case 'Change default percentage limit': - let defaultLimitInPercentage = readlineSync.questionInt('Enter the percentage for default limit: ', { + let defaultLimitInPercentage = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { limit: function(input) { - return 0 < input <= 100; + return (parseInt(input) > 0 && parseInt(input) <= 100); }, limitMessage: "Must be greater than 0 and less than 100" - }); + })); let changeGlobalLimitInPercentageAction = currentTransferManager.methods.changeGlobalLimitInPercentage(defaultLimitInPercentage); - let changeGlobalLimitInPercentageReceipt = await common.sendTransaction(Issuer.address, changeGlobalLimitInPercentageAction, defaultGasPrice); + let changeGlobalLimitInPercentageReceipt = await common.sendTransaction(Issuer, changeGlobalLimitInPercentageAction, defaultGasPrice); let changeGlobalLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); - console.log(chalk.green(`The default transfer limit is ${changeGlobalLimitInPercentageEvent._percentage}%`)); + console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeGlobalLimitInPercentageEvent._percentage)} %`)); break; case 'Change default tokens limit': - let defaultLimitInTokens = readlineSync.questionInt('Enter the amount of tokens for default limit: ', { + let defaultLimitInTokens = web3.utils.toWei(readlineSync.question('Enter the amount of tokens for default limit: ', { limit: function(input) { - return input > 0; + return parseInt(input) > 0; }, limitMessage: "Must be greater than zero" - }); - let changeGlobalLimitInTokensAction = currentTransferManager.methods.changeGlobalLimitInTokens(web3.utils.toWei(defaultLimitInTokens)); - let changeGlobalLimitInTokensReceipt = await common.sendTransaction(Issuer.address, changeGlobalLimitInTokensAction, defaultGasPrice); + })); + let changeGlobalLimitInTokensAction = currentTransferManager.methods.changeGlobalLimitInTokens(defaultLimitInTokens); + let changeGlobalLimitInTokensReceipt = await common.sendTransaction(Issuer, changeGlobalLimitInTokensAction, defaultGasPrice); let changeGlobalLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); - console.log(chalk.green(`The default transfer limit is ${changeGlobalLimitInTokensEvent._amount} ${tokenSymbol}`)); + console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeGlobalLimitInTokensEvent._amount)} ${tokenSymbol}`)); break; case 'Set percentage transfer limit per account': let percentageAccount = readlineSync.question('Enter the wallet: ', { @@ -407,16 +649,16 @@ async function singleTradeVolumeRestrictionTM() { }, limitMessage: "Must be a valid address" }); - let accountLimitInPercentage = readlineSync.questionInt(`Enter the transfer limit for ${percentageAccount} in percentage: `, { + let accountLimitInPercentage = toWeiPercentage(readlineSync.question(`Enter the transfer limit for ${percentageAccount} in percentage: `, { limit: function(input) { - return 0 < input <= 100; + return (parseInt(input) > 0 && parseInt(input) <= 100); }, limitMessage: "Must be greater than 0 and less than 100" - }); - let setTransferLimitInPercentageAction = currentTransferManager.methods.setTransferLimitInPercentage(percentageAccount, web3.utils.toWei(accountLimitInPercentage)); - let setTransferLimitInPercentageReceipt = await common.sendTransaction(Issuer.address, setTransferLimitInPercentageAction, defaultGasPrice); + })); + let setTransferLimitInPercentageAction = currentTransferManager.methods.setTransferLimitInPercentage(percentageAccount, accountLimitInPercentage); + let setTransferLimitInPercentageReceipt = await common.sendTransaction(Issuer, setTransferLimitInPercentageAction, defaultGasPrice); let setTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageSet'); - console.log(chalk.green(`The transfer limit for ${setTransferLimitInPercentageEvent._wallet} is ${setTransferLimitInPercentageEvent._percentage}%`)); + console.log(chalk.green(`The transfer limit for ${setTransferLimitInPercentageEvent._wallet} is ${fromWeiPercentage(setTransferLimitInPercentageEvent._percentage)} %`)); break; case 'Set tokens transfer limit per account': let tokensAccount = readlineSync.question('Enter the wallet: ', { @@ -425,16 +667,16 @@ async function singleTradeVolumeRestrictionTM() { }, limitMessage: "Must be a valid address" }); - let accountLimitInTokens = readlineSync.questionInt(`Enter the transfer limit for ${tokensAccount} in amount of tokens: `, { + let accountLimitInTokens = web3.utils.toWei(readlineSync.question(`Enter the transfer limit for ${tokensAccount} in amount of tokens: `, { limit: function(input) { - return input > 0; + return parseInt(input) > 0; }, limitMessage: "Must be greater than zero" - }); - let setTransferLimitInTokensAction = currentTransferManager.methods.setTransferLimitInTokens(tokensAccount, web3.utils.toWei(accountLimitInTokens)); - let setTransferLimitInTokensReceipt = await common.sendTransaction(Issuer.address, setTransferLimitInTokensAction, defaultGasPrice); + })); + let setTransferLimitInTokensAction = currentTransferManager.methods.setTransferLimitInTokens(tokensAccount, accountLimitInTokens); + let setTransferLimitInTokensReceipt = await common.sendTransaction(Issuer, setTransferLimitInTokensAction, defaultGasPrice); let setTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensSet'); - console.log(chalk.green(`The transfer limit for ${setTransferLimitInTokensEvent._wallet} is ${setTransferLimitInTokensEvent._percentage} ${tokenSymbol}`)); + console.log(chalk.green(`The transfer limit for ${setTransferLimitInTokensEvent._wallet} is ${web3.utils.fromWei(setTransferLimitInTokensEvent._amount)} ${tokenSymbol}`)); break; case 'Remove percentage transfer limit per account': let percentageAccountToRemove = readlineSync.question('Enter the wallet to remove: ', { @@ -444,7 +686,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be a valid address" }); let removeTransferLimitInPercentageAction = currentTransferManager.methods.removeTransferLimitInPercentage(percentageAccountToRemove); - let removeTransferLimitInPercentageReceipt = await common.sendTransaction(Issuer.address, removeTransferLimitInPercentageAction, defaultGasPrice); + let removeTransferLimitInPercentageReceipt = await common.sendTransaction(Issuer, removeTransferLimitInPercentageAction, defaultGasPrice); let removeTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageRemoved'); console.log(chalk.green(`The transfer limit for ${removeTransferLimitInPercentageEvent._wallet} is the default limit`)); break; @@ -456,7 +698,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be a valid address" }); let removeTransferLimitInTokensAction = currentTransferManager.methods.removeTransferLimitInTokens(tokensAccountToRemove); - let removeTransferLimitInTokensReceipt = await common.sendTransaction(Issuer.address, removeTransferLimitInTokensAction, defaultGasPrice); + let removeTransferLimitInTokensReceipt = await common.sendTransaction(Issuer, removeTransferLimitInTokensAction, defaultGasPrice); let removeTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensRemoved'); console.log(chalk.green(`The transfer limit for ${removeTransferLimitInTokensEvent._wallet} is the default limit`)); break; @@ -478,6 +720,14 @@ function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, rest } */ +function toWeiPercentage(number) { + return new web3.utils.BN(web3.utils.toWei(number)).divn(100); +} + +function fromWeiPercentage(number) { + return web3.utils.fromWei(new web3.utils.BN(number).muln(100)); +} + module.exports = { executeApp: async function(type, remoteNetwork) { return executeApp(type, remoteNetwork); From 235462056c2bfa4574a47c4ecde6abe8f8b6dd03 Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Wed, 24 Oct 2018 21:13:14 +0530 Subject: [PATCH 033/582] minor change in test cases --- test/y_blacklist_transfer_manager.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js index 2ecd506f8..b8918d9e2 100644 --- a/test/y_blacklist_transfer_manager.js +++ b/test/y_blacklist_transfer_manager.js @@ -817,6 +817,16 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should fail in deleting the mutiple investor from particular associated blacklist because array length is incorrect.", async() => { + let investor = [account_investor5]; + let blacklistName = ["s_blacklist","g_blacklist"]; + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { + from: token_owner + }) + ); + }); + it("Should delete the investor from the blacklist type", async() => { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); From aec6ec948d43fc4fd3a4fd6b53228512f97114c7 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Wed, 24 Oct 2018 15:34:43 -0300 Subject: [PATCH 034/582] Transfer is verified through ST function --- CLI/commands/ST20Generator.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 630d2e1fc..a52499b2f 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -38,7 +38,6 @@ let securityTokenRegistry; let polyToken; let usdToken; let securityToken; -let generalTransferManager; let currentSTO; // App flow @@ -218,11 +217,6 @@ async function step_Wallet_Issuance(){ multimint = (isAffiliate == "Y" || isAffiliate == "y"); } - // Add address to whitelist - let generalTransferManagerAddress = (await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call())[0]; - let generalTransferManagerABI = abis.generalTransferManager(); - generalTransferManager = new web3.eth.Contract(generalTransferManagerABI,generalTransferManagerAddress); - if (multimint) await multi_mint_tokens(); else { @@ -241,7 +235,11 @@ async function step_Wallet_Issuance(){ canBuyFromSTO = readlineSync.keyInYNStrict(`Is address '(${mintWallet})' allowed to buy tokens from the STO? `); } - let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(mintWallet,Math.floor(Date.now()/1000),Math.floor(Date.now()/1000),Math.floor(Date.now()/1000 + 31536000), canBuyFromSTO); + // Add address to whitelist + let generalTransferManagerAddress = (await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call())[0]; + let generalTransferManagerABI = abis.generalTransferManager(); + let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, generalTransferManagerAddress); + let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(mintWallet,Math.floor(Date.now()/1000),Math.floor(Date.now()/1000),Math.floor(Date.now()/1000 + 31536000), canBuyFromSTO); await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); // Mint tokens @@ -1002,7 +1000,7 @@ async function usdTieredSTO_configure() { switch (index) { case 0: let reserveWallet = await currentSTO.methods.reserveWallet().call(); - let isVerified = await generalTransferManager.methods.verifyTransfer(STO_Address, reserveWallet, 0, web3.utils.fromAscii("")).call(); + let isVerified = await securityToken.methods.verifyTransfer(STO_Address, reserveWallet, 0, web3.utils.fromAscii("")).call(); if (isVerified == "2") { if (readlineSync.keyInYNStrict()) { let finalizeAction = currentSTO.methods.finalize(); From 4f8899e47c9b50e1f0db06726c060659aa2e24b5 Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Thu, 25 Oct 2018 11:21:18 -0300 Subject: [PATCH 035/582] Add support for createCheckpoint() from dividends modules --- CLI/commands/dividends_manager.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index bde3aa900..0efb86758 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -128,8 +128,13 @@ async function start_explorer(){ await transferTokens(_to2,_amount2); break; case 'Create checkpoint': - let createCheckpointAction = securityToken.methods.createCheckpoint(); - await common.sendTransaction(Issuer, createCheckpointAction, defaultGasPrice); + if (await isDividendsModuleAttached()) { + let createCheckpointAction = currentDividendsModule.methods.createCheckpoint(); + await common.sendTransaction(Issuer, createCheckpointAction, defaultGasPrice); + } else { + console.log("You must to attach Dividends module to perform this action."); + process.exit(1); + } break; case 'Set default exclusions for dividends': await setDefaultExclusions(); From 1f3b0f1ec95332d1d6ddd1b3b08675b7766e616b Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Thu, 25 Oct 2018 11:37:32 -0300 Subject: [PATCH 036/582] advices from Victor --- CLI/commands/dividends_manager.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 0efb86758..19280f981 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -128,13 +128,9 @@ async function start_explorer(){ await transferTokens(_to2,_amount2); break; case 'Create checkpoint': - if (await isDividendsModuleAttached()) { - let createCheckpointAction = currentDividendsModule.methods.createCheckpoint(); - await common.sendTransaction(Issuer, createCheckpointAction, defaultGasPrice); - } else { - console.log("You must to attach Dividends module to perform this action."); - process.exit(1); - } + await addDividendsModule(); + let createCheckpointAction = currentDividendsModule.methods.createCheckpoint(); + await common.sendTransaction(Issuer, createCheckpointAction, defaultGasPrice); break; case 'Set default exclusions for dividends': await setDefaultExclusions(); From 54775debbf80cf48c2d594343cc71675390da98f Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Thu, 25 Oct 2018 13:25:14 -0300 Subject: [PATCH 037/582] ST20Generator refactoring and clean up. --- CLI/commands/ST20Generator.js | 1121 +++------------------------------ CLI/polymath-cli.js | 21 +- 2 files changed, 91 insertions(+), 1051 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index a52499b2f..ab230af89 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -1,59 +1,23 @@ -var readlineSync = require('readline-sync'); -var BigNumber = require('bignumber.js'); -var moment = require('moment'); -var chalk = require('chalk'); -const shell = require('shelljs'); -var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis'); -var common = require('./common/common_functions'); -var global = require('./common/global'); +const readlineSync = require('readline-sync'); +const moment = require('moment'); +const chalk = require('chalk'); +const contracts = require('./helpers/contract_addresses'); +const abis = require('./helpers/contract_abis'); +const common = require('./common/common_functions'); +const global = require('./common/global'); +const BigNumber = require('bignumber.js'); +//////////////////////// let securityTokenRegistryAddress; - -/////////////////// -// Crowdsale params -let tokenName; let tokenSymbol; -let selectedSTO; - -const MODULES_TYPES = { - PERMISSION: 1, - TRANSFER: 2, - STO: 3, - DIVIDENDS: 4, - BURN: 5 -} +let tokenLaunched; -const cappedSTOFee = 20000; -const usdTieredSTOFee = 100000; -const tokenDetails = ""; -const FUND_RAISE_TYPES = { - ETH: 0, - POLY: 1, - DAI: 2 -} -//////////////////////// // Artifacts let securityTokenRegistry; let polyToken; -let usdToken; -let securityToken; -let currentSTO; - -// App flow -let _tokenConfig; -let _mintingConfig; -let _stoConfig; -let network; - -async function executeApp(tokenConfig, mintingConfig, stoConfig, remoteNetwork) { - _tokenConfig = tokenConfig; - _mintingConfig = mintingConfig; - _stoConfig = stoConfig; - - network = remoteNetwork; - await global.initialize(remoteNetwork); +async function executeApp(_ticker, _transferOwnership, _name, _details, _divisible, _remoteNetwork) { + await global.initialize(_remoteNetwork); common.logAsciiBull(); console.log("********************************************"); @@ -65,12 +29,11 @@ async function executeApp(tokenConfig, mintingConfig, stoConfig, remoteNetwork) await setup(); try { - await step_ticker_reg(); - await step_token_deploy(); - await step_Wallet_Issuance(); - await step_STO_launch(); - await step_STO_Status(); - await step_STO_configure(); + await step_ticker_registration(_ticker); + if (!tokenLaunched) { + await step_transfer_ticker_ownership(_transferOwnership); + await step_token_deploy(_name, _details, _divisible); + } } catch (err) { console.log(err); return; @@ -88,1049 +51,131 @@ async function setup(){ let polytokenABI = abis.polyToken(); polyToken = new web3.eth.Contract(polytokenABI, polytokenAddress); polyToken.setProvider(web3.currentProvider); - - //TODO: Use proper DAI token here - let usdTokenAddress = await contracts.usdToken(); - usdToken = new web3.eth.Contract(polytokenABI, usdTokenAddress); - usdToken.setProvider(web3.currentProvider); } catch (err) { console.log(err) - console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); + console.log(chalk.red('\nThere was a problem getting the contracts. Make sure they are deployed to the selected network.')); process.exit(0); } } -async function step_ticker_reg(){ - console.log('\n\x1b[34m%s\x1b[0m',"Token Symbol Registration"); +async function step_ticker_registration(_ticker) { + console.log(chalk.blue('\nToken Symbol Registration')); - let available = false; let regFee = web3.utils.fromWei(await securityTokenRegistry.methods.getTickerRegistrationFee().call()); - let isDeployed; + let available = false; while (!available) { - console.log(chalk.green(`\nRegistering the new token symbol requires ${regFee} POLY & deducted from '${Issuer.address}', Current balance is ${(await currentBalance(Issuer.address))} POLY\n`)); + console.log(chalk.yellow(`\nRegistering the new token symbol requires ${regFee} POLY & deducted from '${Issuer.address}', Current balance is ${(web3.utils.fromWei(await polyToken.methods.balanceOf(Issuer.address).call()))} POLY\n`)); - if (typeof _tokenConfig !== 'undefined' && _tokenConfig.hasOwnProperty('symbol')) { - tokenSymbol = _tokenConfig.symbol; + if (typeof _ticker !== 'undefined') { + tokenSymbol = _ticker; + console.log(`Token Symbol: ${tokenSymbol}`); } else { - tokenSymbol = await selectTicker(true); + tokenSymbol = await selectTicker(); } let details = await securityTokenRegistry.methods.getTickerDetails(tokenSymbol).call(); - isDeployed = details[4]; if (new BigNumber(details[1]).toNumber() == 0) { + // If it has no registration date, it is available available = true; await approvePoly(securityTokenRegistryAddress, regFee); let registerTickerAction = securityTokenRegistry.methods.registerTicker(Issuer.address, tokenSymbol, ""); await common.sendTransaction(Issuer, registerTickerAction, defaultGasPrice, 0, 1.5); } else if (details[0] == Issuer.address) { + // If it has registration date and its owner is Issuer available = true; + tokenLaunched = details[4]; } else { - console.log('\n\x1b[31m%s\x1b[0m',"Token Symbol has already been registered, please choose another symbol"); - } - } - - if (!isDeployed) { - if (typeof _tokenConfig === 'undefined' && readlineSync.keyInYNStrict(`Do you want to transfer the ownership of ${tokenSymbol} ticker?`)) { - let newOwner = readlineSync.question('Enter the address that will be the new owner: ', { - limit: function(input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let transferTickerOwnershipAction = securityTokenRegistry.methods.transferTickerOwnership(newOwner, tokenSymbol); - let receipt = await common.sendTransaction(Issuer, transferTickerOwnershipAction, defaultGasPrice, 0, 1.5); - let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'ChangeTickerOwnership'); - console.log(chalk.green(`Ownership trasferred successfully. The new owner is ${event._newOwner}`)); - process.exit(0); - } - } -} - -async function step_token_deploy(){ - // Let's check if token has already been deployed, if it has, skip to STO - let tokenAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); - if (tokenAddress != "0x0000000000000000000000000000000000000000") { - console.log('\n\x1b[32m%s\x1b[0m',"Token has already been deployed at address " + tokenAddress + ". Skipping deployment."); - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, tokenAddress); - } else { - console.log('\n\x1b[34m%s\x1b[0m',"Token Creation - Token Deployment"); - - let launchFee = web3.utils.fromWei(await securityTokenRegistry.methods.getSecurityTokenLaunchFee().call()); - console.log(chalk.green(`\nToken deployment requires ${launchFee} POLY & deducted from '${Issuer.address}', Current balance is ${(await currentBalance(Issuer.address))} POLY\n`)); - - if (typeof _tokenConfig !== 'undefined' && _tokenConfig.hasOwnProperty('name')) { - tokenName = _tokenConfig.name; - } else { - tokenName = readlineSync.question('Enter the name for your new token: '); - } - if (tokenName == "") tokenName = 'default'; - - console.log("\n"); - console.log('\x1b[34m%s\x1b[0m',"Select the Token divisibility type"); - - let divisibility; - if (typeof _tokenConfig !== 'undefined' && _tokenConfig.hasOwnProperty('divisible')) { - divisibility = _tokenConfig.divisible; - } else { - let divisible = readlineSync.question('Press "N" for Non-divisible type token or hit Enter for divisible type token (Default):'); - if (divisible == 'N' || divisible == 'n') - divisibility = false; - else - divisibility = true; - } - - await approvePoly(securityTokenRegistryAddress, launchFee); - let generateSecurityTokenAction = securityTokenRegistry.methods.generateSecurityToken(tokenName, tokenSymbol, tokenDetails, divisibility); - let receipt = await common.sendTransaction(Issuer, generateSecurityTokenAction, defaultGasPrice); - let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'NewSecurityToken'); - console.log(`Deployed Token at address: ${event._securityTokenAddress}`); - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, event._securityTokenAddress); - } -} - -async function step_Wallet_Issuance(){ - let result = await securityToken.methods.getModulesByType(MODULES_TYPES.STO).call(); - if (result.length > 0) { - console.log('\x1b[32m%s\x1b[0m',"STO has already been created at address " + result[0] + ". Skipping initial minting"); - } else { - let initialMint = await securityToken.getPastEvents('Transfer', { - filter: {from: "0x0000000000000000000000000000000000000000"}, // Using an array means OR: e.g. 20 or 23 - fromBlock: 0, - toBlock: 'latest' - }); - if (initialMint.length > 0) { - console.log('\x1b[32m%s\x1b[0m',web3.utils.fromWei(initialMint[0].returnValues.value) +" Tokens have already been minted for " + initialMint[0].returnValues.to + ". Skipping initial minting"); - } else { - console.log("\n"); - console.log('\x1b[34m%s\x1b[0m',"Token Creation - Token Minting for Issuer"); - - console.log("Before setting up the STO, you can mint any amount of tokens that will remain under your control or you can transfer to affiliates"); - - let multimint; - if (typeof _mintingConfig !== 'undefined' && _mintingConfig.hasOwnProperty('multimint')) { - multimint = _mintingConfig.multimint; - } else { - let isAffiliate = readlineSync.question('Press'+ chalk.green(` "Y" `) + 'if you have list of affiliates addresses with you otherwise hit' + chalk.green(' Enter ') + 'and get the minted tokens to a particular address: '); - multimint = (isAffiliate == "Y" || isAffiliate == "y"); - } - - if (multimint) - await multi_mint_tokens(); - else { - let mintWallet; - if (typeof _mintingConfig !== 'undefined' && _mintingConfig.hasOwnProperty('singleMint') && _mintingConfig.singleMint.hasOwnProperty('wallet')) { - mintWallet = _mintingConfig.singleMint.wallet; - } else { - mintWallet = readlineSync.question('Add the address that will hold the issued tokens to the whitelist (' + Issuer.address + '): '); - } - if (mintWallet == "") mintWallet = Issuer.address; - - let canBuyFromSTO; - if (typeof _mintingConfig !== 'undefined' && _mintingConfig.hasOwnProperty('singleMint') && _mintingConfig.singleMint.hasOwnProperty('allowedToBuy')) { - canBuyFromSTO = _mintingConfig.singleMint.allowedToBuy; - } else { - canBuyFromSTO = readlineSync.keyInYNStrict(`Is address '(${mintWallet})' allowed to buy tokens from the STO? `); - } - - // Add address to whitelist - let generalTransferManagerAddress = (await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call())[0]; - let generalTransferManagerABI = abis.generalTransferManager(); - let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, generalTransferManagerAddress); - let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(mintWallet,Math.floor(Date.now()/1000),Math.floor(Date.now()/1000),Math.floor(Date.now()/1000 + 31536000), canBuyFromSTO); - await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); - - // Mint tokens - if (typeof _mintingConfig !== 'undefined' && _mintingConfig.hasOwnProperty('singleMint') && _mintingConfig.singleMint.hasOwnProperty('tokenAmount')) { - issuerTokens = _mintingConfig.singleMint.tokenAmount; - } else { - issuerTokens = readlineSync.question('How many tokens do you plan to mint for the wallet you entered? (500.000): '); - } - if (issuerTokens == "") issuerTokens = '500000'; - - let mintAction = securityToken.methods.mint(mintWallet, web3.utils.toWei(issuerTokens)); - await common.sendTransaction(Issuer, mintAction, defaultGasPrice); - } - } - } -} - -async function multi_mint_tokens() { - //await whitelist.startWhitelisting(tokenSymbol); - shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${network}`); - console.log(chalk.green(`\nCongrats! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); - console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); - - shell.exec(`${__dirname}/scripts//script.sh Multimint ${tokenSymbol} 75 ${network}`); - console.log(chalk.green(`\nHurray!! Tokens get successfully Minted and transferred to token holders`)); -} - -async function step_STO_launch() { - console.log("\n"); - console.log('\x1b[34m%s\x1b[0m',"Token Creation - STO Configuration"); - - let result = await securityToken.methods.getModulesByType(MODULES_TYPES.STO).call(); - if (result.length > 0) { - STO_Address = result[0]; - let stoModuleData = await securityToken.methods.getModule(STO_Address).call(); - selectedSTO = web3.utils.toAscii(stoModuleData[0]).replace(/\u0000/g, ''); - console.log('\x1b[32m%s\x1b[0m',selectedSTO + " has already been created at address " + STO_Address + ". Skipping STO creation"); - switch (selectedSTO) { - case 'CappedSTO': - let cappedSTOABI = abis.cappedSTO(); - currentSTO = new web3.eth.Contract(cappedSTOABI,STO_Address); - break; - case 'USDTieredSTO': - let usdTieredSTOABI = abis.usdTieredSTO(); - currentSTO = new web3.eth.Contract(usdTieredSTOABI,STO_Address); - break; - } - } else { - let index; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('type')) { - index = _stoConfig.type; - } else { - let options = ['Capped STO', 'USD Tiered STO', 'Select STO later']; - index = readlineSync.keyInSelect(options, 'What type of STO do you want?', { cancel: false }); - } - switch (index) { - case 0: - selectedSTO = 'CappedSTO'; - await cappedSTO_launch(); - break; - case 1: - selectedSTO = 'USDTieredSTO'; - await usdTieredSTO_launch(); - break; - case 2: - process.exit(0); - break; + // If it has registration date and its owner is not Issuer + console.log(chalk.yellow('\nToken Symbol has already been registered, please choose another symbol')); } } } -async function step_STO_Status() { - switch (selectedSTO) { - case 'CappedSTO': - await cappedSTO_status(); - break; - case 'USDTieredSTO': - await usdTieredSTO_status(); - break; - } -} - -async function step_STO_configure() { - switch (selectedSTO) { - case 'CappedSTO': - break; - case 'USDTieredSTO': - await usdTieredSTO_configure(); - break; - } -} - -//////////////// -// Capped STO // -//////////////// -async function cappedSTO_launch() { - console.log("\n"); - console.log('\x1b[34m%s\x1b[0m',"Token Creation - Capped STO in No. of Tokens"); - - let stoFee = cappedSTOFee; - let contractBalance = await polyToken.methods.balanceOf(securityToken._address).call(); - let requiredAmount = web3.utils.toWei(stoFee.toString()); - if (parseInt(contractBalance) < parseInt(requiredAmount)) { - let transferAmount = parseInt(requiredAmount) - parseInt(contractBalance); - let ownerBalance = await polyToken.methods.balanceOf(Issuer.address).call(); - if(parseInt(ownerBalance) < transferAmount) { - console.log(chalk.red(`\n**************************************************************************************************************************************************`)); - console.log(chalk.red(`Not enough balance to pay the CappedSTO fee, Requires ${(new BigNumber(transferAmount).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY but have ${(new BigNumber(ownerBalance).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY. Access POLY faucet to get the POLY to complete this txn`)); - console.log(chalk.red(`**************************************************************************************************************************************************\n`)); - process.exit(0); - } else { - let transferAction = polyToken.methods.transfer(securityToken._address, new BigNumber(transferAmount)); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice, 0, 2); - let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); - console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) - } - } - - let cap; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('cap')) { - cap = _stoConfig.cap.toString(); - } else { - cap = readlineSync.question('How many tokens do you plan to sell on the STO? (500.000): '); - } - if (cap == "") cap = '500000'; - - let oneMinuteFromNow = BigNumber((Math.floor(Date.now() / 1000) + 60)); - let startTime; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('startTime')) { - startTime = _stoConfig.startTime; - } else { - startTime = readlineSync.question('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): '); - } - if (startTime == "") startTime = oneMinuteFromNow; - - let oneMonthFromNow = BigNumber((Math.floor(Date.now()/1000)+ (30 * 24 * 60 * 60))); - let endTime; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('endTime')) { - endTime = _stoConfig.endTime; - } else { - endTime = readlineSync.question('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): '); - } - if (endTime == "") endTime = oneMonthFromNow; - - let wallet; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('wallet')) { - wallet = _stoConfig.wallet; - } else { - wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): '); - } - if (wallet == "") wallet = Issuer.address; - - let raiseType; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('raiseType')) { - raiseType = [_stoConfig.raiseType]; - } else { - raiseType = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise or leave empty for Ether raise (E):'); - if (raiseType.toUpperCase() == 'P' ) { - raiseType = [1]; - } else { - raiseType = [0]; - } - } - - let rate; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('rate')) { - rate = _stoConfig.rate; - } else { - rate = readlineSync.question(`Enter the rate (1 ${(raiseType == 1 ? 'POLY' : 'ETH')} = X ST) for the STO (1000): `); - } - if (rate == "") rate = 1000; - - let bytesSTO = web3.eth.abi.encodeFunctionCall( { - name: 'configure', - type: 'function', - inputs: [ - { - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'uint256', - name: '_rate' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes' - },{ - type: 'address', - name: '_fundsReceiver' - } - ] - }, [startTime, endTime, web3.utils.toWei(cap), rate, raiseType, wallet]); - - let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.STO, "CappedSTO"); - let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); - let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); - console.log(`STO deployed at address: ${event._module}`); - - STO_Address = event._module; - let cappedSTOABI = abis.cappedSTO(); - currentSTO = new web3.eth.Contract(cappedSTOABI, STO_Address); -} - -async function cappedSTO_status() { - let displayStartTime = await currentSTO.methods.startTime().call(); - let displayEndTime = await currentSTO.methods.endTime().call(); - let displayRate = await currentSTO.methods.rate().call(); - let displayCap = await currentSTO.methods.cap().call(); - let displayWallet = await currentSTO.methods.wallet().call(); - let displayRaiseType; - let displayFundsRaised; - let displayWalletBalance; - let raiseType = await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.ETH).call(); - if (raiseType) { - displayRaiseType = 'ETH'; - displayFundsRaised = await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES.ETH).call(); - displayWalletBalance = web3.utils.fromWei(await web3.eth.getBalance(displayWallet)); - } else { - displayRaiseType = 'POLY'; - displayFundsRaised = await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES.POLY).call(); - displayWalletBalance = await currentBalance(displayWallet); - } - let displayTokensSold = await currentSTO.methods.totalTokensSold().call(); - let displayInvestorCount = await currentSTO.methods.investorCount().call(); - let displayTokenSymbol = await securityToken.methods.symbol().call(); - - let formattedCap = BigNumber(web3.utils.fromWei(displayCap)); - let formattedSold = BigNumber(web3.utils.fromWei(displayTokensSold)); - - let now = Math.floor(Date.now()/1000); - let timeTitle; - let timeRemaining; - - if (now < displayStartTime) { - timeTitle = "STO starts in: "; - timeRemaining = displayStartTime - now; - } else { - timeTitle = "Time remaining:"; - timeRemaining = displayEndTime - now; - } - - timeRemaining = common.convertToDaysRemaining(timeRemaining); - - console.log(` - ***** STO Information ***** - - Address: ${STO_Address} - - Raise Cap: ${web3.utils.fromWei(displayCap)} ${displayTokenSymbol.toUpperCase()} - - Start Time: ${new Date(displayStartTime * 1000)} - - End Time: ${new Date(displayEndTime * 1000)} - - Raise Type: ${displayRaiseType} - - Rate: 1 ${displayRaiseType} = ${displayRate} ${displayTokenSymbol.toUpperCase()} - - Wallet: ${displayWallet} - - Wallet Balance: ${displayWalletBalance} ${displayRaiseType} - -------------------------------------- - - ${timeTitle} ${timeRemaining} - - Funds raised: ${web3.utils.fromWei(displayFundsRaised)} ${displayRaiseType} - - Tokens sold: ${web3.utils.fromWei(displayTokensSold)} ${displayTokenSymbol.toUpperCase()} - - Tokens remaining: ${formattedCap.minus(formattedSold).toNumber()} ${displayTokenSymbol.toUpperCase()} - - Investor count: ${displayInvestorCount} - `); - - console.log(chalk.green(`\n${(await currentBalance(Issuer.address))} POLY balance remaining at issuer address ${Issuer.address}`)); -} - -//////////////////// -// USD Tiered STO // -//////////////////// -function fundingConfigUSDTieredSTO() { - let funding = {}; - - let selectedFunding; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('fundingType')) { - selectedFunding = _stoConfig.fundingType; - } else { - selectedFunding = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise,' + chalk.green(` D `) + 'for DAI raise,' + chalk.green(` E `) + 'for Ether raise or any combination of them (i.e.'+ chalk.green(` PED `) + 'for all): ').toUpperCase(); - } - - funding.raiseType = []; - if (selectedFunding.includes('E')) { - funding.raiseType.push(FUND_RAISE_TYPES.ETH); - } - if (selectedFunding.includes('P')) { - funding.raiseType.push(FUND_RAISE_TYPES.POLY); - } - if (selectedFunding.includes('D')) { - funding.raiseType.push(FUND_RAISE_TYPES.DAI); - } - if (funding.raiseType.length == 0) { - funding.raiseType = [FUND_RAISE_TYPES.ETH, FUND_RAISE_TYPES.POLY, FUND_RAISE_TYPES.DAI]; - } - - return funding; -} - -function addressesConfigUSDTieredSTO(usdTokenRaise) { - let addresses = {}; - - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('wallet')) { - addresses.wallet = _stoConfig.wallet; - } else { - addresses.wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): ', { - limit: function(input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - defaultInput: Issuer.address - }); - } - if (addresses.wallet == "") addresses.wallet = Issuer.address; - - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('reserveWallet')) { - addresses.reserveWallet = _stoConfig.reserveWallet; - } else { - addresses.reserveWallet = readlineSync.question('Enter the address that will receive remaining tokens in the case the cap is not met (' + Issuer.address + '): ', { - limit: function(input) { +async function step_transfer_ticker_ownership(_transferOwnership) { + let newOwner = null; + if (typeof _transferOwnership !== 'undefined' && _transferOwnership != 'false') { + newOwner = _transferOwnership; + console.log(`Transfer ownership to: ${newOwner}`); + } else if (_transferOwnership != 'false' && readlineSync.keyInYNStrict(`Do you want to transfer the ownership of ${tokenSymbol} ticker?`)) { + newOwner = readlineSync.question('Enter the address that will be the new owner: ', { + limit: function (input) { return web3.utils.isAddress(input); }, - limitMessage: "Must be a valid address", - defaultInput: Issuer.address - }); - } - if (addresses.reserveWallet == "") addresses.reserveWallet = Issuer.address; - - if (usdTokenRaise) { - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('usdToken')) { - addresses.usdToken = _stoConfig.usdToken; - } else { - addresses.usdToken = readlineSync.question('Enter the address of the USD Token or stable coin (' + usdToken.options.address + '): ', { - limit: function(input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - defaultInput: usdToken.options.address - }); - } - if (addresses.usdToken == "") addresses.usdToken = usdToken.options.address; - } else { - addresses.usdToken = '0x0000000000000000000000000000000000000000'; - } - - return addresses; -} - -function tiersConfigUSDTieredSTO(polyRaise) { - let tiers = {}; - - let defaultTiers = 3; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('numberOfTiers')) { - tiers.tiers = _stoConfig.numberOfTiers; - } else { - tiers.tiers = readlineSync.questionInt(`Enter the number of tiers for the STO? (${defaultTiers}): `, { - limit: function(input) { - return input > 0; - }, - limitMessage: 'Must be greater than zero', - defaultInput: defaultTiers + limitMessage: "Must be a valid address" }); } - let defaultTokensPerTier = [190000000, 100000000, 200000000]; - let defaultRatePerTier = ['0.05', '0.10', '0.15']; - let defaultTokensPerTierDiscountPoly = [90000000, 50000000, 100000000]; - let defaultRatePerTierDiscountPoly = ['0.025', '0.05', '0.075']; - tiers.tokensPerTier = []; - tiers.ratePerTier = []; - tiers.tokensPerTierDiscountPoly = []; - tiers.ratePerTierDiscountPoly = []; - for (let i = 0; i < tiers.tiers; i++) { - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('tokensPerTiers') && i < _stoConfig.tokensPerTiers.length) { - tiers.tokensPerTier[i] = web3.utils.toWei(_stoConfig.tokensPerTiers[i].toString()); - } else { - tiers.tokensPerTier[i] = web3.utils.toWei(readlineSync.question(`How many tokens do you plan to sell on tier No. ${i+1}? (${defaultTokensPerTier[i]}): `, { - limit: function(input) { - return parseFloat(input) > 0; - }, - limitMessage: 'Must be greater than zero', - defaultInput: defaultTokensPerTier[i] - })); - } - - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('ratePerTiers') && i < _stoConfig.ratePerTiers.length) { - tiers.ratePerTier[i] = web3.utils.toWei(_stoConfig.ratePerTiers[i].toString()); - } else { - tiers.ratePerTier[i] = web3.utils.toWei(readlineSync.question(`What is the USD per token rate for tier No. ${i+1}? (${defaultRatePerTier[i]}): `, { - limit: function(input) { - return parseFloat(input) > 0; - }, - limitMessage: 'Must be greater than zero', - defaultInput: defaultRatePerTier[i] - })); - } - - let isTPTDPDefined = (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('discountedTokensPerTiers') && i < _stoConfig.discountedTokensPerTiers.length); //If it's defined by config file - let isRPTDPDefined = (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('discountedRatePerTiers') && i < _stoConfig.discountedRatePerTiers.length); //If it's defined by config file - //If funds can be raised in POLY and discounts are defined in config file or are choosen by user - if (polyRaise && ((isTPTDPDefined && isRPTDPDefined) || readlineSync.keyInYNStrict(`Do you plan to have a discounted rate for POLY investments for tier No. ${i+1}? `))) { - if (isTPTDPDefined) { - tiers.tokensPerTierDiscountPoly[i] = web3.utils.toWei(_stoConfig.discountedTokensPerTiers[i].toString()); - } else { - tiers.tokensPerTierDiscountPoly[i] = web3.utils.toWei(readlineSync.question(`How many of those tokens do you plan to sell at discounted rate on tier No. ${i+1}? (${defaultTokensPerTierDiscountPoly[i]}): `, { - limit: function(input) { - return new BigNumber(web3.utils.toWei(input)).lte(tiers.tokensPerTier[i]) - }, - limitMessage: 'Must be less than the No. of tokens of the tier', - defaultInput: defaultTokensPerTierDiscountPoly[i] - })); - } - - if (isRPTDPDefined) { - tiers.ratePerTierDiscountPoly[i] = web3.utils.toWei(_stoConfig.discountedRatePerTiers[i].toString()); - } else { - tiers.ratePerTierDiscountPoly[i] = web3.utils.toWei(readlineSync.question(`What is the discounted rate for tier No. ${i+1}? (${defaultRatePerTierDiscountPoly[i]}): `, { - limit: function(input) { - return new BigNumber(web3.utils.toWei(input)).lte(tiers.ratePerTier[i]) - }, - limitMessage: 'Must be less than the rate of the tier', - defaultInput: defaultRatePerTierDiscountPoly[i] - })); - } - } else { - tiers.tokensPerTierDiscountPoly[i] = 0; - tiers.ratePerTierDiscountPoly[i] = 0; - } - } - - return tiers; -} - -function timesConfigUSDTieredSTO() { - let times = {}; - - let oneMinuteFromNow = Math.floor(Date.now() / 1000) + 60; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('startTime')) { - times.startTime = _stoConfig.startTime; - } else { - times.startTime = readlineSync.questionInt('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): ', { - limit: function(input) { - return input > Math.floor(Date.now() / 1000); - }, - limitMessage: "Must be a future time", - defaultInput: oneMinuteFromNow - }); - } - if (times.startTime == "") times.startTime = oneMinuteFromNow; - - let oneMonthFromNow = Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60); - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('endTime')) { - times.endTime = _stoConfig.endTime; - } else { - times.endTime = readlineSync.questionInt('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): ', { - limit: function(input) { - return input > times.startTime; - }, - limitMessage: "Must be greater than Start Time", - defaultInput: oneMonthFromNow - }); + if (newOwner) { + let transferTickerOwnershipAction = securityTokenRegistry.methods.transferTickerOwnership(newOwner, tokenSymbol); + let receipt = await common.sendTransaction(Issuer, transferTickerOwnershipAction, defaultGasPrice, 0, 1.5); + let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'ChangeTickerOwnership'); + console.log(chalk.green(`Ownership trasferred successfully. The new owner is ${event._newOwner}`)); + process.exit(0); } - if (times.endTime == "") times.endTime = oneMonthFromNow; - - return times; } -function limitsConfigUSDTieredSTO() { - let limits = {}; +async function step_token_deploy(_name, _details, _divisible) { + console.log(chalk.blue('\nToken Creation - Token Deployment')); - let defaultMinimumInvestment = 5; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('minimumInvestmentUSD')) { - limits.minimumInvestmentUSD = web3.utils.toWei(_stoConfig.minimumInvestmentUSD.toString()); - } else { - limits.minimumInvestmentUSD = web3.utils.toWei(readlineSync.question(`What is the minimum investment in USD? (${defaultMinimumInvestment}): `, { - limit: function(input) { - return parseInt(input) > 0; - }, - limitMessage: "Must be greater than zero", - defaultInput: defaultMinimumInvestment - })); - } + let launchFee = web3.utils.fromWei(await securityTokenRegistry.methods.getSecurityTokenLaunchFee().call()); + console.log(chalk.green(`\nToken deployment requires ${launchFee} POLY & deducted from '${Issuer.address}', Current balance is ${(web3.utils.fromWei(await polyToken.methods.balanceOf(Issuer.address).call()))} POLY\n`)); - let nonAccreditedLimit = 2500; - if (typeof _stoConfig !== 'undefined' && _stoConfig.hasOwnProperty('nonAccreditedLimitUSD')) { - limits.nonAccreditedLimitUSD = web3.utils.toWei(_stoConfig.nonAccreditedLimitUSD.toString()); + let tokenName; + if (typeof _name !== 'undefined') { + tokenName = _name; + console.log(`Token Name: ${tokenName}`); } else { - limits.nonAccreditedLimitUSD = web3.utils.toWei(readlineSync.question(`What is the default limit for non accredited investors in USD? (${nonAccreditedLimit}): `, { - limit: function(input) { - return new BigNumber(web3.utils.toWei(input)).gte(limits.minimumInvestmentUSD); - }, - limitMessage: "Must be greater than minimum investment", - defaultInput: nonAccreditedLimit - })); - } - - return limits; -} - -async function usdTieredSTO_launch() { - console.log("\n"); - console.log('\x1b[34m%s\x1b[0m',"Token Creation - USD Tiered STO"); - - let stoFee = usdTieredSTOFee; - let contractBalance = await polyToken.methods.balanceOf(securityToken._address).call(); - let requiredAmount = web3.utils.toWei(stoFee.toString(), "ether"); - if (new web3.utils.BN(contractBalance).lt(new web3.utils.BN(requiredAmount))) { - let transferAmount = (new web3.utils.BN(requiredAmount)).sub(new web3.utils.BN(contractBalance)); - let ownerBalance = new web3.utils.BN(await polyToken.methods.balanceOf(Issuer.address).call()); - if (ownerBalance.lt(transferAmount)) { - console.log(chalk.red(`\n**************************************************************************************************************************************************`)); - console.log(chalk.red(`Not enough balance to pay the ${selectedSTO} fee, Requires ${web3.utils.fromWei(transferAmount)} POLY but have ${web3.utils.fromWei(ownerBalance)} POLY. Access POLY faucet to get the POLY to complete this txn`)); - console.log(chalk.red(`**************************************************************************************************************************************************\n`)); - process.exit(0); - } else { - let transferAction = polyToken.methods.transfer(securityToken._address, transferAmount); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice, 0, 2); - let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); - console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) - } - } - - let funding = fundingConfigUSDTieredSTO(); - let addresses = addressesConfigUSDTieredSTO(funding.raiseType.includes(FUND_RAISE_TYPES.DAI)); - let tiers = tiersConfigUSDTieredSTO(funding.raiseType.includes(FUND_RAISE_TYPES.POLY)); - let limits = limitsConfigUSDTieredSTO(); - let times = timesConfigUSDTieredSTO(); - let bytesSTO = web3.eth.abi.encodeFunctionCall( { - name: 'configure', - type: 'function', - inputs: [ - { - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256[]', - name: '_ratePerTier' - },{ - type: 'uint256[]', - name: '_ratePerTierDiscountPoly' - },{ - type: 'uint256[]', - name: '_tokensPerTier' - },{ - type: 'uint256[]', - name: '_tokensPerTierDiscountPoly' - },{ - type: 'uint256', - name: '_nonAccreditedLimitUSD' - },{ - type: 'uint256', - name: '_minimumInvestmentUSD' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes' - },{ - type: 'address', - name: '_wallet' - },{ - type: 'address', - name: '_reserveWallet' - },{ - type: 'address', - name: '_usdToken' - } - ] - }, [times.startTime, - times.endTime, - tiers.ratePerTier, - tiers.ratePerTierDiscountPoly, - tiers.tokensPerTier, - tiers.tokensPerTierDiscountPoly, - limits.nonAccreditedLimitUSD, - limits.minimumInvestmentUSD, - funding.raiseType, - addresses.wallet, - addresses.reserveWallet, - addresses.usdToken - ]); - - let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.STO, 'USDTieredSTO'); - let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); - let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); - console.log(`STO deployed at address: ${event._module}`); - - STO_Address = event._module; - let usdTieredSTOABI = abis.usdTieredSTO(); - currentSTO = new web3.eth.Contract(usdTieredSTOABI,STO_Address); -} - -async function usdTieredSTO_status() { - let displayStartTime = await currentSTO.methods.startTime().call(); - let displayEndTime = await currentSTO.methods.endTime().call(); - let displayCurrentTier = parseInt(await currentSTO.methods.currentTier().call()) + 1; - let displayNonAccreditedLimitUSD = web3.utils.fromWei(await currentSTO.methods.nonAccreditedLimitUSD().call()); - let displayMinimumInvestmentUSD = web3.utils.fromWei(await currentSTO.methods.minimumInvestmentUSD().call()); - let displayWallet = await currentSTO.methods.wallet().call(); - let displayReserveWallet = await currentSTO.methods.reserveWallet().call(); - let displayTokensSold = web3.utils.fromWei(await currentSTO.methods.getTokensSold().call()); - let displayInvestorCount = await currentSTO.methods.investorCount().call(); - let displayIsFinalized = await currentSTO.methods.isFinalized().call() ? "YES" : "NO"; - let displayTokenSymbol = await securityToken.methods.symbol().call(); - - let tiersLength = await currentSTO.methods.getNumberOfTiers().call();; - - let raiseTypes = []; - for (const fundType in FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES[fundType]).call()) { - raiseTypes.push(fundType); - } + tokenName = readlineSync.question('Enter the name for your new token: ', {defaultInput: 'default'}); } - let displayTiers = ""; - let displayMintedPerTier = ""; - for (let t = 0; t < tiersLength; t++) { - let ratePerTier = await currentSTO.methods.ratePerTier(t).call(); - let tokensPerTierTotal = await currentSTO.methods.tokensPerTierTotal(t).call(); - let mintedPerTierTotal = await currentSTO.methods.mintedPerTierTotal(t).call(); - - let displayMintedPerTierPerType = ""; - let displayDiscountTokens = ""; - for (const type of raiseTypes) { - let displayDiscountMinted = ""; - if (type == 'POLY') { - let tokensPerTierDiscountPoly = await currentSTO.methods.tokensPerTierDiscountPoly(t).call(); - if (tokensPerTierDiscountPoly > 0) { - let ratePerTierDiscountPoly = await currentSTO.methods.ratePerTierDiscountPoly(t).call(); - let mintedPerTierDiscountPoly = await currentSTO.methods.mintedPerTierDiscountPoly(t).call(); - displayDiscountTokens = ` - Tokens at discounted rate: ${web3.utils.fromWei(tokensPerTierDiscountPoly)} ${displayTokenSymbol} - Discounted rate: ${web3.utils.fromWei(ratePerTierDiscountPoly, 'ether')} USD per Token`; - - displayDiscountMinted = `(${web3.utils.fromWei(mintedPerTierDiscountPoly)} ${displayTokenSymbol} at discounted rate)`; - } - } - - let mintedPerTier = await currentSTO.methods.mintedPerTier(FUND_RAISE_TYPES[type], t).call(); - displayMintedPerTierPerType += ` - Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; - } - - displayTiers += ` - - Tier ${t+1}: - Tokens: ${web3.utils.fromWei(tokensPerTierTotal)} ${displayTokenSymbol} - Rate: ${web3.utils.fromWei(ratePerTier)} USD per Token` - + displayDiscountTokens; - - displayMintedPerTier += ` - - Tokens minted in Tier ${t+1}: ${web3.utils.fromWei(mintedPerTierTotal)} ${displayTokenSymbol}` - + displayMintedPerTierPerType; - } - - let displayFundsRaisedUSD = web3.utils.fromWei(await currentSTO.methods.fundsRaisedUSD().call()); - - let displayWalletBalancePerType = ''; - let displayReserveWalletBalancePerType = ''; - let displayFundsRaisedPerType = ''; - let displayTokensSoldPerType = ''; - for (const type of raiseTypes) { - let balance = await getBalance(displayWallet, type); - let walletBalance = web3.utils.fromWei(balance); - let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(FUND_RAISE_TYPES[type], balance).call()); - displayWalletBalancePerType += ` - Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; - - balance = await getBalance(displayReserveWallet, type); - let reserveWalletBalance = web3.utils.fromWei(balance); - let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(FUND_RAISE_TYPES[type], balance).call()); - displayReserveWalletBalancePerType += ` - Balance ${type}:\t\t ${reserveWalletBalance} ${type} (${reserveWalletBalanceUSD} USD)`; - - let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES[type]).call()); - displayFundsRaisedPerType += ` - ${type}:\t\t\t ${fundsRaised} ${type}`; - - //Only show sold for if more than one raise type are allowed - if (raiseTypes.length > 1) { - let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(FUND_RAISE_TYPES[type]).call()); - displayTokensSoldPerType += ` - Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; - } - } - - let displayRaiseType = raiseTypes.join(' - '); - - let now = Math.floor(Date.now()/1000); - let timeTitle; - let timeRemaining; - if (now < displayStartTime) { - timeTitle = "STO starts in: "; - timeRemaining = displayStartTime - now; + let tokenDetails; + if (typeof _details !== 'undefined') { + tokenDetails = _details; + console.log(`Token details: ${tokenDetails.toString()}`) } else { - timeTitle = "Time remaining:"; - timeRemaining = displayEndTime - now; + tokenDetails = readlineSync.question('Enter off-chain details of the token (i.e. Dropbox folder url): '); } - timeRemaining = common.convertToDaysRemaining(timeRemaining); - - console.log(` - ****************** STO Information ****************** - - Address: ${STO_Address} - - Start Time: ${new Date(displayStartTime * 1000)} - - End Time: ${new Date(displayEndTime * 1000)} - - Raise Type: ${displayRaiseType} - - Tiers: ${tiersLength}` - + displayTiers + ` - - Minimum Investment: ${displayMinimumInvestmentUSD} USD - - Non Accredited Limit: ${displayNonAccreditedLimitUSD} USD - - Wallet: ${displayWallet}` - + displayWalletBalancePerType + ` - - Reserve Wallet: ${displayReserveWallet}` - + displayReserveWalletBalancePerType + ` - - -------------------------------------- - - ${timeTitle} ${timeRemaining} - - Is Finalized: ${displayIsFinalized} - - Tokens Sold: ${displayTokensSold} ${displayTokenSymbol}` - + displayTokensSoldPerType + ` - - Current Tier: ${displayCurrentTier}` - + displayMintedPerTier + ` - - Investor count: ${displayInvestorCount} - - Funds Raised` - + displayFundsRaisedPerType + ` - USD: ${displayFundsRaisedUSD} USD - `); - - console.log(chalk.green(`\n${(await currentBalance(Issuer.address))} POLY balance remaining at issuer address ${Issuer.address}`)); -} - -async function usdTieredSTO_configure() { - console.log("\n"); - console.log('\x1b[34m%s\x1b[0m',"STO Configuration - USD Tiered STO"); - - let isFinalized = await currentSTO.methods.isFinalized().call(); - if (isFinalized) { - console.log(chalk.red(`STO is finalized`)); + let divisibility; + if (typeof _divisible !== 'undefined') { + divisibility = _divisible == 'true'; + console.log(`Divisible: ${divisibility.toString()}`) } else { - let options = []; - options.push('Finalize STO', - 'Change accredited account', 'Change accredited in batch', - 'Change non accredited limit for an account', 'Change non accredited limits in batch'); - - // If STO is not started, you can modify configuration - let now = Math.floor(Date.now() / 1000); - let startTime = await currentSTO.methods.startTime().call.call(); - if (now < startTime) { - options.push('Modify times configuration', 'Modify tiers configuration', 'Modify addresses configuration', - 'Modify limits configuration', 'Modify funding configuration'); - } - - if (typeof _stoConfig === 'undefined') { - let index = readlineSync.keyInSelect(options, 'What do you want to do?'); - switch (index) { - case 0: - let reserveWallet = await currentSTO.methods.reserveWallet().call(); - let isVerified = await securityToken.methods.verifyTransfer(STO_Address, reserveWallet, 0, web3.utils.fromAscii("")).call(); - if (isVerified == "2") { - if (readlineSync.keyInYNStrict()) { - let finalizeAction = currentSTO.methods.finalize(); - await common.sendTransaction(Issuer, finalizeAction, defaultGasPrice); - } - } else { - console.log(chalk.red(`Reserve wallet (${reserveWallet}) is not able to receive remaining tokens. Check if this address is whitelisted.`)); - } - break; - case 1: - let investor = readlineSync.question('Enter the address to change accreditation: '); - let isAccredited = readlineSync.keyInYNStrict(`Is ${investor} accredited?`); - let investors = [investor]; - let accredited = [isAccredited]; - let changeAccreditedAction = currentSTO.methods.changeAccredited(investors, accredited); - // 2 GAS? - await common.sendTransaction(Issuer, changeAccreditedAction, defaultGasPrice); - break; - case 2: - shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${network}`); - break; - case 3: - let account = readlineSync.question('Enter the address to change non accredited limit: '); - let limit = readlineSync.question(`Enter the limit in USD: `); - let accounts = [account]; - let limits = [web3.utils.toWei(limit)]; - let changeNonAccreditedLimitAction = currentSTO.methods.changeNonAccreditedLimit(accounts, limits); - // 2 GAS? - await common.sendTransaction(Issuer, changeNonAccreditedLimitAction, defaultGasPrice); - break; - case 4: - shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${network}`); - break; - case 5: - await modfifyTimes(); - await usdTieredSTO_status(); - break; - case 6: - await modfifyTiers(); - await usdTieredSTO_status(); - break; - case 7: - await modfifyAddresses(); - await usdTieredSTO_status(); - break; - case 8: - await modfifyLimits(); - await usdTieredSTO_status(); - break; - case 9: - await modfifyFunding(); - await usdTieredSTO_status(); - break; - } - } + let divisible = readlineSync.question('Press "N" for Non-divisible type token or hit Enter for divisible type token (Default): '); + divisibility = (divisible != 'N' && divisible != 'n'); } -} -async function modfifyTimes() { - let times = timesConfigUSDTieredSTO(); - let modifyTimesAction = currentSTO.methods.modifyTimes(times.startTime, times.endTime); - await common.sendTransaction(Issuer, modifyTimesAction, defaultGasPrice); -} - -async function modfifyLimits() { - let limits = limitsConfigUSDTieredSTO(); - let modifyLimitsAction = currentSTO.methods.modifyLimits(limits.nonAccreditedLimitUSD, limits.minimumInvestmentUSD); - await common.sendTransaction(Issuer, modifyLimitsAction, defaultGasPrice); -} - -async function modfifyFunding() { - let funding = fundingConfigUSDTieredSTO(); - let modifyFundingAction = currentSTO.methods.modifyFunding(funding.raiseType); - await common.sendTransaction(Issuer, modifyFundingAction, defaultGasPrice); -} - -async function modfifyAddresses() { - let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.DAI).call()); - let modifyAddressesAction = currentSTO.methods.modifyAddresses(addresses.wallet, addresses.reserveWallet, addresses.usdToken); - await common.sendTransaction(Issuer, modifyAddressesAction, defaultGasPrice); -} - -async function modfifyTiers() { - let tiers = tiersConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.POLY).call()); - let modifyTiersAction = currentSTO.methods.modifyTiers( - tiers.ratePerTier, - tiers.ratePerTierDiscountPoly, - tiers.tokensPerTier, - tiers.tokensPerTierDiscountPoly, - ); - await common.sendTransaction(Issuer, modifyTiersAction, defaultGasPrice); + await approvePoly(securityTokenRegistryAddress, launchFee); + let generateSecurityTokenAction = securityTokenRegistry.methods.generateSecurityToken(tokenName, tokenSymbol, tokenDetails, divisibility); + let receipt = await common.sendTransaction(Issuer, generateSecurityTokenAction, defaultGasPrice); + let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'NewSecurityToken'); + console.log(chalk.green(`Security Token has been successfully deployed at address ${event._securityTokenAddress}`)); } ////////////////////// // HELPER FUNCTIONS // ////////////////////// -async function getBalance(from, type) { - switch (type) { - case 'ETH': - return await web3.eth.getBalance(from); - case 'POLY': - return await polyToken.methods.balanceOf(from).call(); - case 'DAI': - return await usdToken.methods.balanceOf(from).call(); - } -} - -async function currentBalance(from) { - let balance = await polyToken.methods.balanceOf(from).call(); - let balanceInPoly = new BigNumber(balance).dividedBy(new BigNumber(10).pow(18)); - return balanceInPoly; -} - -async function selectTicker(includeCreate) { +async function selectTicker() { let result; - let userTickers = (await securityTokenRegistry.methods.getTickersByOwner(Issuer.address).call()).map(function (t) {return web3.utils.hexToAscii(t)}); + let userTickers = (await securityTokenRegistry.methods.getTickersByOwner(Issuer.address).call()).map(t => web3.utils.hexToAscii(t)); let options = await Promise.all(userTickers.map(async function (t) { let tickerDetails = await securityTokenRegistry.methods.getTickerDetails(t).call(); - let tickerInfo = tickerDetails[4] ? 'Token launched' : `Expires at: ${moment.unix(tickerDetails[2]).format('MMMM Do YYYY, HH:mm:ss')}`; + let tickerInfo; + if (tickerDetails[4]) { + tickerInfo = `Token launched at ${(await securityTokenRegistry.methods.getSecurityTokenAddress(t).call())}`; + } else { + tickerInfo = `Expires at ${moment.unix(tickerDetails[2]).format('MMMM Do YYYY, HH:mm:ss')}`; + } return `${t} ${tickerInfo}`; })); - if (includeCreate) { - options.push('Register a new ticker'); - } + options.push('Register a new ticker'); let index = readlineSync.keyInSelect(options, 'Select a ticker:'); if (index == -1) { process.exit(0); - } else if (includeCreate && index == options.length - 1) { + } else if (index == options.length - 1) { result = readlineSync.question('Enter a symbol for your new ticker: '); } else { result = userTickers[index]; @@ -1160,7 +205,7 @@ async function approvePoly(spender, fee) { } module.exports = { - executeApp: async function(tokenConfig, mintingConfig, stoConfig, remoteNetwork) { - return executeApp(tokenConfig, mintingConfig, stoConfig, remoteNetwork); + executeApp: async function(ticker, transferOwnership, name, details, divisible, remoteNode) { + return executeApp(ticker, transferOwnership, name, details, divisible, remoteNode); } } diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 98c8d240d..608182dfd 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -17,26 +17,21 @@ const yaml = require('js-yaml'); const fs = require('fs'); program - .version('0.0.1') - .description('CLI for Polymath-core') + .version('1.0.1') + .description('Command Line Interface for Polymath-core') .option('-r, --remote-node ', 'Use Infura to connect to a remote node on selected network'); program .command('st20generator') .alias('st') - .option('-c, --config ', "Uses configuration file to configure ST and STO") + .option('-t, --ticker ', 'Unique token ticker') + .option('-o, --transferOwnership ', `Transfers the ticker's ownership to newOwner account. If newOwner is 'false', this step is skipped`) + .option('-n, --tokenName ', 'Token name') + .option('-d, --details
', 'Off-chain details of the token') + .option('-D, --divisible [div]', 'If token is divisible or not [true]', /^(true|false)/, 'true') .description('Wizard-like script that will guide technical users in the creation and deployment of an ST-20 token') .action(async function(cmd) { - let tokenConfig; - let mintingConfig; - let stoCofig; - if (cmd.config) { - let config = yaml.safeLoad(fs.readFileSync(`${__dirname}/data/${cmd.config}`, 'utf8')); - tokenConfig = config.securityToken; - mintingConfig = config.initialMint; - stoCofig = config.sto; - } - await st20generator.executeApp(tokenConfig, mintingConfig, stoCofig, program.remoteNode); + await st20generator.executeApp(cmd.ticker, cmd.transferOwnership, cmd.tokenName, cmd.details, cmd.divisible, program.remoteNode); }); program From 68bbeadd1b87307f5fb71588e1130f0cddf6f7d5 Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Fri, 26 Oct 2018 10:53:30 -0300 Subject: [PATCH 038/582] first draft --- CLI/commands/ST20Generator.js | 36 ++++++------- CLI/commands/common/common_functions.js | 68 ++++++++++++++++--------- 2 files changed, 61 insertions(+), 43 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index a52499b2f..ccf648c3c 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -122,7 +122,7 @@ async function step_ticker_reg(){ available = true; await approvePoly(securityTokenRegistryAddress, regFee); let registerTickerAction = securityTokenRegistry.methods.registerTicker(Issuer.address, tokenSymbol, ""); - await common.sendTransaction(Issuer, registerTickerAction, defaultGasPrice, 0, 1.5); + await common.sendTransaction(registerTickerAction, {factor: 1.5}); } else if (details[0] == Issuer.address) { available = true; } else { @@ -139,7 +139,7 @@ async function step_ticker_reg(){ limitMessage: "Must be a valid address" }); let transferTickerOwnershipAction = securityTokenRegistry.methods.transferTickerOwnership(newOwner, tokenSymbol); - let receipt = await common.sendTransaction(Issuer, transferTickerOwnershipAction, defaultGasPrice, 0, 1.5); + let receipt = await common.sendTransaction(transferTickerOwnershipAction, {factor: 1.5}); let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'ChangeTickerOwnership'); console.log(chalk.green(`Ownership trasferred successfully. The new owner is ${event._newOwner}`)); process.exit(0); @@ -183,7 +183,7 @@ async function step_token_deploy(){ await approvePoly(securityTokenRegistryAddress, launchFee); let generateSecurityTokenAction = securityTokenRegistry.methods.generateSecurityToken(tokenName, tokenSymbol, tokenDetails, divisibility); - let receipt = await common.sendTransaction(Issuer, generateSecurityTokenAction, defaultGasPrice); + let receipt = await common.sendTransaction(generateSecurityTokenAction, {}); let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'NewSecurityToken'); console.log(`Deployed Token at address: ${event._securityTokenAddress}`); let securityTokenABI = abis.securityToken(); @@ -240,7 +240,7 @@ async function step_Wallet_Issuance(){ let generalTransferManagerABI = abis.generalTransferManager(); let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, generalTransferManagerAddress); let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(mintWallet,Math.floor(Date.now()/1000),Math.floor(Date.now()/1000),Math.floor(Date.now()/1000 + 31536000), canBuyFromSTO); - await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); + await common.sendTransaction(modifyWhitelistAction, {}); // Mint tokens if (typeof _mintingConfig !== 'undefined' && _mintingConfig.hasOwnProperty('singleMint') && _mintingConfig.singleMint.hasOwnProperty('tokenAmount')) { @@ -251,7 +251,7 @@ async function step_Wallet_Issuance(){ if (issuerTokens == "") issuerTokens = '500000'; let mintAction = securityToken.methods.mint(mintWallet, web3.utils.toWei(issuerTokens)); - await common.sendTransaction(Issuer, mintAction, defaultGasPrice); + await common.sendTransaction(mintAction, {}); } } } @@ -352,7 +352,7 @@ async function cappedSTO_launch() { process.exit(0); } else { let transferAction = polyToken.methods.transfer(securityToken._address, new BigNumber(transferAmount)); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice, 0, 2); + let receipt = await common.sendTransaction(transferAction, {factor: 2}); let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) } @@ -440,7 +440,7 @@ async function cappedSTO_launch() { let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.STO, "CappedSTO"); let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); + let receipt = await common.sendTransaction(addModuleAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); @@ -757,7 +757,7 @@ async function usdTieredSTO_launch() { process.exit(0); } else { let transferAction = polyToken.methods.transfer(securityToken._address, transferAmount); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice, 0, 2); + let receipt = await common.sendTransaction(transferAction, {factor: 2}); let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) } @@ -826,7 +826,7 @@ async function usdTieredSTO_launch() { let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.STO, 'USDTieredSTO'); let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); + let receipt = await common.sendTransaction(addModuleAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); @@ -1004,7 +1004,7 @@ async function usdTieredSTO_configure() { if (isVerified == "2") { if (readlineSync.keyInYNStrict()) { let finalizeAction = currentSTO.methods.finalize(); - await common.sendTransaction(Issuer, finalizeAction, defaultGasPrice); + await common.sendTransaction(finalizeAction, {}); } } else { console.log(chalk.red(`Reserve wallet (${reserveWallet}) is not able to receive remaining tokens. Check if this address is whitelisted.`)); @@ -1017,7 +1017,7 @@ async function usdTieredSTO_configure() { let accredited = [isAccredited]; let changeAccreditedAction = currentSTO.methods.changeAccredited(investors, accredited); // 2 GAS? - await common.sendTransaction(Issuer, changeAccreditedAction, defaultGasPrice); + await common.sendTransaction(changeAccreditedAction, {}); break; case 2: shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${network}`); @@ -1029,7 +1029,7 @@ async function usdTieredSTO_configure() { let limits = [web3.utils.toWei(limit)]; let changeNonAccreditedLimitAction = currentSTO.methods.changeNonAccreditedLimit(accounts, limits); // 2 GAS? - await common.sendTransaction(Issuer, changeNonAccreditedLimitAction, defaultGasPrice); + await common.sendTransaction(changeNonAccreditedLimitAction, {}); break; case 4: shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${network}`); @@ -1062,25 +1062,25 @@ async function usdTieredSTO_configure() { async function modfifyTimes() { let times = timesConfigUSDTieredSTO(); let modifyTimesAction = currentSTO.methods.modifyTimes(times.startTime, times.endTime); - await common.sendTransaction(Issuer, modifyTimesAction, defaultGasPrice); + await common.sendTransaction(modifyTimesAction, {}); } async function modfifyLimits() { let limits = limitsConfigUSDTieredSTO(); let modifyLimitsAction = currentSTO.methods.modifyLimits(limits.nonAccreditedLimitUSD, limits.minimumInvestmentUSD); - await common.sendTransaction(Issuer, modifyLimitsAction, defaultGasPrice); + await common.sendTransaction(modifyLimitsAction, {}); } async function modfifyFunding() { let funding = fundingConfigUSDTieredSTO(); let modifyFundingAction = currentSTO.methods.modifyFunding(funding.raiseType); - await common.sendTransaction(Issuer, modifyFundingAction, defaultGasPrice); + await common.sendTransaction(modifyFundingAction, {}); } async function modfifyAddresses() { let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.DAI).call()); let modifyAddressesAction = currentSTO.methods.modifyAddresses(addresses.wallet, addresses.reserveWallet, addresses.usdToken); - await common.sendTransaction(Issuer, modifyAddressesAction, defaultGasPrice); + await common.sendTransaction(modifyAddressesAction, {}); } async function modfifyTiers() { @@ -1091,7 +1091,7 @@ async function modfifyTiers() { tiers.tokensPerTier, tiers.tokensPerTierDiscountPoly, ); - await common.sendTransaction(Issuer, modifyTiersAction, defaultGasPrice); + await common.sendTransaction(modifyTiersAction, {}); } ////////////////////// @@ -1148,7 +1148,7 @@ async function approvePoly(spender, fee) { return true; } else { let approveAction = polyToken.methods.approve(spender, web3.utils.toWei(fee.toString(), "ether")); - await common.sendTransaction(Issuer, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction, {}); } } else { let requiredBalance = parseInt(requiredAmount) - parseInt(polyBalance); diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index af3cdc8fa..4e1bb5d94 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -2,6 +2,7 @@ const chalk = require('chalk'); const Tx = require('ethereumjs-tx'); const permissionsList = require('./permissions_list'); const abis = require('../helpers/contract_abis'); +const global = require('global'); async function connect(abi, address) { contractRegistry = new web3.eth.Contract(abi, address); @@ -25,6 +26,38 @@ async function checkPermission(contractName, functionName, contractRegistry) { } }; +function getFinalOptions(options) { + const defaultOptions = { + from: Issuer, + gasPrice: defaultGasPrice, + value: 0, + factor: 1.2 + } + return Object.assign(defaultOptions, options) +}; + +async function getGas(options, action) { + let block = await web3.eth.getBlock("latest"); + let networkGasLimit = block.gasLimit; + let gas = Math.round(options.factor * (await action.estimateGas({ from: options.from.address, value: options.value}))); + return (gas > networkGasLimit) ? networkGasLimit : gas; +} + +async function checkPermissions(action) { + let contractRegistry = await connect(action._parent.options.jsonInterface, action._parent._address); + //NOTE this is a condition to verify if the transaction comes from a module or not. + if (contractRegistry.methods.hasOwnProperty('factory')) { + let moduleAddress = await contractRegistry.methods.factory().call(); + let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress) + let parentModule = await moduleRegistry.methods.getName().call(); + let result = await checkPermission(web3.utils.hexToUtf8(parentModule), action._method.name, contractRegistry); + if (!result) { + console.log("You haven't the right permissions to execute this method."); + process.exit(0); + } + } +} + module.exports = { convertToDaysRemaining: function (timeRemaining) { var seconds = parseInt(timeRemaining, 10); @@ -71,45 +104,30 @@ module.exports = { @@@@@@@@@@#%####%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ `); }, - sendTransaction: async function (from, action, gasPrice, value, factor) { - let contractRegistry = await connect(action._parent.options.jsonInterface, action._parent._address); - - //NOTE this is a condition to verify if the transaction comes from a module or not. - if (contractRegistry.methods.hasOwnProperty('factory')) { - let moduleAddress = await contractRegistry.methods.factory().call(); - let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress) - let parentModule = await moduleRegistry.methods.getName().call(); - let result = await checkPermission(web3.utils.hexToUtf8(parentModule), action._method.name, contractRegistry); - if (!result) { - console.log("You haven't the right permissions to execute this method."); - process.exit(0); - } - } - - if (typeof factor === 'undefined') factor = 1.2; + //sendTransaction: async function (from, action, gasPrice, value, factor) { + sendTransaction: async function (action, options) { - let block = await web3.eth.getBlock("latest"); - let networkGasLimit = block.gasLimit; + await checkPermissions(action); - let gas = Math.round(factor * (await action.estimateGas({ from: from.address, value: value}))); - if (gas > networkGasLimit) gas = networkGasLimit; + options = getFinalOptions(options); + let gas = await getGas(options, action); console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gas} ----`)); - let nonce = await web3.eth.getTransactionCount(from.address); + let nonce = await web3.eth.getTransactionCount(options.from.address); let abi = action.encodeABI(); let parameter = { - from: from.address, + from: options.from.address, to: action._parent._address, data: abi, gasLimit: gas, - gasPrice: gasPrice, + gasPrice: options.gasPrice, nonce: nonce, - value: web3.utils.toHex(value) + value: web3.utils.toHex(options.value) }; const transaction = new Tx(parameter); - transaction.sign(Buffer.from(from.privateKey.replace('0x', ''), 'hex')); + transaction.sign(Buffer.from(options.from.privateKey.replace('0x', ''), 'hex')); return await web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex')) .on('transactionHash', function(hash){ console.log(` From 6c5a057d5948b9147292a2dfc44f8d8d0a91dbb9 Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Fri, 26 Oct 2018 13:19:51 -0300 Subject: [PATCH 039/582] [WIP] changing all transaction methods calls --- CLI/commands/TickerRollForward.js | 4 ++-- CLI/commands/accredit.js | 2 +- CLI/commands/changeNonAccreditedLimit.js | 2 +- CLI/commands/common/common_functions.js | 4 ++-- CLI/commands/contract_manager.js | 12 +++++------ CLI/commands/dividends_manager.js | 26 ++++++++++++------------ CLI/commands/faucet.js | 4 ++-- CLI/commands/investor_portal.js | 16 +++++++-------- CLI/commands/module_manager.js | 12 +++++------ CLI/commands/multi_mint.js | 2 +- CLI/commands/permission_manager.js | 8 ++++---- CLI/commands/strMigrator.js | 12 +++++------ CLI/commands/transfer.js | 2 +- CLI/commands/transfer_manager.js | 6 +++--- CLI/commands/transfer_ownership.js | 2 +- CLI/commands/whitelist.js | 2 +- 16 files changed, 58 insertions(+), 58 deletions(-) diff --git a/CLI/commands/TickerRollForward.js b/CLI/commands/TickerRollForward.js index 97bd1f519..c3a3a9062 100644 --- a/CLI/commands/TickerRollForward.js +++ b/CLI/commands/TickerRollForward.js @@ -88,7 +88,7 @@ async function registerTickers() { process.exit(0); } else { let approveAction = polyToken.methods.approve(securityTokenRegistryAddress, totalFee); - let receipt = await common.sendTransaction(Issuer, approveAction, defaultGasPrice); + let receipt = await common.sendTransaction(approveAction, {}); totalGas = totalGas.add(receipt.gasUsed); } @@ -115,7 +115,7 @@ async function registerTickers() { if (valid) { try { let registerTickerAction = securityTokenRegistry.methods.registerTicker(owner, ticker_data[i].symbol, ticker_data[i].name); - let receipt = await common.sendTransaction(Issuer, registerTickerAction, defaultGasPrice); + let receipt = await common.sendTransaction(registerTickerAction, {}); registered_tickers.push(ticker_data[i]); console.log(ticker_data[i]); totalGas = totalGas.add(receipt.gasUsed); diff --git a/CLI/commands/accredit.js b/CLI/commands/accredit.js index c4dbd78b6..27d5ec01e 100644 --- a/CLI/commands/accredit.js +++ b/CLI/commands/accredit.js @@ -130,7 +130,7 @@ async function changeAccredited() { } let changeAccreditedAction = usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); - let r = await common.sendTransaction(Issuer, changeAccreditedAction, defaultGasPrice); + let r = await common.sendTransaction(changeAccreditedAction, {}); console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); diff --git a/CLI/commands/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js index b1ececbc7..e6ae47851 100644 --- a/CLI/commands/changeNonAccreditedLimit.js +++ b/CLI/commands/changeNonAccreditedLimit.js @@ -130,7 +130,7 @@ async function changeNonAccreditedLimit() { } let changeNonAccreditedLimitAction = usdTieredSTO.methods.changeNonAccreditedLimit(investorArray, limitArray); - let r = await common.sendTransaction(Issuer, changeNonAccreditedLimitAction, defaultGasPrice); + let r = await common.sendTransaction(changeNonAccreditedLimitAction, {}); console.log(`Batch ${i} - Attempting to change non accredited limits to accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString()), "Ether"); diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index 4e1bb5d94..bb9d7c3fc 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -30,7 +30,7 @@ function getFinalOptions(options) { const defaultOptions = { from: Issuer, gasPrice: defaultGasPrice, - value: 0, + value: undefined, factor: 1.2 } return Object.assign(defaultOptions, options) @@ -138,7 +138,7 @@ module.exports = { .on('receipt', function(receipt){ console.log(` Congratulations! The transaction was successfully completed. - Gas used: ${receipt.gasUsed} - Gas spent: ${web3.utils.fromWei((new web3.utils.BN(gasPrice)).mul(new web3.utils.BN(receipt.gasUsed)))} Ether + Gas used: ${receipt.gasUsed} - Gas spent: ${web3.utils.fromWei((new web3.utils.BN(options.gasPrice)).mul(new web3.utils.BN(receipt.gasUsed)))} Ether Review it on Etherscan. TxHash: ${receipt.transactionHash}\n` ); diff --git a/CLI/commands/contract_manager.js b/CLI/commands/contract_manager.js index bea83ce7d..9853d6931 100644 --- a/CLI/commands/contract_manager.js +++ b/CLI/commands/contract_manager.js @@ -108,7 +108,7 @@ async function strActions() { let tickerExpiryDate = readlineSync.question(`Enter the Unix Epoch time on wich the ticker will expire: `); let tickerStatus = readlineSync.keyInYNStrict(`Is the token deployed?`); let modifyTickerAction = currentContract.methods.modifyTicker(tickerOwner, tickerToModify, tickerSTName, tickerRegistrationDate, tickerExpiryDate, tickerStatus); - await common.sendTransaction(Issuer, modifyTickerAction, defaultGasPrice, 0, 1.5); + await common.sendTransaction(modifyTickerAction, {factor: 1.5}); console.log(chalk.green(`Ticker has been updated successfully`)); break; case 'Remove Ticker': @@ -118,7 +118,7 @@ async function strActions() { console.log(chalk.yellow(`${ticker} does not exist.`)); } else { let removeTickerAction = currentContract.methods.removeTicker(tickerToRemove); - await common.sendTransaction(Issuer, removeTickerAction, defaultGasPrice, 0, 3); + await common.sendTransaction(removeTickerAction, {factor: 3}); console.log(chalk.green(`Ticker has been removed successfully`)); } break; @@ -159,7 +159,7 @@ async function strActions() { let tokenDetails = readlineSync.question(`Enter the token details: `); let deployedAt = readlineSync.questionInt(`Enter the Unix Epoch timestamp at which security token was deployed: `); let modifySTAction = currentContract.methods.modifySecurityToken(name, ticker, owner, stAddress, tokenDetails, deployedAt); - await common.sendTransaction(Issuer, modifySTAction, defaultGasPrice, 0, 1.5); + await common.sendTransaction(modifySTAction, {factor: 1.5}); console.log(chalk.green(`Security Token has been updated successfully`)); break; case 'Change Expiry Limit': @@ -167,7 +167,7 @@ async function strActions() { console.log(chalk.yellow(`Current expiry limit is ${Math.floor(parseInt(currentExpiryLimit)/60/60/24)} days`)); let newExpiryLimit = duration.days(readlineSync.questionInt('Enter a new value in days for expiry limit: ')); let changeExpiryLimitAction = currentContract.methods.changeExpiryLimit(newExpiryLimit); - let changeExpiryLimitReceipt = await common.sendTransaction(Issuer, changeExpiryLimitAction, defaultGasPrice); + let changeExpiryLimitReceipt = await common.sendTransaction(changeExpiryLimitAction, {}); let changeExpiryLimitEvent = common.getEventFromLogs(currentContract._jsonInterface, changeExpiryLimitReceipt.logs, 'ChangeExpiryLimit'); console.log(chalk.green(`Expiry limit was changed successfully. New limit is ${Math.floor(parseInt(changeExpiryLimitEvent._newExpiry)/60/60/24)} days\n`)); break; @@ -176,7 +176,7 @@ async function strActions() { console.log(chalk.yellow(`\nCurrent ticker registration fee is ${currentRegFee} POLY`)); let newRegFee = web3.utils.toWei(readlineSync.questionInt('Enter a new value in POLY for ticker registration fee: ').toString()); let changeRegFeeAction = currentContract.methods.changeTickerRegistrationFee(newRegFee); - let changeRegFeeReceipt = await common.sendTransaction(Issuer, changeRegFeeAction, defaultGasPrice); + let changeRegFeeReceipt = await common.sendTransaction(changeRegFeeAction, {}); let changeRegFeeEvent = common.getEventFromLogs(currentContract._jsonInterface, changeRegFeeReceipt.logs, 'ChangeTickerRegistrationFee'); console.log(chalk.green(`Fee was changed successfully. New fee is ${web3.utils.fromWei(changeRegFeeEvent._newFee)} POLY\n`)); break; @@ -185,7 +185,7 @@ async function strActions() { console.log(chalk.yellow(`\nCurrent ST launch fee is ${currentLaunchFee} POLY`)); let newLaunchFee = web3.utils.toWei(readlineSync.questionInt('Enter a new value in POLY for ST launch fee: ').toString()); let changeLaunchFeeAction = currentContract.methods.changeSecurityLaunchFee(newLaunchFee); - let changeLaunchFeeReceipt = await common.sendTransaction(Issuer, changeLaunchFeeAction, defaultGasPrice); + let changeLaunchFeeReceipt = await common.sendTransaction(changeLaunchFeeAction, {}); let changeLaunchFeeEvent = common.getEventFromLogs(currentContract._jsonInterface, changeLaunchFeeReceipt.logs, 'ChangeSecurityLaunchFee'); console.log(chalk.green(`Fee was changed successfully. New fee is ${web3.utils.fromWei(changeLaunchFeeEvent._newFee)} POLY\n`)); break; diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index bde3aa900..917819500 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -129,7 +129,7 @@ async function start_explorer(){ break; case 'Create checkpoint': let createCheckpointAction = securityToken.methods.createCheckpoint(); - await common.sendTransaction(Issuer, createCheckpointAction, defaultGasPrice); + await common.sendTransaction(createCheckpointAction, {}); break; case 'Set default exclusions for dividends': await setDefaultExclusions(); @@ -199,7 +199,7 @@ async function mintTokens(address, amount){ try { let mintAction = securityToken.methods.mint(address,web3.utils.toWei(amount)); - let receipt = await common.sendTransaction(Issuer, mintAction, defaultGasPrice); + let receipt = await common.sendTransaction(mintAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` Minted ${web3.utils.fromWei(event.value)} tokens @@ -217,7 +217,7 @@ async function transferTokens(address, amount){ try{ let transferAction = securityToken.methods.transfer(address,web3.utils.toWei(amount)); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice, 0, 1.5); + let receipt = await common.sendTransaction(transferAction, {factor: 1.5}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` Account ${event.from} @@ -260,7 +260,7 @@ async function setDefaultExclusions() { if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { let excluded = getExcludedFromDataFile(); let setDefaultExclusionsActions = currentDividendsModule.methods.setDefaultExcluded(excluded); - let receipt = await common.sendTransaction(Issuer, setDefaultExclusionsActions, defaultGasPrice); + let receipt = await common.sendTransaction(setDefaultExclusionsActions, {}); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'SetDefaultExcludedAddresses'); console.log(chalk.green(`Exclusions were successfully set.`)); showExcluded(event._excluded); @@ -290,14 +290,14 @@ async function taxHoldingMenu() { }); let percentageWei = web3.utils.toWei((percentage / 100).toString()); let setWithHoldingFixedAction = currentDividendsModule.methods.setWithholdingFixed([address], percentageWei); - let receipt = await common.sendTransaction(Issuer, setWithHoldingFixedAction, defaultGasPrice); + let receipt = await common.sendTransaction(setWithHoldingFixedAction, {}); console.log(chalk.green(`Successfully set tax withholding of ${percentage}% for ${address}.`)); break; case 'Withdraw withholding for dividend': let _dividend = await selectDividend({withRemainingWithheld: true}); if (_dividend !== null) { let withdrawWithholdingAction = currentDividendsModule.methods.withdrawWithholding(_dividend.index); - let receipt = await common.sendTransaction(Issuer, withdrawWithholdingAction, defaultGasPrice); + let receipt = await common.sendTransaction(withdrawWithholdingAction, {}); let eventName; if (dividendsType == 'POLY') { eventName = 'ERC20DividendWithholdingWithdrawn'; @@ -326,7 +326,7 @@ async function createDividends(name, dividend, checkpointId) { let createDividendAction; if (dividendsType == 'POLY') { let approveAction = polyToken.methods.approve(currentDividendsModule._address, web3.utils.toWei(dividend)); - await common.sendTransaction(Issuer, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction, {}); if (checkpointId > 0) { if (useDefaultExcluded) { createDividendAction = currentDividendsModule.methods.createDividendWithCheckpoint(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), checkpointId, web3.utils.toHex(name)); @@ -342,7 +342,7 @@ async function createDividends(name, dividend, checkpointId) { createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), excluded, web3.utils.toHex(name)); } } - let receipt = await common.sendTransaction(Issuer, createDividendAction, defaultGasPrice); + let receipt = await common.sendTransaction(createDividendAction, {}); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'ERC20DividendDeposited'); console.log(chalk.green(`Dividend ${event._dividendIndex} deposited`)); } else if (dividendsType == 'ETH') { @@ -361,7 +361,7 @@ async function createDividends(name, dividend, checkpointId) { createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, excluded, web3.utils.toHex(name)); } } - let receipt = await common.sendTransaction(Issuer, createDividendAction, defaultGasPrice, web3.utils.toWei(dividend)); + let receipt = await common.sendTransaction(createDividendAction, {gasPrice: web3.utils.toWei(dividend)}); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'EtherDividendDeposited'); console.log(` Dividend ${event._dividendIndex} deposited` @@ -372,7 +372,7 @@ async function createDividends(name, dividend, checkpointId) { async function pushDividends(dividend, account){ let accs = account.split(','); let pushDividendPaymentToAddressesAction = currentDividendsModule.methods.pushDividendPaymentToAddresses(dividend.index, accs); - let receipt = await common.sendTransaction(Issuer, pushDividendPaymentToAddressesAction, defaultGasPrice); + let receipt = await common.sendTransaction(pushDividendPaymentToAddressesAction, {}); let successEventName; if (dividendsType == 'POLY') { successEventName = 'ERC20DividendClaimed'; @@ -400,7 +400,7 @@ async function pushDividends(dividend, account){ async function reclaimedDividend(dividend) { let reclaimDividendAction = currentDividendsModule.methods.reclaimDividend(dividend.index); - let receipt = await common.sendTransaction(Issuer, reclaimDividendAction, defaultGasPrice); + let receipt = await common.sendTransaction(reclaimDividendAction, {}); let eventName; if (dividendsType == 'POLY') { eventName = 'ERC20DividendReclaimed'; @@ -417,7 +417,7 @@ async function reclaimedDividend(dividend) { async function whitelistAddress(address) { let now = Math.floor(Date.now() / 1000); let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(address, now, now, now + 31536000, true); - await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); + await common.sendTransaction(modifyWhitelistAction, {}); console.log(chalk.green(`\nWhitelisting successful for ${address}.`)); } @@ -480,7 +480,7 @@ async function addDividendsModule() { let dividendsFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.DIVIDENDS, dividendsFactoryName); let addModuleAction = securityToken.methods.addModule(dividendsFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); + let receipt = await common.sendTransaction(addModuleAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`Module deployed at address: ${event._module}`); currentDividendsModule = new web3.eth.Contract(dividendsModuleABI, event._module); diff --git a/CLI/commands/faucet.js b/CLI/commands/faucet.js index 556ffa402..6b3d8dde4 100644 --- a/CLI/commands/faucet.js +++ b/CLI/commands/faucet.js @@ -79,7 +79,7 @@ async function send_poly(beneficiary, amount) { beneficiary = readlineSync.question(`Enter beneficiary 10K USD Tokens ('${Issuer.address}'): `); if (beneficiary == "") beneficiary = Issuer.address; let getTokensAction = usdToken.methods.getTokens(web3.utils.toWei('10000'), beneficiary); - await common.sendTransaction(Issuer, getTokensAction, defaultGasPrice); + await common.sendTransaction(getTokensAction, {}); let balance = await usdToken.methods.balanceOf(beneficiary).call(); let balanceInPoly = new BigNumber(balance).dividedBy(new BigNumber(10).pow(18)); console.log(chalk.green(`Congratulations! balance of ${beneficiary} address is ${balanceInPoly.toNumber()} USD Tokens`)); @@ -97,7 +97,7 @@ async function send_poly(beneficiary, amount) { async function transferTokens(to, amount) { try { let getTokensAction = polyToken.methods.getTokens(amount, to); - await common.sendTransaction(Issuer, getTokensAction, defaultGasPrice); + await common.sendTransaction(getTokensAction, {}); } catch (err){ console.log(err.message); return; diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 9a5229a7c..5a50bd823 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -427,10 +427,10 @@ async function investCappedSTO(currency, amount) { let allowance = await polyToken.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { let approveAction = polyToken.methods.approve(STOAddress, costWei); - await common.sendTransaction(User, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction, {from: User}); } let actionBuyTokensWithPoly = currentSTO.methods.buyTokensWithPoly(costWei); - let receipt = await common.sendTransaction(User, actionBuyTokensWithPoly, defaultGasPrice); + let receipt = await common.sendTransaction(actionBuyTokensWithPoly, {from: User}); logTokensPurchasedCappedSTO(receipt); } else { console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} POLY but have ${userBalance} POLY.`)); @@ -439,7 +439,7 @@ async function investCappedSTO(currency, amount) { } } else { let actionBuyTokens = currentSTO.methods.buyTokens(User.address); - let receipt = await common.sendTransaction(User, actionBuyTokens, defaultGasPrice, costWei); + let receipt = await common.sendTransaction(actionBuyTokens, {from: User, value: costWei}); logTokensPurchasedCappedSTO(receipt); } await showTokenInfo(); @@ -493,10 +493,10 @@ async function investUsdTieredSTO(currency, amount) { let allowance = await polyToken.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { let approveAction = polyToken.methods.approve(STOAddress, costWei); - await common.sendTransaction(User, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction, {from: User}); } let actionBuyWithPoly = currentSTO.methods.buyWithPOLY(User.address, costWei); - let receipt = await common.sendTransaction(User, actionBuyWithPoly,defaultGasPrice, 0, 2); + let receipt = await common.sendTransaction(actionBuyWithPoly, {from: User, factor: 2}); logTokensPurchasedUSDTieredSTO(receipt); } else { console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} POLY but have ${userBalance} POLY.`)); @@ -509,10 +509,10 @@ async function investUsdTieredSTO(currency, amount) { let allowance = await usdToken.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { let approveAction = usdToken.methods.approve(STOAddress, costWei); - await common.sendTransaction(User, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction, {from: User}); } let actionBuyWithUSD = currentSTO.methods.buyWithUSD(User.address, costWei); - let receipt = await common.sendTransaction(User, actionBuyWithUSD, defaultGasPrice, 0, 1.5); + let receipt = await common.sendTransaction(actionBuyWithUSD, {from: User, factor: 1.5}); logTokensPurchasedUSDTieredSTO(receipt); } else { console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} DAI but have ${userBalance} DAI.`)); @@ -521,7 +521,7 @@ async function investUsdTieredSTO(currency, amount) { } } else { let actionBuyWithETH = currentSTO.methods.buyWithETH(User.address); - let receipt = await common.sendTransaction(User, actionBuyWithETH, defaultGasPrice, costWei); + let receipt = await common.sendTransaction(actionBuyWithETH, {from: User, value: costWei}); logTokensPurchasedUSDTieredSTO(receipt); } diff --git a/CLI/commands/module_manager.js b/CLI/commands/module_manager.js index b91541a9c..1dcc61e72 100644 --- a/CLI/commands/module_manager.js +++ b/CLI/commands/module_manager.js @@ -283,7 +283,7 @@ async function archiveModule() { if (index != -1) { console.log("\nSelected: ",options[index]); let archiveModuleAction = securityToken.methods.archiveModule(modules[index].module.address); - await common.sendTransaction(Issuer, archiveModuleAction, defaultGasPrice, 0, 2); + await common.sendTransaction(archiveModuleAction, {factor: 2}); console.log(chalk.green(`\nSuccessfully archived ${modules[index].module.name}.`)); } backToMenu() @@ -315,7 +315,7 @@ async function unarchiveModule() { if (index != -1) { console.log("\nSelected: ",options[index]); let unarchiveModuleAction = securityToken.methods.unarchiveModule(modules[index].module.address); - await common.sendTransaction(Issuer, unarchiveModuleAction, defaultGasPrice, 0, 2); + await common.sendTransaction(unarchiveModuleAction, {factor: 2}); console.log(chalk.green(`\nSuccessfully unarchived ${modules[index].module.name}.`)); } backToMenu() @@ -348,7 +348,7 @@ async function removeModule() { if (index != -1) { console.log("\nSelected: ",options[index]); let removeModuleAction = securityToken.methods.removeModule(modules[index].module.address); - await common.sendTransaction(Issuer, removeModuleAction, defaultGasPrice, 0, 2); + await common.sendTransaction(defaultGasPrice, {factor: 2}); console.log(chalk.green(`\nSuccessfully removed ${modules[index].module.name}.`)); } backToMenu() @@ -368,7 +368,7 @@ async function whitelist() { let investor = readlineSync.question(chalk.yellow(`Enter the address to be whitelisted: `)); let now = await latestTime(); let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(investor, now, now, now + 31556952, true); - await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); + await common.sendTransaction(modifyWhitelistAction, {}); console.log(chalk.green(`\nWhitelisting successful for ${investor}.`)); } catch (e) { console.log(e); @@ -390,7 +390,7 @@ async function mintTokens() { let _amount = readlineSync.question(chalk.yellow(`Enter the amount of tokens to mint: `)); try { let mintAction = securityToken.methods.mint(_investor, web3.utils.toWei(_amount)); - await common.sendTransaction(Issuer, mintAction, defaultGasPrice); + await common.sendTransaction(mintAction, {}); console.log(chalk.green(`\nMinting Successful.`)); } catch (e) { console.log(e); @@ -411,7 +411,7 @@ async function freezeMinting() { if (await featureRegistry.methods.getFeatureStatus('freezeMintingAllowed').call()) { let freezeMintingAction = securityToken.methods.freezeMinting(); - await common.sendTransaction(Issuer, freezeMintingAction, defaultGasPrice); + await common.sendTransaction(freezeMintingAction, {}); console.log(chalk.green(`\nFreeze minting was successful.`)); } else { console.log(chalk.red(`\nFreeze minting is not allowed by Polymath.`)); diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index 0b7c272ca..5ade5c386 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -161,7 +161,7 @@ function readFile() { } } let mintMultiAction = securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); - let r = await common.sendTransaction(Issuer, mintMultiAction, defaultGasPrice); + let r = await common.sendTransaction(mintMultiAction, {}); console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Multi Mint transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index a2165f697..266761046 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -77,7 +77,7 @@ async function addPermissionModule() { if (readlineSync.keyInYNStrict('Do you want to add General Permission Manager Module to your Security Token?')) { let permissionManagerFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.PERMISSION, 'GeneralPermissionManager'); let addModuleAction = securityToken.methods.addModule(permissionManagerFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); + let receipt = await common.sendTransaction(addModuleAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`Module deployed at address: ${event._module}`); generalPermissionManagerAddress = event._module; @@ -119,7 +119,7 @@ async function changePermissionAction(selectedDelegate) { async function deleteDelegate(address) { let deleteDelegateAction = generalPermissionManager.methods.deleteDelegate(address); - await common.sendTransaction(Issuer, deleteDelegateAction, defaultGasPrice, 0, 2); + await common.sendTransaction(deleteDelegateAction, {factor: 2}); } // Helper functions @@ -169,7 +169,7 @@ function isPermissionValid() { async function changePermission(delegate, moduleAddress, permission, isValid) { let changePermissionAction = generalPermissionManager.methods.changePermission(delegate, moduleAddress, web3.utils.asciiToHex(permission), isValid); - let receipt = await common.sendTransaction(Issuer, changePermissionAction, defaultGasPrice, 0, 2); + let receipt = await common.sendTransaction(changePermissionAction, {factor: 2}); common.getEventFromLogs(generalPermissionManager._jsonInterface, receipt.logs, 'ChangePermission'); console.log(`Permission changed succesfully,`); } @@ -210,7 +210,7 @@ async function addNewDelegate() { }); let addPermissionAction = generalPermissionManager.methods.addDelegate(newDelegate, web3.utils.asciiToHex(details)); - let receipt = await common.sendTransaction(Issuer, addPermissionAction, defaultGasPrice); + let receipt = await common.sendTransaction(addPermissionAction, {}); let event = common.getEventFromLogs(generalPermissionManager._jsonInterface, receipt.logs, 'AddDelegate'); console.log(`Delegate added succesfully: ${event._delegate} - ${event._details}`); isNewDelegate = true; diff --git a/CLI/commands/strMigrator.js b/CLI/commands/strMigrator.js index 545455f46..fd50d15eb 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -147,7 +147,7 @@ async function step_register_tickers(tickers, securityTokenRegistry) { console.log(``); try { let modifyTickerAction = securityTokenRegistry.methods.modifyTicker(t.owner, t.ticker, t.name, t.registrationDate, t.expiryDate, false); - let receipt = await common.sendTransaction(Issuer, modifyTickerAction, defaultGasPrice); + let receipt = await common.sendTransaction(modifyTickerAction, {}); totalGas = totalGas.add(new web3.utils.BN(receipt.gasUsed)); succeed.push(t); } catch (error) { @@ -277,7 +277,7 @@ async function step_launch_STs(tokens, securityTokenRegistry) { try { // Deploying 2.0.0 Token let deployTokenAction = STFactory.methods.deployToken(t.name, t.ticker, 18, t.details, Issuer.address, t.divisble, polymathRegistryAddress) - let deployTokenReceipt = await common.sendTransaction(Issuer, deployTokenAction, defaultGasPrice); + let deployTokenReceipt = await common.sendTransaction(deployTokenAction, {}); // Instancing Security Token let newTokenAddress = deployTokenReceipt.logs[deployTokenReceipt.logs.length -1].address; //Last log is the ST creation let newTokenABI = abis.securityToken(); @@ -298,25 +298,25 @@ async function step_launch_STs(tokens, securityTokenRegistry) { new web3.utils.BN(gmtEvent.returnValues._expiryTime), gmtEvent.returnValues._canBuyFromSTO ); - let modifyWhitelistReceipt = await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); + let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction, {}); totalGas = totalGas.add(new web3.utils.BN(modifyWhitelistReceipt.gasUsed)); } // Minting tokens for (const mintedEvent of t.mintedEvents) { let mintAction = newToken.methods.mint(mintedEvent.returnValues.to, new web3.utils.BN(mintedEvent.returnValues.value)); - let mintReceipt = await common.sendTransaction(Issuer, mintAction, defaultGasPrice); + let mintReceipt = await common.sendTransaction(mintAction, {}); totalGas = totalGas.add(new web3.utils.BN(mintReceipt.gasUsed)); } } // Transferring onweship to the original owner let transferOwnershipAction = newToken.methods.transferOwnership(t.owner); - let transferOwnershipReceipt = await common.sendTransaction(Issuer, transferOwnershipAction, defaultGasPrice); + let transferOwnershipReceipt = await common.sendTransaction(transferOwnershipAction, {}); totalGas = totalGas.add(new web3.utils.BN(transferOwnershipReceipt.gasUsed)); // Adding 2.0.0 Security Token to SecurityTokenRegistry let modifySecurityTokenAction = securityTokenRegistry.methods.modifySecurityToken(t.name, t.ticker, t.owner, newTokenAddress, t.details, t.deployedAt); - let modifySecurityTokenReceipt = await common.sendTransaction(Issuer, modifySecurityTokenAction, defaultGasPrice); + let modifySecurityTokenReceipt = await common.sendTransaction(modifySecurityTokenAction, {}); totalGas = totalGas.add(new web3.utils.BN(modifySecurityTokenReceipt.gasUsed)); succeed.push(t); diff --git a/CLI/commands/transfer.js b/CLI/commands/transfer.js index 48fbb79e5..bab524210 100644 --- a/CLI/commands/transfer.js +++ b/CLI/commands/transfer.js @@ -46,7 +46,7 @@ async function transfer() { try{ let transferAction = securityToken.methods.transfer(_transferTo,web3.utils.toWei(_transferAmount,"ether")); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice); + let receipt = await common.sendTransaction(transferAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` Account ${event.from} diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index df06c68f4..952b5dc6d 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -71,7 +71,7 @@ async function start_explorer() { case 'Disable controller': if (readlineSync.keyInYNStrict()) { let disableControllerAction = securityToken.methods.disableController(); - await common.sendTransaction(Issuer, disableControllerAction, defaultGasPrice); + await common.sendTransaction(disableControllerAction, {}); console.log(chalk.green(`Forced transfers have been disabled permanently`)); } break; @@ -84,7 +84,7 @@ async function start_explorer() { defaultInput: Issuer.address }); let setControllerAction = securityToken.methods.setController(controllerAddress); - let setControllerReceipt = await common.sendTransaction(Issuer, setControllerAction, defaultGasPrice); + let setControllerReceipt = await common.sendTransaction(setControllerAction, {}); let setControllerEvent = common.getEventFromLogs(securityToken._jsonInterface, setControllerReceipt.logs, 'SetController'); console.log(chalk.green(`New controller is ${setControllerEvent._newController}`)); break; @@ -114,7 +114,7 @@ async function start_explorer() { let data = readlineSync.question('Enter the data to indicate validation: '); let log = readlineSync.question('Enter the data attached to the transfer by controller to emit in event: '); let forceTransferAction = securityToken.methods.forceTransfer(from, to, web3.utils.toWei(amount), web3.utils.asciiToHex(data), web3.utils.asciiToHex(log)); - let forceTransferReceipt = await common.sendTransaction(Issuer, forceTransferAction, defaultGasPrice, 0, 1.5); + let forceTransferReceipt = await common.sendTransaction(forceTransferAction, {factor: 1.5}); let forceTransferEvent = common.getEventFromLogs(securityToken._jsonInterface, forceTransferReceipt.logs, 'ForceTransfer'); console.log(chalk.green(` ${forceTransferEvent._controller} has successfully forced a transfer of ${web3.utils.fromWei(forceTransferEvent._value)} ${tokenSymbol} from ${forceTransferEvent._from} to ${forceTransferEvent._to} diff --git a/CLI/commands/transfer_ownership.js b/CLI/commands/transfer_ownership.js index 68ca7eb7a..7712ad70f 100644 --- a/CLI/commands/transfer_ownership.js +++ b/CLI/commands/transfer_ownership.js @@ -28,7 +28,7 @@ async function transferOwnership(transferTo) { console.log(chalk.red(`You are not the current owner ot this contract. Current owner is ${currentOwner}.`)); } else { let transferOwnershipAction = contract.methods.transferOwnership(transferTo); - let receipt = await common.sendTransaction(Issuer, transferOwnershipAction, defaultGasPrice); + let receipt = await common.sendTransaction(transferOwnershipAction, {}); let event = common.getEventFromLogs(contract._jsonInterface, receipt.logs, 'OwnershipTransferred'); console.log(chalk.green(`Ownership transferred successfully. New owner is ${event.newOwner}`)); } diff --git a/CLI/commands/whitelist.js b/CLI/commands/whitelist.js index 4750adffa..395fd9d77 100644 --- a/CLI/commands/whitelist.js +++ b/CLI/commands/whitelist.js @@ -167,7 +167,7 @@ async function setInvestors() { //toTimes is ability to buy coins TOwards your account (3rd row in csv, 3rd parameter in modifyWhiteList() ) //expiryTime is time at which KYC of investor get expired (4th row in csv, 4rd parameter in modifyWhiteList() ) let modifyWhitelistMultiAction = generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); - let r = await common.sendTransaction(Issuer, modifyWhitelistMultiAction, defaultGasPrice); + let r = await common.sendTransaction(modifyWhitelistMultiAction, {}); console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Whitelist transaxction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); From 9b3386ecd3b10268df28da3780f02049efeccd56 Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Fri, 26 Oct 2018 13:30:51 -0300 Subject: [PATCH 040/582] [WIP] new ascii logo --- CLI/commands/common/common_functions.js | 53 ++++++++++--------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index bb9d7c3fc..a2e96286b 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -71,40 +71,29 @@ module.exports = { return (days + " days, " + hrs + " Hrs, " + mnts + " Minutes, " + seconds + " Seconds"); }, logAsciiBull: function() { - console.log(` -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(@(&&@@@@@@@@@@@@@@@@@@@@@@@@@@(((@&&&&(/@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#(((((((#%%%#@@@@@@@@@@@@@@@@@@@@%##(((/@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(%(((((((((((#%%%%%@#@@@@@@@@@@@@(&#####@@@@@@@@%& -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&#((((((((((((((##%%%%%%%&&&%%##@%#####%(@@@@@@@#%#& -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(%((((((((((((((((((###%%%%%((#####%%%####@@@@@@@###((@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#(((((((((((((((((((((####%%%#((((######%&%@@(##&###(@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#((((((((((((((((((((((((####%%#(((((((#((((((((((((#(@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(%(((((((((((((((((((((((((((######%(((((((((((((#&(/@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&#(((((((((((((((((((((((((((((((###############(##%%#@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#((((##############(((((((((((((((((###################%@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@(&#((#(##################((((((((((((((((((##%%##############@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@/%#(((((((##%((((##############((((((((((((((((((##%%#############%%@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@((((((((((###%%((((((##########(((((((((((((((((((#%%%############%%%#@@@@@@@@@ -@@@@@@@@@@@@@@@@@@%((((((((((####%%%((((((((#######(((((((((((####(((((@%%############%%%#@@@@@@@@@ -@@@@@@@@@####%%%%%#(((((((((#####%%%%(((((((((((###((((#######(((((((((&@@(&#########%%%%&@@@@@@@@@ -@@@@@@@@&(((#####%###(((((((#####%%%%%((((((((####%%%%%%%%&%@%#((((((((@@@@@@(#(####%%%%%%@@@@@@@@@ -@@@@@@@&(((@@@@@@@####(((((######%%%%%%##&########%%%%%#@@@@###(((((#(@@@@@@@@@@@###%%#@@@@@@@@@@@@ -@@@#%&%(((@@@@@@@@#####(((#######%%%%@@@@@@@@@@@((##@@@@@@@@%###((((/@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@#%%&%#@@@@@@@@@@############%%%%@@@@@@@@@@@@@@@@@@@@(@&&&&#####(#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@#%%%%%#((%%%%%%#@@@@@@@@@@@@@@@@@@@@(####%((((%#(@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@&%%%#((((((%%&@@@@@@@@@@@@@@@@@@@@@@###%%#((@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@%%%%((((((((& @@@@@@@@@@@@@@@@@@@@@@@%%&%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@%%(((((&#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@&((###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@#####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@&####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@&&%##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@&&&%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@%##%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@#%####%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + console.log(` + /######%%, /#( + ##########%%%%%, ,%%%. % + *#############%%%%%##%%%%%%# ## + (################%%%%#####%%%%//###%, + .####################%%%%#########/ + (#########%%############%%%%%%%%%#%%% + ,(%#%%%%%%%%%%%%############%%%%%%%###%%%. + (######%%###%%%%%%%%##############%%%%%####%%%* + /#######%%%%######%%%%##########%###,.%######%%%( + #%%%%%#######%%%%%%###########%%%%%*###### /####%%%# + #. ,%%####%%%%%%%(/#%%%%%%%%( #%#### ,#%/ + *#%( .%%%##%%%%%% .%%%#* + .%%%%#%%%% .%%%###( + %%%#####% (%%. + #%###(, + *#%# + %%# + * + &% + %%%. `); }, - //sendTransaction: async function (from, action, gasPrice, value, factor) { sendTransaction: async function (action, options) { await checkPermissions(action); From 76af0abacc3feb97f26fc19c1c51e7a7f4e40d4a Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Mon, 5 Nov 2018 13:06:45 +0100 Subject: [PATCH 041/582] Changed PolyToken Kovan address --- migrations/2_deploy_contracts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 0994e249e..694fdf03e 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -59,7 +59,7 @@ module.exports = function (deployer, network, accounts) { } else if (network === 'kovan') { web3 = new Web3(new Web3.providers.HttpProvider('https://kovan.infura.io/g5xfoQ0jFSE9S5LwM1Ei')) PolymathAccount = accounts[0] - PolyToken = '0xb06d72a24df50d4e2cac133b320c5e7de3ef94cb' // PolyToken Kovan Faucet Address + PolyToken = '0xb347b9f5b56b431b2cf4e1d90a5995f7519ca792' // PolyToken Kovan Faucet Address POLYOracle = '0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C' // Poly Oracle Kovan Address ETHOracle = '0xCE5551FC9d43E9D2CC255139169FC889352405C8' // ETH Oracle Kovan Address } else if (network === 'mainnet') { From 1f07bff5a723c559fd747bb208ca79bbf24d8c88 Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Mon, 5 Nov 2018 12:14:51 -0300 Subject: [PATCH 042/582] [WIP] Moving constants to a single file --- CLI/commands/ST20Generator.js | 16 ++------ CLI/commands/common/constants.js | 29 ++++++++++++++ CLI/commands/common/global.js | 64 +++++++++++++++--------------- CLI/commands/contract_manager.js | 10 +---- CLI/commands/dividends_manager.js | 20 +--------- CLI/commands/permission_manager.js | 14 ++----- 6 files changed, 72 insertions(+), 81 deletions(-) create mode 100644 CLI/commands/common/constants.js diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index ccf648c3c..a68bfda66 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -16,14 +16,6 @@ let tokenName; let tokenSymbol; let selectedSTO; -const MODULES_TYPES = { - PERMISSION: 1, - TRANSFER: 2, - STO: 3, - DIVIDENDS: 4, - BURN: 5 -} - const cappedSTOFee = 20000; const usdTieredSTOFee = 100000; const tokenDetails = ""; @@ -192,7 +184,7 @@ async function step_token_deploy(){ } async function step_Wallet_Issuance(){ - let result = await securityToken.methods.getModulesByType(MODULES_TYPES.STO).call(); + let result = await securityToken.methods.getModulesByType(global.constants.MODULES_TYPES.STO).call(); if (result.length > 0) { console.log('\x1b[32m%s\x1b[0m',"STO has already been created at address " + result[0] + ". Skipping initial minting"); } else { @@ -271,7 +263,7 @@ async function step_STO_launch() { console.log("\n"); console.log('\x1b[34m%s\x1b[0m',"Token Creation - STO Configuration"); - let result = await securityToken.methods.getModulesByType(MODULES_TYPES.STO).call(); + let result = await securityToken.methods.getModulesByType(global.constants.MODULES_TYPES.STO).call(); if (result.length > 0) { STO_Address = result[0]; let stoModuleData = await securityToken.methods.getModule(STO_Address).call(); @@ -438,7 +430,7 @@ async function cappedSTO_launch() { ] }, [startTime, endTime, web3.utils.toWei(cap), rate, raiseType, wallet]); - let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.STO, "CappedSTO"); + let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.STO, "CappedSTO"); let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); let receipt = await common.sendTransaction(addModuleAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); @@ -824,7 +816,7 @@ async function usdTieredSTO_launch() { addresses.usdToken ]); - let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.STO, 'USDTieredSTO'); + let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.STO, 'USDTieredSTO'); let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); let receipt = await common.sendTransaction(addModuleAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); diff --git a/CLI/commands/common/constants.js b/CLI/commands/common/constants.js new file mode 100644 index 000000000..a62fae3e2 --- /dev/null +++ b/CLI/commands/common/constants.js @@ -0,0 +1,29 @@ +module.exports = Object.freeze({ + MODULES_TYPES: { + PERMISSION: 1, + TRANSFER: 2, + STO: 3, + DIVIDENDS: 4, + BURN: 5 + }, + DURATION: { + seconds: function(val) { + return val + }, + minutes: function(val) { + return val * this.seconds(60) + }, + hours: function(val) { + return val * this.minutes(60) + }, + days: function(val) { + return val * this.hours(24) + }, + weeks: function(val) { + return val * this.days(7) + }, + years: function(val) { + return val * this.days(365) + } + } +}); \ No newline at end of file diff --git a/CLI/commands/common/global.js b/CLI/commands/common/global.js index fb898a708..8121f8c65 100644 --- a/CLI/commands/common/global.js +++ b/CLI/commands/common/global.js @@ -1,39 +1,41 @@ const Web3 = require('web3'); +const constants = require('./constants'); function getGasPrice (networkId) { - let gasPrice; - switch (networkId) { - case 1: //Mainnet - gasPrice = 4000000000; - break; - case 3: //Ropsten - gasPrice = 50000000000; - break; - case 15: //Ganache - gasPrice = 50000000000; - break; - case 42: //Kovan - gasPrice = 50000000000; - break; - default: - throw new Error('Network ID not identified'); - } - - return gasPrice; + let gasPrice; + switch (networkId) { + case 1: //Mainnet + gasPrice = 4000000000; + break; + case 3: //Ropsten + gasPrice = 50000000000; + break; + case 15: //Ganache + gasPrice = 50000000000; + break; + case 42: //Kovan + gasPrice = 50000000000; + break; + default: + throw new Error('Network ID not identified'); + } + return gasPrice; } + module.exports = { - initialize: async function (remoteNetwork) { - if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { - if (typeof remoteNetwork !== 'undefined') { - web3 = new Web3(new Web3.providers.HttpProvider(`https://${remoteNetwork}.infura.io/`)); - let privKey = require('fs').readFileSync('./privKey').toString(); - Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKey); - } else { - web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); - let privKeyLocal = require('fs').readFileSync('./privKeyLocal').toString() - Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKeyLocal); - } - defaultGasPrice = getGasPrice(await web3.eth.net.getId()); + initialize: async function (remoteNetwork) { + if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { + if (typeof remoteNetwork !== 'undefined') { + web3 = new Web3(new Web3.providers.HttpProvider(`https://${remoteNetwork}.infura.io/`)); + let privKey = require('fs').readFileSync('./privKey').toString(); + Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKey); + } else { + web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); + let privKeyLocal = require('fs').readFileSync('./privKeyLocal').toString() + Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKeyLocal); } + defaultGasPrice = getGasPrice(await web3.eth.net.getId()); } + }, + constants }; \ No newline at end of file diff --git a/CLI/commands/contract_manager.js b/CLI/commands/contract_manager.js index 9853d6931..ff381a7fa 100644 --- a/CLI/commands/contract_manager.js +++ b/CLI/commands/contract_manager.js @@ -1,11 +1,3 @@ -const duration = { - seconds: function (val) { return val; }, - minutes: function (val) { return val * this.seconds(60); }, - hours: function (val) { return val * this.minutes(60); }, - days: function (val) { return val * this.hours(24); }, - weeks: function (val) { return val * this.days(7); }, - years: function (val) { return val * this.days(365); }, -}; var readlineSync = require('readline-sync'); var chalk = require('chalk'); var common = require('./common/common_functions'); @@ -165,7 +157,7 @@ async function strActions() { case 'Change Expiry Limit': let currentExpiryLimit = await currentContract.methods.getExpiryLimit().call(); console.log(chalk.yellow(`Current expiry limit is ${Math.floor(parseInt(currentExpiryLimit)/60/60/24)} days`)); - let newExpiryLimit = duration.days(readlineSync.questionInt('Enter a new value in days for expiry limit: ')); + let newExpiryLimit = global.constants.DURATION.days(readlineSync.questionInt('Enter a new value in days for expiry limit: ')); let changeExpiryLimitAction = currentContract.methods.changeExpiryLimit(newExpiryLimit); let changeExpiryLimitReceipt = await common.sendTransaction(changeExpiryLimitAction, {}); let changeExpiryLimitEvent = common.getEventFromLogs(currentContract._jsonInterface, changeExpiryLimitReceipt.logs, 'ChangeExpiryLimit'); diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 917819500..9b1c560ad 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -1,11 +1,3 @@ -const duration = { - seconds: function (val) { return val; }, - minutes: function (val) { return val * this.seconds(60); }, - hours: function (val) { return val * this.minutes(60); }, - days: function (val) { return val * this.hours(24); }, - weeks: function (val) { return val * this.days(7); }, - years: function (val) { return val * this.days(365); }, -}; var readlineSync = require('readline-sync'); var chalk = require('chalk'); var moment = require('moment'); @@ -14,14 +6,6 @@ var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); -const MODULES_TYPES = { - PERMISSION: 1, - TRANSFER: 2, - STO: 3, - DIVIDENDS: 4, - BURN: 5 -} - // App flow let tokenSymbol; let securityToken; @@ -318,7 +302,7 @@ async function createDividends(name, dividend, checkpointId) { let time = Math.floor(Date.now()/1000); let maturityTime = readlineSync.questionInt('Enter the dividend maturity time from which dividend can be paid (Unix Epoch time)\n(Now = ' + time + ' ): ', {defaultInput: time}); - let defaultTime = time + duration.minutes(10); + let defaultTime = time + global.constants.DURATION.minutes(10); let expiryTime = readlineSync.questionInt('Enter the dividend expiry time (Unix Epoch time)\n(10 minutes from now = ' + defaultTime + ' ): ', {defaultInput: defaultTime}); let useDefaultExcluded = readlineSync.keyInYNStrict(`Do you want to use the default excluded addresses for this dividend? If not, data from 'dividendsExclusions_data.csv' will be used instead.`); @@ -478,7 +462,7 @@ async function addDividendsModule() { dividendsModuleABI = abis.etherDividendCheckpoint(); } - let dividendsFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.DIVIDENDS, dividendsFactoryName); + let dividendsFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.DIVIDENDS, dividendsFactoryName); let addModuleAction = securityToken.methods.addModule(dividendsFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); let receipt = await common.sendTransaction(addModuleAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index 266761046..57c3edb45 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -12,14 +12,6 @@ let securityToken; let generalPermissionManager; let isNewDelegate = false; -const MODULES_TYPES = { - PERMISSION: 1, - TRANSFER: 2, - STO: 3, - DIVIDEND: 4, - BURN: 5 -} - async function executeApp(remoteNetwork) { await global.initialize(remoteNetwork); @@ -75,7 +67,7 @@ async function addPermissionModule() { if (result.length == 0) { console.log(chalk.red(`General Permission Manager is not attached.`)); if (readlineSync.keyInYNStrict('Do you want to add General Permission Manager Module to your Security Token?')) { - let permissionManagerFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.PERMISSION, 'GeneralPermissionManager'); + let permissionManagerFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.PERMISSION, 'GeneralPermissionManager'); let addModuleAction = securityToken.methods.addModule(permissionManagerFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); let receipt = await common.sendTransaction(addModuleAction, {}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); @@ -221,8 +213,8 @@ async function getModulesWithPermissions() { let modules = []; let moduleABI = abis.moduleInterface(); - for (const type in MODULES_TYPES) { - let modulesAttached = await securityToken.methods.getModulesByType(MODULES_TYPES[type]).call(); + for (const type in global.constants.MODULES_TYPES) { + let modulesAttached = await securityToken.methods.getModulesByType(global.constants.MODULES_TYPES[type]).call(); for (const m of modulesAttached) { let contractTemp = new web3.eth.Contract(moduleABI, m); let permissions = await contractTemp.methods.getPermissions().call(); From 50eecf31445be03f63ee21316ab1ecb6c36d1dc7 Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Mon, 5 Nov 2018 13:06:32 -0300 Subject: [PATCH 043/582] [WIP] fund raise type --- CLI/commands/ST20Generator.js | 42 +++++++++++++++----------------- CLI/commands/common/constants.js | 5 ++++ CLI/commands/investor_portal.js | 37 ++++++++++++---------------- 3 files changed, 40 insertions(+), 44 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index a68bfda66..58c22ab86 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -19,11 +19,7 @@ let selectedSTO; const cappedSTOFee = 20000; const usdTieredSTOFee = 100000; const tokenDetails = ""; -const FUND_RAISE_TYPES = { - ETH: 0, - POLY: 1, - DAI: 2 -} + //////////////////////// // Artifacts let securityTokenRegistry; @@ -450,14 +446,14 @@ async function cappedSTO_status() { let displayRaiseType; let displayFundsRaised; let displayWalletBalance; - let raiseType = await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.ETH).call(); + let raiseType = await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.ETH).call(); if (raiseType) { displayRaiseType = 'ETH'; - displayFundsRaised = await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES.ETH).call(); + displayFundsRaised = await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES.ETH).call(); displayWalletBalance = web3.utils.fromWei(await web3.eth.getBalance(displayWallet)); } else { displayRaiseType = 'POLY'; - displayFundsRaised = await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES.POLY).call(); + displayFundsRaised = await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES.POLY).call(); displayWalletBalance = await currentBalance(displayWallet); } let displayTokensSold = await currentSTO.methods.totalTokensSold().call(); @@ -517,16 +513,16 @@ function fundingConfigUSDTieredSTO() { funding.raiseType = []; if (selectedFunding.includes('E')) { - funding.raiseType.push(FUND_RAISE_TYPES.ETH); + funding.raiseType.push(global.constants.FUND_RAISE_TYPES.ETH); } if (selectedFunding.includes('P')) { - funding.raiseType.push(FUND_RAISE_TYPES.POLY); + funding.raiseType.push(global.constants.FUND_RAISE_TYPES.POLY); } if (selectedFunding.includes('D')) { - funding.raiseType.push(FUND_RAISE_TYPES.DAI); + funding.raiseType.push(global.constants.FUND_RAISE_TYPES.DAI); } if (funding.raiseType.length == 0) { - funding.raiseType = [FUND_RAISE_TYPES.ETH, FUND_RAISE_TYPES.POLY, FUND_RAISE_TYPES.DAI]; + funding.raiseType = [global.constants.FUND_RAISE_TYPES.ETH, global.constants.FUND_RAISE_TYPES.POLY, global.constants.FUND_RAISE_TYPES.DAI]; } return funding; @@ -756,8 +752,8 @@ async function usdTieredSTO_launch() { } let funding = fundingConfigUSDTieredSTO(); - let addresses = addressesConfigUSDTieredSTO(funding.raiseType.includes(FUND_RAISE_TYPES.DAI)); - let tiers = tiersConfigUSDTieredSTO(funding.raiseType.includes(FUND_RAISE_TYPES.POLY)); + let addresses = addressesConfigUSDTieredSTO(funding.raiseType.includes(global.constants.FUND_RAISE_TYPES.DAI)); + let tiers = tiersConfigUSDTieredSTO(funding.raiseType.includes(global.constants.FUND_RAISE_TYPES.POLY)); let limits = limitsConfigUSDTieredSTO(); let times = timesConfigUSDTieredSTO(); let bytesSTO = web3.eth.abi.encodeFunctionCall( { @@ -843,8 +839,8 @@ async function usdTieredSTO_status() { let tiersLength = await currentSTO.methods.getNumberOfTiers().call();; let raiseTypes = []; - for (const fundType in FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES[fundType]).call()) { + for (const fundType in global.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES[fundType]).call()) { raiseTypes.push(fundType); } } @@ -873,7 +869,7 @@ async function usdTieredSTO_status() { } } - let mintedPerTier = await currentSTO.methods.mintedPerTier(FUND_RAISE_TYPES[type], t).call(); + let mintedPerTier = await currentSTO.methods.mintedPerTier(global.constants.FUND_RAISE_TYPES[type], t).call(); displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; } @@ -898,23 +894,23 @@ async function usdTieredSTO_status() { for (const type of raiseTypes) { let balance = await getBalance(displayWallet, type); let walletBalance = web3.utils.fromWei(balance); - let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(FUND_RAISE_TYPES[type], balance).call()); + let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(global.constants.FUND_RAISE_TYPES[type], balance).call()); displayWalletBalancePerType += ` Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; balance = await getBalance(displayReserveWallet, type); let reserveWalletBalance = web3.utils.fromWei(balance); - let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(FUND_RAISE_TYPES[type], balance).call()); + let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(global.constants.FUND_RAISE_TYPES[type], balance).call()); displayReserveWalletBalancePerType += ` Balance ${type}:\t\t ${reserveWalletBalance} ${type} (${reserveWalletBalanceUSD} USD)`; - let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES[type]).call()); + let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES[type]).call()); displayFundsRaisedPerType += ` ${type}:\t\t\t ${fundsRaised} ${type}`; //Only show sold for if more than one raise type are allowed if (raiseTypes.length > 1) { - let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(FUND_RAISE_TYPES[type]).call()); + let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(global.constants.FUND_RAISE_TYPES[type]).call()); displayTokensSoldPerType += ` Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; } @@ -1070,13 +1066,13 @@ async function modfifyFunding() { } async function modfifyAddresses() { - let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.DAI).call()); + let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.DAI).call()); let modifyAddressesAction = currentSTO.methods.modifyAddresses(addresses.wallet, addresses.reserveWallet, addresses.usdToken); await common.sendTransaction(modifyAddressesAction, {}); } async function modfifyTiers() { - let tiers = tiersConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.POLY).call()); + let tiers = tiersConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.POLY).call()); let modifyTiersAction = currentSTO.methods.modifyTiers( tiers.ratePerTier, tiers.ratePerTierDiscountPoly, diff --git a/CLI/commands/common/constants.js b/CLI/commands/common/constants.js index a62fae3e2..c3e2b796c 100644 --- a/CLI/commands/common/constants.js +++ b/CLI/commands/common/constants.js @@ -25,5 +25,10 @@ module.exports = Object.freeze({ years: function(val) { return val * this.days(365) } + }, + FUND_RAISE_TYPES: { + ETH: 0, + POLY: 1, + DAI: 2 } }); \ No newline at end of file diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 5a50bd823..1bd495b04 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -10,11 +10,6 @@ var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); const STO_KEY = 3; -const FUND_RAISE_TYPES = { - ETH: 0, - POLY: 1, - DAI: 2 -} let securityTokenRegistry; let securityToken; @@ -163,13 +158,13 @@ async function showUserInfo(_user) { console.log(` ******************* User Information ******************** - Address: ${_user}`); - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.POLY)) { + if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.POLY)) { console.log(` - POLY balance:\t ${await polyBalance(_user)}`); } - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.ETH)) { + if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.ETH)) { console.log(` - ETH balance:\t ${web3.utils.fromWei(await web3.eth.getBalance(_user))}`); } - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.DAI)) { + if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.DAI)) { console.log(` - DAI balance:\t ${await usdBalance(_user)}`); } } @@ -185,11 +180,11 @@ async function showCappedSTOInfo() { let displayRaiseType; let displayFundsRaised; - for (const fundType in FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES[fundType]).call()) { + for (const fundType in global.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES[fundType]).call()) { raiseTypes.push(fundType); displayRaiseType = fundType; - displayFundsRaised = await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES[fundType]).call(); + displayFundsRaised = await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES[fundType]).call(); } } @@ -245,9 +240,9 @@ async function showCappedSTOInfo() { async function showUserInfoForUSDTieredSTO() { - for (const fundType in FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES[fundType]).call()) { - let displayInvestorInvested = web3.utils.fromWei(await currentSTO.methods.investorInvested(User.address, FUND_RAISE_TYPES[fundType]).call()); + for (const fundType in global.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES[fundType]).call()) { + let displayInvestorInvested = web3.utils.fromWei(await currentSTO.methods.investorInvested(User.address, global.constants.FUND_RAISE_TYPES[fundType]).call()); console.log(` - Invested in ${fundType}:\t ${displayInvestorInvested} ${fundType}`); } } @@ -287,8 +282,8 @@ async function showUSDTieredSTOInfo() { let displayTokenSymbol = await securityToken.methods.symbol().call(); let tiersLength = await currentSTO.methods.getNumberOfTiers().call(); - for (const fundType in FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES[fundType]).call()) { + for (const fundType in global.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES[fundType]).call()) { raiseTypes.push(fundType); } } @@ -317,7 +312,7 @@ async function showUSDTieredSTOInfo() { } } - let mintedPerTier = await currentSTO.methods.mintedPerTier(FUND_RAISE_TYPES[type], t).call(); + let mintedPerTier = await currentSTO.methods.mintedPerTier(global.constants.FUND_RAISE_TYPES[type], t).call(); displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; } @@ -338,13 +333,13 @@ async function showUSDTieredSTOInfo() { let displayFundsRaisedPerType = ''; let displayTokensSoldPerType = ''; for (const type of raiseTypes) { - let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES[type]).call()); + let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES[type]).call()); displayFundsRaisedPerType += ` ${type}:\t\t\t ${fundsRaised} ${type}`; //Only show sold per raise type is more than one are allowed if (raiseTypes.length > 1) { - let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(FUND_RAISE_TYPES[type]).call()); + let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(global.constants.FUND_RAISE_TYPES[type]).call()); displayTokensSoldPerType += ` Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; } @@ -457,7 +452,7 @@ async function investUsdTieredSTO(currency, amount) { } } else { for (const type of raiseTypes) { - let displayPrice = web3.utils.fromWei(await currentSTO.methods.convertToUSD(FUND_RAISE_TYPES[type], web3.utils.toWei("1")).call()); + let displayPrice = web3.utils.fromWei(await currentSTO.methods.convertToUSD(global.constants.FUND_RAISE_TYPES[type], web3.utils.toWei("1")).call()); console.log(chalk.green(` Current ${type} price:\t\t ${displayPrice} USD`)); } if (raiseTypes.length > 1) { @@ -473,7 +468,7 @@ async function investUsdTieredSTO(currency, amount) { if (typeof amount === 'undefined') { let investorInvestedUSD = web3.utils.fromWei(await currentSTO.methods.investorInvestedUSD(User.address).call()); let minimumInvestmentUSD = await currentSTO.methods.minimumInvestmentUSD().call(); - let minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(FUND_RAISE_TYPES[raiseType], minimumInvestmentUSD).call(); + let minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(global.constants.FUND_RAISE_TYPES[raiseType], minimumInvestmentUSD).call(); cost = readlineSync.question(chalk.yellow(`Enter the amount of ${raiseType} you would like to invest or press 'Enter' to exit: `), { limit: function(input) { return investorInvestedUSD != 0 || parseInt(input) > parseInt(web3.utils.fromWei(minimumInvestmentRaiseType)); From e0dec6f218e46be12dd808062d757848c24d0569 Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Mon, 5 Nov 2018 16:25:59 -0300 Subject: [PATCH 044/582] [WIP] network name --- CLI/commands/ST20Generator.js | 19 ++++++++----------- CLI/commands/common/constants.js | 1 + CLI/commands/common/global.js | 3 ++- CLI/commands/contract_manager.js | 8 ++++---- CLI/commands/dividends_manager.js | 8 ++++---- CLI/commands/faucet.js | 8 ++++---- CLI/commands/investor_portal.js | 8 ++++---- CLI/commands/module_manager.js | 8 ++++---- CLI/commands/permission_manager.js | 8 ++++---- CLI/commands/strMigrator.js | 13 +++++-------- CLI/commands/transfer.js | 8 ++++---- CLI/commands/transfer_manager.js | 8 ++++---- CLI/commands/transfer_ownership.js | 8 ++++---- CLI/polymath-cli.js | 25 ++++++++++++++----------- 14 files changed, 66 insertions(+), 67 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 58c22ab86..2bb196cc5 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -33,15 +33,12 @@ let _tokenConfig; let _mintingConfig; let _stoConfig; -let network; - -async function executeApp(tokenConfig, mintingConfig, stoConfig, remoteNetwork) { +async function executeApp(tokenConfig, mintingConfig, stoConfig) { _tokenConfig = tokenConfig; _mintingConfig = mintingConfig; _stoConfig = stoConfig; - network = remoteNetwork; - await global.initialize(remoteNetwork); + await global.initialize(); common.logAsciiBull(); console.log("********************************************"); @@ -247,11 +244,11 @@ async function step_Wallet_Issuance(){ async function multi_mint_tokens() { //await whitelist.startWhitelisting(tokenSymbol); - shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${network}`); + shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${global.constants.NETWORK}`); console.log(chalk.green(`\nCongrats! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); - shell.exec(`${__dirname}/scripts//script.sh Multimint ${tokenSymbol} 75 ${network}`); + shell.exec(`${__dirname}/scripts//script.sh Multimint ${tokenSymbol} 75 ${global.constants.NETWORK}`); console.log(chalk.green(`\nHurray!! Tokens get successfully Minted and transferred to token holders`)); } @@ -1008,7 +1005,7 @@ async function usdTieredSTO_configure() { await common.sendTransaction(changeAccreditedAction, {}); break; case 2: - shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${network}`); + shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${global.constants.NETWORK}`); break; case 3: let account = readlineSync.question('Enter the address to change non accredited limit: '); @@ -1020,7 +1017,7 @@ async function usdTieredSTO_configure() { await common.sendTransaction(changeNonAccreditedLimitAction, {}); break; case 4: - shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${network}`); + shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${global.constants.NETWORK}`); break; case 5: await modfifyTimes(); @@ -1148,7 +1145,7 @@ async function approvePoly(spender, fee) { } module.exports = { - executeApp: async function(tokenConfig, mintingConfig, stoConfig, remoteNetwork) { - return executeApp(tokenConfig, mintingConfig, stoConfig, remoteNetwork); + executeApp: async function(tokenConfig, mintingConfig, stoConfig) { + return executeApp(tokenConfig, mintingConfig, stoConfig); } } diff --git a/CLI/commands/common/constants.js b/CLI/commands/common/constants.js index c3e2b796c..92050f428 100644 --- a/CLI/commands/common/constants.js +++ b/CLI/commands/common/constants.js @@ -1,4 +1,5 @@ module.exports = Object.freeze({ + NETWORK: undefined, MODULES_TYPES: { PERMISSION: 1, TRANSFER: 2, diff --git a/CLI/commands/common/global.js b/CLI/commands/common/global.js index 8121f8c65..6942b5509 100644 --- a/CLI/commands/common/global.js +++ b/CLI/commands/common/global.js @@ -23,7 +23,8 @@ function getGasPrice (networkId) { } module.exports = { - initialize: async function (remoteNetwork) { + initialize: async function() { + let remoteNetwork = constants.NETWORK; if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { if (typeof remoteNetwork !== 'undefined') { web3 = new Web3(new Web3.providers.HttpProvider(`https://${remoteNetwork}.infura.io/`)); diff --git a/CLI/commands/contract_manager.js b/CLI/commands/contract_manager.js index ff381a7fa..27c6c7569 100644 --- a/CLI/commands/contract_manager.js +++ b/CLI/commands/contract_manager.js @@ -8,8 +8,8 @@ var abis = require('./helpers/contract_abis'); // App flow let currentContract = null; -async function executeApp(remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp() { + await global.initialize(); common.logAsciiBull(); console.log("*********************************************"); @@ -189,7 +189,7 @@ async function strActions() { } module.exports = { - executeApp: async function(remoteNetwork) { - return executeApp(remoteNetwork); + executeApp: async function() { + return executeApp(); } } \ No newline at end of file diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 9b1c560ad..0faad11e0 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -14,9 +14,9 @@ let securityTokenRegistry; let generalTransferManager; let currentDividendsModule; -async function executeApp(type, remoteNetwork) { +async function executeApp(type) { dividendsType = type; - await global.initialize(remoteNetwork); + await global.initialize(); common.logAsciiBull(); console.log("**********************************************"); @@ -583,7 +583,7 @@ function showExcluded(excluded) { } module.exports = { - executeApp: async function(type, remoteNetwork) { - return executeApp(type, remoteNetwork); + executeApp: async function(type) { + return executeApp(type); } } diff --git a/CLI/commands/faucet.js b/CLI/commands/faucet.js index 6b3d8dde4..69c28f2dd 100644 --- a/CLI/commands/faucet.js +++ b/CLI/commands/faucet.js @@ -11,8 +11,8 @@ var chalk = require('chalk'); let polyToken; let usdToken; -async function executeApp(beneficiary, amount, remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp(beneficiary, amount) { + await global.initialize(); console.log("\n"); console.log("***************************") @@ -108,7 +108,7 @@ async function transferTokens(to, amount) { } module.exports = { - executeApp: async function(beneficiary, amount, remoteNetwork) { - return executeApp(beneficiary, amount, remoteNetwork); + executeApp: async function(beneficiary, amount) { + return executeApp(beneficiary, amount); } } \ No newline at end of file diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 1bd495b04..b65348b1a 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -34,8 +34,8 @@ let displayCanBuy; let displayValidKYC; // Start Script -async function executeApp(investorAddress, investorPrivKey, symbol, currency, amount, remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp(investorAddress, investorPrivKey, symbol, currency, amount) { + await global.initialize(); common.logAsciiBull(); console.log("********************************************"); @@ -559,7 +559,7 @@ function logTokensPurchasedCappedSTO(receipt) { } module.exports = { - executeApp: async function(investorAddress, investorPrivKey, symbol, currency, amount, remoteNetwork) { - return executeApp(investorAddress, investorPrivKey, symbol, currency, amount, remoteNetwork); + executeApp: async function(investorAddress, investorPrivKey, symbol, currency, amount) { + return executeApp(investorAddress, investorPrivKey, symbol, currency, amount); } } diff --git a/CLI/commands/module_manager.js b/CLI/commands/module_manager.js index 1dcc61e72..a4c8ba92d 100644 --- a/CLI/commands/module_manager.js +++ b/CLI/commands/module_manager.js @@ -47,8 +47,8 @@ async function setup() { } // Start function -async function executeApp(remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp() { + await global.initialize(); common.logAsciiBull(); console.log(chalk.yellow(`******************************************`)); @@ -441,7 +441,7 @@ async function polyBalance(_user) { } module.exports = { - executeApp: async function(remoteNetwork) { - return executeApp(remoteNetwork); + executeApp: async function() { + return executeApp(); } } diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index 57c3edb45..c53e80b21 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -12,8 +12,8 @@ let securityToken; let generalPermissionManager; let isNewDelegate = false; -async function executeApp(remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp() { + await global.initialize(); common.logAsciiBull(); console.log("***********************************************"); @@ -232,7 +232,7 @@ async function getModulesWithPermissions() { } module.exports = { - executeApp: async function(remoteNetwork) { - return executeApp(remoteNetwork); + executeApp: async function() { + return executeApp(); } } \ No newline at end of file diff --git a/CLI/commands/strMigrator.js b/CLI/commands/strMigrator.js index fd50d15eb..8dbcb6511 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -6,11 +6,8 @@ var contracts = require('./helpers/contract_addresses'); var common = require('./common/common_functions'); var global = require('./common/global'); -let network; - -async function executeApp(toStrAddress, fromTrAddress, fromStrAddress, remoteNetwork) { - network = remoteNetwork; - await global.initialize(remoteNetwork); +async function executeApp(toStrAddress, fromTrAddress, fromStrAddress) { + await global.initialize(); common.logAsciiBull(); console.log("****************************************"); @@ -360,7 +357,7 @@ ${failed.map(ticker => chalk.red(`${ticker.ticker}`)).join('\n')} } async function getABIfromEtherscan(_address) { - let urlDomain = network == 'kovan' ? 'api-kovan' : 'api'; + let urlDomain = global.constants.NETWORK == 'kovan' ? 'api-kovan' : 'api'; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { @@ -377,7 +374,7 @@ async function getABIfromEtherscan(_address) { } module.exports = { - executeApp: async function(toStrAddress, fromTrAddress, fromStrAddress, remoteNetwork) { - return executeApp(toStrAddress, fromTrAddress, fromStrAddress, remoteNetwork); + executeApp: async function(toStrAddress, fromTrAddress, fromStrAddress) { + return executeApp(toStrAddress, fromTrAddress, fromStrAddress); } }; \ No newline at end of file diff --git a/CLI/commands/transfer.js b/CLI/commands/transfer.js index bab524210..ac782a919 100644 --- a/CLI/commands/transfer.js +++ b/CLI/commands/transfer.js @@ -14,12 +14,12 @@ let securityToken; //////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// -async function startScript(tokenSymbol, transferTo, transferAmount, remoteNetwork) { +async function startScript(tokenSymbol, transferTo, transferAmount) { _tokenSymbol = tokenSymbol; _transferTo = transferTo; _transferAmount = transferAmount; - await global.initialize(remoteNetwork); + await global.initialize(); try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); @@ -61,7 +61,7 @@ async function transfer() { }; module.exports = { - executeApp: async function(tokenSymbol, transferTo, transferAmount, remoteNetwork) { - return startScript(tokenSymbol, transferTo, transferAmount, remoteNetwork); + executeApp: async function(tokenSymbol, transferTo, transferAmount) { + return startScript(tokenSymbol, transferTo, transferAmount); } } diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 952b5dc6d..0853254cd 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -11,8 +11,8 @@ let tokenSymbol; let securityToken; let securityTokenRegistry; -async function executeApp(remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp() { + await global.initialize(); common.logAsciiBull(); console.log("*********************************************"); @@ -138,7 +138,7 @@ async function start_explorer() { } module.exports = { - executeApp: async function(type, remoteNetwork) { - return executeApp(type, remoteNetwork); + executeApp: async function(type) { + return executeApp(type); } } \ No newline at end of file diff --git a/CLI/commands/transfer_ownership.js b/CLI/commands/transfer_ownership.js index 7712ad70f..0f5e634b4 100644 --- a/CLI/commands/transfer_ownership.js +++ b/CLI/commands/transfer_ownership.js @@ -8,8 +8,8 @@ var abis = require('./helpers/contract_abis') let contract; //////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// -async function startScript(contractAddress, transferTo, remoteNetwork) { - await global.initialize(remoteNetwork); +async function startScript(contractAddress, transferTo) { + await global.initialize(); if (!web3.utils.isAddress(contractAddress) || !web3.utils.isAddress(transferTo)) { console.log(chlak.red(`Please enter valid addresses`)); @@ -35,7 +35,7 @@ async function transferOwnership(transferTo) { }; module.exports = { - executeApp: async function(contractAddress, transferTo, remoteNetwork) { - return startScript(contractAddress, transferTo, remoteNetwork); + executeApp: async function(contractAddress, transferTo) { + return startScript(contractAddress, transferTo); } } diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 49f578df0..40b32cae6 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -13,6 +13,7 @@ var contract_manager = require('./commands/contract_manager'); var strMigrator = require('./commands/strMigrator'); var permission_manager = require('./commands/permission_manager'); var program = require('commander'); +var global = require('./commands/common/global'); const yaml = require('js-yaml'); const fs = require('fs'); @@ -36,7 +37,7 @@ program mintingConfig = config.initialMint; stoCofig = config.sto; } - await st20generator.executeApp(tokenConfig, mintingConfig, stoCofig, program.remoteNode); + await st20generator.executeApp(tokenConfig, mintingConfig, stoCofig); }); program @@ -44,7 +45,7 @@ program .alias('f') .description('Poly faucet for local private netwtorks') .action(async function(beneficiary, amount) { - await faucet.executeApp(beneficiary, amount, program.remoteNode); + await faucet.executeApp(beneficiary, amount); }); program @@ -52,7 +53,7 @@ program .alias('i') .description('Participate in any STO you have been whitelisted for') .action(async function(investor, privateKey, symbol, currency, amount) { - await investor_portal.executeApp(investor, privateKey, symbol, currency, amount, program.remoteNode); + await investor_portal.executeApp(investor, privateKey, symbol, currency, amount); }); program @@ -60,7 +61,7 @@ program .alias('mm') .description('View modules attached to a token and their status') .action(async function() { - await module_manager.executeApp(program.remoteNode); + await module_manager.executeApp(); }); program @@ -76,7 +77,7 @@ program .alias('t') .description('Transfer ST tokens to another account') .action(async function(tokenSymbol, transferTo, transferAmount) { - await transfer.executeApp(tokenSymbol, transferTo, transferAmount, program.remoteNode); + await transfer.executeApp(tokenSymbol, transferTo, transferAmount); }); program @@ -84,7 +85,7 @@ program .alias('to') .description('Transfer Ownership of an own contract to another account') .action(async function(contractAddress, transferTo) { - await transfer_ownership.executeApp(contractAddress, transferTo, program.remoteNode); + await transfer_ownership.executeApp(contractAddress, transferTo); }); program @@ -100,7 +101,7 @@ program .alias('dm') .description('Runs dividends_manager') .action(async function(dividendsType) { - await dividends_manager.executeApp(dividendsType, program.remoteNode); + await dividends_manager.executeApp(dividendsType); }); program @@ -108,7 +109,7 @@ program .alias('tm') .description('Runs transfer_manager') .action(async function() { - await transfer_manager.executeApp(program.remoteNode); + await transfer_manager.executeApp(); }); program @@ -116,7 +117,7 @@ program .alias('cm') .description('Runs contract_manager') .action(async function() { - await contract_manager.executeApp(program.remoteNode); + await contract_manager.executeApp(); }); program @@ -140,7 +141,7 @@ program .alias('str') .description('Runs STR Migrator') .action(async function(toStrAddress, fromTrAddress, fromStrAddress) { - await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress, program.remoteNode); + await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress); }); program @@ -148,7 +149,7 @@ program .alias('pm') .description('Runs permission_manager') .action(async function() { - await permission_manager.executeApp(program.remoteNode); + await permission_manager.executeApp(); }); program.parse(process.argv); @@ -156,4 +157,6 @@ program.parse(process.argv); if (typeof program.commands.length == 0) { console.error('No command given!'); process.exit(1); +} else { + global.constants.NETWORK = program.remoteNode } \ No newline at end of file From a8da518d6d4579348d7810b4180e27100f732e0f Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Tue, 6 Nov 2018 11:05:03 -0300 Subject: [PATCH 045/582] minor fixes --- CLI/commands/ST20Generator.js | 28 ++++++++++++------------ CLI/commands/TickerRollForward.js | 4 ++-- CLI/commands/accredit.js | 2 +- CLI/commands/changeNonAccreditedLimit.js | 2 +- CLI/commands/common/common_functions.js | 12 +++++----- CLI/commands/contract_manager.js | 6 ++--- CLI/commands/dividends_manager.js | 22 +++++++++---------- CLI/commands/faucet.js | 4 ++-- CLI/commands/module_manager.js | 6 ++--- CLI/commands/multi_mint.js | 2 +- CLI/commands/permission_manager.js | 4 ++-- CLI/commands/strMigrator.js | 12 +++++----- CLI/commands/transfer.js | 2 +- CLI/commands/transfer_manager.js | 4 ++-- CLI/commands/transfer_ownership.js | 2 +- CLI/commands/whitelist.js | 2 +- 16 files changed, 58 insertions(+), 56 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 2bb196cc5..591b0dae5 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -168,7 +168,7 @@ async function step_token_deploy(){ await approvePoly(securityTokenRegistryAddress, launchFee); let generateSecurityTokenAction = securityTokenRegistry.methods.generateSecurityToken(tokenName, tokenSymbol, tokenDetails, divisibility); - let receipt = await common.sendTransaction(generateSecurityTokenAction, {}); + let receipt = await common.sendTransaction(generateSecurityTokenAction); let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'NewSecurityToken'); console.log(`Deployed Token at address: ${event._securityTokenAddress}`); let securityTokenABI = abis.securityToken(); @@ -225,7 +225,7 @@ async function step_Wallet_Issuance(){ let generalTransferManagerABI = abis.generalTransferManager(); let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, generalTransferManagerAddress); let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(mintWallet,Math.floor(Date.now()/1000),Math.floor(Date.now()/1000),Math.floor(Date.now()/1000 + 31536000), canBuyFromSTO); - await common.sendTransaction(modifyWhitelistAction, {}); + await common.sendTransaction(modifyWhitelistAction); // Mint tokens if (typeof _mintingConfig !== 'undefined' && _mintingConfig.hasOwnProperty('singleMint') && _mintingConfig.singleMint.hasOwnProperty('tokenAmount')) { @@ -236,7 +236,7 @@ async function step_Wallet_Issuance(){ if (issuerTokens == "") issuerTokens = '500000'; let mintAction = securityToken.methods.mint(mintWallet, web3.utils.toWei(issuerTokens)); - await common.sendTransaction(mintAction, {}); + await common.sendTransaction(mintAction); } } } @@ -425,7 +425,7 @@ async function cappedSTO_launch() { let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.STO, "CappedSTO"); let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); - let receipt = await common.sendTransaction(addModuleAction, {}); + let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); @@ -811,7 +811,7 @@ async function usdTieredSTO_launch() { let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.STO, 'USDTieredSTO'); let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); - let receipt = await common.sendTransaction(addModuleAction, {}); + let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); @@ -989,7 +989,7 @@ async function usdTieredSTO_configure() { if (isVerified == "2") { if (readlineSync.keyInYNStrict()) { let finalizeAction = currentSTO.methods.finalize(); - await common.sendTransaction(finalizeAction, {}); + await common.sendTransaction(finalizeAction); } } else { console.log(chalk.red(`Reserve wallet (${reserveWallet}) is not able to receive remaining tokens. Check if this address is whitelisted.`)); @@ -1002,7 +1002,7 @@ async function usdTieredSTO_configure() { let accredited = [isAccredited]; let changeAccreditedAction = currentSTO.methods.changeAccredited(investors, accredited); // 2 GAS? - await common.sendTransaction(changeAccreditedAction, {}); + await common.sendTransaction(changeAccreditedAction); break; case 2: shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${global.constants.NETWORK}`); @@ -1014,7 +1014,7 @@ async function usdTieredSTO_configure() { let limits = [web3.utils.toWei(limit)]; let changeNonAccreditedLimitAction = currentSTO.methods.changeNonAccreditedLimit(accounts, limits); // 2 GAS? - await common.sendTransaction(changeNonAccreditedLimitAction, {}); + await common.sendTransaction(changeNonAccreditedLimitAction); break; case 4: shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${global.constants.NETWORK}`); @@ -1047,25 +1047,25 @@ async function usdTieredSTO_configure() { async function modfifyTimes() { let times = timesConfigUSDTieredSTO(); let modifyTimesAction = currentSTO.methods.modifyTimes(times.startTime, times.endTime); - await common.sendTransaction(modifyTimesAction, {}); + await common.sendTransaction(modifyTimesAction); } async function modfifyLimits() { let limits = limitsConfigUSDTieredSTO(); let modifyLimitsAction = currentSTO.methods.modifyLimits(limits.nonAccreditedLimitUSD, limits.minimumInvestmentUSD); - await common.sendTransaction(modifyLimitsAction, {}); + await common.sendTransaction(modifyLimitsAction); } async function modfifyFunding() { let funding = fundingConfigUSDTieredSTO(); let modifyFundingAction = currentSTO.methods.modifyFunding(funding.raiseType); - await common.sendTransaction(modifyFundingAction, {}); + await common.sendTransaction(modifyFundingAction); } async function modfifyAddresses() { let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.DAI).call()); let modifyAddressesAction = currentSTO.methods.modifyAddresses(addresses.wallet, addresses.reserveWallet, addresses.usdToken); - await common.sendTransaction(modifyAddressesAction, {}); + await common.sendTransaction(modifyAddressesAction); } async function modfifyTiers() { @@ -1076,7 +1076,7 @@ async function modfifyTiers() { tiers.tokensPerTier, tiers.tokensPerTierDiscountPoly, ); - await common.sendTransaction(modifyTiersAction, {}); + await common.sendTransaction(modifyTiersAction); } ////////////////////// @@ -1133,7 +1133,7 @@ async function approvePoly(spender, fee) { return true; } else { let approveAction = polyToken.methods.approve(spender, web3.utils.toWei(fee.toString(), "ether")); - await common.sendTransaction(approveAction, {}); + await common.sendTransaction(approveAction); } } else { let requiredBalance = parseInt(requiredAmount) - parseInt(polyBalance); diff --git a/CLI/commands/TickerRollForward.js b/CLI/commands/TickerRollForward.js index c3a3a9062..0c8db13ca 100644 --- a/CLI/commands/TickerRollForward.js +++ b/CLI/commands/TickerRollForward.js @@ -88,7 +88,7 @@ async function registerTickers() { process.exit(0); } else { let approveAction = polyToken.methods.approve(securityTokenRegistryAddress, totalFee); - let receipt = await common.sendTransaction(approveAction, {}); + let receipt = await common.sendTransaction(approveAction); totalGas = totalGas.add(receipt.gasUsed); } @@ -115,7 +115,7 @@ async function registerTickers() { if (valid) { try { let registerTickerAction = securityTokenRegistry.methods.registerTicker(owner, ticker_data[i].symbol, ticker_data[i].name); - let receipt = await common.sendTransaction(registerTickerAction, {}); + let receipt = await common.sendTransaction(registerTickerAction); registered_tickers.push(ticker_data[i]); console.log(ticker_data[i]); totalGas = totalGas.add(receipt.gasUsed); diff --git a/CLI/commands/accredit.js b/CLI/commands/accredit.js index 27d5ec01e..d9a860f28 100644 --- a/CLI/commands/accredit.js +++ b/CLI/commands/accredit.js @@ -130,7 +130,7 @@ async function changeAccredited() { } let changeAccreditedAction = usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); - let r = await common.sendTransaction(changeAccreditedAction, {}); + let r = await common.sendTransaction(changeAccreditedAction); console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); diff --git a/CLI/commands/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js index e6ae47851..9e1aa59bf 100644 --- a/CLI/commands/changeNonAccreditedLimit.js +++ b/CLI/commands/changeNonAccreditedLimit.js @@ -130,7 +130,7 @@ async function changeNonAccreditedLimit() { } let changeNonAccreditedLimitAction = usdTieredSTO.methods.changeNonAccreditedLimit(investorArray, limitArray); - let r = await common.sendTransaction(changeNonAccreditedLimitAction, {}); + let r = await common.sendTransaction(changeNonAccreditedLimitAction); console.log(`Batch ${i} - Attempting to change non accredited limits to accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString()), "Ether"); diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index a2e96286b..123e158cb 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -2,7 +2,6 @@ const chalk = require('chalk'); const Tx = require('ethereumjs-tx'); const permissionsList = require('./permissions_list'); const abis = require('../helpers/contract_abis'); -const global = require('global'); async function connect(abi, address) { contractRegistry = new web3.eth.Contract(abi, address); @@ -27,6 +26,9 @@ async function checkPermission(contractName, functionName, contractRegistry) { }; function getFinalOptions(options) { + if (typeof options != "object") { + options = {} + } const defaultOptions = { from: Issuer, gasPrice: defaultGasPrice, @@ -36,7 +38,7 @@ function getFinalOptions(options) { return Object.assign(defaultOptions, options) }; -async function getGas(options, action) { +async function getGasLimit(options, action) { let block = await web3.eth.getBlock("latest"); let networkGasLimit = block.gasLimit; let gas = Math.round(options.factor * (await action.estimateGas({ from: options.from.address, value: options.value}))); @@ -99,9 +101,9 @@ module.exports = { await checkPermissions(action); options = getFinalOptions(options); - let gas = await getGas(options, action); + let gasLimit = await getGasLimit(options, action); - console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gas} ----`)); + console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gasLimit} ----`)); let nonce = await web3.eth.getTransactionCount(options.from.address); let abi = action.encodeABI(); @@ -109,7 +111,7 @@ module.exports = { from: options.from.address, to: action._parent._address, data: abi, - gasLimit: gas, + gasLimit: gasLimit, gasPrice: options.gasPrice, nonce: nonce, value: web3.utils.toHex(options.value) diff --git a/CLI/commands/contract_manager.js b/CLI/commands/contract_manager.js index 27c6c7569..e87d046d7 100644 --- a/CLI/commands/contract_manager.js +++ b/CLI/commands/contract_manager.js @@ -159,7 +159,7 @@ async function strActions() { console.log(chalk.yellow(`Current expiry limit is ${Math.floor(parseInt(currentExpiryLimit)/60/60/24)} days`)); let newExpiryLimit = global.constants.DURATION.days(readlineSync.questionInt('Enter a new value in days for expiry limit: ')); let changeExpiryLimitAction = currentContract.methods.changeExpiryLimit(newExpiryLimit); - let changeExpiryLimitReceipt = await common.sendTransaction(changeExpiryLimitAction, {}); + let changeExpiryLimitReceipt = await common.sendTransaction(changeExpiryLimitAction); let changeExpiryLimitEvent = common.getEventFromLogs(currentContract._jsonInterface, changeExpiryLimitReceipt.logs, 'ChangeExpiryLimit'); console.log(chalk.green(`Expiry limit was changed successfully. New limit is ${Math.floor(parseInt(changeExpiryLimitEvent._newExpiry)/60/60/24)} days\n`)); break; @@ -168,7 +168,7 @@ async function strActions() { console.log(chalk.yellow(`\nCurrent ticker registration fee is ${currentRegFee} POLY`)); let newRegFee = web3.utils.toWei(readlineSync.questionInt('Enter a new value in POLY for ticker registration fee: ').toString()); let changeRegFeeAction = currentContract.methods.changeTickerRegistrationFee(newRegFee); - let changeRegFeeReceipt = await common.sendTransaction(changeRegFeeAction, {}); + let changeRegFeeReceipt = await common.sendTransaction(changeRegFeeAction); let changeRegFeeEvent = common.getEventFromLogs(currentContract._jsonInterface, changeRegFeeReceipt.logs, 'ChangeTickerRegistrationFee'); console.log(chalk.green(`Fee was changed successfully. New fee is ${web3.utils.fromWei(changeRegFeeEvent._newFee)} POLY\n`)); break; @@ -177,7 +177,7 @@ async function strActions() { console.log(chalk.yellow(`\nCurrent ST launch fee is ${currentLaunchFee} POLY`)); let newLaunchFee = web3.utils.toWei(readlineSync.questionInt('Enter a new value in POLY for ST launch fee: ').toString()); let changeLaunchFeeAction = currentContract.methods.changeSecurityLaunchFee(newLaunchFee); - let changeLaunchFeeReceipt = await common.sendTransaction(changeLaunchFeeAction, {}); + let changeLaunchFeeReceipt = await common.sendTransaction(changeLaunchFeeAction); let changeLaunchFeeEvent = common.getEventFromLogs(currentContract._jsonInterface, changeLaunchFeeReceipt.logs, 'ChangeSecurityLaunchFee'); console.log(chalk.green(`Fee was changed successfully. New fee is ${web3.utils.fromWei(changeLaunchFeeEvent._newFee)} POLY\n`)); break; diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 0faad11e0..0b9d8d379 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -113,7 +113,7 @@ async function start_explorer(){ break; case 'Create checkpoint': let createCheckpointAction = securityToken.methods.createCheckpoint(); - await common.sendTransaction(createCheckpointAction, {}); + await common.sendTransaction(createCheckpointAction); break; case 'Set default exclusions for dividends': await setDefaultExclusions(); @@ -183,7 +183,7 @@ async function mintTokens(address, amount){ try { let mintAction = securityToken.methods.mint(address,web3.utils.toWei(amount)); - let receipt = await common.sendTransaction(mintAction, {}); + let receipt = await common.sendTransaction(mintAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` Minted ${web3.utils.fromWei(event.value)} tokens @@ -244,7 +244,7 @@ async function setDefaultExclusions() { if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { let excluded = getExcludedFromDataFile(); let setDefaultExclusionsActions = currentDividendsModule.methods.setDefaultExcluded(excluded); - let receipt = await common.sendTransaction(setDefaultExclusionsActions, {}); + let receipt = await common.sendTransaction(setDefaultExclusionsActions); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'SetDefaultExcludedAddresses'); console.log(chalk.green(`Exclusions were successfully set.`)); showExcluded(event._excluded); @@ -274,14 +274,14 @@ async function taxHoldingMenu() { }); let percentageWei = web3.utils.toWei((percentage / 100).toString()); let setWithHoldingFixedAction = currentDividendsModule.methods.setWithholdingFixed([address], percentageWei); - let receipt = await common.sendTransaction(setWithHoldingFixedAction, {}); + let receipt = await common.sendTransaction(setWithHoldingFixedAction); console.log(chalk.green(`Successfully set tax withholding of ${percentage}% for ${address}.`)); break; case 'Withdraw withholding for dividend': let _dividend = await selectDividend({withRemainingWithheld: true}); if (_dividend !== null) { let withdrawWithholdingAction = currentDividendsModule.methods.withdrawWithholding(_dividend.index); - let receipt = await common.sendTransaction(withdrawWithholdingAction, {}); + let receipt = await common.sendTransaction(withdrawWithholdingAction); let eventName; if (dividendsType == 'POLY') { eventName = 'ERC20DividendWithholdingWithdrawn'; @@ -310,7 +310,7 @@ async function createDividends(name, dividend, checkpointId) { let createDividendAction; if (dividendsType == 'POLY') { let approveAction = polyToken.methods.approve(currentDividendsModule._address, web3.utils.toWei(dividend)); - await common.sendTransaction(approveAction, {}); + await common.sendTransaction(approveAction); if (checkpointId > 0) { if (useDefaultExcluded) { createDividendAction = currentDividendsModule.methods.createDividendWithCheckpoint(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), checkpointId, web3.utils.toHex(name)); @@ -326,7 +326,7 @@ async function createDividends(name, dividend, checkpointId) { createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), excluded, web3.utils.toHex(name)); } } - let receipt = await common.sendTransaction(createDividendAction, {}); + let receipt = await common.sendTransaction(createDividendAction); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'ERC20DividendDeposited'); console.log(chalk.green(`Dividend ${event._dividendIndex} deposited`)); } else if (dividendsType == 'ETH') { @@ -356,7 +356,7 @@ async function createDividends(name, dividend, checkpointId) { async function pushDividends(dividend, account){ let accs = account.split(','); let pushDividendPaymentToAddressesAction = currentDividendsModule.methods.pushDividendPaymentToAddresses(dividend.index, accs); - let receipt = await common.sendTransaction(pushDividendPaymentToAddressesAction, {}); + let receipt = await common.sendTransaction(pushDividendPaymentToAddressesAction); let successEventName; if (dividendsType == 'POLY') { successEventName = 'ERC20DividendClaimed'; @@ -384,7 +384,7 @@ async function pushDividends(dividend, account){ async function reclaimedDividend(dividend) { let reclaimDividendAction = currentDividendsModule.methods.reclaimDividend(dividend.index); - let receipt = await common.sendTransaction(reclaimDividendAction, {}); + let receipt = await common.sendTransaction(reclaimDividendAction); let eventName; if (dividendsType == 'POLY') { eventName = 'ERC20DividendReclaimed'; @@ -401,7 +401,7 @@ async function reclaimedDividend(dividend) { async function whitelistAddress(address) { let now = Math.floor(Date.now() / 1000); let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(address, now, now, now + 31536000, true); - await common.sendTransaction(modifyWhitelistAction, {}); + await common.sendTransaction(modifyWhitelistAction); console.log(chalk.green(`\nWhitelisting successful for ${address}.`)); } @@ -464,7 +464,7 @@ async function addDividendsModule() { let dividendsFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.DIVIDENDS, dividendsFactoryName); let addModuleAction = securityToken.methods.addModule(dividendsFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); - let receipt = await common.sendTransaction(addModuleAction, {}); + let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`Module deployed at address: ${event._module}`); currentDividendsModule = new web3.eth.Contract(dividendsModuleABI, event._module); diff --git a/CLI/commands/faucet.js b/CLI/commands/faucet.js index 69c28f2dd..474cb3a6c 100644 --- a/CLI/commands/faucet.js +++ b/CLI/commands/faucet.js @@ -79,7 +79,7 @@ async function send_poly(beneficiary, amount) { beneficiary = readlineSync.question(`Enter beneficiary 10K USD Tokens ('${Issuer.address}'): `); if (beneficiary == "") beneficiary = Issuer.address; let getTokensAction = usdToken.methods.getTokens(web3.utils.toWei('10000'), beneficiary); - await common.sendTransaction(getTokensAction, {}); + await common.sendTransaction(getTokensAction); let balance = await usdToken.methods.balanceOf(beneficiary).call(); let balanceInPoly = new BigNumber(balance).dividedBy(new BigNumber(10).pow(18)); console.log(chalk.green(`Congratulations! balance of ${beneficiary} address is ${balanceInPoly.toNumber()} USD Tokens`)); @@ -97,7 +97,7 @@ async function send_poly(beneficiary, amount) { async function transferTokens(to, amount) { try { let getTokensAction = polyToken.methods.getTokens(amount, to); - await common.sendTransaction(getTokensAction, {}); + await common.sendTransaction(getTokensAction); } catch (err){ console.log(err.message); return; diff --git a/CLI/commands/module_manager.js b/CLI/commands/module_manager.js index a4c8ba92d..d9b550e63 100644 --- a/CLI/commands/module_manager.js +++ b/CLI/commands/module_manager.js @@ -368,7 +368,7 @@ async function whitelist() { let investor = readlineSync.question(chalk.yellow(`Enter the address to be whitelisted: `)); let now = await latestTime(); let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(investor, now, now, now + 31556952, true); - await common.sendTransaction(modifyWhitelistAction, {}); + await common.sendTransaction(modifyWhitelistAction); console.log(chalk.green(`\nWhitelisting successful for ${investor}.`)); } catch (e) { console.log(e); @@ -390,7 +390,7 @@ async function mintTokens() { let _amount = readlineSync.question(chalk.yellow(`Enter the amount of tokens to mint: `)); try { let mintAction = securityToken.methods.mint(_investor, web3.utils.toWei(_amount)); - await common.sendTransaction(mintAction, {}); + await common.sendTransaction(mintAction); console.log(chalk.green(`\nMinting Successful.`)); } catch (e) { console.log(e); @@ -411,7 +411,7 @@ async function freezeMinting() { if (await featureRegistry.methods.getFeatureStatus('freezeMintingAllowed').call()) { let freezeMintingAction = securityToken.methods.freezeMinting(); - await common.sendTransaction(freezeMintingAction, {}); + await common.sendTransaction(freezeMintingAction); console.log(chalk.green(`\nFreeze minting was successful.`)); } else { console.log(chalk.red(`\nFreeze minting is not allowed by Polymath.`)); diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index 5ade5c386..b138ef849 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -161,7 +161,7 @@ function readFile() { } } let mintMultiAction = securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); - let r = await common.sendTransaction(mintMultiAction, {}); + let r = await common.sendTransaction(mintMultiAction); console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Multi Mint transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index c53e80b21..333f7704c 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -69,7 +69,7 @@ async function addPermissionModule() { if (readlineSync.keyInYNStrict('Do you want to add General Permission Manager Module to your Security Token?')) { let permissionManagerFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.PERMISSION, 'GeneralPermissionManager'); let addModuleAction = securityToken.methods.addModule(permissionManagerFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); - let receipt = await common.sendTransaction(addModuleAction, {}); + let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`Module deployed at address: ${event._module}`); generalPermissionManagerAddress = event._module; @@ -202,7 +202,7 @@ async function addNewDelegate() { }); let addPermissionAction = generalPermissionManager.methods.addDelegate(newDelegate, web3.utils.asciiToHex(details)); - let receipt = await common.sendTransaction(addPermissionAction, {}); + let receipt = await common.sendTransaction(addPermissionAction); let event = common.getEventFromLogs(generalPermissionManager._jsonInterface, receipt.logs, 'AddDelegate'); console.log(`Delegate added succesfully: ${event._delegate} - ${event._details}`); isNewDelegate = true; diff --git a/CLI/commands/strMigrator.js b/CLI/commands/strMigrator.js index 8dbcb6511..424313d32 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -144,7 +144,7 @@ async function step_register_tickers(tickers, securityTokenRegistry) { console.log(``); try { let modifyTickerAction = securityTokenRegistry.methods.modifyTicker(t.owner, t.ticker, t.name, t.registrationDate, t.expiryDate, false); - let receipt = await common.sendTransaction(modifyTickerAction, {}); + let receipt = await common.sendTransaction(modifyTickerAction); totalGas = totalGas.add(new web3.utils.BN(receipt.gasUsed)); succeed.push(t); } catch (error) { @@ -274,7 +274,7 @@ async function step_launch_STs(tokens, securityTokenRegistry) { try { // Deploying 2.0.0 Token let deployTokenAction = STFactory.methods.deployToken(t.name, t.ticker, 18, t.details, Issuer.address, t.divisble, polymathRegistryAddress) - let deployTokenReceipt = await common.sendTransaction(deployTokenAction, {}); + let deployTokenReceipt = await common.sendTransaction(deployTokenAction); // Instancing Security Token let newTokenAddress = deployTokenReceipt.logs[deployTokenReceipt.logs.length -1].address; //Last log is the ST creation let newTokenABI = abis.securityToken(); @@ -295,25 +295,25 @@ async function step_launch_STs(tokens, securityTokenRegistry) { new web3.utils.BN(gmtEvent.returnValues._expiryTime), gmtEvent.returnValues._canBuyFromSTO ); - let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction, {}); + let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); totalGas = totalGas.add(new web3.utils.BN(modifyWhitelistReceipt.gasUsed)); } // Minting tokens for (const mintedEvent of t.mintedEvents) { let mintAction = newToken.methods.mint(mintedEvent.returnValues.to, new web3.utils.BN(mintedEvent.returnValues.value)); - let mintReceipt = await common.sendTransaction(mintAction, {}); + let mintReceipt = await common.sendTransaction(mintAction); totalGas = totalGas.add(new web3.utils.BN(mintReceipt.gasUsed)); } } // Transferring onweship to the original owner let transferOwnershipAction = newToken.methods.transferOwnership(t.owner); - let transferOwnershipReceipt = await common.sendTransaction(transferOwnershipAction, {}); + let transferOwnershipReceipt = await common.sendTransaction(transferOwnershipAction); totalGas = totalGas.add(new web3.utils.BN(transferOwnershipReceipt.gasUsed)); // Adding 2.0.0 Security Token to SecurityTokenRegistry let modifySecurityTokenAction = securityTokenRegistry.methods.modifySecurityToken(t.name, t.ticker, t.owner, newTokenAddress, t.details, t.deployedAt); - let modifySecurityTokenReceipt = await common.sendTransaction(modifySecurityTokenAction, {}); + let modifySecurityTokenReceipt = await common.sendTransaction(modifySecurityTokenAction); totalGas = totalGas.add(new web3.utils.BN(modifySecurityTokenReceipt.gasUsed)); succeed.push(t); diff --git a/CLI/commands/transfer.js b/CLI/commands/transfer.js index ac782a919..7a60dfe20 100644 --- a/CLI/commands/transfer.js +++ b/CLI/commands/transfer.js @@ -46,7 +46,7 @@ async function transfer() { try{ let transferAction = securityToken.methods.transfer(_transferTo,web3.utils.toWei(_transferAmount,"ether")); - let receipt = await common.sendTransaction(transferAction, {}); + let receipt = await common.sendTransaction(transferAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` Account ${event.from} diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 0853254cd..26598ba4f 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -71,7 +71,7 @@ async function start_explorer() { case 'Disable controller': if (readlineSync.keyInYNStrict()) { let disableControllerAction = securityToken.methods.disableController(); - await common.sendTransaction(disableControllerAction, {}); + await common.sendTransaction(disableControllerAction); console.log(chalk.green(`Forced transfers have been disabled permanently`)); } break; @@ -84,7 +84,7 @@ async function start_explorer() { defaultInput: Issuer.address }); let setControllerAction = securityToken.methods.setController(controllerAddress); - let setControllerReceipt = await common.sendTransaction(setControllerAction, {}); + let setControllerReceipt = await common.sendTransaction(setControllerAction); let setControllerEvent = common.getEventFromLogs(securityToken._jsonInterface, setControllerReceipt.logs, 'SetController'); console.log(chalk.green(`New controller is ${setControllerEvent._newController}`)); break; diff --git a/CLI/commands/transfer_ownership.js b/CLI/commands/transfer_ownership.js index 0f5e634b4..d7a1d4c23 100644 --- a/CLI/commands/transfer_ownership.js +++ b/CLI/commands/transfer_ownership.js @@ -28,7 +28,7 @@ async function transferOwnership(transferTo) { console.log(chalk.red(`You are not the current owner ot this contract. Current owner is ${currentOwner}.`)); } else { let transferOwnershipAction = contract.methods.transferOwnership(transferTo); - let receipt = await common.sendTransaction(transferOwnershipAction, {}); + let receipt = await common.sendTransaction(transferOwnershipAction); let event = common.getEventFromLogs(contract._jsonInterface, receipt.logs, 'OwnershipTransferred'); console.log(chalk.green(`Ownership transferred successfully. New owner is ${event.newOwner}`)); } diff --git a/CLI/commands/whitelist.js b/CLI/commands/whitelist.js index 395fd9d77..5ef201195 100644 --- a/CLI/commands/whitelist.js +++ b/CLI/commands/whitelist.js @@ -167,7 +167,7 @@ async function setInvestors() { //toTimes is ability to buy coins TOwards your account (3rd row in csv, 3rd parameter in modifyWhiteList() ) //expiryTime is time at which KYC of investor get expired (4th row in csv, 4rd parameter in modifyWhiteList() ) let modifyWhitelistMultiAction = generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); - let r = await common.sendTransaction(modifyWhitelistMultiAction, {}); + let r = await common.sendTransaction(modifyWhitelistMultiAction); console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Whitelist transaxction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); From 3b5013d652f00ce076ab318bf24527a8f910ba21 Mon Sep 17 00:00:00 2001 From: Federico Elgarte Date: Tue, 6 Nov 2018 13:48:01 -0300 Subject: [PATCH 046/582] rename global to glb (reserved name) and other changes --- CLI/commands/ST20Generator.js | 56 ++++++++++++------------ CLI/commands/TickerRollForward.js | 5 --- CLI/commands/accredit.js | 5 +-- CLI/commands/changeNonAccreditedLimit.js | 5 +-- CLI/commands/common/constants.js | 1 - CLI/commands/common/global.js | 5 ++- CLI/commands/contract_manager.js | 5 +-- CLI/commands/dividends_manager.js | 7 ++- CLI/commands/faucet.js | 2 - CLI/commands/investor_portal.js | 35 +++++++-------- CLI/commands/module_manager.js | 2 - CLI/commands/multi_mint.js | 4 -- CLI/commands/permission_manager.js | 9 ++-- CLI/commands/strMigrator.js | 5 +-- CLI/commands/transfer.js | 3 -- CLI/commands/transfer_manager.js | 3 -- CLI/commands/transfer_ownership.js | 2 - CLI/commands/whitelist.js | 4 -- CLI/polymath-cli.js | 19 ++++++-- 19 files changed, 76 insertions(+), 101 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 591b0dae5..9a7ac39b6 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -6,7 +6,7 @@ const shell = require('shelljs'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); let securityTokenRegistryAddress; @@ -38,8 +38,6 @@ async function executeApp(tokenConfig, mintingConfig, stoConfig) { _mintingConfig = mintingConfig; _stoConfig = stoConfig; - await global.initialize(); - common.logAsciiBull(); console.log("********************************************"); console.log("Welcome to the Command-Line ST-20 Generator."); @@ -177,7 +175,7 @@ async function step_token_deploy(){ } async function step_Wallet_Issuance(){ - let result = await securityToken.methods.getModulesByType(global.constants.MODULES_TYPES.STO).call(); + let result = await securityToken.methods.getModulesByType(gbl.constants.MODULES_TYPES.STO).call(); if (result.length > 0) { console.log('\x1b[32m%s\x1b[0m',"STO has already been created at address " + result[0] + ". Skipping initial minting"); } else { @@ -244,11 +242,11 @@ async function step_Wallet_Issuance(){ async function multi_mint_tokens() { //await whitelist.startWhitelisting(tokenSymbol); - shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${global.constants.NETWORK}`); + shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${gbl.constants.NETWORK}`); console.log(chalk.green(`\nCongrats! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); - shell.exec(`${__dirname}/scripts//script.sh Multimint ${tokenSymbol} 75 ${global.constants.NETWORK}`); + shell.exec(`${__dirname}/scripts//script.sh Multimint ${tokenSymbol} 75 ${gbl.constants.NETWORK}`); console.log(chalk.green(`\nHurray!! Tokens get successfully Minted and transferred to token holders`)); } @@ -256,7 +254,7 @@ async function step_STO_launch() { console.log("\n"); console.log('\x1b[34m%s\x1b[0m',"Token Creation - STO Configuration"); - let result = await securityToken.methods.getModulesByType(global.constants.MODULES_TYPES.STO).call(); + let result = await securityToken.methods.getModulesByType(gbl.constants.MODULES_TYPES.STO).call(); if (result.length > 0) { STO_Address = result[0]; let stoModuleData = await securityToken.methods.getModule(STO_Address).call(); @@ -423,7 +421,7 @@ async function cappedSTO_launch() { ] }, [startTime, endTime, web3.utils.toWei(cap), rate, raiseType, wallet]); - let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.STO, "CappedSTO"); + let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.STO, "CappedSTO"); let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); @@ -443,14 +441,14 @@ async function cappedSTO_status() { let displayRaiseType; let displayFundsRaised; let displayWalletBalance; - let raiseType = await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.ETH).call(); + let raiseType = await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.ETH).call(); if (raiseType) { displayRaiseType = 'ETH'; - displayFundsRaised = await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES.ETH).call(); + displayFundsRaised = await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES.ETH).call(); displayWalletBalance = web3.utils.fromWei(await web3.eth.getBalance(displayWallet)); } else { displayRaiseType = 'POLY'; - displayFundsRaised = await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES.POLY).call(); + displayFundsRaised = await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES.POLY).call(); displayWalletBalance = await currentBalance(displayWallet); } let displayTokensSold = await currentSTO.methods.totalTokensSold().call(); @@ -510,16 +508,16 @@ function fundingConfigUSDTieredSTO() { funding.raiseType = []; if (selectedFunding.includes('E')) { - funding.raiseType.push(global.constants.FUND_RAISE_TYPES.ETH); + funding.raiseType.push(gbl.constants.FUND_RAISE_TYPES.ETH); } if (selectedFunding.includes('P')) { - funding.raiseType.push(global.constants.FUND_RAISE_TYPES.POLY); + funding.raiseType.push(gbl.constants.FUND_RAISE_TYPES.POLY); } if (selectedFunding.includes('D')) { - funding.raiseType.push(global.constants.FUND_RAISE_TYPES.DAI); + funding.raiseType.push(gbl.constants.FUND_RAISE_TYPES.DAI); } if (funding.raiseType.length == 0) { - funding.raiseType = [global.constants.FUND_RAISE_TYPES.ETH, global.constants.FUND_RAISE_TYPES.POLY, global.constants.FUND_RAISE_TYPES.DAI]; + funding.raiseType = [gbl.constants.FUND_RAISE_TYPES.ETH, gbl.constants.FUND_RAISE_TYPES.POLY, gbl.constants.FUND_RAISE_TYPES.DAI]; } return funding; @@ -749,8 +747,8 @@ async function usdTieredSTO_launch() { } let funding = fundingConfigUSDTieredSTO(); - let addresses = addressesConfigUSDTieredSTO(funding.raiseType.includes(global.constants.FUND_RAISE_TYPES.DAI)); - let tiers = tiersConfigUSDTieredSTO(funding.raiseType.includes(global.constants.FUND_RAISE_TYPES.POLY)); + let addresses = addressesConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.DAI)); + let tiers = tiersConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.POLY)); let limits = limitsConfigUSDTieredSTO(); let times = timesConfigUSDTieredSTO(); let bytesSTO = web3.eth.abi.encodeFunctionCall( { @@ -809,7 +807,7 @@ async function usdTieredSTO_launch() { addresses.usdToken ]); - let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.STO, 'USDTieredSTO'); + let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.STO, 'USDTieredSTO'); let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); @@ -836,8 +834,8 @@ async function usdTieredSTO_status() { let tiersLength = await currentSTO.methods.getNumberOfTiers().call();; let raiseTypes = []; - for (const fundType in global.constants.FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES[fundType]).call()) { + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { raiseTypes.push(fundType); } } @@ -866,7 +864,7 @@ async function usdTieredSTO_status() { } } - let mintedPerTier = await currentSTO.methods.mintedPerTier(global.constants.FUND_RAISE_TYPES[type], t).call(); + let mintedPerTier = await currentSTO.methods.mintedPerTier(gbl.constants.FUND_RAISE_TYPES[type], t).call(); displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; } @@ -891,23 +889,23 @@ async function usdTieredSTO_status() { for (const type of raiseTypes) { let balance = await getBalance(displayWallet, type); let walletBalance = web3.utils.fromWei(balance); - let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(global.constants.FUND_RAISE_TYPES[type], balance).call()); + let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); displayWalletBalancePerType += ` Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; balance = await getBalance(displayReserveWallet, type); let reserveWalletBalance = web3.utils.fromWei(balance); - let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(global.constants.FUND_RAISE_TYPES[type], balance).call()); + let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); displayReserveWalletBalancePerType += ` Balance ${type}:\t\t ${reserveWalletBalance} ${type} (${reserveWalletBalanceUSD} USD)`; - let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES[type]).call()); + let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); displayFundsRaisedPerType += ` ${type}:\t\t\t ${fundsRaised} ${type}`; //Only show sold for if more than one raise type are allowed if (raiseTypes.length > 1) { - let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(global.constants.FUND_RAISE_TYPES[type]).call()); + let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(gbl.constants.FUND_RAISE_TYPES[type]).call()); displayTokensSoldPerType += ` Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; } @@ -1005,7 +1003,7 @@ async function usdTieredSTO_configure() { await common.sendTransaction(changeAccreditedAction); break; case 2: - shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${global.constants.NETWORK}`); + shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${gbl.constants.NETWORK}`); break; case 3: let account = readlineSync.question('Enter the address to change non accredited limit: '); @@ -1017,7 +1015,7 @@ async function usdTieredSTO_configure() { await common.sendTransaction(changeNonAccreditedLimitAction); break; case 4: - shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${global.constants.NETWORK}`); + shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${gbl.constants.NETWORK}`); break; case 5: await modfifyTimes(); @@ -1063,13 +1061,13 @@ async function modfifyFunding() { } async function modfifyAddresses() { - let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.DAI).call()); + let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.DAI).call()); let modifyAddressesAction = currentSTO.methods.modifyAddresses(addresses.wallet, addresses.reserveWallet, addresses.usdToken); await common.sendTransaction(modifyAddressesAction); } async function modfifyTiers() { - let tiers = tiersConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.POLY).call()); + let tiers = tiersConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.POLY).call()); let modifyTiersAction = currentSTO.methods.modifyTiers( tiers.ratePerTier, tiers.ratePerTierDiscountPoly, diff --git a/CLI/commands/TickerRollForward.js b/CLI/commands/TickerRollForward.js index 0c8db13ca..69d36575d 100644 --- a/CLI/commands/TickerRollForward.js +++ b/CLI/commands/TickerRollForward.js @@ -3,15 +3,11 @@ var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); ///////////////////////// ARTIFACTS ///////////////////////// var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); -////////////////////////////USER INPUTS////////////////////////////////////////// -let remoteNetwork = process.argv.slice(2)[0]; //batch size - ///////////////////////// GLOBAL VARS ///////////////////////// let ticker_data = []; let registered_tickers = []; @@ -47,7 +43,6 @@ function FailedRegistration(_ticker, _error) { startScript(); async function startScript() { - await global.initialize(remoteNetwork); securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); diff --git a/CLI/commands/accredit.js b/CLI/commands/accredit.js index d9a860f28..43fbac4ae 100644 --- a/CLI/commands/accredit.js +++ b/CLI/commands/accredit.js @@ -3,7 +3,6 @@ var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis') @@ -16,7 +15,6 @@ let usdTieredSTO; let tokenSymbol = process.argv.slice(2)[0]; //token symbol let BATCH_SIZE = process.argv.slice(2)[1]; //batch size if (!BATCH_SIZE) BATCH_SIZE = 75; -let remoteNetwork = process.argv.slice(2)[2]; /////////////////////////GLOBAL VARS////////////////////////////////////////// //distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] @@ -33,8 +31,7 @@ let badData = new Array(); startScript(); async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); + try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); diff --git a/CLI/commands/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js index 9e1aa59bf..8a27036a6 100644 --- a/CLI/commands/changeNonAccreditedLimit.js +++ b/CLI/commands/changeNonAccreditedLimit.js @@ -3,7 +3,6 @@ var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis') @@ -16,7 +15,6 @@ let usdTieredSTO; let tokenSymbol = process.argv.slice(2)[0]; //token symbol let BATCH_SIZE = process.argv.slice(2)[1]; //batch size if (!BATCH_SIZE) BATCH_SIZE = 75; -let remoteNetwork = process.argv.slice(2)[2]; /////////////////////////GLOBAL VARS////////////////////////////////////////// //distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] @@ -33,8 +31,7 @@ let badData = new Array(); startScript(); async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); + try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); diff --git a/CLI/commands/common/constants.js b/CLI/commands/common/constants.js index 92050f428..c3e2b796c 100644 --- a/CLI/commands/common/constants.js +++ b/CLI/commands/common/constants.js @@ -1,5 +1,4 @@ module.exports = Object.freeze({ - NETWORK: undefined, MODULES_TYPES: { PERMISSION: 1, TRANSFER: 2, diff --git a/CLI/commands/common/global.js b/CLI/commands/common/global.js index 6942b5509..b4aa96607 100644 --- a/CLI/commands/common/global.js +++ b/CLI/commands/common/global.js @@ -1,6 +1,8 @@ const Web3 = require('web3'); const constants = require('./constants'); +global.web3, global.Issuer, global.defaultGasPrice; + function getGasPrice (networkId) { let gasPrice; switch (networkId) { @@ -23,8 +25,7 @@ function getGasPrice (networkId) { } module.exports = { - initialize: async function() { - let remoteNetwork = constants.NETWORK; + initialize: async function(remoteNetwork) { if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { if (typeof remoteNetwork !== 'undefined') { web3 = new Web3(new Web3.providers.HttpProvider(`https://${remoteNetwork}.infura.io/`)); diff --git a/CLI/commands/contract_manager.js b/CLI/commands/contract_manager.js index e87d046d7..cce93444e 100644 --- a/CLI/commands/contract_manager.js +++ b/CLI/commands/contract_manager.js @@ -1,7 +1,7 @@ var readlineSync = require('readline-sync'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); @@ -9,7 +9,6 @@ var abis = require('./helpers/contract_abis'); let currentContract = null; async function executeApp() { - await global.initialize(); common.logAsciiBull(); console.log("*********************************************"); @@ -157,7 +156,7 @@ async function strActions() { case 'Change Expiry Limit': let currentExpiryLimit = await currentContract.methods.getExpiryLimit().call(); console.log(chalk.yellow(`Current expiry limit is ${Math.floor(parseInt(currentExpiryLimit)/60/60/24)} days`)); - let newExpiryLimit = global.constants.DURATION.days(readlineSync.questionInt('Enter a new value in days for expiry limit: ')); + let newExpiryLimit = gbl.constants.DURATION.days(readlineSync.questionInt('Enter a new value in days for expiry limit: ')); let changeExpiryLimitAction = currentContract.methods.changeExpiryLimit(newExpiryLimit); let changeExpiryLimitReceipt = await common.sendTransaction(changeExpiryLimitAction); let changeExpiryLimitEvent = common.getEventFromLogs(currentContract._jsonInterface, changeExpiryLimitReceipt.logs, 'ChangeExpiryLimit'); diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 0b9d8d379..f47d3fd67 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -2,7 +2,7 @@ var readlineSync = require('readline-sync'); var chalk = require('chalk'); var moment = require('moment'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); @@ -16,7 +16,6 @@ let currentDividendsModule; async function executeApp(type) { dividendsType = type; - await global.initialize(); common.logAsciiBull(); console.log("**********************************************"); @@ -302,7 +301,7 @@ async function createDividends(name, dividend, checkpointId) { let time = Math.floor(Date.now()/1000); let maturityTime = readlineSync.questionInt('Enter the dividend maturity time from which dividend can be paid (Unix Epoch time)\n(Now = ' + time + ' ): ', {defaultInput: time}); - let defaultTime = time + global.constants.DURATION.minutes(10); + let defaultTime = time + gbl.constants.DURATION.minutes(10); let expiryTime = readlineSync.questionInt('Enter the dividend expiry time (Unix Epoch time)\n(10 minutes from now = ' + defaultTime + ' ): ', {defaultInput: defaultTime}); let useDefaultExcluded = readlineSync.keyInYNStrict(`Do you want to use the default excluded addresses for this dividend? If not, data from 'dividendsExclusions_data.csv' will be used instead.`); @@ -462,7 +461,7 @@ async function addDividendsModule() { dividendsModuleABI = abis.etherDividendCheckpoint(); } - let dividendsFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.DIVIDENDS, dividendsFactoryName); + let dividendsFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.DIVIDENDS, dividendsFactoryName); let addModuleAction = securityToken.methods.addModule(dividendsFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); diff --git a/CLI/commands/faucet.js b/CLI/commands/faucet.js index 474cb3a6c..70eadd57b 100644 --- a/CLI/commands/faucet.js +++ b/CLI/commands/faucet.js @@ -1,7 +1,6 @@ var readlineSync = require('readline-sync'); var BigNumber = require('bignumber.js'); var common = require('./common/common_functions'); -var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis') var chalk = require('chalk'); @@ -12,7 +11,6 @@ let polyToken; let usdToken; async function executeApp(beneficiary, amount) { - await global.initialize(); console.log("\n"); console.log("***************************") diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index b65348b1a..276f8bda3 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -3,7 +3,7 @@ var readlineSync = require('readline-sync'); var BigNumber = require('bignumber.js'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); // Load Contract artifacts var contracts = require('./helpers/contract_addresses'); @@ -35,7 +35,6 @@ let displayValidKYC; // Start Script async function executeApp(investorAddress, investorPrivKey, symbol, currency, amount) { - await global.initialize(); common.logAsciiBull(); console.log("********************************************"); @@ -158,13 +157,13 @@ async function showUserInfo(_user) { console.log(` ******************* User Information ******************** - Address: ${_user}`); - if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.POLY)) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.POLY)) { console.log(` - POLY balance:\t ${await polyBalance(_user)}`); } - if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.ETH)) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.ETH)) { console.log(` - ETH balance:\t ${web3.utils.fromWei(await web3.eth.getBalance(_user))}`); } - if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES.DAI)) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.DAI)) { console.log(` - DAI balance:\t ${await usdBalance(_user)}`); } } @@ -180,11 +179,11 @@ async function showCappedSTOInfo() { let displayRaiseType; let displayFundsRaised; - for (const fundType in global.constants.FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES[fundType]).call()) { + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { raiseTypes.push(fundType); displayRaiseType = fundType; - displayFundsRaised = await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES[fundType]).call(); + displayFundsRaised = await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[fundType]).call(); } } @@ -240,9 +239,9 @@ async function showCappedSTOInfo() { async function showUserInfoForUSDTieredSTO() { - for (const fundType in global.constants.FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES[fundType]).call()) { - let displayInvestorInvested = web3.utils.fromWei(await currentSTO.methods.investorInvested(User.address, global.constants.FUND_RAISE_TYPES[fundType]).call()); + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { + let displayInvestorInvested = web3.utils.fromWei(await currentSTO.methods.investorInvested(User.address, gbl.constants.FUND_RAISE_TYPES[fundType]).call()); console.log(` - Invested in ${fundType}:\t ${displayInvestorInvested} ${fundType}`); } } @@ -282,8 +281,8 @@ async function showUSDTieredSTOInfo() { let displayTokenSymbol = await securityToken.methods.symbol().call(); let tiersLength = await currentSTO.methods.getNumberOfTiers().call(); - for (const fundType in global.constants.FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(global.constants.FUND_RAISE_TYPES[fundType]).call()) { + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { raiseTypes.push(fundType); } } @@ -312,7 +311,7 @@ async function showUSDTieredSTOInfo() { } } - let mintedPerTier = await currentSTO.methods.mintedPerTier(global.constants.FUND_RAISE_TYPES[type], t).call(); + let mintedPerTier = await currentSTO.methods.mintedPerTier(gbl.constants.FUND_RAISE_TYPES[type], t).call(); displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; } @@ -333,13 +332,13 @@ async function showUSDTieredSTOInfo() { let displayFundsRaisedPerType = ''; let displayTokensSoldPerType = ''; for (const type of raiseTypes) { - let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(global.constants.FUND_RAISE_TYPES[type]).call()); + let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); displayFundsRaisedPerType += ` ${type}:\t\t\t ${fundsRaised} ${type}`; //Only show sold per raise type is more than one are allowed if (raiseTypes.length > 1) { - let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(global.constants.FUND_RAISE_TYPES[type]).call()); + let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(gbl.constants.FUND_RAISE_TYPES[type]).call()); displayTokensSoldPerType += ` Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; } @@ -452,7 +451,7 @@ async function investUsdTieredSTO(currency, amount) { } } else { for (const type of raiseTypes) { - let displayPrice = web3.utils.fromWei(await currentSTO.methods.convertToUSD(global.constants.FUND_RAISE_TYPES[type], web3.utils.toWei("1")).call()); + let displayPrice = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], web3.utils.toWei("1")).call()); console.log(chalk.green(` Current ${type} price:\t\t ${displayPrice} USD`)); } if (raiseTypes.length > 1) { @@ -468,7 +467,7 @@ async function investUsdTieredSTO(currency, amount) { if (typeof amount === 'undefined') { let investorInvestedUSD = web3.utils.fromWei(await currentSTO.methods.investorInvestedUSD(User.address).call()); let minimumInvestmentUSD = await currentSTO.methods.minimumInvestmentUSD().call(); - let minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(global.constants.FUND_RAISE_TYPES[raiseType], minimumInvestmentUSD).call(); + let minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(gbl.constants.FUND_RAISE_TYPES[raiseType], minimumInvestmentUSD).call(); cost = readlineSync.question(chalk.yellow(`Enter the amount of ${raiseType} you would like to invest or press 'Enter' to exit: `), { limit: function(input) { return investorInvestedUSD != 0 || parseInt(input) > parseInt(web3.utils.fromWei(minimumInvestmentRaiseType)); diff --git a/CLI/commands/module_manager.js b/CLI/commands/module_manager.js index d9b550e63..53f2a863a 100644 --- a/CLI/commands/module_manager.js +++ b/CLI/commands/module_manager.js @@ -2,7 +2,6 @@ var readlineSync = require('readline-sync'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); // Load contract artifacts var contracts = require('./helpers/contract_addresses'); @@ -48,7 +47,6 @@ async function setup() { // Start function async function executeApp() { - await global.initialize(); common.logAsciiBull(); console.log(chalk.yellow(`******************************************`)); diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index b138ef849..064e51bad 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -3,7 +3,6 @@ var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); const chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); /////////////////////////////ARTIFACTS////////////////////////////////////////// var contracts = require('./helpers/contract_addresses'); @@ -17,7 +16,6 @@ let securityToken; let tokenSymbol = process.argv.slice(2)[0]; //token symbol let BATCH_SIZE = process.argv.slice(2)[1]; //batch size if (!BATCH_SIZE) BATCH_SIZE = 75; -let remoteNetwork = process.argv.slice(2)[2]; /////////////////////////GLOBAL VARS////////////////////////////////////////// @@ -35,8 +33,6 @@ let badData = new Array(); startScript(); async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index 333f7704c..9bba9d8b0 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -1,7 +1,7 @@ var readlineSync = require('readline-sync'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); @@ -13,7 +13,6 @@ let generalPermissionManager; let isNewDelegate = false; async function executeApp() { - await global.initialize(); common.logAsciiBull(); console.log("***********************************************"); @@ -67,7 +66,7 @@ async function addPermissionModule() { if (result.length == 0) { console.log(chalk.red(`General Permission Manager is not attached.`)); if (readlineSync.keyInYNStrict('Do you want to add General Permission Manager Module to your Security Token?')) { - let permissionManagerFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, global.constants.MODULES_TYPES.PERMISSION, 'GeneralPermissionManager'); + let permissionManagerFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.PERMISSION, 'GeneralPermissionManager'); let addModuleAction = securityToken.methods.addModule(permissionManagerFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); @@ -213,8 +212,8 @@ async function getModulesWithPermissions() { let modules = []; let moduleABI = abis.moduleInterface(); - for (const type in global.constants.MODULES_TYPES) { - let modulesAttached = await securityToken.methods.getModulesByType(global.constants.MODULES_TYPES[type]).call(); + for (const type in gbl.constants.MODULES_TYPES) { + let modulesAttached = await securityToken.methods.getModulesByType(gbl.constants.MODULES_TYPES[type]).call(); for (const m of modulesAttached) { let contractTemp = new web3.eth.Contract(moduleABI, m); let permissions = await contractTemp.methods.getPermissions().call(); diff --git a/CLI/commands/strMigrator.js b/CLI/commands/strMigrator.js index 424313d32..edc965236 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -4,10 +4,9 @@ var request = require('request-promise') var abis = require('./helpers/contract_abis'); var contracts = require('./helpers/contract_addresses'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); async function executeApp(toStrAddress, fromTrAddress, fromStrAddress) { - await global.initialize(); common.logAsciiBull(); console.log("****************************************"); @@ -357,7 +356,7 @@ ${failed.map(ticker => chalk.red(`${ticker.ticker}`)).join('\n')} } async function getABIfromEtherscan(_address) { - let urlDomain = global.constants.NETWORK == 'kovan' ? 'api-kovan' : 'api'; + let urlDomain = gbl.constants.NETWORK == 'kovan' ? 'api-kovan' : 'api'; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { diff --git a/CLI/commands/transfer.js b/CLI/commands/transfer.js index 7a60dfe20..5bd6d1859 100644 --- a/CLI/commands/transfer.js +++ b/CLI/commands/transfer.js @@ -1,5 +1,4 @@ var common = require('./common/common_functions'); -var global = require('./common/global'); /////////////////////////////ARTIFACTS////////////////////////////////////////// var contracts = require('./helpers/contract_addresses'); @@ -19,8 +18,6 @@ async function startScript(tokenSymbol, transferTo, transferAmount) { _transferTo = transferTo; _transferAmount = transferAmount; - await global.initialize(); - try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 26598ba4f..eb5eb1a26 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1,8 +1,6 @@ var readlineSync = require('readline-sync'); var chalk = require('chalk'); -var moment = require('moment'); var common = require('./common/common_functions'); -var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); @@ -12,7 +10,6 @@ let securityToken; let securityTokenRegistry; async function executeApp() { - await global.initialize(); common.logAsciiBull(); console.log("*********************************************"); diff --git a/CLI/commands/transfer_ownership.js b/CLI/commands/transfer_ownership.js index d7a1d4c23..99e12b80f 100644 --- a/CLI/commands/transfer_ownership.js +++ b/CLI/commands/transfer_ownership.js @@ -1,6 +1,5 @@ var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); /////////////////////////////ARTIFACTS////////////////////////////////////////// var abis = require('./helpers/contract_abis') @@ -9,7 +8,6 @@ let contract; //////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// async function startScript(contractAddress, transferTo) { - await global.initialize(); if (!web3.utils.isAddress(contractAddress) || !web3.utils.isAddress(transferTo)) { console.log(chlak.red(`Please enter valid addresses`)); diff --git a/CLI/commands/whitelist.js b/CLI/commands/whitelist.js index 5ef201195..8722d3789 100644 --- a/CLI/commands/whitelist.js +++ b/CLI/commands/whitelist.js @@ -2,7 +2,6 @@ var fs = require('fs'); var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); var common = require('./common/common_functions'); -var global = require('./common/global'); /////////////////////////////ARTIFACTS////////////////////////////////////////// var contracts = require('./helpers/contract_addresses'); @@ -12,7 +11,6 @@ var abis = require('./helpers/contract_abis'); let tokenSymbol = process.argv.slice(2)[0]; //token symbol let BATCH_SIZE = process.argv.slice(2)[1]; //batch size if (!BATCH_SIZE) BATCH_SIZE = 70; -let remoteNetwork = process.argv.slice(2)[2]; /////////////////////////GLOBAL VARS////////////////////////////////////////// @@ -32,8 +30,6 @@ const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); startScript(); async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 40b32cae6..f802ab4c0 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -13,7 +13,7 @@ var contract_manager = require('./commands/contract_manager'); var strMigrator = require('./commands/strMigrator'); var permission_manager = require('./commands/permission_manager'); var program = require('commander'); -var global = require('./commands/common/global'); +var gbl = require('./commands/common/global'); const yaml = require('js-yaml'); const fs = require('fs'); @@ -37,6 +37,7 @@ program mintingConfig = config.initialMint; stoCofig = config.sto; } + await gbl.initialize(program.remoteNode); await st20generator.executeApp(tokenConfig, mintingConfig, stoCofig); }); @@ -45,6 +46,7 @@ program .alias('f') .description('Poly faucet for local private netwtorks') .action(async function(beneficiary, amount) { + await gbl.initialize(program.remoteNode); await faucet.executeApp(beneficiary, amount); }); @@ -53,6 +55,7 @@ program .alias('i') .description('Participate in any STO you have been whitelisted for') .action(async function(investor, privateKey, symbol, currency, amount) { + await gbl.initialize(program.remoteNode); await investor_portal.executeApp(investor, privateKey, symbol, currency, amount); }); @@ -61,6 +64,7 @@ program .alias('mm') .description('View modules attached to a token and their status') .action(async function() { + await gbl.initialize(program.remoteNode); await module_manager.executeApp(); }); @@ -69,6 +73,7 @@ program .alias('mi') .description('Distribute tokens to previously whitelisted investors') .action(async function(tokenSymbol, batchSize) { + await gbl.initialize(program.remoteNode); shell.exec(`${__dirname}/commands/scripts/script.sh Multimint ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; }); @@ -77,6 +82,7 @@ program .alias('t') .description('Transfer ST tokens to another account') .action(async function(tokenSymbol, transferTo, transferAmount) { + await gbl.initialize(program.remoteNode); await transfer.executeApp(tokenSymbol, transferTo, transferAmount); }); @@ -85,6 +91,7 @@ program .alias('to') .description('Transfer Ownership of an own contract to another account') .action(async function(contractAddress, transferTo) { + await gbl.initialize(program.remoteNode); await transfer_ownership.executeApp(contractAddress, transferTo); }); @@ -93,6 +100,7 @@ program .alias('w') .description('Mass-update a whitelist of allowed/known investors') .action(async function(tokenSymbol, batchSize) { + await gbl.initialize(program.remoteNode); shell.exec(`${__dirname}/commands/scripts/script.sh Whitelist ${tokenSymbol} ${batchSize} ${program.remoteNode}`); }); @@ -101,6 +109,7 @@ program .alias('dm') .description('Runs dividends_manager') .action(async function(dividendsType) { + await gbl.initialize(program.remoteNode); await dividends_manager.executeApp(dividendsType); }); @@ -109,6 +118,7 @@ program .alias('tm') .description('Runs transfer_manager') .action(async function() { + await gbl.initialize(program.remoteNode); await transfer_manager.executeApp(); }); @@ -117,6 +127,7 @@ program .alias('cm') .description('Runs contract_manager') .action(async function() { + await gbl.initialize(program.remoteNode); await contract_manager.executeApp(); }); @@ -125,6 +136,7 @@ program .alias('a') .description('Runs accredit') .action(async function(tokenSymbol, batchSize) { + await gbl.initialize(program.remoteNode); shell.exec(`${__dirname}/commands/scripts/script.sh Accredit ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; }); @@ -133,6 +145,7 @@ program .alias('nal') .description('Runs changeNonAccreditedLimit') .action(async function(tokenSymbol, batchSize) { + await gbl.initialize(program.remoteNode); shell.exec(`${__dirname}/commands/scripts/script.sh NonAccreditedLimit ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; }); @@ -141,6 +154,7 @@ program .alias('str') .description('Runs STR Migrator') .action(async function(toStrAddress, fromTrAddress, fromStrAddress) { + await gbl.initialize(program.remoteNode); await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress); }); @@ -149,6 +163,7 @@ program .alias('pm') .description('Runs permission_manager') .action(async function() { + await gbl.initialize(program.remoteNode); await permission_manager.executeApp(); }); @@ -157,6 +172,4 @@ program.parse(process.argv); if (typeof program.commands.length == 0) { console.error('No command given!'); process.exit(1); -} else { - global.constants.NETWORK = program.remoteNode } \ No newline at end of file From 4c1f7951b8f61c68f2fa298a4b148be942d3204d Mon Sep 17 00:00:00 2001 From: Polymath Date: Wed, 7 Nov 2018 15:20:31 -0300 Subject: [PATCH 047/582] [CLI] [WIP] print json format --- CLI/commands/permission_manager.js | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index a2165f697..fcb6366a9 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -126,11 +126,13 @@ async function deleteDelegate(address) { async function selectDelegate() { let result; let delegates = await getDelegates(); + let permissions = await getDelegatesAndPermissions(); let options = ['Add new delegate']; options = options.concat(delegates.map(function(d) { return `Account: ${d.address} - Details: ${d.details}` + Details: ${d.details} + Permisions: ${JSON.stringify(permissions[d.address])}` })); let index = readlineSync.keyInSelect(options, 'Select a delegate:', {cancel: false}); @@ -239,6 +241,33 @@ async function getModulesWithPermissions() { return modules; } +async function getDelegatesAndPermissions() { + let moduleABI = abis.moduleInterface(); + let result = []; + for (const type in MODULES_TYPES) { + let modulesAttached = await securityToken.methods.getModulesByType(MODULES_TYPES[type]).call(); + for (const module of modulesAttached) { + let contractTemp = new web3.eth.Contract(moduleABI, module); + let permissions = await contractTemp.methods.getPermissions().call(); + if (permissions.length > 0) { + for (const permission of permissions) { + let allDelegates = await generalPermissionManager.methods.getAllDelegatesWithPerm(module, permission).call(); + let moduleName = web3.utils.hexToUtf8((await securityToken.methods.getModule(module).call())[0]); + let permissionName = web3.utils.hexToUtf8(permission); + for (delegateAddr of allDelegates) { + if (result[delegateAddr] != undefined) { + result[delegateAddr].push({module: moduleName, permission: permissionName}) + } else { + result[delegateAddr] = [{module: moduleName, permission: permissionName}] + } + } + } + } + } + } + return result +} + module.exports = { executeApp: async function(remoteNetwork) { return executeApp(remoteNetwork); From d5478a4a55815079b14f5a0e484d2a006d6bfa66 Mon Sep 17 00:00:00 2001 From: Polymath Date: Wed, 7 Nov 2018 17:10:58 -0300 Subject: [PATCH 048/582] permission table --- CLI/commands/permission_manager.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index fcb6366a9..4fd649467 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -129,10 +129,13 @@ async function selectDelegate() { let permissions = await getDelegatesAndPermissions(); let options = ['Add new delegate']; + options = options.concat(delegates.map(function(d) { + let perm = renderTable(permissions, d.address); + return `Account: ${d.address} Details: ${d.details} - Permisions: ${JSON.stringify(permissions[d.address])}` + Permisions: ${perm}` })); let index = readlineSync.keyInSelect(options, 'Select a delegate:', {cancel: false}); @@ -268,6 +271,19 @@ async function getDelegatesAndPermissions() { return result } +function renderTable(permisions, address) { + let result = ``; + if (permisions[address] != undefined) { + for (const obj of permisions[address]) { + result += ` + ${obj.module} -> ${obj.permission}`; + } + } else { + result = `-`; + } + return result +} + module.exports = { executeApp: async function(remoteNetwork) { return executeApp(remoteNetwork); From 655bf524a60dddb1c40b37f03cfce29eeee72668 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Wed, 7 Nov 2018 17:47:15 -0300 Subject: [PATCH 049/582] Typo --- CLI/commands/permission_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index 4fd649467..bf96eff66 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -217,7 +217,7 @@ async function addNewDelegate() { let addPermissionAction = generalPermissionManager.methods.addDelegate(newDelegate, web3.utils.asciiToHex(details)); let receipt = await common.sendTransaction(Issuer, addPermissionAction, defaultGasPrice); let event = common.getEventFromLogs(generalPermissionManager._jsonInterface, receipt.logs, 'AddDelegate'); - console.log(`Delegate added succesfully: ${event._delegate} - ${event._details}`); + console.log(`Delegate added succesfully: ${event._delegate} - ${web3.utils.hexToAscii(event._details)}`); isNewDelegate = true; return event._delegate; } From e714e48b11e76e739f0461c80c9e3c829901239a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 8 Nov 2018 12:39:59 +0530 Subject: [PATCH 050/582] Sanity checks --- contracts/modules/Module.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index aa3e6d865..1e27d424e 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -25,6 +25,7 @@ contract Module is IModule { * @param _polyAddress Address of the polytoken */ constructor (address _securityToken, address _polyAddress) public { + require(_securityToken != address(0) && _polyAddress != address(0), "Invalid address"); securityToken = _securityToken; factory = msg.sender; polyToken = IERC20(_polyAddress); From dbd0e81bcc8054f026c06eaba8d34e5a78895a57 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 8 Nov 2018 12:40:39 +0530 Subject: [PATCH 051/582] Configure reworked --- contracts/modules/STO/USDTieredSTO.sol | 182 +++++++++++++++---------- 1 file changed, 107 insertions(+), 75 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 894744451..ace8fcdbb 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -17,6 +17,15 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { ///////////// // Storage // ///////////// + struct Tier { + uint256 rate; + uint256 rateDiscountPoly; + uint256 tokenTotal; + uint256 tokensDiscountPoly; + uint256 mintedTotal; + mapping (uint8 => uint256) minted; //fundtype => minted + uint256 mintedDiscountPoly; + } string public POLY_ORACLE = "PolyUsdOracle"; string public ETH_ORACLE = "EthUsdOracle"; @@ -27,32 +36,35 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Determine whether users can invest on behalf of a beneficiary bool public allowBeneficialInvestments = false; + // Whether or not the STO has been finalized + bool public isFinalized; + // Address where ETH, POLY & DAI funds are delivered address public wallet; // Address of issuer reserve wallet for unsold tokens address public reserveWallet; - // How many token units a buyer gets per USD per tier (multiplied by 10**18) - uint256[] public ratePerTier; + // // How many token units a buyer gets per USD per tier (multiplied by 10**18) + // uint256[] public ratePerTier; - // How many token units a buyer gets per USD per tier (multiplied by 10**18) when investing in POLY up to tokensPerTierDiscountPoly - uint256[] public ratePerTierDiscountPoly; + // // How many token units a buyer gets per USD per tier (multiplied by 10**18) when investing in POLY up to tokensPerTierDiscountPoly + // uint256[] public ratePerTierDiscountPoly; - // How many tokens are available in each tier (relative to totalSupply) - uint256[] public tokensPerTierTotal; + // // How many tokens are available in each tier (relative to totalSupply) + // uint256[] public tokensPerTierTotal; - // How many token units are available in each tier (relative to totalSupply) at the ratePerTierDiscountPoly rate - uint256[] public tokensPerTierDiscountPoly; + // // How many token units are available in each tier (relative to totalSupply) at the ratePerTierDiscountPoly rate + // uint256[] public tokensPerTierDiscountPoly; - // How many tokens have been minted in each tier (relative to totalSupply) - uint256[] public mintedPerTierTotal; + // // How many tokens have been minted in each tier (relative to totalSupply) + // uint256[] public mintedPerTierTotal; - // How many tokens have been minted in each tier (relative to totalSupply) for each fund raise type - mapping (uint8 => uint256[]) public mintedPerTier; + // // How many tokens have been minted in each tier (relative to totalSupply) for each fund raise type + // mapping (uint8 => uint256[]) public mintedPerTier; - // How many tokens have been minted in each tier (relative to totalSupply) at discounted POLY rate - uint256[] public mintedPerTierDiscountPoly; + // // How many tokens have been minted in each tier (relative to totalSupply) at discounted POLY rate + // uint256[] public mintedPerTierDiscountPoly; // Current tier uint8 public currentTier; @@ -78,12 +90,12 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Minimum investable amount in USD uint256 public minimumInvestmentUSD; - // Whether or not the STO has been finalized - bool public isFinalized; - // Final amount of tokens returned to issuer uint256 public finalAmountReturned; + // Tiers + Tier public tiers; + //////////// // Events // //////////// @@ -108,16 +120,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _spentValue, uint256 _rate ); - event FundsReceivedPOLY( - address indexed _purchaser, - address indexed _beneficiary, - uint256 _usdAmount, - uint256 _receivedValue, - uint256 _spentValue, - uint256 _rate - ); event ReserveTokenMint(address indexed _owner, address indexed _wallet, uint256 _tokens, uint8 _latestTier); - event SetAddresses( address indexed _wallet, address indexed _reserveWallet, @@ -143,19 +146,19 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { /////////////// modifier validETH { - require(_getOracle(bytes32("ETH"), bytes32("USD")) != address(0), "Invalid ETHUSD Oracle"); - require(fundRaiseTypes[uint8(FundRaiseType.ETH)], "Fund raise in ETH should be allowed"); + require(_getOracle(bytes32("ETH"), bytes32("USD")) != address(0), "Invalid Oracle"); + require(fundRaiseTypes[uint8(FundRaiseType.ETH)], "ETH not allowed"); _; } modifier validPOLY { - require(_getOracle(bytes32("POLY"), bytes32("USD")) != address(0), "Invalid POLYUSD Oracle"); - require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "Fund raise in POLY should be allowed"); + require(_getOracle(bytes32("POLY"), bytes32("USD")) != address(0), "Invalid Oracle"); + require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "POLY not allowed"); _; } modifier validDAI { - require(fundRaiseTypes[uint8(FundRaiseType.DAI)], "Fund raise in DAI should be allowed"); + require(fundRaiseTypes[uint8(FundRaiseType.DAI)], "DAI not allowed"); _; } @@ -164,10 +167,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { /////////////////////// constructor (address _securityToken, address _polyAddress, address _factory) public Module(_securityToken, _polyAddress) { + require(_factory != address(0), "Invalid factory"); oracleKeys[bytes32("ETH")][bytes32("USD")] = ETH_ORACLE; oracleKeys[bytes32("POLY")][bytes32("USD")] = POLY_ORACLE; - require(_factory != address(0), "In-valid address"); - factory = _factory; + factory = _factory; //Explicitly setting factory as we are using proxy deployment for this module } /** @@ -197,33 +200,26 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { address _reserveWallet, address _usdToken ) public onlyFactory { - modifyTimes(_startTime, _endTime); - // NB - modifyTiers must come before modifyFunding - modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); - // NB - modifyFunding must come before modifyAddresses - modifyFunding(_fundRaiseTypes); - modifyAddresses(_wallet, _reserveWallet, _usdToken); - modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); + _modifyTimes(_startTime, _endTime); + _modifyTimes(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); + // NB - _setFundRaiseType must come before modifyAddresses + _setFundRaiseType(_fundRaiseTypes); + _modifyAddresses(_wallet, _reserveWallet, _usdToken); + _modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); } - function modifyFunding(FundRaiseType[] _fundRaiseTypes) public onlyFactoryOrOwner { + function modifyFunding(FundRaiseType[] _fundRaiseTypes) external { /*solium-disable-next-line security/no-block-members*/ - require(now < startTime, "STO shouldn't be started"); + require(now < startTime, "STO already started"); _setFundRaiseType(_fundRaiseTypes); - uint256 length = getNumberOfTiers(); - mintedPerTierTotal = new uint256[](length); - mintedPerTierDiscountPoly = new uint256[](length); - for (uint8 i = 0; i < _fundRaiseTypes.length; i++) { - mintedPerTier[uint8(_fundRaiseTypes[i])] = new uint256[](length); - } } function modifyLimits( uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD - ) public onlyFactoryOrOwner { + ) external onlyFactoryOrOwner { /*solium-disable-next-line security/no-block-members*/ - require(now < startTime, "STO shouldn't be started"); + require(now < startTime, "STO already started"); minimumInvestmentUSD = _minimumInvestmentUSD; nonAccreditedLimitUSD = _nonAccreditedLimitUSD; emit SetLimits(minimumInvestmentUSD, nonAccreditedLimitUSD); @@ -234,32 +230,70 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256[] _ratePerTierDiscountPoly, uint256[] _tokensPerTierTotal, uint256[] _tokensPerTierDiscountPoly - ) public onlyFactoryOrOwner { + ) external onlyFactoryOrOwner { /*solium-disable-next-line security/no-block-members*/ - require(now < startTime, "STO shouldn't be started"); - require(_tokensPerTierTotal.length > 0, "Length should be > 0"); - require(_ratePerTier.length == _tokensPerTierTotal.length, "Mismatch b/w rates & tokens / tier"); - require(_ratePerTierDiscountPoly.length == _tokensPerTierTotal.length, "Mismatch b/w discount rates & tokens / tier"); - require(_tokensPerTierDiscountPoly.length == _tokensPerTierTotal.length, "Mismatch b/w discount tokens / tier & tokens / tier"); - for (uint8 i = 0; i < _ratePerTier.length; i++) { - require(_ratePerTier[i] > 0, "Rate > 0"); - require(_tokensPerTierTotal[i] > 0, "Tokens per tier > 0"); - require(_tokensPerTierDiscountPoly[i] <= _tokensPerTierTotal[i], "Discounted tokens / tier <= tokens / tier"); - require(_ratePerTierDiscountPoly[i] <= _ratePerTier[i], "Discounted rate / tier <= rate / tier"); - } - ratePerTier = _ratePerTier; - ratePerTierDiscountPoly = _ratePerTierDiscountPoly; - tokensPerTierTotal = _tokensPerTierTotal; - tokensPerTierDiscountPoly = _tokensPerTierDiscountPoly; - emit SetTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); + require(now < startTime, "STO already started"); + _modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); } function modifyTimes( uint256 _startTime, uint256 _endTime - ) public onlyFactoryOrOwner { + ) external onlyFactoryOrOwner { + _modifyTimes(_startTime, _endTime); + } + + function modifyAddresses( + address _wallet, + address _reserveWallet, + address _usdToken + ) external onlyFactoryOrOwner { /*solium-disable-next-line security/no-block-members*/ - require((startTime == 0) || (now < startTime), "Invalid startTime"); + require(now < startTime, "STO already started"); + _modifyAddresses(_wallet, _reserveWallet, _usdToken); + } + + function _modifyLimits( + uint256 _nonAccreditedLimitUSD, + uint256 _minimumInvestmentUSD + ) internal { + minimumInvestmentUSD = _minimumInvestmentUSD; + nonAccreditedLimitUSD = _nonAccreditedLimitUSD; + emit SetLimits(minimumInvestmentUSD, nonAccreditedLimitUSD); + } + + function _modifyTiers( + uint256[] _ratePerTier, + uint256[] _ratePerTierDiscountPoly, + uint256[] _tokensPerTierTotal, + uint256[] _tokensPerTierDiscountPoly + ) internal { + require(_tokensPerTierTotal.length > 0, "No tiers provided"); + require(_ratePerTier.length == _tokensPerTierTotal.length && + _ratePerTierDiscountPoly.length == _tokensPerTierTotal.length && + _tokensPerTierDiscountPoly.length == _tokensPerTierTotal.length, + "Tier data length mismatch" + ); + delete tiers; + for (uint256 i = 0; i < _ratePerTier.length; i++) { + require(_ratePerTier[i] > 0, "Invalid rate"); + require(_tokensPerTierTotal[i] > 0, "Invalid token amount"); + require(_tokensPerTierDiscountPoly[i] <= _tokensPerTierTotal[i], "Too many discounted tokens"); + require(_ratePerTierDiscountPoly[i] <= _ratePerTier[i], "Invalid discount"); + tiers.length++; + Tier storage currentTier = tiers[i]; + currentTier.rate = _ratePerTier[i]; + currentTier.rateDiscountPoly = _ratePerTierDiscountPoly[i]; + currentTier.tokenTotal = _tokensPerTierTotal[i]; + currentTier.tokensDiscountPoly = _tokensPerTierDiscountPoly[i]; + } + emit SetTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); + } + + function _modifyTimes( + uint256 _startTime, + uint256 _endTime + ) internal { /*solium-disable-next-line security/no-block-members*/ require((_endTime > _startTime) && (_startTime > now), "Invalid times"); startTime = _startTime; @@ -267,16 +301,14 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { emit SetTimes(_startTime, _endTime); } - function modifyAddresses( + function _modifyAddresses( address _wallet, address _reserveWallet, address _usdToken - ) public onlyFactoryOrOwner { - /*solium-disable-next-line security/no-block-members*/ - require(now < startTime, "STO shouldn't be started"); - require(_wallet != address(0) && _reserveWallet != address(0), "Invalid address"); + ) internal { + require(_wallet != address(0) && _reserveWallet != address(0), "Invalid wallet"); if (fundRaiseTypes[uint8(FundRaiseType.DAI)]) { - require(_usdToken != address(0), "Invalid address"); + require(_usdToken != address(0), "Invalid usdToken"); } wallet = _wallet; reserveWallet = _reserveWallet; From 5b5e4a14b066c7b1e241fb6487fc72dbb07b365d Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 8 Nov 2018 14:21:00 +0530 Subject: [PATCH 052/582] Changes in tier handling --- contracts/modules/STO/USDTieredSTO.sol | 114 +++++++++++++------------ 1 file changed, 60 insertions(+), 54 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index ace8fcdbb..50763604b 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -67,7 +67,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // uint256[] public mintedPerTierDiscountPoly; // Current tier - uint8 public currentTier; + uint256 public currentTier; // Amount of USD funds raised uint256 public fundsRaisedUSD; @@ -94,7 +94,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 public finalAmountReturned; // Tiers - Tier public tiers; + Tier[] public tiers; //////////// // Events // @@ -109,7 +109,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _tokens, uint256 _usdAmount, uint256 _tierPrice, - uint8 _tier + uint256 _tier ); event FundsReceived( address indexed _purchaser, @@ -120,7 +120,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _spentValue, uint256 _rate ); - event ReserveTokenMint(address indexed _owner, address indexed _wallet, uint256 _tokens, uint8 _latestTier); + event ReserveTokenMint(address indexed _owner, address indexed _wallet, uint256 _tokens, uint256 _latestTier); event SetAddresses( address indexed _wallet, address indexed _reserveWallet, @@ -201,7 +201,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { address _usdToken ) public onlyFactory { _modifyTimes(_startTime, _endTime); - _modifyTimes(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); + _modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); // NB - _setFundRaiseType must come before modifyAddresses _setFundRaiseType(_fundRaiseTypes); _modifyAddresses(_wallet, _reserveWallet, _usdToken); @@ -280,12 +280,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { require(_tokensPerTierTotal[i] > 0, "Invalid token amount"); require(_tokensPerTierDiscountPoly[i] <= _tokensPerTierTotal[i], "Too many discounted tokens"); require(_ratePerTierDiscountPoly[i] <= _ratePerTier[i], "Invalid discount"); - tiers.length++; - Tier storage currentTier = tiers[i]; - currentTier.rate = _ratePerTier[i]; - currentTier.rateDiscountPoly = _ratePerTierDiscountPoly[i]; - currentTier.tokenTotal = _tokensPerTierTotal[i]; - currentTier.tokensDiscountPoly = _tokensPerTierDiscountPoly[i]; + tiers.push(Tier(_ratePerTier[i], _ratePerTierDiscountPoly[i], _tokensPerTierTotal[i], _tokensPerTierDiscountPoly[i], 0, 0)); } emit SetTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); } @@ -330,12 +325,12 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 tempReturned; uint256 tempSold; uint256 remainingTokens; - for (uint8 i = 0; i < tokensPerTierTotal.length; i++) { - remainingTokens = tokensPerTierTotal[i].sub(mintedPerTierTotal[i]); + for (uint256 i = 0; i < tiers.length; i++) { + remainingTokens = tiers[i].tokenTotal.sub(tiers[i].mintedTotal); tempReturned = tempReturned.add(remainingTokens); - tempSold = tempSold.add(mintedPerTierTotal[i]); + tempSold = tempSold.add(tiers[i].mintedTotal); if (remainingTokens > 0) { - mintedPerTierTotal[i] = tokensPerTierTotal[i]; + tiers[i].mintedTotal = tiers[i].tokenTotal; } } require(ISecurityToken(securityToken).mint(reserveWallet, tempReturned), "Error in minting"); @@ -366,7 +361,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { //nonAccreditedLimitUSDOverride require(_investors.length == _nonAccreditedLimit.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { - require(_nonAccreditedLimit[i] > 0, "Limit can not be 0"); + require(_nonAccreditedLimit[i] > 0, "Limit = 0"); nonAccreditedLimitUSDOverride[_investors[i]] = _nonAccreditedLimit[i]; emit SetNonAccreditedLimit(_investors[i], _nonAccreditedLimit[i]); } @@ -390,15 +385,18 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @notice fallback function - assumes ETH being invested */ function () external payable { - buyWithETH(msg.sender); + uint256 rate = getRate(FundRaiseType.ETH); + buyWithETH(msg.sender, rate); } /** * @notice Purchase tokens using ETH * @param _beneficiary Address where security tokens will be sent + * @param _minRate Minumum conversion rate (FundType => USD) at which buying is authorized */ - function buyWithETH(address _beneficiary) public payable validETH { + function buyWithETH(address _beneficiary, uint256 _minRate) public payable validETH { uint256 rate = getRate(FundRaiseType.ETH); + require(rate >= _minRate, "Current rate below min"); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, msg.value, rate, FundRaiseType.ETH); // Modify storage investorInvested[_beneficiary][uint8(FundRaiseType.ETH)] = investorInvested[_beneficiary][uint8(FundRaiseType.ETH)].add(spentValue); @@ -414,23 +412,26 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @notice Purchase tokens using POLY * @param _beneficiary Address where security tokens will be sent * @param _investedPOLY Amount of POLY invested + * @param _minRate Maximum rate at which buying is authorized */ - function buyWithPOLY(address _beneficiary, uint256 _investedPOLY) public validPOLY { - _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY); + function buyWithPOLY(address _beneficiary, uint256 _investedPOLY, uint256 _minRate) public validPOLY { + _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, _minRate); } /** * @notice Purchase tokens using POLY * @param _beneficiary Address where security tokens will be sent * @param _investedDAI Amount of POLY invested + * @param _minRate Maximum rate at which buying is authorized */ - function buyWithUSD(address _beneficiary, uint256 _investedDAI) public validDAI { - _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI); + function buyWithUSD(address _beneficiary, uint256 _investedDAI, uint256 _minRate) public validDAI { + _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, _minRate); } - function _buyWithTokens(address _beneficiary, uint256 _tokenAmount, FundRaiseType _fundRaiseType) internal { - require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI, "POLY & DAI supported"); + function _buyWithTokens(address _beneficiary, uint256 _tokenAmount, FundRaiseType _fundRaiseType, uint256 _minRate) internal { + require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI, "Invalid raise type"); uint256 rate = getRate(_fundRaiseType); + require(rate >= _minRate, "Current rate below min"); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, _tokenAmount, rate, _fundRaiseType); // Modify storage investorInvested[_beneficiary][uint8(_fundRaiseType)] = investorInvested[_beneficiary][uint8(_fundRaiseType)].add(spentValue); @@ -459,37 +460,40 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { returns(uint256, uint256) { if (!allowBeneficialInvestments) { - require(_beneficiary == msg.sender, "Beneficiary does not match funder"); + require(_beneficiary == msg.sender, "Beneficiary != funder"); } - require(isOpen(), "STO is not open"); + require(isOpen(), "STO not open"); require(_investmentValue > 0, "No funds were sent"); uint256 investedUSD = DecimalMath.mul(_rate, _investmentValue); uint256 originalUSD = investedUSD; // Check for minimum investment - require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); + //require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); + require(investedUSD >= minimumInvestmentUSD, "investment < minimumInvestmentUSD"); //Why do we need to add? // Check for non-accredited cap if (!accredited[_beneficiary]) { uint256 investorLimitUSD = (nonAccreditedLimitUSDOverride[_beneficiary] == 0) ? nonAccreditedLimitUSD : nonAccreditedLimitUSDOverride[_beneficiary]; - require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Non-accredited investor has reached limit"); + //require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Non-accredited investor has reached limit"); not required. if (investedUSD.add(investorInvestedUSD[_beneficiary]) > investorLimitUSD) investedUSD = investorLimitUSD.sub(investorInvestedUSD[_beneficiary]); } uint256 spentUSD; // Iterate over each tier and process payment - for (uint8 i = currentTier; i < ratePerTier.length; i++) { + for (uint256 i = currentTier; i < tiers.length; i++) { // Update current tier if needed if (currentTier != i) currentTier = i; // If there are tokens remaining, process investment - if (mintedPerTierTotal[i] < tokensPerTierTotal[i]) + if (tiers[i].mintedTotal < tiers[i].tokenTotal) { spentUSD = spentUSD.add(_calculateTier(_beneficiary, i, investedUSD.sub(spentUSD), _fundRaiseType)); - // If all funds have been spent, exit the loop - if (investedUSD == spentUSD) - break; + // If all funds have been spent, exit the loop + if (investedUSD == spentUSD) + break; + } + } // Modify storage @@ -514,7 +518,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { function _calculateTier( address _beneficiary, - uint8 _tier, + uint256 _tier, uint256 _investedUSD, FundRaiseType _fundRaiseType ) @@ -526,25 +530,26 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 tierSpentUSD; uint256 tierPurchasedTokens; uint256 investedUSD = _investedUSD; + Tier storage tierData = tiers[_tier]; // Check whether there are any remaining discounted tokens - if ((_fundRaiseType == FundRaiseType.POLY) && (tokensPerTierDiscountPoly[_tier] > mintedPerTierDiscountPoly[_tier])) { - uint256 discountRemaining = tokensPerTierDiscountPoly[_tier].sub(mintedPerTierDiscountPoly[_tier]); - uint256 totalRemaining = tokensPerTierTotal[_tier].sub(mintedPerTierTotal[_tier]); + if ((_fundRaiseType == FundRaiseType.POLY) && (tierData.tokensDiscountPoly > tierData.mintedDiscountPoly)) { + uint256 discountRemaining = tierData.tokensDiscountPoly.sub(tierData.mintedDiscountPoly); + uint256 totalRemaining = tierData.tokenTotal.sub(tierData.mintedTotal); if (totalRemaining < discountRemaining) - (spentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, ratePerTierDiscountPoly[_tier], totalRemaining, investedUSD, _tier); + (spentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, totalRemaining, investedUSD, _tier); else - (spentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, ratePerTierDiscountPoly[_tier], discountRemaining, investedUSD, _tier); + (spentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, discountRemaining, investedUSD, _tier); investedUSD = investedUSD.sub(spentUSD); - mintedPerTierDiscountPoly[_tier] = mintedPerTierDiscountPoly[_tier].add(tierPurchasedTokens); - mintedPerTier[uint8(FundRaiseType.POLY)][_tier] = mintedPerTier[uint8(FundRaiseType.POLY)][_tier].add(tierPurchasedTokens); - mintedPerTierTotal[_tier] = mintedPerTierTotal[_tier].add(tierPurchasedTokens); + tierData.mintedDiscountPoly = tierData.mintedDiscountPoly.add(tierPurchasedTokens); + tierData.minted[uint8(_fundRaiseType)] = tierData.minted[uint8(_fundRaiseType)].add(tierPurchasedTokens); + tierData.mintedTotal = tierData.mintedTotal.add(tierPurchasedTokens); } // Now, if there is any remaining USD to be invested, purchase at non-discounted rate - if ((investedUSD > 0) && (tokensPerTierTotal[_tier].sub(mintedPerTierTotal[_tier]) > 0)) { - (tierSpentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, ratePerTier[_tier], tokensPerTierTotal[_tier].sub(mintedPerTierTotal[_tier]), investedUSD, _tier); + if ((investedUSD > 0) && (tierData.tokenTotal.sub(tierData.mintedTotal) > 0)) { + (tierSpentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), investedUSD, _tier); spentUSD = spentUSD.add(tierSpentUSD); - mintedPerTier[uint8(_fundRaiseType)][_tier] = mintedPerTier[uint8(_fundRaiseType)][_tier].add(tierPurchasedTokens); - mintedPerTierTotal[_tier] = mintedPerTierTotal[_tier].add(tierPurchasedTokens); + tierData.minted[uint8(_fundRaiseType)] = tierData.minted[uint8(_fundRaiseType)].add(tierPurchasedTokens); + tierData.mintedTotal = tierData.mintedTotal.add(tierPurchasedTokens); } return spentUSD; } @@ -554,12 +559,13 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _tierPrice, uint256 _tierRemaining, uint256 _investedUSD, - uint8 _tier + uint256 _tier ) internal returns(uint256, uint256) { uint256 maximumTokens = DecimalMath.div(_investedUSD, _tierPrice); + maximumTokens = maximumTokens.sub(maximumTokens.div(ISecurityToken(securityToken).granularity())); uint256 spentUSD; uint256 purchasedTokens; if (maximumTokens > _tierRemaining) { @@ -570,7 +576,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } purchasedTokens = _tierRemaining; } else { - spentUSD = _investedUSD; + spentUSD = DecimalMath.mul(maximumTokens, _tierPrice); purchasedTokens = maximumTokens; } require(ISecurityToken(securityToken).mint(_beneficiary, purchasedTokens), "Error in minting"); @@ -608,7 +614,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { if (isFinalized) { return (finalAmountReturned == 0); } - return (mintedPerTierTotal[mintedPerTierTotal.length - 1] == tokensPerTierTotal[tokensPerTierTotal.length - 1]); + return (tiers[tiers.length - 1].mintedTotal == tiers[tiers.length - 1].tokenTotal); } function getRate(FundRaiseType _fundRaiseType) public view returns (uint256) { @@ -662,8 +668,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { */ function getTokensMinted() public view returns (uint256) { uint256 tokensMinted; - for (uint8 i = 0; i < mintedPerTierTotal.length; i++) { - tokensMinted = tokensMinted.add(mintedPerTierTotal[i]); + for (uint256 i = 0; i < tiers.length; i++) { + tokensMinted = tokensMinted.add(tiers[i].mintedTotal); } return tokensMinted; } @@ -674,8 +680,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { */ function getTokensSoldFor(FundRaiseType _fundRaiseType) public view returns (uint256) { uint256 tokensSold; - for (uint8 i = 0; i < mintedPerTier[uint8(_fundRaiseType)].length; i++) { - tokensSold = tokensSold.add(mintedPerTier[uint8(_fundRaiseType)][i]); + for (uint256 i = 0; i < tiers.length; i++) { + tokensSold = tokensSold.add(tiers[i].minted[uint8(_fundRaiseType)]); } return tokensSold; } @@ -685,7 +691,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @return uint256 Total number of tiers */ function getNumberOfTiers() public view returns (uint256) { - return tokensPerTierTotal.length; + return tiers.length; } /** From 7c1d555f700cd7942f1bbe2f1e68b5f41f00c8b9 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 8 Nov 2018 15:50:35 +0530 Subject: [PATCH 053/582] bug fixes --- contracts/modules/STO/USDTieredSTO.sol | 30 ++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 50763604b..225d61895 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -385,8 +385,16 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @notice fallback function - assumes ETH being invested */ function () external payable { - uint256 rate = getRate(FundRaiseType.ETH); - buyWithETH(msg.sender, rate); + buyWithETHRateLimited(msg.sender, 0); + } + + // For backwards compatibility + function buyWithETH(address _beneficiary) public payable { + buyWithETHRateLimited(_beneficiary, 0); + } + + function buyWithPOLY(address _beneficiary, uint256 _investedPOLY) public { + _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, 0); } /** @@ -394,7 +402,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @param _beneficiary Address where security tokens will be sent * @param _minRate Minumum conversion rate (FundType => USD) at which buying is authorized */ - function buyWithETH(address _beneficiary, uint256 _minRate) public payable validETH { + function buyWithETHRateLimited(address _beneficiary, uint256 _minRate) public payable validETH { uint256 rate = getRate(FundRaiseType.ETH); require(rate >= _minRate, "Current rate below min"); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, msg.value, rate, FundRaiseType.ETH); @@ -414,7 +422,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @param _investedPOLY Amount of POLY invested * @param _minRate Maximum rate at which buying is authorized */ - function buyWithPOLY(address _beneficiary, uint256 _investedPOLY, uint256 _minRate) public validPOLY { + function buyWithPOLYRateLimited(address _beneficiary, uint256 _investedPOLY, uint256 _minRate) public validPOLY { _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, _minRate); } @@ -422,10 +430,9 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @notice Purchase tokens using POLY * @param _beneficiary Address where security tokens will be sent * @param _investedDAI Amount of POLY invested - * @param _minRate Maximum rate at which buying is authorized */ - function buyWithUSD(address _beneficiary, uint256 _investedDAI, uint256 _minRate) public validDAI { - _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, _minRate); + function buyWithUSD(address _beneficiary, uint256 _investedDAI) public validDAI { + _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, uint256(10) ** 18); } function _buyWithTokens(address _beneficiary, uint256 _tokenAmount, FundRaiseType _fundRaiseType, uint256 _minRate) internal { @@ -467,7 +474,6 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { require(_investmentValue > 0, "No funds were sent"); uint256 investedUSD = DecimalMath.mul(_rate, _investmentValue); - uint256 originalUSD = investedUSD; // Check for minimum investment //require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); @@ -476,7 +482,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Check for non-accredited cap if (!accredited[_beneficiary]) { uint256 investorLimitUSD = (nonAccreditedLimitUSDOverride[_beneficiary] == 0) ? nonAccreditedLimitUSD : nonAccreditedLimitUSDOverride[_beneficiary]; - //require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Non-accredited investor has reached limit"); not required. + require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Over Non-accredited investor limit"); if (investedUSD.add(investorInvestedUSD[_beneficiary]) > investorLimitUSD) investedUSD = investorLimitUSD.sub(investorInvestedUSD[_beneficiary]); } @@ -509,7 +515,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { if (spentUSD == 0) { spentValue = 0; } else { - spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, originalUSD), _investmentValue); + spentValue = DecimalMath.div(spentUSD, _rate); } // Return calculated amounts @@ -565,7 +571,9 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { returns(uint256, uint256) { uint256 maximumTokens = DecimalMath.div(_investedUSD, _tierPrice); - maximumTokens = maximumTokens.sub(maximumTokens.div(ISecurityToken(securityToken).granularity())); + uint256 granularity = ISecurityToken(securityToken).granularity(); + maximumTokens = maximumTokens.div(granularity); + maximumTokens = maximumTokens.mul(granularity); uint256 spentUSD; uint256 purchasedTokens; if (maximumTokens > _tierRemaining) { From 1ee784cd25368d90ea3167ddf469390924fa542e Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 8 Nov 2018 15:54:26 +0530 Subject: [PATCH 054/582] test cases fixed --- test/p_usd_tiered_sto.js | 151 +++++++++++++++++------------------ test/q_usd_tiered_sto_sim.js | 52 ++++++------ 2 files changed, 98 insertions(+), 105 deletions(-) diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 5332700b4..fb8f8659e 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -165,8 +165,8 @@ contract("USDTieredSTO", accounts => { async function convert(_stoID, _tier, _discount, _currencyFrom, _currencyTo, _amount) { let USDTOKEN; - if (_discount) USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTierDiscountPoly.call(_tier); - else USDTOKEN = await I_USDTieredSTO_Array[_stoID].ratePerTier.call(_tier); + if (_discount) USDTOKEN = ((await I_USDTieredSTO_Array[_stoID].tiers.call(_tier))[1]); + else USDTOKEN = ((await I_USDTieredSTO_Array[_stoID].tiers.call(_tier))[0]); if (_currencyFrom == "TOKEN") { let tokenToUSD = _amount .div(10 ** 18) @@ -327,28 +327,28 @@ contract("USDTieredSTO", accounts => { assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(), _startTime[stoId], "Incorrect _startTime in config"); assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(), _endTime[stoId], "Incorrect _endTime in config"); - for (var i = 0; i < _ratePerTier[stoId].length; i++) { - assert.equal( - (await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), - _ratePerTier[stoId][i].toNumber(), - "Incorrect _ratePerTier in config" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), - _ratePerTierDiscountPoly[stoId][i].toNumber(), - "Incorrect _ratePerTierDiscountPoly in config" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), - _tokensPerTierTotal[stoId][i].toNumber(), - "Incorrect _tokensPerTierTotal in config" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), - _tokensPerTierDiscountPoly[stoId][i].toNumber(), - "Incorrect _tokensPerTierDiscountPoly in config" - ); - } + // for (var i = 0; i < _ratePerTier[stoId].length; i++) { + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), + // _ratePerTier[stoId][i].toNumber(), + // "Incorrect _ratePerTier in config" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), + // _ratePerTierDiscountPoly[stoId][i].toNumber(), + // "Incorrect _ratePerTierDiscountPoly in config" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), + // _tokensPerTierTotal[stoId][i].toNumber(), + // "Incorrect _tokensPerTierTotal in config" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), + // _tokensPerTierDiscountPoly[stoId][i].toNumber(), + // "Incorrect _tokensPerTierDiscountPoly in config" + // ); + // } assert.equal( (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), @@ -512,28 +512,28 @@ contract("USDTieredSTO", accounts => { assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(), _startTime[stoId], "Incorrect _startTime in config"); assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(), _endTime[stoId], "Incorrect _endTime in config"); - for (var i = 0; i < _ratePerTier[stoId].length; i++) { - assert.equal( - (await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), - _ratePerTier[stoId][i].toNumber(), - "Incorrect _ratePerTier in config" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), - _ratePerTierDiscountPoly[stoId][i].toNumber(), - "Incorrect _ratePerTierDiscountPoly in config" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), - _tokensPerTierTotal[stoId][i].toNumber(), - "Incorrect _tokensPerTierTotal in config" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), - _tokensPerTierDiscountPoly[stoId][i].toNumber(), - "Incorrect _tokensPerTierDiscountPoly in config" - ); - } + // for (var i = 0; i < _ratePerTier[stoId].length; i++) { + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), + // _ratePerTier[stoId][i].toNumber(), + // "Incorrect _ratePerTier in config" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), + // _ratePerTierDiscountPoly[stoId][i].toNumber(), + // "Incorrect _ratePerTierDiscountPoly in config" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), + // _tokensPerTierTotal[stoId][i].toNumber(), + // "Incorrect _tokensPerTierTotal in config" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), + // _tokensPerTierDiscountPoly[stoId][i].toNumber(), + // "Incorrect _tokensPerTierDiscountPoly in config" + // ); + // } assert.equal( (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), @@ -864,26 +864,26 @@ contract("USDTieredSTO", accounts => { [BigNumber(15 * 10 ** 20)], { from: ISSUER } ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].ratePerTier.call(0)).toNumber(), - BigNumber(15 * 10 ** 18).toNumber(), - "STO Configuration doesn't set as expected" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(0)).toNumber(), - BigNumber(13 * 10 ** 18).toNumber(), - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(0), - BigNumber(15 * 10 ** 20).toNumber(), - "STO Configuration doesn't set as expected" - ); - assert.equal( - await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(0), - BigNumber(15 * 10 ** 20).toNumber(), - "STO Configuration doesn't set as expected" - ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].ratePerTier.call(0)).toNumber(), + // BigNumber(15 * 10 ** 18).toNumber(), + // "STO Configuration doesn't set as expected" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(0)).toNumber(), + // BigNumber(13 * 10 ** 18).toNumber(), + // "STO Configuration doesn't set as expected" + // ); + // assert.equal( + // await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(0), + // BigNumber(15 * 10 ** 20).toNumber(), + // "STO Configuration doesn't set as expected" + // ); + // assert.equal( + // await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(0), + // BigNumber(15 * 10 ** 20).toNumber(), + // "STO Configuration doesn't set as expected" + // ); let tempTime1 = latestTime() + duration.days(0.1); let tempTime2 = latestTime() + duration.days(0.2); @@ -989,25 +989,18 @@ contract("USDTieredSTO", accounts => { await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, { from: NONACCREDITED1 }); await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, { from: ACCREDITED1 }); - // NONACCREDITED ETH await catchRevert(I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH })); - // NONACCREDITED POLY await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1 })); - // NONACCREDITED DAI await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1 })); - // ACCREDITED ETH await catchRevert(I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH })); - // ACCREDITED POLY await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1 })); - // ACCREDITED DAI await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1 })); - await revertToSnapshot(snapId); }); @@ -2850,7 +2843,7 @@ contract("USDTieredSTO", accounts => { let stoId = 1; let tierId = 5; - let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); + let minted = (await I_USDTieredSTO_Array[stoId].tiers.call(tierId))[4]; console.log(minted.toNumber() + ":" + _tokensPerTierTotal[stoId][tierId]); let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); console.log(investment_Token.toNumber()); @@ -3840,8 +3833,8 @@ contract("USDTieredSTO", accounts => { let investment_Token = delta_Token.add(delta_Token); // 10 Token let investment_POLY = polyTier0.add(polyTier1); // 0.0025 ETH - let tokensRemaining = (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier)).sub( - await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier) + let tokensRemaining = (await I_USDTieredSTO_Array[stoId].tiers.call(startTier))[2].sub( + (await I_USDTieredSTO_Array[stoId].tiers.call(startTier))[4] ); let prep_Token = tokensRemaining.sub(delta_Token); let prep_POLY = await convert(stoId, startTier, true, "TOKEN", "POLY", prep_Token); @@ -3851,8 +3844,8 @@ contract("USDTieredSTO", accounts => { let tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, prep_POLY, { from: ACCREDITED1, gasPrice: GAS_PRICE }); console.log(" Gas buyWithPOLY: ".grey + tx.receipt.gasUsed.toString().grey); - let Tier0Token = await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(startTier); - let Tier0Minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(startTier); + let Tier0Token = (await I_USDTieredSTO_Array[stoId].tiers.call(startTier))[2]; + let Tier0Minted = (await I_USDTieredSTO_Array[stoId].tiers.call(startTier))[4]; assert.equal(Tier0Minted.toNumber(), Tier0Token.sub(delta_Token).toNumber()); await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); @@ -4027,7 +4020,7 @@ contract("USDTieredSTO", accounts => { let stoId = 2; let tierId = 1; - let minted = await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(tierId); + let minted = (await I_USDTieredSTO_Array[stoId].tiers.call(tierId))[4]; let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Token); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 53a12e74a..e22c9c4ac 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -297,28 +297,28 @@ contract("USDTieredSTO Sim", accounts => { assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(), _startTime[stoId], "Incorrect _startTime in config"); assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(), _endTime[stoId], "Incorrect _endTime in config"); - for (var i = 0; i < _ratePerTier[stoId].length; i++) { - assert.equal( - (await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), - _ratePerTier[stoId][i].toNumber(), - "Incorrect _ratePerTier in config" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), - _ratePerTierDiscountPoly[stoId][i].toNumber(), - "Incorrect _ratePerTierDiscountPoly in config" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), - _tokensPerTierTotal[stoId][i].toNumber(), - "Incorrect _tokensPerTierTotal in config" - ); - assert.equal( - (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), - _tokensPerTierDiscountPoly[stoId][i].toNumber(), - "Incorrect _tokensPerTierDiscountPoly in config" - ); - } + // for (var i = 0; i < _ratePerTier[stoId].length; i++) { + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), + // _ratePerTier[stoId][i].toNumber(), + // "Incorrect _ratePerTier in config" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), + // _ratePerTierDiscountPoly[stoId][i].toNumber(), + // "Incorrect _ratePerTierDiscountPoly in config" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), + // _tokensPerTierTotal[stoId][i].toNumber(), + // "Incorrect _tokensPerTierTotal in config" + // ); + // assert.equal( + // (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), + // _tokensPerTierDiscountPoly[stoId][i].toNumber(), + // "Incorrect _tokensPerTierDiscountPoly in config" + // ); + // } assert.equal( (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), @@ -455,13 +455,13 @@ contract("USDTieredSTO Sim", accounts => { let Tokens_discount = []; for (var i = 0; i < _ratePerTier[stoId].length; i++) { Tokens_total.push( - (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).sub( - await I_USDTieredSTO_Array[stoId].mintedPerTierTotal.call(i) + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].sub( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[4] ) ); Tokens_discount.push( - (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).sub( - await I_USDTieredSTO_Array[stoId].mintedPerTierDiscountPoly.call(i) + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].sub( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[5] ) ); } From 32b3869fadfd96eefd14a51760eb989615f465ef Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 8 Nov 2018 19:58:03 +0530 Subject: [PATCH 055/582] WIP --- contracts/modules/STO/USDTieredSTO.sol | 70 +++-- test/p_usd_tiered_sto.js | 352 ++++++++++++++++++++----- test/q_usd_tiered_sto_sim.js | 44 ++-- 3 files changed, 340 insertions(+), 126 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 225d61895..694f16e7e 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -18,12 +18,25 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Storage // ///////////// struct Tier { + // How many token units a buyer gets per USD in this tier (multiplied by 10**18) uint256 rate; - uint256 rateDiscountPoly; + + // How many token units a buyer gets per USD in this tier (multiplied by 10**18) when investing in POLY up to tokensDiscountPoly + uint256 rateDiscountPoly; + + // How many tokens are available in this tier (relative to totalSupply) uint256 tokenTotal; + + // How many token units are available in this tier (relative to totalSupply) at the ratePerTierDiscountPoly rate uint256 tokensDiscountPoly; + + // How many tokens have been minted in this tier (relative to totalSupply) uint256 mintedTotal; - mapping (uint8 => uint256) minted; //fundtype => minted + + // How many tokens have been minted in this tier (relative to totalSupply) for each fund raise type + mapping (uint8 => uint256) minted; + + // How many tokens have been minted in this tier (relative to totalSupply) at discounted POLY rate uint256 mintedDiscountPoly; } @@ -45,27 +58,6 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Address of issuer reserve wallet for unsold tokens address public reserveWallet; - // // How many token units a buyer gets per USD per tier (multiplied by 10**18) - // uint256[] public ratePerTier; - - // // How many token units a buyer gets per USD per tier (multiplied by 10**18) when investing in POLY up to tokensPerTierDiscountPoly - // uint256[] public ratePerTierDiscountPoly; - - // // How many tokens are available in each tier (relative to totalSupply) - // uint256[] public tokensPerTierTotal; - - // // How many token units are available in each tier (relative to totalSupply) at the ratePerTierDiscountPoly rate - // uint256[] public tokensPerTierDiscountPoly; - - // // How many tokens have been minted in each tier (relative to totalSupply) - // uint256[] public mintedPerTierTotal; - - // // How many tokens have been minted in each tier (relative to totalSupply) for each fund raise type - // mapping (uint8 => uint256[]) public mintedPerTier; - - // // How many tokens have been minted in each tier (relative to totalSupply) at discounted POLY rate - // uint256[] public mintedPerTierDiscountPoly; - // Current tier uint256 public currentTier; @@ -93,7 +85,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Final amount of tokens returned to issuer uint256 public finalAmountReturned; - // Tiers + // Array of Tiers Tier[] public tiers; //////////// @@ -427,9 +419,9 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } /** - * @notice Purchase tokens using POLY + * @notice Purchase tokens using DAI * @param _beneficiary Address where security tokens will be sent - * @param _investedDAI Amount of POLY invested + * @param _investedDAI Amount of DAI invested */ function buyWithUSD(address _beneficiary, uint256 _investedDAI) public validDAI { _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, uint256(10) ** 18); @@ -487,16 +479,20 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { investedUSD = investorLimitUSD.sub(investorInvestedUSD[_beneficiary]); } uint256 spentUSD; + uint256 spentValue; // Iterate over each tier and process payment for (uint256 i = currentTier; i < tiers.length; i++) { + bool gotoNextTier; // Update current tier if needed if (currentTier != i) currentTier = i; // If there are tokens remaining, process investment if (tiers[i].mintedTotal < tiers[i].tokenTotal) { - spentUSD = spentUSD.add(_calculateTier(_beneficiary, i, investedUSD.sub(spentUSD), _fundRaiseType)); + //spentValue used as temp variable here to prevent stackoverflow + (spentValue, gotoNextTier) = _calculateTier(_beneficiary, i, investedUSD.sub(spentUSD), _fundRaiseType); + spentUSD = spentUSD.add(spentValue); // If all funds have been spent, exit the loop - if (investedUSD == spentUSD) + if (!gotoNextTier) break; } @@ -510,8 +506,6 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { fundsRaisedUSD = fundsRaisedUSD.add(spentUSD); } - // Calculate spent in base currency (ETH, DAI or POLY) - uint256 spentValue; if (spentUSD == 0) { spentValue = 0; } else { @@ -529,10 +523,9 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { FundRaiseType _fundRaiseType ) internal - returns(uint256) + returns(uint256 spentUSD, bool gotoNextTier) { // First purchase any discounted tokens if POLY investment - uint256 spentUSD; uint256 tierSpentUSD; uint256 tierPurchasedTokens; uint256 investedUSD = _investedUSD; @@ -542,9 +535,9 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 discountRemaining = tierData.tokensDiscountPoly.sub(tierData.mintedDiscountPoly); uint256 totalRemaining = tierData.tokenTotal.sub(tierData.mintedTotal); if (totalRemaining < discountRemaining) - (spentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, totalRemaining, investedUSD, _tier); + (spentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, totalRemaining, investedUSD, _tier); else - (spentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, discountRemaining, investedUSD, _tier); + (spentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, discountRemaining, investedUSD, _tier); investedUSD = investedUSD.sub(spentUSD); tierData.mintedDiscountPoly = tierData.mintedDiscountPoly.add(tierPurchasedTokens); tierData.minted[uint8(_fundRaiseType)] = tierData.minted[uint8(_fundRaiseType)].add(tierPurchasedTokens); @@ -552,12 +545,11 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } // Now, if there is any remaining USD to be invested, purchase at non-discounted rate if ((investedUSD > 0) && (tierData.tokenTotal.sub(tierData.mintedTotal) > 0)) { - (tierSpentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), investedUSD, _tier); + (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), investedUSD, _tier); spentUSD = spentUSD.add(tierSpentUSD); tierData.minted[uint8(_fundRaiseType)] = tierData.minted[uint8(_fundRaiseType)].add(tierPurchasedTokens); tierData.mintedTotal = tierData.mintedTotal.add(tierPurchasedTokens); } - return spentUSD; } function _purchaseTier( @@ -568,14 +560,12 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _tier ) internal - returns(uint256, uint256) + returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) { uint256 maximumTokens = DecimalMath.div(_investedUSD, _tierPrice); uint256 granularity = ISecurityToken(securityToken).granularity(); maximumTokens = maximumTokens.div(granularity); maximumTokens = maximumTokens.mul(granularity); - uint256 spentUSD; - uint256 purchasedTokens; if (maximumTokens > _tierRemaining) { spentUSD = DecimalMath.mul(_tierRemaining, _tierPrice); // In case of rounding issues, ensure that spentUSD is never more than investedUSD @@ -583,13 +573,13 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { spentUSD = _investedUSD; } purchasedTokens = _tierRemaining; + gotoNextTier = true; } else { spentUSD = DecimalMath.mul(maximumTokens, _tierPrice); purchasedTokens = maximumTokens; } require(ISecurityToken(securityToken).mint(_beneficiary, purchasedTokens), "Error in minting"); emit TokenPurchase(msg.sender, _beneficiary, purchasedTokens, spentUSD, _tierPrice, _tier); - return (spentUSD, purchasedTokens); } ///////////// diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index fb8f8659e..fedf52294 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -327,28 +327,28 @@ contract("USDTieredSTO", accounts => { assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(), _startTime[stoId], "Incorrect _startTime in config"); assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(), _endTime[stoId], "Incorrect _endTime in config"); - // for (var i = 0; i < _ratePerTier[stoId].length; i++) { - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), - // _ratePerTier[stoId][i].toNumber(), - // "Incorrect _ratePerTier in config" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), - // _ratePerTierDiscountPoly[stoId][i].toNumber(), - // "Incorrect _ratePerTierDiscountPoly in config" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), - // _tokensPerTierTotal[stoId][i].toNumber(), - // "Incorrect _tokensPerTierTotal in config" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), - // _tokensPerTierDiscountPoly[stoId][i].toNumber(), - // "Incorrect _tokensPerTierDiscountPoly in config" - // ); - // } + for (var i = 0; i < _ratePerTier[stoId].length; i++) { + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[0].toNumber(), + _ratePerTier[stoId][i].toNumber(), + "Incorrect _ratePerTier in config" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[1].toNumber(), + _ratePerTierDiscountPoly[stoId][i].toNumber(), + "Incorrect _ratePerTierDiscountPoly in config" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].toNumber(), + _tokensPerTierTotal[stoId][i].toNumber(), + "Incorrect _tokensPerTierTotal in config" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toNumber(), + _tokensPerTierDiscountPoly[stoId][i].toNumber(), + "Incorrect _tokensPerTierDiscountPoly in config" + ); + } assert.equal( (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), @@ -512,28 +512,28 @@ contract("USDTieredSTO", accounts => { assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(), _startTime[stoId], "Incorrect _startTime in config"); assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(), _endTime[stoId], "Incorrect _endTime in config"); - // for (var i = 0; i < _ratePerTier[stoId].length; i++) { - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), - // _ratePerTier[stoId][i].toNumber(), - // "Incorrect _ratePerTier in config" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), - // _ratePerTierDiscountPoly[stoId][i].toNumber(), - // "Incorrect _ratePerTierDiscountPoly in config" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), - // _tokensPerTierTotal[stoId][i].toNumber(), - // "Incorrect _tokensPerTierTotal in config" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), - // _tokensPerTierDiscountPoly[stoId][i].toNumber(), - // "Incorrect _tokensPerTierDiscountPoly in config" - // ); - // } + for (var i = 0; i < _ratePerTier[stoId].length; i++) { + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[0].toNumber(), + _ratePerTier[stoId][i].toNumber(), + "Incorrect _ratePerTier in config" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[1].toNumber(), + _ratePerTierDiscountPoly[stoId][i].toNumber(), + "Incorrect _ratePerTierDiscountPoly in config" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].toNumber(), + _tokensPerTierTotal[stoId][i].toNumber(), + "Incorrect _tokensPerTierTotal in config" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toNumber(), + _tokensPerTierDiscountPoly[stoId][i].toNumber(), + "Incorrect _tokensPerTierDiscountPoly in config" + ); + } assert.equal( (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), @@ -637,6 +637,45 @@ contract("USDTieredSTO", accounts => { I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); }); + it("Should successfully attach the fifth STO module to the security token", async () => { + let stoId = 4; // Non-divisible tokens + + _startTime.push(latestTime() + duration.days(2)); + _endTime.push(_startTime[stoId] + duration.days(100)); + _ratePerTier.push([BigNumber(1 * 10 ** 18), BigNumber(1.5 * 10 ** 18)]); // [ 1 USD/Token, 1.5 USD/Token ] + _ratePerTierDiscountPoly.push([BigNumber(0.5 * 10 ** 18), BigNumber(1 * 10 ** 18)]); // [ 0.5 USD/Token, 1.5 USD/Token ] + _tokensPerTierTotal.push([BigNumber(100 * 10 ** 18), BigNumber(50 * 10 ** 18)]); // [ 100 Token, 50 Token ] + _tokensPerTierDiscountPoly.push([BigNumber(100 * 10 ** 18), BigNumber(25 * 10 ** 18)]); // [ 100 Token, 25 Token ] + _nonAccreditedLimitUSD.push(BigNumber(25 * 10 ** 18)); // [ 25 USD ] + _minimumInvestmentUSD.push(BigNumber(5)); + _fundRaiseTypes.push([0, 1, 2]); + _wallet.push(WALLET); + _reserveWallet.push(RESERVEWALLET); + _usdToken.push(I_DaiToken.address); + + let config = [ + _startTime[stoId], + _endTime[stoId], + _ratePerTier[stoId], + _ratePerTierDiscountPoly[stoId], + _tokensPerTierTotal[stoId], + _tokensPerTierDiscountPoly[stoId], + _nonAccreditedLimitUSD[stoId], + _minimumInvestmentUSD[stoId], + _fundRaiseTypes[stoId], + _wallet[stoId], + _reserveWallet[stoId], + _usdToken[stoId] + ]; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); + console.log(" Gas addModule: ".grey + tx.receipt.gasUsed.toString().grey); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[2].args._name), "USDTieredSTO", "USDTieredSTOFactory module was not added"); + I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + }); + it("Should fail because rates and tier array of different length", async () => { let stoId = 0; @@ -864,26 +903,26 @@ contract("USDTieredSTO", accounts => { [BigNumber(15 * 10 ** 20)], { from: ISSUER } ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].ratePerTier.call(0)).toNumber(), - // BigNumber(15 * 10 ** 18).toNumber(), - // "STO Configuration doesn't set as expected" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(0)).toNumber(), - // BigNumber(13 * 10 ** 18).toNumber(), - // "STO Configuration doesn't set as expected" - // ); - // assert.equal( - // await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(0), - // BigNumber(15 * 10 ** 20).toNumber(), - // "STO Configuration doesn't set as expected" - // ); - // assert.equal( - // await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(0), - // BigNumber(15 * 10 ** 20).toNumber(), - // "STO Configuration doesn't set as expected" - // ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(0))[0].toNumber(), + BigNumber(15 * 10 ** 18).toNumber(), + "STO Configuration doesn't set as expected" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(0))[1].toNumber(), + BigNumber(13 * 10 ** 18).toNumber(), + "STO Configuration doesn't set as expected" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(0))[2], + BigNumber(15 * 10 ** 20).toNumber(), + "STO Configuration doesn't set as expected" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(0))[3], + BigNumber(15 * 10 ** 20).toNumber(), + "STO Configuration doesn't set as expected" + ); let tempTime1 = latestTime() + duration.days(0.1); let tempTime2 = latestTime() + duration.days(0.2); @@ -3725,6 +3764,191 @@ contract("USDTieredSTO", accounts => { ); }); + it("should successfully buy a granular amount and refund balance when buying indivisible token with POLY", async () => { + await I_SecurityToken.changeGranularity(10 ** 18, {from: ISSUER}); + let stoId = 4; + let tierId = 0; + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + let investment_Tokens = (new BigNumber(10.5)).mul(10 ** 18); + let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Tokens); + + let refund_Tokens = (new BigNumber(0.5)).mul(10 ** 18); + let refund_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", refund_Tokens); + + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: ACCREDITED1 }); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { + from: ACCREDITED1, + gasPrice: GAS_PRICE + }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal( + final_TokenSupply.toNumber(), + init_TokenSupply + .add(investment_Tokens) + .sub(refund_Tokens) + .toNumber(), + "Token Supply not changed as expected" + ); + assert.equal( + final_InvestorTokenBal.toNumber(), + init_InvestorTokenBal + .add(investment_Tokens) + .sub(refund_Tokens) + .toNumber(), + "Investor Token Balance not changed as expected" + ); + assert.equal( + final_InvestorETHBal.toNumber(), + init_InvestorETHBal.sub(gasCost2).toNumber(), + "Investor ETH Balance not changed as expected" + ); + assert.equal( + final_InvestorPOLYBal.toNumber(), + init_InvestorPOLYBal + .sub(investment_POLY) + .add(refund_POLY) + .toNumber(), + "Investor POLY Balance not changed as expected" + ); + assert.equal( + final_STOTokenSold.toNumber(), + init_STOTokenSold + .add(investment_Tokens) + .sub(refund_Tokens) + .toNumber(), + "STO Token Sold not changed as expected" + ); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal( + final_RaisedPOLY.toNumber(), + init_RaisedPOLY + .add(investment_POLY) + .sub(refund_POLY) + .toNumber(), + "Raised POLY not changed as expected" + ); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal( + final_WalletPOLYBal.toNumber(), + init_WalletPOLYBal + .add(investment_POLY) + .sub(refund_POLY) + .toNumber(), + "Wallet POLY Balance not changed as expected" + ); + await I_SecurityToken.changeGranularity(1, {from: ISSUER}); + }); + + it("should successfully buy a granular amount and refund balance when buying indivisible token with ETH", async () => { + await I_SecurityToken.changeGranularity(10**18, {from: ISSUER}); + let stoId = 4; + let tierId = 0; + let investment_Tokens = BigNumber(10.5).mul(10**18); + let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Tokens); + console.log(investment_ETH.toString()); + let refund_Tokens = BigNumber(0.5).mul(10**18); + let refund_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", refund_Tokens); + console.log(refund_ETH.toString()); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + + + // Buy With ETH + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { + from: ACCREDITED1, + gasPrice: GAS_PRICE, + value: investment_ETH + }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithETH: ".grey + tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + + assert.equal( + final_TokenSupply.toNumber(), + init_TokenSupply + .add(investment_Tokens) + .sub(refund_Tokens) + .toNumber(), + "Token Supply not changed as expected" + ); + assert.equal( + final_InvestorTokenBal.toNumber(), + init_InvestorTokenBal + .add(investment_Tokens) + .sub(refund_Tokens) + .toNumber(), + "Investor Token Balance not changed as expected" + ); + assert.equal( + final_InvestorETHBal.toNumber(), + init_InvestorETHBal.sub(investment_ETH).sub(gasCost2).add(refund_ETH).toNumber(), + "Investor ETH Balance not changed as expected" + ); + assert.equal( + final_STOTokenSold.toNumber(), + init_STOTokenSold + .add(investment_Tokens) + .sub(refund_Tokens) + .toNumber(), + "STO Token Sold not changed as expected" + ); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.add(investment_ETH).sub(refund_ETH).toNumber(), "Raised ETH not changed as expected"); + assert.equal( + final_RaisedPOLY.toNumber(), + init_RaisedPOLY, + "Raised POLY not changed as expected" + ); + await I_SecurityToken.changeGranularity(1, {from: ISSUER}); + }); + it("should fail and revert when NONACCREDITED cap reached", async () => { let stoId = 2; let tierId = 0; diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index e22c9c4ac..55f84f2b3 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -297,28 +297,28 @@ contract("USDTieredSTO Sim", accounts => { assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(), _startTime[stoId], "Incorrect _startTime in config"); assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(), _endTime[stoId], "Incorrect _endTime in config"); - // for (var i = 0; i < _ratePerTier[stoId].length; i++) { - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].ratePerTier.call(i)).toNumber(), - // _ratePerTier[stoId][i].toNumber(), - // "Incorrect _ratePerTier in config" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].ratePerTierDiscountPoly.call(i)).toNumber(), - // _ratePerTierDiscountPoly[stoId][i].toNumber(), - // "Incorrect _ratePerTierDiscountPoly in config" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].tokensPerTierTotal.call(i)).toNumber(), - // _tokensPerTierTotal[stoId][i].toNumber(), - // "Incorrect _tokensPerTierTotal in config" - // ); - // assert.equal( - // (await I_USDTieredSTO_Array[stoId].tokensPerTierDiscountPoly.call(i)).toNumber(), - // _tokensPerTierDiscountPoly[stoId][i].toNumber(), - // "Incorrect _tokensPerTierDiscountPoly in config" - // ); - // } + for (var i = 0; i < _ratePerTier[stoId].length; i++) { + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[0].toNumber(), + _ratePerTier[stoId][i].toNumber(), + "Incorrect _ratePerTier in config" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[1].toNumber(), + _ratePerTierDiscountPoly[stoId][i].toNumber(), + "Incorrect _ratePerTierDiscountPoly in config" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].toNumber(), + _tokensPerTierTotal[stoId][i].toNumber(), + "Incorrect _tokensPerTierTotal in config" + ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toNumber(), + _tokensPerTierDiscountPoly[stoId][i].toNumber(), + "Incorrect _tokensPerTierDiscountPoly in config" + ); + } assert.equal( (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), _nonAccreditedLimitUSD[stoId].toNumber(), From aecda44f7d763a7f056a3c6721533b98e3352be8 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 8 Nov 2018 20:06:26 +0530 Subject: [PATCH 056/582] Minor bug fix in test --- test/p_usd_tiered_sto.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index fedf52294..bb73757a4 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -3875,11 +3875,9 @@ contract("USDTieredSTO", accounts => { let stoId = 4; let tierId = 0; let investment_Tokens = BigNumber(10.5).mul(10**18); - let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Tokens); - console.log(investment_ETH.toString()); + let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Tokens); let refund_Tokens = BigNumber(0.5).mul(10**18); - let refund_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", refund_Tokens); - console.log(refund_ETH.toString()); + let refund_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", refund_Tokens); let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); From e6b200a97f84effdf3c64f6953480951f749a58d Mon Sep 17 00:00:00 2001 From: vpanwar821 Date: Thu, 8 Nov 2018 22:34:48 +0530 Subject: [PATCH 057/582] minor changes --- test/y_blacklist_transfer_manager.js | 988 --------------------------- 1 file changed, 988 deletions(-) delete mode 100644 test/y_blacklist_transfer_manager.js diff --git a/test/y_blacklist_transfer_manager.js b/test/y_blacklist_transfer_manager.js deleted file mode 100644 index b8918d9e2..000000000 --- a/test/y_blacklist_transfer_manager.js +++ /dev/null @@ -1,988 +0,0 @@ -import latestTime from './helpers/latestTime'; -import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; -import { setUpPolymathNetwork, deployGPMAndVerifyed, deployBlacklistTMAndVerified } from "./helpers/createInstances"; -import { catchRevert } from "./helpers/exceptions"; - -const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); -const BlacklistTransferManager = artifacts.require("./BlacklistTransferManager"); -const SecurityToken = artifacts.require("./SecurityToken.sol"); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('BlacklistTransferManager', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_investor5; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_GeneralPermissionManagerFactory; - let I_SecurityTokenRegistryProxy; - let I_GeneralTransferManagerFactory; - let I_BlacklistTransferManagerFactory; - let I_GeneralPermissionManager; - let I_BlacklistTransferManager; - let P_BlacklistTransferManagerFactory; - let P_BlacklistTransferManager; - let I_GeneralTransferManager; - let I_ExchangeTransferManager; - let I_ModuleRegistry; - let I_ModuleRegistryProxy; - let I_MRProxied; - let I_STRProxied; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - // BlacklistTransferManager details - const holderCount = 2; // Maximum number of token holders - const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const MRProxyParameters = ['address', 'address']; - let bytesSTO = encodeModuleCall(['uint256'], [holderCount]); - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[7]; - account_investor2 = accounts[8]; - account_investor3 = accounts[9]; - account_investor4 = accounts[5]; - account_investor5 = accounts[6]; - - let instances = await setUpPolymathNetwork(account_polymath, token_owner); - - [ - I_PolymathRegistry, - I_PolyToken, - I_FeatureRegistry, - I_ModuleRegistry, - I_ModuleRegistryProxy, - I_MRProxied, - I_GeneralTransferManagerFactory, - I_STFactory, - I_SecurityTokenRegistry, - I_SecurityTokenRegistryProxy, - I_STRProxied - ] = instances; - - // STEP 2: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - - // STEP 3(a): Deploy the PercentageTransferManager - [I_BlacklistTransferManagerFactory] = await deployBlacklistTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); - - // STEP 4(b): Deploy the PercentageTransferManager - [P_BlacklistTransferManagerFactory] = await deployBlacklistTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); - // ----------- POLYMATH NETWORK Configuration ------------ - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${I_PolymathRegistry.address} - SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} - ModuleRegistry: ${I_ModuleRegistry.address} - ModuleRegistryProxy: ${I_ModuleRegistryProxy.address} - FeatureRegistry: ${I_FeatureRegistry.address} - - STFactory: ${I_STFactory.address} - GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${I_GeneralPermissionManagerFactory.address} - - BlacklistTransferManagerFactory: ${I_BlacklistTransferManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner}); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - - }); - - it("Should successfully attach the BlacklistTransferManager factory with the security token", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - await catchRevert ( - I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { - from: token_owner - }) - ); - }); - - it("Should successfully attach the BlacklistTransferManager factory with the security token", async () => { - let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "BlacklistTransferManager", - "BlacklistTransferManagerFactory module was not added" - ); - P_BlacklistTransferManager = BlacklistTransferManager.at(tx.logs[3].args._module); - await revertToSnapshot(snapId); - }); - - it("Should successfully attach the BlacklistTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_BlacklistTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "BlacklistTransferManager", - "BlacklistTransferManager module was not added" - ); - I_BlacklistTransferManager = BlacklistTransferManager.at(tx.logs[2].args._module); - }); - - }); - - describe("Buy tokens using on-chain whitelist", async() => { - - it("Should Buy the tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(50), - true, - { - from: account_issuer - }); - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('5', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('5', 'ether') - ); - - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(50), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(50), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor4, - latestTime(), - latestTime(), - latestTime() + duration.days(50), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor4.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor4, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor5, - latestTime(), - latestTime(), - latestTime() + duration.days(50), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor5.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor5, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor5)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - - it("Should add the blacklist", async() => { - //Add the new blacklist - let tx = await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in adding the type in blacklist"); - }); - - it("Should fail in adding the blacklist as blacklist type already exist", async() => { - await catchRevert( - I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { - from: token_owner - }) - ); - }); - - it("Should fail in adding the blacklist as the blacklist name is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "", 20, { - from: token_owner - }) - ); - }); - - it("Should fail in adding the blacklist as the start date is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.addBlacklistType(0, latestTime()+3000, "b_blacklist", 20, { - from: token_owner - }) - ); - }); - - it("Should fail in adding the blacklist as the dates are invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.addBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { - from: token_owner - }) - ); - }); - - it("Should fail in adding the blacklist as repeat in days is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 0, { - from: token_owner - }) - ); - }); - - it("Should fail in adding the blacklist because only owner can add the blacklist", async() => { - await catchRevert( - I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { - from: account_investor1 - }) - ); - }); - - it("Should add the mutiple blacklist", async() => { - //Add the new blacklist - let startTime = [latestTime()+2000,latestTime()+3000]; - let endTime = [latestTime()+5000,latestTime()+8000]; - let name = ["y_blacklist","z_blacklist"]; - let repeatTime = [15,30]; - let tx = await I_BlacklistTransferManager.addBlacklistTypeMulti(startTime, endTime, name, repeatTime, { from: token_owner }); - - let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let blacklistName = event_data[i].args._name; - assert.equal(web3.utils.hexToUtf8(blacklistName), name[i], "Failed in adding the blacklist"); - } - }); - - it("Should fail in adding the mutiple blacklist because only owner can add it", async() => { - //Add the new blacklist - let startTime = [latestTime()+2000,latestTime()+3000]; - let endTime = [latestTime()+5000,latestTime()+8000]; - let name = ["y_blacklist","z_blacklist"]; - let repeatTime = [15,30]; - await catchRevert( - I_BlacklistTransferManager.addBlacklistTypeMulti(startTime, endTime, name, repeatTime, { - from: account_investor1 - }) - ); - }); - - it("Should fail in adding the mutiple blacklist because array lenth are different", async() => { - //Add the new blacklist - let startTime = [latestTime()+2000,latestTime()+3000]; - let endTime = [latestTime()+5000,latestTime()+8000]; - let name = ["y_blacklist","z_blacklist","w_blacklist"]; - let repeatTime = [15,30]; - await catchRevert( - I_BlacklistTransferManager.addBlacklistTypeMulti(startTime, endTime, name, repeatTime, { - from: token_owner - }) - ); - }); - - it("Should modify the blacklist", async() => { - //Modify the existing blacklist - let tx = await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in modifying the startdate of blacklist"); - - }); - - it("Should fail in modifying the blacklist as the name is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "", 20, { - from: token_owner - }) - ); - }); - - it("Should fail in modifying the blacklist as the dates are invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.modifyBlacklistType(latestTime()+4000, latestTime()+3000, "b_blacklist", 20, { - from: token_owner - }) - ); - }); - - it("Should fail in modifying the blacklist as the repeat in days is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "b_blacklist", 0, { - from: token_owner - }) - ); - }); - - - it("Should fail in modifying the blacklist as only owner can modify the blacklist", async() => { - await catchRevert( - I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { - from: account_investor1 - }) - ); - }); - - it("Should fail in modifying the blacklist as blacklist type doesnot exist", async() => { - await catchRevert( - I_BlacklistTransferManager.modifyBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { - from: token_owner - }) - ); - }); - - it("Should modify the mutiple blacklist", async() => { - //Add the new blacklist - let startTime = [latestTime()+3000,latestTime()+3000]; - let endTime = [latestTime()+5000,latestTime()+7000]; - let name = ["y_blacklist","z_blacklist"]; - let repeatTime = [15,30]; - let tx = await I_BlacklistTransferManager.modifyBlacklistTypeMulti(startTime, endTime, name, repeatTime, { from: token_owner }); - - let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let blacklistName = event_data[i].args._name; - assert.equal(web3.utils.hexToUtf8(blacklistName), name[i], "Failed in adding the blacklist"); - } - }); - - it("Should fail in modifying the mutiple blacklist because only owner can add it", async() => { - //Add the new blacklist - let startTime = [latestTime()+3000,latestTime()+3000]; - let endTime = [latestTime()+5000,latestTime()+7000]; - let name = ["y_blacklist","z_blacklist"]; - let repeatTime = [15,30]; - await catchRevert( - I_BlacklistTransferManager.modifyBlacklistTypeMulti(startTime, endTime, name, repeatTime, { - from: account_investor1 - }) - ); - }); - - it("Should fail in modifying the mutiple blacklist because array length are different", async() => { - //Add the new blacklist - let startTime = [latestTime()+3000,latestTime()+3000]; - let endTime = [latestTime()+5000,latestTime()+7000]; - let name = ["y_blacklist","z_blacklist","w_blacklist"]; - let repeatTime = [15,30]; - await catchRevert( - I_BlacklistTransferManager.modifyBlacklistTypeMulti(startTime, endTime, name, repeatTime, { - from: token_owner - }) - ); - }); - - it("Should add investor to the blacklist", async() => { - //Add investor to the existing blacklist - let tx = await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor to the blacklist"); - - }); - - it("Should fail in adding the investor to the blacklist because only owner can add the investor", async() => { - await catchRevert( - I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "a_blacklist", { - from: account_investor1 - }) - ); - }); - - it("Should fail in adding the investor to the blacklist as investor address is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.addInvestorToBlacklist(0x0, "a_blacklist", { - from: token_owner - }) - ); - }); - - - it("Should fail in adding the investor to the non existing blacklist", async() => { - await catchRevert( - I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "b_blacklist", { - from: token_owner - }) - ); - }); - - it("Should get the list of investors associated to blacklist", async() => { - let perm = await I_BlacklistTransferManager.getListOfAddresses.call("a_blacklist"); - assert.equal(perm.length, 1); - }); - - it("Should fail in getting the list of investors from the non existing blacklist", async() => { - await catchRevert( - I_BlacklistTransferManager.getListOfAddresses.call("b_blacklist") - ); - }); - - it("Should investor be able to transfer token because current time is less than the blacklist start time", async() => { - //Trasfer tokens - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('3', 'ether') - ); - }); - - it("Should investor be able to transfer token as it is not in blacklist time period", async() => { - // Jump time - await increaseTime(4000); - - //Trasfer tokens - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('4', 'ether') - ); - }); - - it("Should fail in transfer the tokens as the investor in blacklist", async() => { - // Jump time - await increaseTime(1727500); - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { - from: account_investor1 - }) - ); - }); - - it("Should investor is able transfer the tokens- because BlacklistTransferManager is paused", async() => { - await I_BlacklistTransferManager.pause({from:token_owner}); - //Trasfer tokens - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('5', 'ether') - ); - }); - - it("Should investor fail in transfer token as it is in blacklist time period", async() => { - await I_BlacklistTransferManager.unpause({from:token_owner}); - await I_BlacklistTransferManager.addBlacklistType(latestTime()+500, latestTime()+4000, "k_blacklist", 8, { from: token_owner }); - - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "k_blacklist", { from: token_owner }); - // Jump time - await increaseTime(3500); - - //Trasfer tokens - await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { - from: account_investor2 - }) - ) - }); - - it("Should investor be able to transfer token as it is not in blacklist time period", async() => { - // Jump time - await increaseTime(1000); - - //Trasfer tokens - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('3', 'ether') - ); - }); - - it("Should investor fail in transfer token as it is in blacklist time period", async() => { - - // Jump time - await increaseTime(690800); - - //Trasfer tokens - await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { - from: account_investor2 - }) - ); - }); - - it("Should investor fail in transfer token as it is in blacklist time period", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+5000, latestTime()+8000, "l_blacklist", 5, { from: token_owner }); - - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor3, "l_blacklist", { from: token_owner }); - // Jump time - await increaseTime(5500); - - //Trasfer tokens - await catchRevert( - I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { - from: account_investor3 - }) - ); - }); - - it("Should investor be able to transfer token as it is not in blacklist time period", async() => { - // Jump time - await increaseTime(3000); - - //Trasfer tokens - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { from: account_investor3 }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor4)).toNumber(), - web3.utils.toWei('3', 'ether') - ); - }); - - it("Should investor fail in transfer token as it is in blacklist time period", async() => { - - // Jump time - await increaseTime(431600); - - //Trasfer tokens - await catchRevert( - I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { - from: account_investor3 - }) - ); - }); - - - it("Should delete the blacklist type", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "b_blacklist", "Failed in deleting the blacklist"); - - }); - - it("Only owner have the permission to delete thr blacklist type", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); - await catchRevert( - I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { - from: account_investor1 - }) - ); - }); - - it("Should fail in deleting the blacklist type as the blacklist has associated addresses", async() => { - await catchRevert( - I_BlacklistTransferManager.deleteBlacklistType("a_blacklist", { - from: token_owner - }) - ); - }); - - it("Should fail in deleting the blacklist type as the blacklist doesnot exist", async() => { - await catchRevert( - I_BlacklistTransferManager.deleteBlacklistType("c_blacklist", { - from: token_owner - }) - ); - }); - - it("Should delete the mutiple blacklist type", async() => { - let name = ["y_blacklist","z_blacklist"]; - let tx = await I_BlacklistTransferManager.deleteBlacklistTypeMulti(name, { from: token_owner }); - - let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let blacklistName = event_data[i].args._name; - assert.equal(web3.utils.hexToUtf8(blacklistName), name[i], "Failed in deleting the blacklist"); - } - - }); - - it("Should fail in deleting multiple blacklist type because only owner can do it.", async() => { - let name = ["b_blacklist","a_blacklist"]; - await catchRevert( - I_BlacklistTransferManager.deleteBlacklistTypeMulti(name, { - from: account_investor1 - }) - ); - }); - - it("Should delete the investor from all the associated blacklist", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "g_blacklist", 20, { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "g_blacklist", { from: token_owner }); - let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: token_owner }); - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); - - }); - - it("Only owner has the permission to delete the investor from all the blacklist type", async() => { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { - from: account_investor2 - }) - ) - }); - - it("Should fail in deleting the investor from all the associated blacklist as th address is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(0x0, { - from: token_owner - }) - ); - }); - - it("Should fail in deleting the investor because investor is not associated to any blacklist", async() => { - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor5, { - from: token_owner - }) - ); - }); - - it("Should delete the mutiple investor from all the associated blacklist", async() => { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "g_blacklist", { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); - let investor = [account_investor5,account_investor2]; - let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklistMulti(investor, { from: token_owner }); - let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let investorName = event_data[i].args._investor; - assert.equal(investorName.toLowerCase(), investor[i].toLowerCase(), "Failed in deleting the blacklist"); - } - }); - - it("Should fail in deleting the mutiple investor from all the associated blacklist because only owner can do it.", async() => { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "g_blacklist", { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); - let investor = [account_investor5,account_investor2]; - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromAllBlacklistMulti(investor, { - from: account_investor1 - }) - ); - }); - - it("Should delete the mutiple investor from particular associated blacklists", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "s_blacklist", 20, { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "s_blacklist", { from: token_owner }); - // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); - let investor = [account_investor5,account_investor2]; - let blacklistName = ["s_blacklist","g_blacklist"]; - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { from: token_owner }); - let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let investorName = event_data[i].args._investor; - assert.equal(investorName.toLowerCase(), investor[i].toLowerCase(), "Failed in deleting the blacklist"); - } - }); - - it("Should fail in deleting the mutiple investor from particular associated blacklist because only owner can do it.", async() => { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "s_blacklist", { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); - let investor = [account_investor5,account_investor2]; - let blacklistName = ["s_blacklist","g_blacklist"]; - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { - from: account_investor1 - }) - ); - }); - - it("Should fail in deleting the mutiple investor from particular associated blacklist because array length is incorrect.", async() => { - let investor = [account_investor5]; - let blacklistName = ["s_blacklist","g_blacklist"]; - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { - from: token_owner - }) - ); - }); - - it("Should delete the investor from the blacklist type", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "f_blacklist", 20, { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, "f_blacklist", { from: token_owner }); - await I_BlacklistTransferManager.addBlacklistType(latestTime()+500, latestTime()+8000, "q_blacklist", 10, { from: token_owner }); - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "q_blacklist", { from: token_owner }); - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); - - }); - - it("Only owner can delete the investor from the blacklist type", async() => { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { - from: account_investor2 - }) - ); - }); - - it("Should fail in deleting the investor because the investor address is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromBlacklist(0x0, "f_blacklist", { - from: token_owner - }) - ); - }); - - it("Should fail in deleting the investor because the investor is not associated to blacklist", async() => { - await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { from: token_owner }); - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "f_blacklist", { - from: token_owner - }) - ); - }); - - it("Should fail in deleting the investor because the blacklist name is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, "", { - from: token_owner - }) - ); - }); - - it("Should add investor and new blacklist type", async() => { - let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "c_blacklist", "Failed in adding the blacklist"); - assert.equal(tx.logs[1].args._investor, account_investor3, "Failed in adding the investor to blacklist"); - - }); - - it("Should fail in adding the investor and new blacklist type", async() => { - await catchRevert( - I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { - from: account_investor2 - }) - ); - }); - - it("Should add mutiple investor to blacklist", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "d_blacklist", 20, { from: token_owner }); - let investor = [account_investor4,account_investor5]; - let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "d_blacklist", { from: token_owner }); - - let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let user = event_data[i].args._investor; - assert.equal(user, investor[i], "Failed in adding the investor to blacklist"); - } - - }); - - it("Should fail in adding the mutiple investor to the blacklist", async() => { - await catchRevert( - I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], "b_blacklist", { - from: account_investor1 - }) - ); - }); - - it("Should add mutiple investor to the mutiple blacklist", async() => { - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "m_blacklist", 20, { from: token_owner }); - await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "n_blacklist", 20, { from: token_owner }); - let investor = [account_investor4,account_investor5]; - let blacklistName =["m_blacklist","n_blacklist"]; - let tx = await I_BlacklistTransferManager.addMultiInvestorToBlacklistMulti(investor, blacklistName, { from: token_owner }); - - let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let user = event_data[i].args._investor; - let blacklist = event_data[i].args._blacklistName; - assert.equal(user, investor[i], "Failed in adding the investor to blacklist"); - assert.equal(web3.utils.hexToUtf8(blacklist), blacklistName[i], "Failed in adding the investor to blacklist"); - } - - }); - - it("Should fail in adding the mutiple investor to the mutiple blacklist because only owner can do it.", async() => { - let investor = [account_investor4,account_investor5]; - let blacklistName = ["m_blacklist","n_blacklist"]; - await I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { from: token_owner }); - await catchRevert( - I_BlacklistTransferManager.addMultiInvestorToBlacklistMulti(investor, blacklistName, { - from: account_investor1 - }) - ); - }); - - it("Should fail in adding mutiple investor to the mutiple blacklist because array length is not same", async() => { - let investor = [account_investor4,account_investor5]; - let blacklistName =["m_blacklist"]; - await catchRevert( - I_BlacklistTransferManager.addMultiInvestorToBlacklistMulti(investor, blacklistName, { - from: token_owner - }) - ); - }); - - it("Should get the init function", async() => { - let byte = await I_BlacklistTransferManager.getInitFunction.call(); - assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ''), 0); - }); - - it("Should get the permission", async() => { - let perm = await I_BlacklistTransferManager.getPermissions.call(); - assert.equal(perm.length, 1); - }); - - - }); - - describe("Test cases for the factory", async() => { - it("Should get the exact details of the factory", async() => { - assert.equal(await I_BlacklistTransferManagerFactory.setupCost.call(),0); - assert.equal((await I_BlacklistTransferManagerFactory.getTypes.call())[0],2); - assert.equal(web3.utils.toAscii(await I_BlacklistTransferManagerFactory.getName.call()) - .replace(/\u0000/g, ''), - "BlacklistTransferManager", - "Wrong Module added"); - assert.equal(await I_BlacklistTransferManagerFactory.getDescription.call(), - "Automate blacklist to restrict selling", - "Wrong Module added"); - assert.equal(await I_BlacklistTransferManagerFactory.getTitle.call(), - "Blacklist Transfer Manager", - "Wrong Module added"); - assert.equal(await I_BlacklistTransferManagerFactory.getInstructions.call(), - "Allows an issuer to blacklist the addresses.", - "Wrong Module added"); - - }); - - it("Should get the tags of the factory", async() => { - let tags = await I_BlacklistTransferManagerFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Blacklist"); - }); - }); - -}); From 001549201e5ea08c50280698f63c6ba965ba35cb Mon Sep 17 00:00:00 2001 From: Polymath Date: Thu, 8 Nov 2018 14:29:29 -0300 Subject: [PATCH 058/582] typo fix --- CLI/commands/permission_manager.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index 4fd649467..edcf9d5a0 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -258,10 +258,13 @@ async function getDelegatesAndPermissions() { let moduleName = web3.utils.hexToUtf8((await securityToken.methods.getModule(module).call())[0]); let permissionName = web3.utils.hexToUtf8(permission); for (delegateAddr of allDelegates) { - if (result[delegateAddr] != undefined) { - result[delegateAddr].push({module: moduleName, permission: permissionName}) + if (result[delegateAddr] == undefined) { + result[delegateAddr] = [] + } + if (result[delegateAddr][moduleName] == undefined) { + result[delegateAddr][moduleName] = [{permission: permissionName}] } else { - result[delegateAddr] = [{module: moduleName, permission: permissionName}] + result[delegateAddr][moduleName].push({permission: permissionName}) } } } @@ -271,15 +274,19 @@ async function getDelegatesAndPermissions() { return result } -function renderTable(permisions, address) { +function renderTable(permissions, address) { let result = ``; - if (permisions[address] != undefined) { - for (const obj of permisions[address]) { + if (permissions[address] != undefined) { + Object.keys(permissions[address]).forEach((module) => { result += ` - ${obj.module} -> ${obj.permission}`; - } + ${module} -> `; + (permissions[address][module]).forEach((perm) => { + result += `${perm.permission}, `; + }) + result = result.slice(0, -2); + }) } else { - result = `-`; + result += `-`; } return result } From f928a6fd95cde6ddbdecd438341ba0fe1ddd3185 Mon Sep 17 00:00:00 2001 From: Polymath Date: Thu, 8 Nov 2018 15:51:06 -0300 Subject: [PATCH 059/582] WA for external calls --- CLI/commands/accredit.js | 4 ++++ CLI/commands/changeNonAccreditedLimit.js | 4 ++++ CLI/commands/multi_mint.js | 4 ++++ CLI/commands/whitelist.js | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/CLI/commands/accredit.js b/CLI/commands/accredit.js index 43fbac4ae..a0aa306a2 100644 --- a/CLI/commands/accredit.js +++ b/CLI/commands/accredit.js @@ -3,6 +3,7 @@ var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); var chalk = require('chalk'); var common = require('./common/common_functions'); +var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis') @@ -15,6 +16,7 @@ let usdTieredSTO; let tokenSymbol = process.argv.slice(2)[0]; //token symbol let BATCH_SIZE = process.argv.slice(2)[1]; //batch size if (!BATCH_SIZE) BATCH_SIZE = 75; +let remoteNetwork = process.argv.slice(2)[2]; /////////////////////////GLOBAL VARS////////////////////////////////////////// //distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] @@ -31,6 +33,8 @@ let badData = new Array(); startScript(); async function startScript() { + if (remoteNetwork == 'undefined') remoteNetwork = undefined; + await global.initialize(remoteNetwork); try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); diff --git a/CLI/commands/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js index 8a27036a6..b4d5e3c6b 100644 --- a/CLI/commands/changeNonAccreditedLimit.js +++ b/CLI/commands/changeNonAccreditedLimit.js @@ -3,6 +3,7 @@ var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); var chalk = require('chalk'); var common = require('./common/common_functions'); +var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis') @@ -15,6 +16,7 @@ let usdTieredSTO; let tokenSymbol = process.argv.slice(2)[0]; //token symbol let BATCH_SIZE = process.argv.slice(2)[1]; //batch size if (!BATCH_SIZE) BATCH_SIZE = 75; +let remoteNetwork = process.argv.slice(2)[2]; /////////////////////////GLOBAL VARS////////////////////////////////////////// //distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] @@ -31,6 +33,8 @@ let badData = new Array(); startScript(); async function startScript() { + if (remoteNetwork == 'undefined') remoteNetwork = undefined; + await global.initialize(remoteNetwork); try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index 064e51bad..b138ef849 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -3,6 +3,7 @@ var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); const chalk = require('chalk'); var common = require('./common/common_functions'); +var global = require('./common/global'); /////////////////////////////ARTIFACTS////////////////////////////////////////// var contracts = require('./helpers/contract_addresses'); @@ -16,6 +17,7 @@ let securityToken; let tokenSymbol = process.argv.slice(2)[0]; //token symbol let BATCH_SIZE = process.argv.slice(2)[1]; //batch size if (!BATCH_SIZE) BATCH_SIZE = 75; +let remoteNetwork = process.argv.slice(2)[2]; /////////////////////////GLOBAL VARS////////////////////////////////////////// @@ -33,6 +35,8 @@ let badData = new Array(); startScript(); async function startScript() { + if (remoteNetwork == 'undefined') remoteNetwork = undefined; + await global.initialize(remoteNetwork); try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); diff --git a/CLI/commands/whitelist.js b/CLI/commands/whitelist.js index 8722d3789..5ef201195 100644 --- a/CLI/commands/whitelist.js +++ b/CLI/commands/whitelist.js @@ -2,6 +2,7 @@ var fs = require('fs'); var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); var common = require('./common/common_functions'); +var global = require('./common/global'); /////////////////////////////ARTIFACTS////////////////////////////////////////// var contracts = require('./helpers/contract_addresses'); @@ -11,6 +12,7 @@ var abis = require('./helpers/contract_abis'); let tokenSymbol = process.argv.slice(2)[0]; //token symbol let BATCH_SIZE = process.argv.slice(2)[1]; //batch size if (!BATCH_SIZE) BATCH_SIZE = 70; +let remoteNetwork = process.argv.slice(2)[2]; /////////////////////////GLOBAL VARS////////////////////////////////////////// @@ -30,6 +32,8 @@ const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); startScript(); async function startScript() { + if (remoteNetwork == 'undefined') remoteNetwork = undefined; + await global.initialize(remoteNetwork); try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); From 95d296b186421a7b2b3bdcbcf30bf535bca1a882 Mon Sep 17 00:00:00 2001 From: Polymath Date: Thu, 8 Nov 2018 20:34:15 -0300 Subject: [PATCH 060/582] fixing remoteNetwork error for external execution --- CLI/commands/ST20Generator.js | 8 ++++---- CLI/commands/common/global.js | 5 +++-- CLI/commands/strMigrator.js | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 9a7ac39b6..a7dabe7d7 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -242,11 +242,11 @@ async function step_Wallet_Issuance(){ async function multi_mint_tokens() { //await whitelist.startWhitelisting(tokenSymbol); - shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${gbl.constants.NETWORK}`); + shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${remoteNetwork}`); console.log(chalk.green(`\nCongrats! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); - shell.exec(`${__dirname}/scripts//script.sh Multimint ${tokenSymbol} 75 ${gbl.constants.NETWORK}`); + shell.exec(`${__dirname}/scripts//script.sh Multimint ${tokenSymbol} 75 ${remoteNetwork}`); console.log(chalk.green(`\nHurray!! Tokens get successfully Minted and transferred to token holders`)); } @@ -1003,7 +1003,7 @@ async function usdTieredSTO_configure() { await common.sendTransaction(changeAccreditedAction); break; case 2: - shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${gbl.constants.NETWORK}`); + shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${remoteNetwork}`); break; case 3: let account = readlineSync.question('Enter the address to change non accredited limit: '); @@ -1015,7 +1015,7 @@ async function usdTieredSTO_configure() { await common.sendTransaction(changeNonAccreditedLimitAction); break; case 4: - shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${gbl.constants.NETWORK}`); + shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${remoteNetwork}`); break; case 5: await modfifyTimes(); diff --git a/CLI/commands/common/global.js b/CLI/commands/common/global.js index b4aa96607..e1fb648e2 100644 --- a/CLI/commands/common/global.js +++ b/CLI/commands/common/global.js @@ -1,7 +1,7 @@ const Web3 = require('web3'); const constants = require('./constants'); -global.web3, global.Issuer, global.defaultGasPrice; +global.web3, global.Issuer, global.defaultGasPrice, global.remoteNetwork; function getGasPrice (networkId) { let gasPrice; @@ -25,7 +25,8 @@ function getGasPrice (networkId) { } module.exports = { - initialize: async function(remoteNetwork) { + initialize: async function(network) { + remoteNetwork = network; if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { if (typeof remoteNetwork !== 'undefined') { web3 = new Web3(new Web3.providers.HttpProvider(`https://${remoteNetwork}.infura.io/`)); diff --git a/CLI/commands/strMigrator.js b/CLI/commands/strMigrator.js index edc965236..1e42ec46d 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -356,7 +356,7 @@ ${failed.map(ticker => chalk.red(`${ticker.ticker}`)).join('\n')} } async function getABIfromEtherscan(_address) { - let urlDomain = gbl.constants.NETWORK == 'kovan' ? 'api-kovan' : 'api'; + let urlDomain = remoteNetwork == 'kovan' ? 'api-kovan' : 'api'; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { From df78471efed8d0b658ae1999fc697088bceb407e Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 9 Nov 2018 11:24:13 +0530 Subject: [PATCH 061/582] Update tokenInfo.js --- scripts/tokenInfo.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/tokenInfo.js b/scripts/tokenInfo.js index 2df8c57c4..e8a59ca1a 100644 --- a/scripts/tokenInfo.js +++ b/scripts/tokenInfo.js @@ -14,7 +14,11 @@ async function getTokens() { let strEvents = await web3.eth.getPastLogs({fromBlock:'0x5C5C18', address:securityTokenRegistry.address, topics: ["0x2510d802a0818e71139a7680a6388bcffcd3fa686e02a0f7319488c5bdb38fcb"]}); for (let i = 0; i < strEvents.length; i++) { let tokenAddress = '0x' + strEvents[i].topics[1].slice(26,66) - await getInfo(tokenAddress); + try { + await getInfo(tokenAddress); + } catch(exception) { + console.log('Failed to load info of', tokenAddress, exception); + } } } From a59d1c080b34268ee8c72fc39017dac46c465fc4 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 9 Nov 2018 13:09:21 +0530 Subject: [PATCH 062/582] Code cleanup --- contracts/modules/STO/USDTieredSTO.sol | 30 +++++++++++++++----------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 694f16e7e..0f5b083ad 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -389,15 +389,20 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, 0); } + function buyWithUSD(address _beneficiary, uint256 _investedDAI) public validDAI { + _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, 0); + } + /** * @notice Purchase tokens using ETH * @param _beneficiary Address where security tokens will be sent - * @param _minRate Minumum conversion rate (FundType => USD) at which buying is authorized + * @param _minTokens Minumum number of tokens to buy or else revert */ - function buyWithETHRateLimited(address _beneficiary, uint256 _minRate) public payable validETH { + function buyWithETHRateLimited(address _beneficiary, uint256 _minTokens) public payable validETH { uint256 rate = getRate(FundRaiseType.ETH); - require(rate >= _minRate, "Current rate below min"); + uint256 initialMinted = getTokensMinted(); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, msg.value, rate, FundRaiseType.ETH); + require(getTokensMinted().sub(initialMinted) >= _minTokens, "Insufficient tokens minted"); // Modify storage investorInvested[_beneficiary][uint8(FundRaiseType.ETH)] = investorInvested[_beneficiary][uint8(FundRaiseType.ETH)].add(spentValue); fundsRaised[uint8(FundRaiseType.ETH)] = fundsRaised[uint8(FundRaiseType.ETH)].add(spentValue); @@ -412,26 +417,28 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @notice Purchase tokens using POLY * @param _beneficiary Address where security tokens will be sent * @param _investedPOLY Amount of POLY invested - * @param _minRate Maximum rate at which buying is authorized + * @param _minTokens Minumum number of tokens to buy or else revert */ - function buyWithPOLYRateLimited(address _beneficiary, uint256 _investedPOLY, uint256 _minRate) public validPOLY { - _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, _minRate); + function buyWithPOLYRateLimited(address _beneficiary, uint256 _investedPOLY, uint256 _minTokens) public validPOLY { + _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, _minTokens); } /** * @notice Purchase tokens using DAI * @param _beneficiary Address where security tokens will be sent * @param _investedDAI Amount of DAI invested + * @param _minTokens Minumum number of tokens to buy or else revert */ - function buyWithUSD(address _beneficiary, uint256 _investedDAI) public validDAI { - _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, uint256(10) ** 18); + function buyWithUSDRateLimited(address _beneficiary, uint256 _investedDAI, uint256 _minTokens) public validDAI { + _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, _minTokens); } - function _buyWithTokens(address _beneficiary, uint256 _tokenAmount, FundRaiseType _fundRaiseType, uint256 _minRate) internal { + function _buyWithTokens(address _beneficiary, uint256 _tokenAmount, FundRaiseType _fundRaiseType, uint256 _minTokens) internal { require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI, "Invalid raise type"); + uint256 initialMinted = getTokensMinted(); uint256 rate = getRate(_fundRaiseType); - require(rate >= _minRate, "Current rate below min"); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, _tokenAmount, rate, _fundRaiseType); + require(getTokensMinted().sub(initialMinted) >= _minTokens, "Insufficient tokens minted"); // Modify storage investorInvested[_beneficiary][uint8(_fundRaiseType)] = investorInvested[_beneficiary][uint8(_fundRaiseType)].add(spentValue); fundsRaised[uint8(_fundRaiseType)] = fundsRaised[uint8(_fundRaiseType)].add(spentValue); @@ -468,8 +475,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 investedUSD = DecimalMath.mul(_rate, _investmentValue); // Check for minimum investment - //require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); - require(investedUSD >= minimumInvestmentUSD, "investment < minimumInvestmentUSD"); //Why do we need to add? + require(investedUSD >= minimumInvestmentUSD, "investment < minimumInvestmentUSD"); // Check for non-accredited cap if (!accredited[_beneficiary]) { From 7b8d265fff6045c31585a8b35b1253e9cddb2b20 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 9 Nov 2018 13:09:38 +0530 Subject: [PATCH 063/582] Added test of min rate --- test/p_usd_tiered_sto.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index bb73757a4..86a2eded4 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -3972,6 +3972,30 @@ contract("USDTieredSTO", accounts => { ); }); + it("should fail when rate set my contract is too low", async () => { + let stoId = 4; + let tierId = 0; + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + let investment_Tokens = new BigNumber(10 ** 18); + let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Tokens); + let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Tokens); + const minTokens = new BigNumber(10 ** 20); + + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: ACCREDITED1 }); + + // Buy With POLY + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLYRateLimited(ACCREDITED1, investment_POLY, minTokens, { + from: ACCREDITED1, + gasPrice: GAS_PRICE + })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithETHRateLimited(ACCREDITED1, minTokens, { + from: ACCREDITED1, + gasPrice: GAS_PRICE, + value: investment_ETH + })); + }); + it("should fail and revert despite oracle price change when NONACCREDITED cap reached", async () => { let stoId = 2; let tierId = 0; From dd6ff86372291226117416075b56724a4aff0ef6 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 9 Nov 2018 13:10:08 +0530 Subject: [PATCH 064/582] Updated changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c5796e34..19b70b8a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file. [__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ ## Added +* Added an Array of Tiers that will hold data about every tier in USDSTO. +* Added `buyWithETHRateLimited`, `buyWithPOLYRateLimited` and `buyWithUSDRateLimited` to USDTSTO. * Added `getInvestorsAt` which returns the investors (non-zero balances) at a particular checkpoint * Added `iterateInvestors` to allow an a subset of `investors` to be returned from the security token in case `investors` is large. * `ChangeModuleBudget` in SecurityToken now takes in the change in budget rather than absoulte budget. Added boolean paramter to decide increase/decrease. @@ -42,6 +44,7 @@ All notable changes to this project will be documented in this file. * Change the function name of `withdraPoly` to `withdrawERC20` and make the function generalize to extract tokens from the ST contract. parmeters are contract address and the value need to extract from the securityToken. ## Removed +* Individual mappings for tier data removed in UDSTSTO. * Removed investors list pruning * Remove `swarmHash` from the `registerTicker(), addCustomTicker(), generateSecurityToken(), addCustomSecurityToken()` functions of TickerRegistry.sol and SecurityTokenRegistry.sol. #230 * Remove `Log` prefix from all the event present in the ecosystem. From 38881915551055013184b19a8d9dd67c31bc6610 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 9 Nov 2018 13:18:18 +0530 Subject: [PATCH 065/582] Minor nig fix --- contracts/modules/STO/USDTieredSTO.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 0f5b083ad..27d714a0e 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -473,7 +473,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { require(_investmentValue > 0, "No funds were sent"); uint256 investedUSD = DecimalMath.mul(_rate, _investmentValue); - + _rate = investedUSD; // Reusing variable to prevent stackoverflow // Check for minimum investment require(investedUSD >= minimumInvestmentUSD, "investment < minimumInvestmentUSD"); @@ -515,7 +515,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { if (spentUSD == 0) { spentValue = 0; } else { - spentValue = DecimalMath.div(spentUSD, _rate); + //_rate is actually OriginalUSD. Reusing variable to prevent stackoverflow + spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, _rate), _investmentValue); } // Return calculated amounts From a65bed9c9982817822c23feabc0426c82df4dca8 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 9 Nov 2018 14:32:10 +0530 Subject: [PATCH 066/582] final fix --- .../BlacklistTransferManager.sol | 4 +- .../BlacklistTransferManagerFactory.sol | 38 +------------------ 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index cdc7fe8d7..4052a1d4d 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -55,13 +55,13 @@ contract BlacklistTransferManager is ITransferManager { // Emit when new investor is added to the blacklist type event AddInvestorToBlacklist( - address _investor, + address indexed _investor, bytes32 _blacklistName ); // Emit when investor is deleted from the blacklist type event DeleteInvestorFromBlacklist( - address _investor, + address indexed _investor, bytes32 _blacklist ); diff --git a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol index 61bea2531..86357c39c 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol @@ -35,6 +35,7 @@ contract BlacklistTransferManagerFactory is ModuleFactory { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); address blacklistTransferManager = new BlacklistTransferManager(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(blacklistTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(blacklistTransferManager); } @@ -48,41 +49,6 @@ contract BlacklistTransferManagerFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() public view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() public view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Get the Instructions that helped to used the module */ @@ -96,7 +62,7 @@ contract BlacklistTransferManagerFactory is ModuleFactory { function getTags() public view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Blacklist"; - availableTags[1] = "Restrict selling of token"; + availableTags[1] = "Restricted transfer"; return availableTags; } From 7dc32254ec1228878074ce431922e44d91685c31 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 9 Nov 2018 14:50:15 +0530 Subject: [PATCH 067/582] Added getSTODetails to USDTSTO --- CHANGELOG.md | 3 ++- contracts/modules/STO/USDTieredSTO.sol | 31 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19b70b8a2..869af0d8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ All notable changes to this project will be documented in this file. [__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ ## Added -* Added an Array of Tiers that will hold data about every tier in USDSTO. +* Added `getSTODetails` to USDTSTO. +* Added an Array of Tiers that will hold data about every tier in USDTSTO. * Added `buyWithETHRateLimited`, `buyWithPOLYRateLimited` and `buyWithUSDRateLimited` to USDTSTO. * Added `getInvestorsAt` which returns the investors (non-zero balances) at a particular checkpoint * Added `iterateInvestors` to allow an a subset of `investors` to be returned from the security token in case `investors` is large. diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 27d714a0e..1a38b559b 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -707,6 +707,37 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { return allPermissions; } + /** + * @notice Return the STO details + * @return Unixtimestamp at which offering gets start. + * @return Unixtimestamp at which offering ends. + * @return Currently active tier + * @return Array of Number of tokens this STO will be allowed to sell at different tiers. + * @return Array Rate at which tokens are sold at different tiers + * @return Amount of funds raised + * @return Number of individual investors this STO have. + * @return Amount of tokens sold. + */ + function getSTODetails() public view returns(uint256, uint256, uint256, uint256[], uint256[], uint256, uint256, uint256) { + uint256 len = tiers.length; + uint256[] memory cap = new uint256[](len); + uint256[] memory rate = new uint256[](len); + for(uint256 i = 0; i < len; i++) { + cap[i] = tiers[i].tokenTotal; + rate[i] = tiers[i].rate; + } + return ( + startTime, + endTime, + currentTier, + cap, + rate, + fundsRaisedUSD, + investorCount, + getTokensSold() + ); + } + /** * @notice This function returns the signature of configure function * @return bytes4 Configure function signature From 8059c0e217cc34da28ec8141c6b16bba4cde855a Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 9 Nov 2018 15:27:03 +0530 Subject: [PATCH 068/582] typo fixes --- .../BlacklistTransferManager.sol | 154 +++++++++--------- test/z_blacklist_transfer_manager.js | 15 +- 2 files changed, 88 insertions(+), 81 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 4052a1d4d..ac4770462 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -4,7 +4,7 @@ import "./ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** - * @title Transfer Manager module to automate blacklist to restrict transfer + * @title Transfer Manager module to automate blacklist and restrict transfers */ contract BlacklistTransferManager is ITransferManager { using SafeMath for uint256; @@ -17,19 +17,19 @@ contract BlacklistTransferManager is ITransferManager { uint256 repeatPeriodTime; } - //hold the different blacklist corresponds to name of blacklist type + //hold the different blacklist details corresponds to its name mapping(bytes32 => BlacklistsDetails) blacklists; - //hold the blacklisted address corresponds to the blacklist type + //hold the different name of blacklist corresponds to a investor mapping(address => bytes32[]) investorToBlacklist; //get list of the addresses for a particular blacklist mapping(bytes32 => address[]) blacklistToInvestor; - //store the index of the investor to blacklist + //mapping use to store the indexes for different blacklist types for a investor mapping(address => mapping(bytes32 => uint256)) investorToIndex; - //store the index of the blacklist to investor + //mapping use to store the indexes for different investor for a blacklist type mapping(bytes32 => mapping(address => uint256)) blacklistToIndex; // Emit when new blacklist type is added @@ -40,7 +40,7 @@ contract BlacklistTransferManager is ITransferManager { uint256 _repeatPeriodTime ); - // Emit when there is change in the blacklist type + // Emit when there is a change in the blacklist type event ModifyBlacklistType( uint256 _startTime, uint256 _endTime, @@ -88,9 +88,9 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Used to verify the transfer transaction * @param _from Address of the sender - * @dev Restrict the blacklist address to transfer token - * if the current time is in the time frame define for the - * blacklist type associated with the blacklist address + * @dev Restrict the blacklist address to transfer tokens + * if the current time is between the timeframe define for the + * blacklist type associated with the _from address */ function verifyTransfer(address _from, address /* _to */, uint256 /* _amount */, bytes /* _data */, bool /* _isTransfer */) public returns(Result) { if (!paused) { @@ -103,10 +103,13 @@ contract BlacklistTransferManager is ITransferManager { // suppose startTime=500,endTime=1500,repeatPeriodTime=500 then blacklistTime =1500 // if you add blacklistTime to startTime and endTime i.e startTime = 2000 and endTime = 3000 uint256 blacklistTime = (endTimeTemp.sub(startTimeTemp)).add(repeatPeriodTimeTemp); + /*solium-disable-next-line security/no-block-members*/ if (now > startTimeTemp) { // Find the repeating parameter that will be used to calculate the new startTime and endTime // based on the new current time value + /*solium-disable-next-line security/no-block-members*/ uint256 repeater = (now.sub(startTimeTemp)).div(blacklistTime); + /*solium-disable-next-line security/no-block-members*/ if (startTimeTemp.add(blacklistTime.mul(repeater)) <= now && endTimeTemp.add(blacklistTime.mul(repeater)) >= now) { return Result.INVALID; } @@ -119,10 +122,10 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Used to add the blacklist type - * @param _startTime start date of the blacklist type - * @param _endTime end date of the blacklist type - * @param _name name of the blacklist type - * @param _repeatPeriodTime repeat period of the blacklist type + * @param _startTime Start date of the blacklist type + * @param _endTime End date of the blacklist type + * @param _name Name of the blacklist type + * @param _repeatPeriodTime Repeat period of the blacklist type */ function addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) public withPerm(ADMIN) { require(blacklists[_name].endTime == 0, "Blacklist type already exist"); @@ -133,15 +136,15 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Used to add the multiple blacklist type - * @param _startTime start date of the blacklist type - * @param _endTime end date of the blacklist type - * @param _name name of the blacklist type - * @param _repeatPeriodTime repeat period of the blacklist type + * @param _startTimes Start date of the blacklist type + * @param _endTimes End date of the blacklist type + * @param _names Name of the blacklist type + * @param _repeatPeriodTimes Repeat period of the blacklist type */ - function addBlacklistTypeMulti(uint256[] _startTime, uint256[] _endTime, bytes32[] _name, uint256[] _repeatPeriodTime) public withPerm(ADMIN) { - require (_startTime.length == _endTime.length && _endTime.length == _name.length && _name.length == _repeatPeriodTime.length, "Input array's length mismatch"); - for (uint256 i = 0; i < _startTime.length; i++){ - addBlacklistType(_startTime[i], _endTime[i], _name[i], _repeatPeriodTime[i]); + function addBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _names, uint256[] _repeatPeriodTimes) public withPerm(ADMIN) { + require (_startTimes.length == _endTimes.length && _endTimes.length == _names.length && _names.length == _repeatPeriodTimes.length, "Input array's length mismatch"); + for (uint256 i = 0; i < _startTimes.length; i++){ + addBlacklistType(_startTimes[i], _endTimes[i], _names[i], _repeatPeriodTimes[i]); } } @@ -155,11 +158,11 @@ contract BlacklistTransferManager is ITransferManager { } /** - * @notice Used to edit the blacklist type - * @param _startTime start date of the blacklist type - * @param _endTime end date of the blacklist type - * @param _name name of the blacklist type - * @param _repeatPeriodTime repeat period of the blacklist type + * @notice Used to modify the details of a given blacklist type + * @param _startTime Start date of the blacklist type + * @param _endTime End date of the blacklist type + * @param _name Name of the blacklist type + * @param _repeatPeriodTime Repeat period of the blacklist type */ function modifyBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) public withPerm(ADMIN) { require(blacklists[_name].endTime != 0, "Blacklist type doesn't exist"); @@ -169,22 +172,22 @@ contract BlacklistTransferManager is ITransferManager { } /** - * @notice Used to edit the mutiple blacklist type - * @param _startTime start date of the blacklist type - * @param _endTime end date of the blacklist type - * @param _name name of the blacklist type - * @param _repeatPeriodTime repeat period of the blacklist type + * @notice Used to modify the details of a given multpile blacklist types + * @param _startTimes Start date of the blacklist type + * @param _endTimes End date of the blacklist type + * @param _names Name of the blacklist type + * @param _repeatPeriodTimes Repeat period of the blacklist type */ - function modifyBlacklistTypeMulti(uint256[] _startTime, uint256[] _endTime, bytes32[] _name, uint256[] _repeatPeriodTime) public withPerm(ADMIN) { - require (_startTime.length == _endTime.length && _endTime.length == _name.length && _name.length == _repeatPeriodTime.length, "Input array's length mismatch"); - for (uint256 i = 0; i < _startTime.length; i++){ - modifyBlacklistType(_startTime[i], _endTime[i], _name[i], _repeatPeriodTime[i]); + function modifyBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _names, uint256[] _repeatPeriodTimes) public withPerm(ADMIN) { + require (_startTimes.length == _endTimes.length && _endTimes.length == _names.length && _names.length == _repeatPeriodTimes.length, "Input array's length mismatch"); + for (uint256 i = 0; i < _startTimes.length; i++){ + modifyBlacklistType(_startTimes[i], _endTimes[i], _names[i], _repeatPeriodTimes[i]); } } /** * @notice Used to delete the blacklist type - * @param _name name of the blacklist type + * @param _name Name of the blacklist type */ function deleteBlacklistType(bytes32 _name) public withPerm(ADMIN) { require(blacklists[_name].endTime != 0, "Blacklist type doesn’t exist"); @@ -195,19 +198,19 @@ contract BlacklistTransferManager is ITransferManager { } /** - * @notice Used to delete the mutiple blacklist type - * @param _name name of the blacklist type + * @notice Used to delete the multiple blacklist type + * @param _names Name of the blacklist type */ - function deleteBlacklistTypeMulti(bytes32[] _name) public withPerm(ADMIN) { - for(uint256 i = 0; i < _name.length; i++){ - deleteBlacklistType(_name[i]); + function deleteBlacklistTypeMulti(bytes32[] _names) public withPerm(ADMIN) { + for(uint256 i = 0; i < _names.length; i++){ + deleteBlacklistType(_names[i]); } } /** * @notice Used to assign the blacklist type to the investor - * @param _investor address of the investor - * @param _blacklistName name of the blacklist + * @param _investor Address of the investor + * @param _blacklistName Name of the blacklist */ function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); @@ -225,34 +228,34 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Used to assign the blacklist type to the multiple investor - * @param _investor address of the investor - * @param _blacklistName name of the blacklist + * @param _investors Address of the investor + * @param _blacklistName Name of the blacklist */ - function addInvestorToBlacklistMulti(address[] _investor, bytes32 _blacklistName) public withPerm(ADMIN){ - for(uint256 i = 0; i < _investor.length; i++){ - addInvestorToBlacklist(_investor[i], _blacklistName); + function addInvestorToBlacklistMulti(address[] _investors, bytes32 _blacklistName) public withPerm(ADMIN){ + for(uint256 i = 0; i < _investors.length; i++){ + addInvestorToBlacklist(_investors[i], _blacklistName); } } /** - * @notice Used to assign the mutiple blacklist type to the multiple investor - * @param _investor address of the investor - * @param _blacklistName name of the blacklist + * @notice Used to assign the multiple blacklist type to the multiple investor + * @param _investors Address of the investor + * @param _blacklistNames Name of the blacklist */ - function addMultiInvestorToBlacklistMulti(address[] _investor, bytes32[] _blacklistName) public withPerm(ADMIN){ - require (_investor.length == _blacklistName.length, "Input array's length mismatch"); - for(uint256 i = 0; i < _investor.length; i++){ - addInvestorToBlacklist(_investor[i], _blacklistName[i]); + function addMultiInvestorToBlacklistMulti(address[] _investors, bytes32[] _blacklistNames) public withPerm(ADMIN){ + require (_investors.length == _blacklistNames.length, "Input array's length mismatch"); + for(uint256 i = 0; i < _investors.length; i++){ + addInvestorToBlacklist(_investors[i], _blacklistNames[i]); } } /** * @notice Used to assign the new blacklist type to the investor - * @param _startTime start date of the blacklist type - * @param _endTime end date of the blacklist type - * @param _name name of the blacklist type - * @param _repeatPeriodTime repeat period of the blacklist type - * @param _investor address of the investor + * @param _startTime Start date of the blacklist type + * @param _endTime End date of the blacklist type + * @param _name Name of the blacklist type + * @param _repeatPeriodTime Repeat period of the blacklist type + * @param _investor Address of the investor */ function addInvestorToNewBlacklist(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime, address _investor) public withPerm(ADMIN){ addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); @@ -260,8 +263,8 @@ contract BlacklistTransferManager is ITransferManager { } /** - * @notice Used to delete the investor from the all associated blacklists - * @param _investor address of the investor + * @notice Used to delete the investor from all the associated blacklist types + * @param _investor Address of the investor */ function deleteInvestorFromAllBlacklist(address _investor) public withPerm(ADMIN) { require(_investor != address(0), "Invalid investor address"); @@ -272,8 +275,8 @@ contract BlacklistTransferManager is ITransferManager { } /** - * @notice Used to delete the mutiple investor from the all associated blacklists - * @param _investor address of the investor + * @notice Used to delete the multiple investor from all the associated blacklist types + * @param _investor Address of the investor */ function deleteInvestorFromAllBlacklistMulti(address[] _investor) public withPerm(ADMIN) { for(uint256 i = 0; i < _investor.length; i++){ @@ -283,8 +286,8 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Used to delete the investor from the blacklist - * @param _investor address of the investor - * @param _blacklistName name of the blacklist + * @param _investor Address of the investor + * @param _blacklistName Name of the blacklist */ function deleteInvestorFromBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { require(_investor != address(0), "Invalid investor address"); @@ -314,21 +317,22 @@ contract BlacklistTransferManager is ITransferManager { } /** - * @notice Used to delete the mutiple investor from the blacklist - * @param _investor address of the investor - * @param _blacklistName name of the blacklist + * @notice Used to delete the multiple investor from the blacklist + * @param _investors address of the investor + * @param _blacklistNames name of the blacklist */ - function deleteInvestorFromBlacklistMulti(address[] _investor, bytes32[] _blacklistName) public withPerm(ADMIN) { - require (_investor.length == _blacklistName.length, "Input array's length mismatch"); - for(uint256 i = 0; i < _investor.length; i++){ - deleteInvestorFromBlacklist(_investor[i], _blacklistName[i]); + function deleteMultiInvestorsFromBlacklistMulti(address[] _investors, bytes32[] _blacklistNames) public withPerm(ADMIN) { + require (_investors.length == _blacklistNames.length, "Input array's length mismatch"); + for(uint256 i = 0; i < _investors.length; i++){ + deleteInvestorFromBlacklist(_investors[i], _blacklistNames[i]); } } /** * @notice get the list of the investors of a blacklist type - * @param _blacklistName name of the blacklist type + * @param _blacklistName Name of the blacklist type + * @return address List of investors associated with the blacklist */ function getListOfAddresses(bytes32 _blacklistName) public view returns(address[]) { require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); @@ -336,7 +340,7 @@ contract BlacklistTransferManager is ITransferManager { } /** - * @notice Return the permissions flag that are associated with general transfer manager + * @notice Return the permissions flag that are associated with blacklist transfer manager */ function getPermissions() public view returns(bytes32[]) { bytes32[] memory allPermissions = new bytes32[](1); diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index b8918d9e2..ae6d8b9f2 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -797,7 +797,7 @@ contract('BlacklistTransferManager', accounts => { // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); let investor = [account_investor5,account_investor2]; let blacklistName = ["s_blacklist","g_blacklist"]; - let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteMultiInvestorsFromBlacklistMulti(investor,blacklistName, { from: token_owner }); let event_data = tx.logs; for (var i = 0; i < event_data.length; i++) { let investorName = event_data[i].args._investor; @@ -811,7 +811,7 @@ contract('BlacklistTransferManager', accounts => { let investor = [account_investor5,account_investor2]; let blacklistName = ["s_blacklist","g_blacklist"]; await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { + I_BlacklistTransferManager.deleteMultiInvestorsFromBlacklistMulti(investor,blacklistName, { from: account_investor1 }) ); @@ -821,7 +821,7 @@ contract('BlacklistTransferManager', accounts => { let investor = [account_investor5]; let blacklistName = ["s_blacklist","g_blacklist"]; await catchRevert( - I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { + I_BlacklistTransferManager.deleteMultiInvestorsFromBlacklistMulti(investor,blacklistName, { from: token_owner }) ); @@ -928,7 +928,7 @@ contract('BlacklistTransferManager', accounts => { it("Should fail in adding the mutiple investor to the mutiple blacklist because only owner can do it.", async() => { let investor = [account_investor4,account_investor5]; let blacklistName = ["m_blacklist","n_blacklist"]; - await I_BlacklistTransferManager.deleteInvestorFromBlacklistMulti(investor,blacklistName, { from: token_owner }); + await I_BlacklistTransferManager.deleteMultiInvestorsFromBlacklistMulti(investor,blacklistName, { from: token_owner }); await catchRevert( I_BlacklistTransferManager.addMultiInvestorToBlacklistMulti(investor, blacklistName, { from: account_investor1 @@ -967,15 +967,18 @@ contract('BlacklistTransferManager', accounts => { .replace(/\u0000/g, ''), "BlacklistTransferManager", "Wrong Module added"); - assert.equal(await I_BlacklistTransferManagerFactory.getDescription.call(), + assert.equal(await I_BlacklistTransferManagerFactory.description.call(), "Automate blacklist to restrict selling", "Wrong Module added"); - assert.equal(await I_BlacklistTransferManagerFactory.getTitle.call(), + assert.equal(await I_BlacklistTransferManagerFactory.title.call(), "Blacklist Transfer Manager", "Wrong Module added"); assert.equal(await I_BlacklistTransferManagerFactory.getInstructions.call(), "Allows an issuer to blacklist the addresses.", "Wrong Module added"); + assert.equal(await I_BlacklistTransferManagerFactory.version.call(), + "1.0.0", + "Wrong Module added"); }); From 6c32108efdf492fc7748c0c2686105065630648d Mon Sep 17 00:00:00 2001 From: Polymath Date: Fri, 9 Nov 2018 09:04:06 -0300 Subject: [PATCH 069/582] gasPrice <-> value --- CLI/commands/dividends_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index f47d3fd67..0f423bf5d 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -344,7 +344,7 @@ async function createDividends(name, dividend, checkpointId) { createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, excluded, web3.utils.toHex(name)); } } - let receipt = await common.sendTransaction(createDividendAction, {gasPrice: web3.utils.toWei(dividend)}); + let receipt = await common.sendTransaction(createDividendAction, {value: web3.utils.toWei(dividend)}); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'EtherDividendDeposited'); console.log(` Dividend ${event._dividendIndex} deposited` From 601744478e6defe1c5f00d518d58ff7c72fe0c1e Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 9 Nov 2018 17:56:35 +0530 Subject: [PATCH 070/582] Updated getSTODetails --- contracts/modules/STO/USDTieredSTO.sol | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 1a38b559b..ebc4517bb 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -717,15 +717,19 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @return Amount of funds raised * @return Number of individual investors this STO have. * @return Amount of tokens sold. + * @return Array of bools to show if funding is allowed in ETH, POLY, DAI respectively */ - function getSTODetails() public view returns(uint256, uint256, uint256, uint256[], uint256[], uint256, uint256, uint256) { - uint256 len = tiers.length; - uint256[] memory cap = new uint256[](len); - uint256[] memory rate = new uint256[](len); - for(uint256 i = 0; i < len; i++) { + function getSTODetails() public view returns(uint256, uint256, uint256, uint256[], uint256[], uint256, uint256, uint256, bool[]) { + uint256[] memory cap = new uint256[](tiers.length); + uint256[] memory rate = new uint256[](tiers.length); + for(uint256 i = 0; i < tiers.length; i++) { cap[i] = tiers[i].tokenTotal; rate[i] = tiers[i].rate; } + bool[] memory _fundRaiseTypes = new bool[](3); + _fundRaiseTypes[0] = fundRaiseTypes[uint8(FundRaiseType.ETH)]; + _fundRaiseTypes[1] = fundRaiseTypes[uint8(FundRaiseType.POLY)]; + _fundRaiseTypes[2] = fundRaiseTypes[uint8(FundRaiseType.DAI)]; return ( startTime, endTime, @@ -734,7 +738,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { rate, fundsRaisedUSD, investorCount, - getTokensSold() + getTokensSold(), + _fundRaiseTypes ); } From 6f1743453fbdb870c1f9059267c37afb9af1e493 Mon Sep 17 00:00:00 2001 From: Polymath Date: Fri, 9 Nov 2018 14:59:04 -0300 Subject: [PATCH 071/582] adding module address --- CLI/commands/permission_manager.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index c75b7af69..15f73d6c5 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -261,10 +261,10 @@ async function getDelegatesAndPermissions() { if (result[delegateAddr] == undefined) { result[delegateAddr] = [] } - if (result[delegateAddr][moduleName] == undefined) { - result[delegateAddr][moduleName] = [{permission: permissionName}] + if (result[delegateAddr][moduleName + '-' + module] == undefined) { + result[delegateAddr][moduleName + '-' + module] = [{permission: permissionName}] } else { - result[delegateAddr][moduleName].push({permission: permissionName}) + result[delegateAddr][moduleName + '-' + module].push({permission: permissionName}) } } } @@ -279,7 +279,7 @@ function renderTable(permissions, address) { if (permissions[address] != undefined) { Object.keys(permissions[address]).forEach((module) => { result += ` - ${module} -> `; + ${module.split('-')[0]} (${module.split('-')[1]}) -> `; (permissions[address][module]).forEach((perm) => { result += `${perm.permission}, `; }) From 01b7b72bdf2ff5a6ac5058d9204bb8b0f069b3aa Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Fri, 9 Nov 2018 15:23:04 -0300 Subject: [PATCH 072/582] gbl MODULES_TYPES fix --- CLI/commands/permission_manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index 06fbf69a1..ef3e2ea60 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -238,8 +238,8 @@ async function getModulesWithPermissions() { async function getDelegatesAndPermissions() { let moduleABI = abis.moduleInterface(); let result = []; - for (const type in MODULES_TYPES) { - let modulesAttached = await securityToken.methods.getModulesByType(MODULES_TYPES[type]).call(); + for (const type in gbl.constants.MODULES_TYPES) { + let modulesAttached = await securityToken.methods.getModulesByType(gbl.constants.MODULES_TYPES[type]).call(); for (const module of modulesAttached) { let contractTemp = new web3.eth.Contract(moduleABI, module); let permissions = await contractTemp.methods.getPermissions().call(); From 491c46027d59f2a57b21c6fcd84b86ecdaa74760 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 12 Nov 2018 14:23:23 +0530 Subject: [PATCH 073/582] Function modifier changes --- contracts/modules/STO/USDTieredSTO.sol | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index ebc4517bb..e2a139ce4 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -200,7 +200,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); } - function modifyFunding(FundRaiseType[] _fundRaiseTypes) external { + function modifyFunding(FundRaiseType[] _fundRaiseTypes) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); _setFundRaiseType(_fundRaiseTypes); @@ -209,12 +209,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { function modifyLimits( uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD - ) external onlyFactoryOrOwner { + ) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); - minimumInvestmentUSD = _minimumInvestmentUSD; - nonAccreditedLimitUSD = _nonAccreditedLimitUSD; - emit SetLimits(minimumInvestmentUSD, nonAccreditedLimitUSD); + _modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); } function modifyTiers( @@ -222,7 +220,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256[] _ratePerTierDiscountPoly, uint256[] _tokensPerTierTotal, uint256[] _tokensPerTierDiscountPoly - ) external onlyFactoryOrOwner { + ) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); _modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); @@ -231,7 +229,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { function modifyTimes( uint256 _startTime, uint256 _endTime - ) external onlyFactoryOrOwner { + ) external onlyOwner { _modifyTimes(_startTime, _endTime); } @@ -239,7 +237,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { address _wallet, address _reserveWallet, address _usdToken - ) external onlyFactoryOrOwner { + ) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); _modifyAddresses(_wallet, _reserveWallet, _usdToken); @@ -381,16 +379,16 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } // For backwards compatibility - function buyWithETH(address _beneficiary) public payable { + function buyWithETH(address _beneficiary) external payable { buyWithETHRateLimited(_beneficiary, 0); } - function buyWithPOLY(address _beneficiary, uint256 _investedPOLY) public { - _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, 0); + function buyWithPOLY(address _beneficiary, uint256 _investedPOLY) external { + buyWithPOLYRateLimited(_beneficiary, _investedPOLY, 0); } - function buyWithUSD(address _beneficiary, uint256 _investedDAI) public validDAI { - _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, 0); + function buyWithUSD(address _beneficiary, uint256 _investedDAI) external { + buyWithUSDRateLimited(_beneficiary, _investedDAI, 0); } /** From be22b4d7ad4b0006bc977a5bec5bab5edbd32cf6 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 12 Nov 2018 14:38:45 +0530 Subject: [PATCH 074/582] Minimum investment logic change --- contracts/modules/STO/USDTieredSTO.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index e2a139ce4..bd2df86c3 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -473,7 +473,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 investedUSD = DecimalMath.mul(_rate, _investmentValue); _rate = investedUSD; // Reusing variable to prevent stackoverflow // Check for minimum investment - require(investedUSD >= minimumInvestmentUSD, "investment < minimumInvestmentUSD"); + require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); // Check for non-accredited cap if (!accredited[_beneficiary]) { From 32d4b3cfb826c324f14d91e0671feb6808f3f097 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Mon, 12 Nov 2018 14:28:00 -0300 Subject: [PATCH 075/582] Merge remote-tracking branch 'origin/dev-2.1.0' into CLI-st20generator-refactoring --- .solcover.js | 4 +- CHANGELOG.md | 4 + CLI/commands/ST20Generator.js | 31 +- CLI/commands/TickerRollForward.js | 9 +- CLI/commands/accredit.js | 3 +- CLI/commands/changeNonAccreditedLimit.js | 3 +- CLI/commands/common/common_functions.js | 127 +++--- CLI/commands/common/constants.js | 34 ++ CLI/commands/common/global.js | 67 +-- CLI/commands/common/permissions_list.js | 2 +- CLI/commands/contract_manager.js | 31 +- CLI/commands/dividends_manager.js | 55 +-- CLI/commands/faucet.js | 12 +- CLI/commands/helpers/contract_addresses.js | 2 +- CLI/commands/investor_portal.js | 62 ++- CLI/commands/module_manager.js | 20 +- CLI/commands/multi_mint.js | 2 +- CLI/commands/permission_manager.js | 87 +++- CLI/commands/strMigrator.js | 26 +- CLI/commands/transfer.js | 11 +- CLI/commands/transfer_manager.js | 15 +- CLI/commands/transfer_ownership.js | 10 +- CLI/commands/whitelist.js | 2 +- CLI/polymath-cli.js | 42 +- README.md | 29 ++ contracts/Migrations.sol | 2 +- contracts/ModuleRegistry.sol | 19 +- contracts/Pausable.sol | 10 +- contracts/PolymathRegistry.sol | 6 +- contracts/ReclaimTokens.sol | 4 +- contracts/RegistryUpdater.sol | 4 +- contracts/SecurityTokenRegistry.sol | 60 ++- contracts/external/IMedianizer.sol | 1 + contracts/external/oraclizeAPI.sol | 2 +- contracts/helpers/PolyToken.sol | 64 +-- contracts/interfaces/IModule.sol | 6 +- contracts/interfaces/IModuleFactory.sol | 41 +- contracts/interfaces/IPolymathRegistry.sol | 4 +- contracts/interfaces/ISTFactory.sol | 15 +- contracts/interfaces/ISecurityToken.sol | 137 +++--- .../interfaces/ISecurityTokenRegistry.sol | 60 ++- contracts/interfaces/IUSDTieredSTOProxy.sol | 6 +- contracts/libraries/TokenLib.sol | 38 +- contracts/libraries/Util.sol | 14 +- contracts/libraries/VersionUtils.sol | 16 +- contracts/mocks/MockBurnFactory.sol | 7 +- contracts/mocks/MockModuleRegistry.sol | 2 +- contracts/mocks/MockRedemptionManager.sol | 11 +- contracts/mocks/PolyTokenFaucet.sol | 24 +- contracts/mocks/SecurityTokenRegistryMock.sol | 2 +- contracts/mocks/TestSTOFactory.sol | 2 +- contracts/modules/Burn/IBurn.sol | 1 + .../modules/Checkpoint/DividendCheckpoint.sol | 48 ++- .../Checkpoint/ERC20DividendCheckpoint.sol | 105 ++++- .../ERC20DividendCheckpointFactory.sol | 40 +- .../Checkpoint/EtherDividendCheckpoint.sol | 63 ++- .../EtherDividendCheckpointFactory.sol | 42 +- contracts/modules/Checkpoint/ICheckpoint.sol | 1 + .../Burn/TrackedRedemption.sol | 13 +- .../Burn/TrackedRedemptionFactory.sol | 44 +- .../Mixed/ScheduledCheckpoint.sol | 155 +++++++ .../Mixed/ScheduledCheckpointFactory.sol | 102 +++++ .../LockupVolumeRestrictionTM.sol | 15 +- .../LockupVolumeRestrictionTMFactory.sol | 42 +- .../SingleTradeVolumeRestrictionTM.sol | 53 ++- .../SingleTradeVolumeRestrictionTMFactory.sol | 49 +-- contracts/modules/ModuleFactory.sol | 52 ++- .../GeneralPermissionManager.sol | 28 +- .../GeneralPermissionManagerFactory.sol | 43 +- .../PermissionManager/IPermissionManager.sol | 18 +- contracts/modules/STO/CappedSTO.sol | 25 +- contracts/modules/STO/CappedSTOFactory.sol | 40 +- contracts/modules/STO/DummySTO.sol | 8 +- contracts/modules/STO/DummySTOFactory.sol | 39 +- contracts/modules/STO/ISTO.sol | 19 +- contracts/modules/STO/PreSaleSTO.sol | 33 +- contracts/modules/STO/PreSaleSTOFactory.sol | 41 +- .../ProxyFactory/USDTieredSTOProxyFactory.sol | 4 +- contracts/modules/STO/USDTieredSTO.sol | 111 +++-- contracts/modules/STO/USDTieredSTOFactory.sol | 42 +- .../TransferManager/CountTransferManager.sol | 15 +- .../CountTransferManagerFactory.sol | 41 +- .../GeneralTransferManager.sol | 40 +- .../GeneralTransferManagerFactory.sol | 43 +- .../ManualApprovalTransferManager.sol | 40 +- .../ManualApprovalTransferManagerFactory.sol | 37 +- .../PercentageTransferManager.sol | 4 +- .../PercentageTransferManagerFactory.sol | 39 +- contracts/oracles/MakerDAOOracle.sol | 4 + contracts/oracles/PolyOracle.sol | 47 ++- contracts/proxy/ModuleRegistryProxy.sol | 1 + contracts/proxy/OwnedUpgradeabilityProxy.sol | 3 +- contracts/proxy/Proxy.sol | 1 + .../proxy/SecurityTokenRegistryProxy.sol | 1 + contracts/proxy/UpgradeabilityProxy.sol | 7 +- contracts/tokens/SecurityToken.sol | 203 +++++---- docs/permissions_list.md | 3 +- migrations/2_deploy_contracts.js | 2 +- package.json | 9 +- scripts/tokenInfo.js | 72 ++++ test/b_capped_sto.js | 12 +- test/d_count_transfer_manager.js | 8 +- test/e_erc20_dividends.js | 8 +- test/f_ether_dividends.js | 10 +- test/g_general_permission_manager.js | 12 +- test/h_general_transfer_manager.js | 77 +++- test/helpers/createInstances.js | 22 +- test/helpers/signData.js | 6 +- test/j_manual_approval_transfer_manager.js | 8 +- test/l_percentage_transfer_manager.js | 47 ++- test/m_presale_sto.js | 6 +- test/o_security_token.js | 82 +++- test/p_usd_tiered_sto.js | 10 +- test/v_tracked_redemptions.js | 8 +- ...kup_volume_restriction_transfer_manager.js | 8 +- test/x_single_trade_volume_restriction.js | 8 +- test/y_scheduled_checkpoints.js | 389 ++++++++++++++++++ 117 files changed, 2397 insertions(+), 1459 deletions(-) create mode 100644 CLI/commands/common/constants.js rename contracts/modules/{ => Experimental}/Burn/TrackedRedemption.sol (81%) rename contracts/modules/{ => Experimental}/Burn/TrackedRedemptionFactory.sol (68%) create mode 100644 contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol create mode 100644 contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol rename contracts/modules/{ => Experimental}/TransferManager/LockupVolumeRestrictionTM.sol (96%) rename contracts/modules/{ => Experimental}/TransferManager/LockupVolumeRestrictionTMFactory.sol (75%) rename contracts/modules/{ => Experimental}/TransferManager/SingleTradeVolumeRestrictionTM.sol (90%) rename contracts/modules/{ => Experimental}/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol (75%) create mode 100644 scripts/tokenInfo.js create mode 100644 test/y_scheduled_checkpoints.js diff --git a/.solcover.js b/.solcover.js index ffd077e28..23ac4d3ef 100644 --- a/.solcover.js +++ b/.solcover.js @@ -4,6 +4,6 @@ module.exports = { copyPackages: ['openzeppelin-solidity'], testCommand: 'node ../node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js` --network coverage', deepSkip: true, - skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'storage'], - forceParse: ['mocks', 'oracles'] + skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'storage', 'modules/Experimental'], + forceParse: ['mocks', 'oracles', 'modules/Experimental'] }; diff --git a/CHANGELOG.md b/CHANGELOG.md index 319d15ebb..4c5796e34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ All notable changes to this project will be documented in this file. [__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ ## Added +* Added `getInvestorsAt` which returns the investors (non-zero balances) at a particular checkpoint +* Added `iterateInvestors` to allow an a subset of `investors` to be returned from the security token in case `investors` is large. +* `ChangeModuleBudget` in SecurityToken now takes in the change in budget rather than absoulte budget. Added boolean paramter to decide increase/decrease. * Added `createCheckpoint() withPerm(CHECKPOINT)` to dividend checkpoint modules. * Added `deleteDelegate()` to general permission manager. It will disable the delegate but not delete the perms. * Migrated from `npm` to `yarn`. @@ -39,6 +42,7 @@ All notable changes to this project will be documented in this file. * Change the function name of `withdraPoly` to `withdrawERC20` and make the function generalize to extract tokens from the ST contract. parmeters are contract address and the value need to extract from the securityToken. ## Removed +* Removed investors list pruning * Remove `swarmHash` from the `registerTicker(), addCustomTicker(), generateSecurityToken(), addCustomSecurityToken()` functions of TickerRegistry.sol and SecurityTokenRegistry.sol. #230 * Remove `Log` prefix from all the event present in the ecosystem. * Removed `addTagByModuleType` & `removeTagsByModuleType` from MR. diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index ab230af89..556baf8eb 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -1,11 +1,10 @@ -const readlineSync = require('readline-sync'); -const moment = require('moment'); -const chalk = require('chalk'); -const contracts = require('./helpers/contract_addresses'); -const abis = require('./helpers/contract_abis'); -const common = require('./common/common_functions'); -const global = require('./common/global'); -const BigNumber = require('bignumber.js'); +var readlineSync = require('readline-sync'); +var BigNumber = require('bignumber.js'); +var moment = require('moment'); +var chalk = require('chalk'); +var contracts = require('./helpers/contract_addresses'); +var abis = require('./helpers/contract_abis'); +var common = require('./common/common_functions'); //////////////////////// let securityTokenRegistryAddress; @@ -16,9 +15,7 @@ let tokenLaunched; let securityTokenRegistry; let polyToken; -async function executeApp(_ticker, _transferOwnership, _name, _details, _divisible, _remoteNetwork) { - await global.initialize(_remoteNetwork); - +async function executeApp(_ticker, _transferOwnership, _name, _details, _divisible) { common.logAsciiBull(); console.log("********************************************"); console.log("Welcome to the Command-Line ST-20 Generator."); @@ -80,7 +77,7 @@ async function step_ticker_registration(_ticker) { available = true; await approvePoly(securityTokenRegistryAddress, regFee); let registerTickerAction = securityTokenRegistry.methods.registerTicker(Issuer.address, tokenSymbol, ""); - await common.sendTransaction(Issuer, registerTickerAction, defaultGasPrice, 0, 1.5); + await common.sendTransaction(registerTickerAction, {factor: 1.5}); } else if (details[0] == Issuer.address) { // If it has registration date and its owner is Issuer available = true; @@ -108,7 +105,7 @@ async function step_transfer_ticker_ownership(_transferOwnership) { if (newOwner) { let transferTickerOwnershipAction = securityTokenRegistry.methods.transferTickerOwnership(newOwner, tokenSymbol); - let receipt = await common.sendTransaction(Issuer, transferTickerOwnershipAction, defaultGasPrice, 0, 1.5); + let receipt = await common.sendTransaction(transferTickerOwnershipAction, {factor: 1.5}); let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'ChangeTickerOwnership'); console.log(chalk.green(`Ownership trasferred successfully. The new owner is ${event._newOwner}`)); process.exit(0); @@ -148,7 +145,7 @@ async function step_token_deploy(_name, _details, _divisible) { await approvePoly(securityTokenRegistryAddress, launchFee); let generateSecurityTokenAction = securityTokenRegistry.methods.generateSecurityToken(tokenName, tokenSymbol, tokenDetails, divisibility); - let receipt = await common.sendTransaction(Issuer, generateSecurityTokenAction, defaultGasPrice); + let receipt = await common.sendTransaction(generateSecurityTokenAction); let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'NewSecurityToken'); console.log(chalk.green(`Security Token has been successfully deployed at address ${event._securityTokenAddress}`)); } @@ -193,7 +190,7 @@ async function approvePoly(spender, fee) { return true; } else { let approveAction = polyToken.methods.approve(spender, web3.utils.toWei(fee.toString(), "ether")); - await common.sendTransaction(Issuer, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction); } } else { let requiredBalance = parseInt(requiredAmount) - parseInt(polyBalance); @@ -205,7 +202,7 @@ async function approvePoly(spender, fee) { } module.exports = { - executeApp: async function(ticker, transferOwnership, name, details, divisible, remoteNode) { - return executeApp(ticker, transferOwnership, name, details, divisible, remoteNode); + executeApp: async function(ticker, transferOwnership, name, details, divisible) { + return executeApp(ticker, transferOwnership, name, details, divisible); } } diff --git a/CLI/commands/TickerRollForward.js b/CLI/commands/TickerRollForward.js index 97bd1f519..69d36575d 100644 --- a/CLI/commands/TickerRollForward.js +++ b/CLI/commands/TickerRollForward.js @@ -3,15 +3,11 @@ var csv = require('fast-csv'); var BigNumber = require('bignumber.js'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); ///////////////////////// ARTIFACTS ///////////////////////// var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); -////////////////////////////USER INPUTS////////////////////////////////////////// -let remoteNetwork = process.argv.slice(2)[0]; //batch size - ///////////////////////// GLOBAL VARS ///////////////////////// let ticker_data = []; let registered_tickers = []; @@ -47,7 +43,6 @@ function FailedRegistration(_ticker, _error) { startScript(); async function startScript() { - await global.initialize(remoteNetwork); securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -88,7 +83,7 @@ async function registerTickers() { process.exit(0); } else { let approveAction = polyToken.methods.approve(securityTokenRegistryAddress, totalFee); - let receipt = await common.sendTransaction(Issuer, approveAction, defaultGasPrice); + let receipt = await common.sendTransaction(approveAction); totalGas = totalGas.add(receipt.gasUsed); } @@ -115,7 +110,7 @@ async function registerTickers() { if (valid) { try { let registerTickerAction = securityTokenRegistry.methods.registerTicker(owner, ticker_data[i].symbol, ticker_data[i].name); - let receipt = await common.sendTransaction(Issuer, registerTickerAction, defaultGasPrice); + let receipt = await common.sendTransaction(registerTickerAction); registered_tickers.push(ticker_data[i]); console.log(ticker_data[i]); totalGas = totalGas.add(receipt.gasUsed); diff --git a/CLI/commands/accredit.js b/CLI/commands/accredit.js index c4dbd78b6..a0aa306a2 100644 --- a/CLI/commands/accredit.js +++ b/CLI/commands/accredit.js @@ -35,6 +35,7 @@ startScript(); async function startScript() { if (remoteNetwork == 'undefined') remoteNetwork = undefined; await global.initialize(remoteNetwork); + try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -130,7 +131,7 @@ async function changeAccredited() { } let changeAccreditedAction = usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); - let r = await common.sendTransaction(Issuer, changeAccreditedAction, defaultGasPrice); + let r = await common.sendTransaction(changeAccreditedAction); console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); diff --git a/CLI/commands/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js index b1ececbc7..b4d5e3c6b 100644 --- a/CLI/commands/changeNonAccreditedLimit.js +++ b/CLI/commands/changeNonAccreditedLimit.js @@ -35,6 +35,7 @@ startScript(); async function startScript() { if (remoteNetwork == 'undefined') remoteNetwork = undefined; await global.initialize(remoteNetwork); + try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -130,7 +131,7 @@ async function changeNonAccreditedLimit() { } let changeNonAccreditedLimitAction = usdTieredSTO.methods.changeNonAccreditedLimit(investorArray, limitArray); - let r = await common.sendTransaction(Issuer, changeNonAccreditedLimitAction, defaultGasPrice); + let r = await common.sendTransaction(changeNonAccreditedLimitAction); console.log(`Batch ${i} - Attempting to change non accredited limits to accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString()), "Ether"); diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index af3cdc8fa..123e158cb 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -25,6 +25,41 @@ async function checkPermission(contractName, functionName, contractRegistry) { } }; +function getFinalOptions(options) { + if (typeof options != "object") { + options = {} + } + const defaultOptions = { + from: Issuer, + gasPrice: defaultGasPrice, + value: undefined, + factor: 1.2 + } + return Object.assign(defaultOptions, options) +}; + +async function getGasLimit(options, action) { + let block = await web3.eth.getBlock("latest"); + let networkGasLimit = block.gasLimit; + let gas = Math.round(options.factor * (await action.estimateGas({ from: options.from.address, value: options.value}))); + return (gas > networkGasLimit) ? networkGasLimit : gas; +} + +async function checkPermissions(action) { + let contractRegistry = await connect(action._parent.options.jsonInterface, action._parent._address); + //NOTE this is a condition to verify if the transaction comes from a module or not. + if (contractRegistry.methods.hasOwnProperty('factory')) { + let moduleAddress = await contractRegistry.methods.factory().call(); + let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress) + let parentModule = await moduleRegistry.methods.getName().call(); + let result = await checkPermission(web3.utils.hexToUtf8(parentModule), action._method.name, contractRegistry); + if (!result) { + console.log("You haven't the right permissions to execute this method."); + process.exit(0); + } + } +} + module.exports = { convertToDaysRemaining: function (timeRemaining) { var seconds = parseInt(timeRemaining, 10); @@ -38,78 +73,52 @@ module.exports = { return (days + " days, " + hrs + " Hrs, " + mnts + " Minutes, " + seconds + " Seconds"); }, logAsciiBull: function() { - console.log(` -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(@(&&@@@@@@@@@@@@@@@@@@@@@@@@@@(((@&&&&(/@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#(((((((#%%%#@@@@@@@@@@@@@@@@@@@@%##(((/@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(%(((((((((((#%%%%%@#@@@@@@@@@@@@(&#####@@@@@@@@%& -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&#((((((((((((((##%%%%%%%&&&%%##@%#####%(@@@@@@@#%#& -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(%((((((((((((((((((###%%%%%((#####%%%####@@@@@@@###((@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#(((((((((((((((((((((####%%%#((((######%&%@@(##&###(@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#((((((((((((((((((((((((####%%#(((((((#((((((((((((#(@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(%(((((((((((((((((((((((((((######%(((((((((((((#&(/@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&#(((((((((((((((((((((((((((((((###############(##%%#@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#((((##############(((((((((((((((((###################%@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@(&#((#(##################((((((((((((((((((##%%##############@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@/%#(((((((##%((((##############((((((((((((((((((##%%#############%%@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@((((((((((###%%((((((##########(((((((((((((((((((#%%%############%%%#@@@@@@@@@ -@@@@@@@@@@@@@@@@@@%((((((((((####%%%((((((((#######(((((((((((####(((((@%%############%%%#@@@@@@@@@ -@@@@@@@@@####%%%%%#(((((((((#####%%%%(((((((((((###((((#######(((((((((&@@(&#########%%%%&@@@@@@@@@ -@@@@@@@@&(((#####%###(((((((#####%%%%%((((((((####%%%%%%%%&%@%#((((((((@@@@@@(#(####%%%%%%@@@@@@@@@ -@@@@@@@&(((@@@@@@@####(((((######%%%%%%##&########%%%%%#@@@@###(((((#(@@@@@@@@@@@###%%#@@@@@@@@@@@@ -@@@#%&%(((@@@@@@@@#####(((#######%%%%@@@@@@@@@@@((##@@@@@@@@%###((((/@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@#%%&%#@@@@@@@@@@############%%%%@@@@@@@@@@@@@@@@@@@@(@&&&&#####(#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@#%%%%%#((%%%%%%#@@@@@@@@@@@@@@@@@@@@(####%((((%#(@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@&%%%#((((((%%&@@@@@@@@@@@@@@@@@@@@@@###%%#((@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@%%%%((((((((& @@@@@@@@@@@@@@@@@@@@@@@%%&%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@%%(((((&#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@&((###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@#####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@&####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@&&%##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@&&&%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@%##%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@#%####%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + console.log(` + /######%%, /#( + ##########%%%%%, ,%%%. % + *#############%%%%%##%%%%%%# ## + (################%%%%#####%%%%//###%, + .####################%%%%#########/ + (#########%%############%%%%%%%%%#%%% + ,(%#%%%%%%%%%%%%############%%%%%%%###%%%. + (######%%###%%%%%%%%##############%%%%%####%%%* + /#######%%%%######%%%%##########%###,.%######%%%( + #%%%%%#######%%%%%%###########%%%%%*###### /####%%%# + #. ,%%####%%%%%%%(/#%%%%%%%%( #%#### ,#%/ + *#%( .%%%##%%%%%% .%%%#* + .%%%%#%%%% .%%%###( + %%%#####% (%%. + #%###(, + *#%# + %%# + * + &% + %%%. `); }, - sendTransaction: async function (from, action, gasPrice, value, factor) { - let contractRegistry = await connect(action._parent.options.jsonInterface, action._parent._address); - - //NOTE this is a condition to verify if the transaction comes from a module or not. - if (contractRegistry.methods.hasOwnProperty('factory')) { - let moduleAddress = await contractRegistry.methods.factory().call(); - let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress) - let parentModule = await moduleRegistry.methods.getName().call(); - let result = await checkPermission(web3.utils.hexToUtf8(parentModule), action._method.name, contractRegistry); - if (!result) { - console.log("You haven't the right permissions to execute this method."); - process.exit(0); - } - } - - if (typeof factor === 'undefined') factor = 1.2; + sendTransaction: async function (action, options) { - let block = await web3.eth.getBlock("latest"); - let networkGasLimit = block.gasLimit; + await checkPermissions(action); - let gas = Math.round(factor * (await action.estimateGas({ from: from.address, value: value}))); - if (gas > networkGasLimit) gas = networkGasLimit; + options = getFinalOptions(options); + let gasLimit = await getGasLimit(options, action); - console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gas} ----`)); + console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gasLimit} ----`)); - let nonce = await web3.eth.getTransactionCount(from.address); + let nonce = await web3.eth.getTransactionCount(options.from.address); let abi = action.encodeABI(); let parameter = { - from: from.address, + from: options.from.address, to: action._parent._address, data: abi, - gasLimit: gas, - gasPrice: gasPrice, + gasLimit: gasLimit, + gasPrice: options.gasPrice, nonce: nonce, - value: web3.utils.toHex(value) + value: web3.utils.toHex(options.value) }; const transaction = new Tx(parameter); - transaction.sign(Buffer.from(from.privateKey.replace('0x', ''), 'hex')); + transaction.sign(Buffer.from(options.from.privateKey.replace('0x', ''), 'hex')); return await web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex')) .on('transactionHash', function(hash){ console.log(` @@ -120,7 +129,7 @@ module.exports = { .on('receipt', function(receipt){ console.log(` Congratulations! The transaction was successfully completed. - Gas used: ${receipt.gasUsed} - Gas spent: ${web3.utils.fromWei((new web3.utils.BN(gasPrice)).mul(new web3.utils.BN(receipt.gasUsed)))} Ether + Gas used: ${receipt.gasUsed} - Gas spent: ${web3.utils.fromWei((new web3.utils.BN(options.gasPrice)).mul(new web3.utils.BN(receipt.gasUsed)))} Ether Review it on Etherscan. TxHash: ${receipt.transactionHash}\n` ); diff --git a/CLI/commands/common/constants.js b/CLI/commands/common/constants.js new file mode 100644 index 000000000..c3e2b796c --- /dev/null +++ b/CLI/commands/common/constants.js @@ -0,0 +1,34 @@ +module.exports = Object.freeze({ + MODULES_TYPES: { + PERMISSION: 1, + TRANSFER: 2, + STO: 3, + DIVIDENDS: 4, + BURN: 5 + }, + DURATION: { + seconds: function(val) { + return val + }, + minutes: function(val) { + return val * this.seconds(60) + }, + hours: function(val) { + return val * this.minutes(60) + }, + days: function(val) { + return val * this.hours(24) + }, + weeks: function(val) { + return val * this.days(7) + }, + years: function(val) { + return val * this.days(365) + } + }, + FUND_RAISE_TYPES: { + ETH: 0, + POLY: 1, + DAI: 2 + } +}); \ No newline at end of file diff --git a/CLI/commands/common/global.js b/CLI/commands/common/global.js index fb898a708..e1fb648e2 100644 --- a/CLI/commands/common/global.js +++ b/CLI/commands/common/global.js @@ -1,39 +1,44 @@ const Web3 = require('web3'); +const constants = require('./constants'); -function getGasPrice (networkId) { - let gasPrice; - switch (networkId) { - case 1: //Mainnet - gasPrice = 4000000000; - break; - case 3: //Ropsten - gasPrice = 50000000000; - break; - case 15: //Ganache - gasPrice = 50000000000; - break; - case 42: //Kovan - gasPrice = 50000000000; - break; - default: - throw new Error('Network ID not identified'); - } +global.web3, global.Issuer, global.defaultGasPrice, global.remoteNetwork; - return gasPrice; +function getGasPrice (networkId) { + let gasPrice; + switch (networkId) { + case 1: //Mainnet + gasPrice = 4000000000; + break; + case 3: //Ropsten + gasPrice = 50000000000; + break; + case 15: //Ganache + gasPrice = 50000000000; + break; + case 42: //Kovan + gasPrice = 50000000000; + break; + default: + throw new Error('Network ID not identified'); + } + return gasPrice; } + module.exports = { - initialize: async function (remoteNetwork) { - if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { - if (typeof remoteNetwork !== 'undefined') { - web3 = new Web3(new Web3.providers.HttpProvider(`https://${remoteNetwork}.infura.io/`)); - let privKey = require('fs').readFileSync('./privKey').toString(); - Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKey); - } else { - web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); - let privKeyLocal = require('fs').readFileSync('./privKeyLocal').toString() - Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKeyLocal); - } - defaultGasPrice = getGasPrice(await web3.eth.net.getId()); + initialize: async function(network) { + remoteNetwork = network; + if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { + if (typeof remoteNetwork !== 'undefined') { + web3 = new Web3(new Web3.providers.HttpProvider(`https://${remoteNetwork}.infura.io/`)); + let privKey = require('fs').readFileSync('./privKey').toString(); + Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKey); + } else { + web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); + let privKeyLocal = require('fs').readFileSync('./privKeyLocal').toString() + Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKeyLocal); } + defaultGasPrice = getGasPrice(await web3.eth.net.getId()); } + }, + constants }; \ No newline at end of file diff --git a/CLI/commands/common/permissions_list.js b/CLI/commands/common/permissions_list.js index f5779612b..4d2b58cf7 100644 --- a/CLI/commands/common/permissions_list.js +++ b/CLI/commands/common/permissions_list.js @@ -68,7 +68,7 @@ function getPermissionList() { modifyWhitelist: "WHITELIST", modifyWhitelistMulti: "WHITELIST", setAllowPrimaryIssuance: "ADMIN", - changeHolderPercentage: "ONLY_OWNER" + changeHolderPercentage: "ADMIN" }, LockupVolumeRestrictionTM: { addLockup: "ADMIN", diff --git a/CLI/commands/contract_manager.js b/CLI/commands/contract_manager.js index bea83ce7d..cce93444e 100644 --- a/CLI/commands/contract_manager.js +++ b/CLI/commands/contract_manager.js @@ -1,23 +1,14 @@ -const duration = { - seconds: function (val) { return val; }, - minutes: function (val) { return val * this.seconds(60); }, - hours: function (val) { return val * this.minutes(60); }, - days: function (val) { return val * this.hours(24); }, - weeks: function (val) { return val * this.days(7); }, - years: function (val) { return val * this.days(365); }, -}; var readlineSync = require('readline-sync'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); // App flow let currentContract = null; -async function executeApp(remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp() { common.logAsciiBull(); console.log("*********************************************"); @@ -108,7 +99,7 @@ async function strActions() { let tickerExpiryDate = readlineSync.question(`Enter the Unix Epoch time on wich the ticker will expire: `); let tickerStatus = readlineSync.keyInYNStrict(`Is the token deployed?`); let modifyTickerAction = currentContract.methods.modifyTicker(tickerOwner, tickerToModify, tickerSTName, tickerRegistrationDate, tickerExpiryDate, tickerStatus); - await common.sendTransaction(Issuer, modifyTickerAction, defaultGasPrice, 0, 1.5); + await common.sendTransaction(modifyTickerAction, {factor: 1.5}); console.log(chalk.green(`Ticker has been updated successfully`)); break; case 'Remove Ticker': @@ -118,7 +109,7 @@ async function strActions() { console.log(chalk.yellow(`${ticker} does not exist.`)); } else { let removeTickerAction = currentContract.methods.removeTicker(tickerToRemove); - await common.sendTransaction(Issuer, removeTickerAction, defaultGasPrice, 0, 3); + await common.sendTransaction(removeTickerAction, {factor: 3}); console.log(chalk.green(`Ticker has been removed successfully`)); } break; @@ -159,15 +150,15 @@ async function strActions() { let tokenDetails = readlineSync.question(`Enter the token details: `); let deployedAt = readlineSync.questionInt(`Enter the Unix Epoch timestamp at which security token was deployed: `); let modifySTAction = currentContract.methods.modifySecurityToken(name, ticker, owner, stAddress, tokenDetails, deployedAt); - await common.sendTransaction(Issuer, modifySTAction, defaultGasPrice, 0, 1.5); + await common.sendTransaction(modifySTAction, {factor: 1.5}); console.log(chalk.green(`Security Token has been updated successfully`)); break; case 'Change Expiry Limit': let currentExpiryLimit = await currentContract.methods.getExpiryLimit().call(); console.log(chalk.yellow(`Current expiry limit is ${Math.floor(parseInt(currentExpiryLimit)/60/60/24)} days`)); - let newExpiryLimit = duration.days(readlineSync.questionInt('Enter a new value in days for expiry limit: ')); + let newExpiryLimit = gbl.constants.DURATION.days(readlineSync.questionInt('Enter a new value in days for expiry limit: ')); let changeExpiryLimitAction = currentContract.methods.changeExpiryLimit(newExpiryLimit); - let changeExpiryLimitReceipt = await common.sendTransaction(Issuer, changeExpiryLimitAction, defaultGasPrice); + let changeExpiryLimitReceipt = await common.sendTransaction(changeExpiryLimitAction); let changeExpiryLimitEvent = common.getEventFromLogs(currentContract._jsonInterface, changeExpiryLimitReceipt.logs, 'ChangeExpiryLimit'); console.log(chalk.green(`Expiry limit was changed successfully. New limit is ${Math.floor(parseInt(changeExpiryLimitEvent._newExpiry)/60/60/24)} days\n`)); break; @@ -176,7 +167,7 @@ async function strActions() { console.log(chalk.yellow(`\nCurrent ticker registration fee is ${currentRegFee} POLY`)); let newRegFee = web3.utils.toWei(readlineSync.questionInt('Enter a new value in POLY for ticker registration fee: ').toString()); let changeRegFeeAction = currentContract.methods.changeTickerRegistrationFee(newRegFee); - let changeRegFeeReceipt = await common.sendTransaction(Issuer, changeRegFeeAction, defaultGasPrice); + let changeRegFeeReceipt = await common.sendTransaction(changeRegFeeAction); let changeRegFeeEvent = common.getEventFromLogs(currentContract._jsonInterface, changeRegFeeReceipt.logs, 'ChangeTickerRegistrationFee'); console.log(chalk.green(`Fee was changed successfully. New fee is ${web3.utils.fromWei(changeRegFeeEvent._newFee)} POLY\n`)); break; @@ -185,7 +176,7 @@ async function strActions() { console.log(chalk.yellow(`\nCurrent ST launch fee is ${currentLaunchFee} POLY`)); let newLaunchFee = web3.utils.toWei(readlineSync.questionInt('Enter a new value in POLY for ST launch fee: ').toString()); let changeLaunchFeeAction = currentContract.methods.changeSecurityLaunchFee(newLaunchFee); - let changeLaunchFeeReceipt = await common.sendTransaction(Issuer, changeLaunchFeeAction, defaultGasPrice); + let changeLaunchFeeReceipt = await common.sendTransaction(changeLaunchFeeAction); let changeLaunchFeeEvent = common.getEventFromLogs(currentContract._jsonInterface, changeLaunchFeeReceipt.logs, 'ChangeSecurityLaunchFee'); console.log(chalk.green(`Fee was changed successfully. New fee is ${web3.utils.fromWei(changeLaunchFeeEvent._newFee)} POLY\n`)); break; @@ -197,7 +188,7 @@ async function strActions() { } module.exports = { - executeApp: async function(remoteNetwork) { - return executeApp(remoteNetwork); + executeApp: async function() { + return executeApp(); } } \ No newline at end of file diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index bde3aa900..0f423bf5d 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -1,27 +1,11 @@ -const duration = { - seconds: function (val) { return val; }, - minutes: function (val) { return val * this.seconds(60); }, - hours: function (val) { return val * this.minutes(60); }, - days: function (val) { return val * this.hours(24); }, - weeks: function (val) { return val * this.days(7); }, - years: function (val) { return val * this.days(365); }, -}; var readlineSync = require('readline-sync'); var chalk = require('chalk'); var moment = require('moment'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); -const MODULES_TYPES = { - PERMISSION: 1, - TRANSFER: 2, - STO: 3, - DIVIDENDS: 4, - BURN: 5 -} - // App flow let tokenSymbol; let securityToken; @@ -30,9 +14,8 @@ let securityTokenRegistry; let generalTransferManager; let currentDividendsModule; -async function executeApp(type, remoteNetwork) { +async function executeApp(type) { dividendsType = type; - await global.initialize(remoteNetwork); common.logAsciiBull(); console.log("**********************************************"); @@ -129,7 +112,7 @@ async function start_explorer(){ break; case 'Create checkpoint': let createCheckpointAction = securityToken.methods.createCheckpoint(); - await common.sendTransaction(Issuer, createCheckpointAction, defaultGasPrice); + await common.sendTransaction(createCheckpointAction); break; case 'Set default exclusions for dividends': await setDefaultExclusions(); @@ -199,7 +182,7 @@ async function mintTokens(address, amount){ try { let mintAction = securityToken.methods.mint(address,web3.utils.toWei(amount)); - let receipt = await common.sendTransaction(Issuer, mintAction, defaultGasPrice); + let receipt = await common.sendTransaction(mintAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` Minted ${web3.utils.fromWei(event.value)} tokens @@ -217,7 +200,7 @@ async function transferTokens(address, amount){ try{ let transferAction = securityToken.methods.transfer(address,web3.utils.toWei(amount)); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice, 0, 1.5); + let receipt = await common.sendTransaction(transferAction, {factor: 1.5}); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` Account ${event.from} @@ -260,7 +243,7 @@ async function setDefaultExclusions() { if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { let excluded = getExcludedFromDataFile(); let setDefaultExclusionsActions = currentDividendsModule.methods.setDefaultExcluded(excluded); - let receipt = await common.sendTransaction(Issuer, setDefaultExclusionsActions, defaultGasPrice); + let receipt = await common.sendTransaction(setDefaultExclusionsActions); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'SetDefaultExcludedAddresses'); console.log(chalk.green(`Exclusions were successfully set.`)); showExcluded(event._excluded); @@ -290,14 +273,14 @@ async function taxHoldingMenu() { }); let percentageWei = web3.utils.toWei((percentage / 100).toString()); let setWithHoldingFixedAction = currentDividendsModule.methods.setWithholdingFixed([address], percentageWei); - let receipt = await common.sendTransaction(Issuer, setWithHoldingFixedAction, defaultGasPrice); + let receipt = await common.sendTransaction(setWithHoldingFixedAction); console.log(chalk.green(`Successfully set tax withholding of ${percentage}% for ${address}.`)); break; case 'Withdraw withholding for dividend': let _dividend = await selectDividend({withRemainingWithheld: true}); if (_dividend !== null) { let withdrawWithholdingAction = currentDividendsModule.methods.withdrawWithholding(_dividend.index); - let receipt = await common.sendTransaction(Issuer, withdrawWithholdingAction, defaultGasPrice); + let receipt = await common.sendTransaction(withdrawWithholdingAction); let eventName; if (dividendsType == 'POLY') { eventName = 'ERC20DividendWithholdingWithdrawn'; @@ -318,7 +301,7 @@ async function createDividends(name, dividend, checkpointId) { let time = Math.floor(Date.now()/1000); let maturityTime = readlineSync.questionInt('Enter the dividend maturity time from which dividend can be paid (Unix Epoch time)\n(Now = ' + time + ' ): ', {defaultInput: time}); - let defaultTime = time + duration.minutes(10); + let defaultTime = time + gbl.constants.DURATION.minutes(10); let expiryTime = readlineSync.questionInt('Enter the dividend expiry time (Unix Epoch time)\n(10 minutes from now = ' + defaultTime + ' ): ', {defaultInput: defaultTime}); let useDefaultExcluded = readlineSync.keyInYNStrict(`Do you want to use the default excluded addresses for this dividend? If not, data from 'dividendsExclusions_data.csv' will be used instead.`); @@ -326,7 +309,7 @@ async function createDividends(name, dividend, checkpointId) { let createDividendAction; if (dividendsType == 'POLY') { let approveAction = polyToken.methods.approve(currentDividendsModule._address, web3.utils.toWei(dividend)); - await common.sendTransaction(Issuer, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction); if (checkpointId > 0) { if (useDefaultExcluded) { createDividendAction = currentDividendsModule.methods.createDividendWithCheckpoint(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), checkpointId, web3.utils.toHex(name)); @@ -342,7 +325,7 @@ async function createDividends(name, dividend, checkpointId) { createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), excluded, web3.utils.toHex(name)); } } - let receipt = await common.sendTransaction(Issuer, createDividendAction, defaultGasPrice); + let receipt = await common.sendTransaction(createDividendAction); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'ERC20DividendDeposited'); console.log(chalk.green(`Dividend ${event._dividendIndex} deposited`)); } else if (dividendsType == 'ETH') { @@ -361,7 +344,7 @@ async function createDividends(name, dividend, checkpointId) { createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, excluded, web3.utils.toHex(name)); } } - let receipt = await common.sendTransaction(Issuer, createDividendAction, defaultGasPrice, web3.utils.toWei(dividend)); + let receipt = await common.sendTransaction(createDividendAction, {value: web3.utils.toWei(dividend)}); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'EtherDividendDeposited'); console.log(` Dividend ${event._dividendIndex} deposited` @@ -372,7 +355,7 @@ async function createDividends(name, dividend, checkpointId) { async function pushDividends(dividend, account){ let accs = account.split(','); let pushDividendPaymentToAddressesAction = currentDividendsModule.methods.pushDividendPaymentToAddresses(dividend.index, accs); - let receipt = await common.sendTransaction(Issuer, pushDividendPaymentToAddressesAction, defaultGasPrice); + let receipt = await common.sendTransaction(pushDividendPaymentToAddressesAction); let successEventName; if (dividendsType == 'POLY') { successEventName = 'ERC20DividendClaimed'; @@ -400,7 +383,7 @@ async function pushDividends(dividend, account){ async function reclaimedDividend(dividend) { let reclaimDividendAction = currentDividendsModule.methods.reclaimDividend(dividend.index); - let receipt = await common.sendTransaction(Issuer, reclaimDividendAction, defaultGasPrice); + let receipt = await common.sendTransaction(reclaimDividendAction); let eventName; if (dividendsType == 'POLY') { eventName = 'ERC20DividendReclaimed'; @@ -417,7 +400,7 @@ async function reclaimedDividend(dividend) { async function whitelistAddress(address) { let now = Math.floor(Date.now() / 1000); let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(address, now, now, now + 31536000, true); - await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); + await common.sendTransaction(modifyWhitelistAction); console.log(chalk.green(`\nWhitelisting successful for ${address}.`)); } @@ -478,9 +461,9 @@ async function addDividendsModule() { dividendsModuleABI = abis.etherDividendCheckpoint(); } - let dividendsFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.DIVIDENDS, dividendsFactoryName); + let dividendsFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.DIVIDENDS, dividendsFactoryName); let addModuleAction = securityToken.methods.addModule(dividendsFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); + let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`Module deployed at address: ${event._module}`); currentDividendsModule = new web3.eth.Contract(dividendsModuleABI, event._module); @@ -599,7 +582,7 @@ function showExcluded(excluded) { } module.exports = { - executeApp: async function(type, remoteNetwork) { - return executeApp(type, remoteNetwork); + executeApp: async function(type) { + return executeApp(type); } } diff --git a/CLI/commands/faucet.js b/CLI/commands/faucet.js index 556ffa402..70eadd57b 100644 --- a/CLI/commands/faucet.js +++ b/CLI/commands/faucet.js @@ -1,7 +1,6 @@ var readlineSync = require('readline-sync'); var BigNumber = require('bignumber.js'); var common = require('./common/common_functions'); -var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis') var chalk = require('chalk'); @@ -11,8 +10,7 @@ var chalk = require('chalk'); let polyToken; let usdToken; -async function executeApp(beneficiary, amount, remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp(beneficiary, amount) { console.log("\n"); console.log("***************************") @@ -79,7 +77,7 @@ async function send_poly(beneficiary, amount) { beneficiary = readlineSync.question(`Enter beneficiary 10K USD Tokens ('${Issuer.address}'): `); if (beneficiary == "") beneficiary = Issuer.address; let getTokensAction = usdToken.methods.getTokens(web3.utils.toWei('10000'), beneficiary); - await common.sendTransaction(Issuer, getTokensAction, defaultGasPrice); + await common.sendTransaction(getTokensAction); let balance = await usdToken.methods.balanceOf(beneficiary).call(); let balanceInPoly = new BigNumber(balance).dividedBy(new BigNumber(10).pow(18)); console.log(chalk.green(`Congratulations! balance of ${beneficiary} address is ${balanceInPoly.toNumber()} USD Tokens`)); @@ -97,7 +95,7 @@ async function send_poly(beneficiary, amount) { async function transferTokens(to, amount) { try { let getTokensAction = polyToken.methods.getTokens(amount, to); - await common.sendTransaction(Issuer, getTokensAction, defaultGasPrice); + await common.sendTransaction(getTokensAction); } catch (err){ console.log(err.message); return; @@ -108,7 +106,7 @@ async function transferTokens(to, amount) { } module.exports = { - executeApp: async function(beneficiary, amount, remoteNetwork) { - return executeApp(beneficiary, amount, remoteNetwork); + executeApp: async function(beneficiary, amount) { + return executeApp(beneficiary, amount); } } \ No newline at end of file diff --git a/CLI/commands/helpers/contract_addresses.js b/CLI/commands/helpers/contract_addresses.js index b6dca4eeb..4d5971714 100644 --- a/CLI/commands/helpers/contract_addresses.js +++ b/CLI/commands/helpers/contract_addresses.js @@ -16,7 +16,7 @@ function getPolymathRegistryAddress(networkId) { result = JSON.parse(require('fs').readFileSync('./build/contracts/PolymathRegistry.json').toString()).networks[networkId].address; break; case 42: // KOVAN - result = "0x05a6519e49e34239f78167abf293d94dae61b299"; + result = "0xad09dc7939f09601674c69a07132bc642abeeb10"; break; } diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 9a5229a7c..276f8bda3 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -3,18 +3,13 @@ var readlineSync = require('readline-sync'); var BigNumber = require('bignumber.js'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); // Load Contract artifacts var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); const STO_KEY = 3; -const FUND_RAISE_TYPES = { - ETH: 0, - POLY: 1, - DAI: 2 -} let securityTokenRegistry; let securityToken; @@ -39,8 +34,7 @@ let displayCanBuy; let displayValidKYC; // Start Script -async function executeApp(investorAddress, investorPrivKey, symbol, currency, amount, remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp(investorAddress, investorPrivKey, symbol, currency, amount) { common.logAsciiBull(); console.log("********************************************"); @@ -163,13 +157,13 @@ async function showUserInfo(_user) { console.log(` ******************* User Information ******************** - Address: ${_user}`); - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.POLY)) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.POLY)) { console.log(` - POLY balance:\t ${await polyBalance(_user)}`); } - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.ETH)) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.ETH)) { console.log(` - ETH balance:\t ${web3.utils.fromWei(await web3.eth.getBalance(_user))}`); } - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.DAI)) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.DAI)) { console.log(` - DAI balance:\t ${await usdBalance(_user)}`); } } @@ -185,11 +179,11 @@ async function showCappedSTOInfo() { let displayRaiseType; let displayFundsRaised; - for (const fundType in FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES[fundType]).call()) { + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { raiseTypes.push(fundType); displayRaiseType = fundType; - displayFundsRaised = await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES[fundType]).call(); + displayFundsRaised = await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[fundType]).call(); } } @@ -245,9 +239,9 @@ async function showCappedSTOInfo() { async function showUserInfoForUSDTieredSTO() { - for (const fundType in FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES[fundType]).call()) { - let displayInvestorInvested = web3.utils.fromWei(await currentSTO.methods.investorInvested(User.address, FUND_RAISE_TYPES[fundType]).call()); + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { + let displayInvestorInvested = web3.utils.fromWei(await currentSTO.methods.investorInvested(User.address, gbl.constants.FUND_RAISE_TYPES[fundType]).call()); console.log(` - Invested in ${fundType}:\t ${displayInvestorInvested} ${fundType}`); } } @@ -287,8 +281,8 @@ async function showUSDTieredSTOInfo() { let displayTokenSymbol = await securityToken.methods.symbol().call(); let tiersLength = await currentSTO.methods.getNumberOfTiers().call(); - for (const fundType in FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES[fundType]).call()) { + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { raiseTypes.push(fundType); } } @@ -317,7 +311,7 @@ async function showUSDTieredSTOInfo() { } } - let mintedPerTier = await currentSTO.methods.mintedPerTier(FUND_RAISE_TYPES[type], t).call(); + let mintedPerTier = await currentSTO.methods.mintedPerTier(gbl.constants.FUND_RAISE_TYPES[type], t).call(); displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; } @@ -338,13 +332,13 @@ async function showUSDTieredSTOInfo() { let displayFundsRaisedPerType = ''; let displayTokensSoldPerType = ''; for (const type of raiseTypes) { - let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES[type]).call()); + let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); displayFundsRaisedPerType += ` ${type}:\t\t\t ${fundsRaised} ${type}`; //Only show sold per raise type is more than one are allowed if (raiseTypes.length > 1) { - let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(FUND_RAISE_TYPES[type]).call()); + let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(gbl.constants.FUND_RAISE_TYPES[type]).call()); displayTokensSoldPerType += ` Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; } @@ -427,10 +421,10 @@ async function investCappedSTO(currency, amount) { let allowance = await polyToken.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { let approveAction = polyToken.methods.approve(STOAddress, costWei); - await common.sendTransaction(User, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction, {from: User}); } let actionBuyTokensWithPoly = currentSTO.methods.buyTokensWithPoly(costWei); - let receipt = await common.sendTransaction(User, actionBuyTokensWithPoly, defaultGasPrice); + let receipt = await common.sendTransaction(actionBuyTokensWithPoly, {from: User}); logTokensPurchasedCappedSTO(receipt); } else { console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} POLY but have ${userBalance} POLY.`)); @@ -439,7 +433,7 @@ async function investCappedSTO(currency, amount) { } } else { let actionBuyTokens = currentSTO.methods.buyTokens(User.address); - let receipt = await common.sendTransaction(User, actionBuyTokens, defaultGasPrice, costWei); + let receipt = await common.sendTransaction(actionBuyTokens, {from: User, value: costWei}); logTokensPurchasedCappedSTO(receipt); } await showTokenInfo(); @@ -457,7 +451,7 @@ async function investUsdTieredSTO(currency, amount) { } } else { for (const type of raiseTypes) { - let displayPrice = web3.utils.fromWei(await currentSTO.methods.convertToUSD(FUND_RAISE_TYPES[type], web3.utils.toWei("1")).call()); + let displayPrice = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], web3.utils.toWei("1")).call()); console.log(chalk.green(` Current ${type} price:\t\t ${displayPrice} USD`)); } if (raiseTypes.length > 1) { @@ -473,7 +467,7 @@ async function investUsdTieredSTO(currency, amount) { if (typeof amount === 'undefined') { let investorInvestedUSD = web3.utils.fromWei(await currentSTO.methods.investorInvestedUSD(User.address).call()); let minimumInvestmentUSD = await currentSTO.methods.minimumInvestmentUSD().call(); - let minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(FUND_RAISE_TYPES[raiseType], minimumInvestmentUSD).call(); + let minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(gbl.constants.FUND_RAISE_TYPES[raiseType], minimumInvestmentUSD).call(); cost = readlineSync.question(chalk.yellow(`Enter the amount of ${raiseType} you would like to invest or press 'Enter' to exit: `), { limit: function(input) { return investorInvestedUSD != 0 || parseInt(input) > parseInt(web3.utils.fromWei(minimumInvestmentRaiseType)); @@ -493,10 +487,10 @@ async function investUsdTieredSTO(currency, amount) { let allowance = await polyToken.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { let approveAction = polyToken.methods.approve(STOAddress, costWei); - await common.sendTransaction(User, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction, {from: User}); } let actionBuyWithPoly = currentSTO.methods.buyWithPOLY(User.address, costWei); - let receipt = await common.sendTransaction(User, actionBuyWithPoly,defaultGasPrice, 0, 2); + let receipt = await common.sendTransaction(actionBuyWithPoly, {from: User, factor: 2}); logTokensPurchasedUSDTieredSTO(receipt); } else { console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} POLY but have ${userBalance} POLY.`)); @@ -509,10 +503,10 @@ async function investUsdTieredSTO(currency, amount) { let allowance = await usdToken.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { let approveAction = usdToken.methods.approve(STOAddress, costWei); - await common.sendTransaction(User, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction, {from: User}); } let actionBuyWithUSD = currentSTO.methods.buyWithUSD(User.address, costWei); - let receipt = await common.sendTransaction(User, actionBuyWithUSD, defaultGasPrice, 0, 1.5); + let receipt = await common.sendTransaction(actionBuyWithUSD, {from: User, factor: 1.5}); logTokensPurchasedUSDTieredSTO(receipt); } else { console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} DAI but have ${userBalance} DAI.`)); @@ -521,7 +515,7 @@ async function investUsdTieredSTO(currency, amount) { } } else { let actionBuyWithETH = currentSTO.methods.buyWithETH(User.address); - let receipt = await common.sendTransaction(User, actionBuyWithETH, defaultGasPrice, costWei); + let receipt = await common.sendTransaction(actionBuyWithETH, {from: User, value: costWei}); logTokensPurchasedUSDTieredSTO(receipt); } @@ -564,7 +558,7 @@ function logTokensPurchasedCappedSTO(receipt) { } module.exports = { - executeApp: async function(investorAddress, investorPrivKey, symbol, currency, amount, remoteNetwork) { - return executeApp(investorAddress, investorPrivKey, symbol, currency, amount, remoteNetwork); + executeApp: async function(investorAddress, investorPrivKey, symbol, currency, amount) { + return executeApp(investorAddress, investorPrivKey, symbol, currency, amount); } } diff --git a/CLI/commands/module_manager.js b/CLI/commands/module_manager.js index b91541a9c..53f2a863a 100644 --- a/CLI/commands/module_manager.js +++ b/CLI/commands/module_manager.js @@ -2,7 +2,6 @@ var readlineSync = require('readline-sync'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); // Load contract artifacts var contracts = require('./helpers/contract_addresses'); @@ -47,8 +46,7 @@ async function setup() { } // Start function -async function executeApp(remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp() { common.logAsciiBull(); console.log(chalk.yellow(`******************************************`)); @@ -283,7 +281,7 @@ async function archiveModule() { if (index != -1) { console.log("\nSelected: ",options[index]); let archiveModuleAction = securityToken.methods.archiveModule(modules[index].module.address); - await common.sendTransaction(Issuer, archiveModuleAction, defaultGasPrice, 0, 2); + await common.sendTransaction(archiveModuleAction, {factor: 2}); console.log(chalk.green(`\nSuccessfully archived ${modules[index].module.name}.`)); } backToMenu() @@ -315,7 +313,7 @@ async function unarchiveModule() { if (index != -1) { console.log("\nSelected: ",options[index]); let unarchiveModuleAction = securityToken.methods.unarchiveModule(modules[index].module.address); - await common.sendTransaction(Issuer, unarchiveModuleAction, defaultGasPrice, 0, 2); + await common.sendTransaction(unarchiveModuleAction, {factor: 2}); console.log(chalk.green(`\nSuccessfully unarchived ${modules[index].module.name}.`)); } backToMenu() @@ -348,7 +346,7 @@ async function removeModule() { if (index != -1) { console.log("\nSelected: ",options[index]); let removeModuleAction = securityToken.methods.removeModule(modules[index].module.address); - await common.sendTransaction(Issuer, removeModuleAction, defaultGasPrice, 0, 2); + await common.sendTransaction(defaultGasPrice, {factor: 2}); console.log(chalk.green(`\nSuccessfully removed ${modules[index].module.name}.`)); } backToMenu() @@ -368,7 +366,7 @@ async function whitelist() { let investor = readlineSync.question(chalk.yellow(`Enter the address to be whitelisted: `)); let now = await latestTime(); let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(investor, now, now, now + 31556952, true); - await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); + await common.sendTransaction(modifyWhitelistAction); console.log(chalk.green(`\nWhitelisting successful for ${investor}.`)); } catch (e) { console.log(e); @@ -390,7 +388,7 @@ async function mintTokens() { let _amount = readlineSync.question(chalk.yellow(`Enter the amount of tokens to mint: `)); try { let mintAction = securityToken.methods.mint(_investor, web3.utils.toWei(_amount)); - await common.sendTransaction(Issuer, mintAction, defaultGasPrice); + await common.sendTransaction(mintAction); console.log(chalk.green(`\nMinting Successful.`)); } catch (e) { console.log(e); @@ -411,7 +409,7 @@ async function freezeMinting() { if (await featureRegistry.methods.getFeatureStatus('freezeMintingAllowed').call()) { let freezeMintingAction = securityToken.methods.freezeMinting(); - await common.sendTransaction(Issuer, freezeMintingAction, defaultGasPrice); + await common.sendTransaction(freezeMintingAction); console.log(chalk.green(`\nFreeze minting was successful.`)); } else { console.log(chalk.red(`\nFreeze minting is not allowed by Polymath.`)); @@ -441,7 +439,7 @@ async function polyBalance(_user) { } module.exports = { - executeApp: async function(remoteNetwork) { - return executeApp(remoteNetwork); + executeApp: async function() { + return executeApp(); } } diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index 0b7c272ca..b138ef849 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -161,7 +161,7 @@ function readFile() { } } let mintMultiAction = securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); - let r = await common.sendTransaction(Issuer, mintMultiAction, defaultGasPrice); + let r = await common.sendTransaction(mintMultiAction); console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Multi Mint transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index a2165f697..ef3e2ea60 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -1,7 +1,7 @@ var readlineSync = require('readline-sync'); var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); @@ -12,16 +12,7 @@ let securityToken; let generalPermissionManager; let isNewDelegate = false; -const MODULES_TYPES = { - PERMISSION: 1, - TRANSFER: 2, - STO: 3, - DIVIDEND: 4, - BURN: 5 -} - -async function executeApp(remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp() { common.logAsciiBull(); console.log("***********************************************"); @@ -75,9 +66,9 @@ async function addPermissionModule() { if (result.length == 0) { console.log(chalk.red(`General Permission Manager is not attached.`)); if (readlineSync.keyInYNStrict('Do you want to add General Permission Manager Module to your Security Token?')) { - let permissionManagerFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.PERMISSION, 'GeneralPermissionManager'); + let permissionManagerFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.PERMISSION, 'GeneralPermissionManager'); let addModuleAction = securityToken.methods.addModule(permissionManagerFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); + let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`Module deployed at address: ${event._module}`); generalPermissionManagerAddress = event._module; @@ -119,18 +110,23 @@ async function changePermissionAction(selectedDelegate) { async function deleteDelegate(address) { let deleteDelegateAction = generalPermissionManager.methods.deleteDelegate(address); - await common.sendTransaction(Issuer, deleteDelegateAction, defaultGasPrice, 0, 2); + await common.sendTransaction(deleteDelegateAction, {factor: 2}); } // Helper functions async function selectDelegate() { let result; let delegates = await getDelegates(); + let permissions = await getDelegatesAndPermissions(); let options = ['Add new delegate']; + options = options.concat(delegates.map(function(d) { + let perm = renderTable(permissions, d.address); + return `Account: ${d.address} - Details: ${d.details}` + Details: ${d.details} + Permisions: ${perm}` })); let index = readlineSync.keyInSelect(options, 'Select a delegate:', {cancel: false}); @@ -169,7 +165,7 @@ function isPermissionValid() { async function changePermission(delegate, moduleAddress, permission, isValid) { let changePermissionAction = generalPermissionManager.methods.changePermission(delegate, moduleAddress, web3.utils.asciiToHex(permission), isValid); - let receipt = await common.sendTransaction(Issuer, changePermissionAction, defaultGasPrice, 0, 2); + let receipt = await common.sendTransaction(changePermissionAction, {factor: 2}); common.getEventFromLogs(generalPermissionManager._jsonInterface, receipt.logs, 'ChangePermission'); console.log(`Permission changed succesfully,`); } @@ -210,9 +206,9 @@ async function addNewDelegate() { }); let addPermissionAction = generalPermissionManager.methods.addDelegate(newDelegate, web3.utils.asciiToHex(details)); - let receipt = await common.sendTransaction(Issuer, addPermissionAction, defaultGasPrice); + let receipt = await common.sendTransaction(addPermissionAction); let event = common.getEventFromLogs(generalPermissionManager._jsonInterface, receipt.logs, 'AddDelegate'); - console.log(`Delegate added succesfully: ${event._delegate} - ${event._details}`); + console.log(`Delegate added succesfully: ${event._delegate} - ${web3.utils.hexToAscii(event._details)}`); isNewDelegate = true; return event._delegate; } @@ -221,8 +217,8 @@ async function getModulesWithPermissions() { let modules = []; let moduleABI = abis.moduleInterface(); - for (const type in MODULES_TYPES) { - let modulesAttached = await securityToken.methods.getModulesByType(MODULES_TYPES[type]).call(); + for (const type in gbl.constants.MODULES_TYPES) { + let modulesAttached = await securityToken.methods.getModulesByType(gbl.constants.MODULES_TYPES[type]).call(); for (const m of modulesAttached) { let contractTemp = new web3.eth.Contract(moduleABI, m); let permissions = await contractTemp.methods.getPermissions().call(); @@ -239,8 +235,55 @@ async function getModulesWithPermissions() { return modules; } +async function getDelegatesAndPermissions() { + let moduleABI = abis.moduleInterface(); + let result = []; + for (const type in gbl.constants.MODULES_TYPES) { + let modulesAttached = await securityToken.methods.getModulesByType(gbl.constants.MODULES_TYPES[type]).call(); + for (const module of modulesAttached) { + let contractTemp = new web3.eth.Contract(moduleABI, module); + let permissions = await contractTemp.methods.getPermissions().call(); + if (permissions.length > 0) { + for (const permission of permissions) { + let allDelegates = await generalPermissionManager.methods.getAllDelegatesWithPerm(module, permission).call(); + let moduleName = web3.utils.hexToUtf8((await securityToken.methods.getModule(module).call())[0]); + let permissionName = web3.utils.hexToUtf8(permission); + for (delegateAddr of allDelegates) { + if (result[delegateAddr] == undefined) { + result[delegateAddr] = [] + } + if (result[delegateAddr][moduleName + '-' + module] == undefined) { + result[delegateAddr][moduleName + '-' + module] = [{permission: permissionName}] + } else { + result[delegateAddr][moduleName + '-' + module].push({permission: permissionName}) + } + } + } + } + } + } + return result +} + +function renderTable(permissions, address) { + let result = ``; + if (permissions[address] != undefined) { + Object.keys(permissions[address]).forEach((module) => { + result += ` + ${module.split('-')[0]} (${module.split('-')[1]}) -> `; + (permissions[address][module]).forEach((perm) => { + result += `${perm.permission}, `; + }) + result = result.slice(0, -2); + }) + } else { + result += `-`; + } + return result +} + module.exports = { - executeApp: async function(remoteNetwork) { - return executeApp(remoteNetwork); + executeApp: async function() { + return executeApp(); } } \ No newline at end of file diff --git a/CLI/commands/strMigrator.js b/CLI/commands/strMigrator.js index 545455f46..1e42ec46d 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -4,13 +4,9 @@ var request = require('request-promise') var abis = require('./helpers/contract_abis'); var contracts = require('./helpers/contract_addresses'); var common = require('./common/common_functions'); -var global = require('./common/global'); +var gbl = require('./common/global'); -let network; - -async function executeApp(toStrAddress, fromTrAddress, fromStrAddress, remoteNetwork) { - network = remoteNetwork; - await global.initialize(remoteNetwork); +async function executeApp(toStrAddress, fromTrAddress, fromStrAddress) { common.logAsciiBull(); console.log("****************************************"); @@ -147,7 +143,7 @@ async function step_register_tickers(tickers, securityTokenRegistry) { console.log(``); try { let modifyTickerAction = securityTokenRegistry.methods.modifyTicker(t.owner, t.ticker, t.name, t.registrationDate, t.expiryDate, false); - let receipt = await common.sendTransaction(Issuer, modifyTickerAction, defaultGasPrice); + let receipt = await common.sendTransaction(modifyTickerAction); totalGas = totalGas.add(new web3.utils.BN(receipt.gasUsed)); succeed.push(t); } catch (error) { @@ -277,7 +273,7 @@ async function step_launch_STs(tokens, securityTokenRegistry) { try { // Deploying 2.0.0 Token let deployTokenAction = STFactory.methods.deployToken(t.name, t.ticker, 18, t.details, Issuer.address, t.divisble, polymathRegistryAddress) - let deployTokenReceipt = await common.sendTransaction(Issuer, deployTokenAction, defaultGasPrice); + let deployTokenReceipt = await common.sendTransaction(deployTokenAction); // Instancing Security Token let newTokenAddress = deployTokenReceipt.logs[deployTokenReceipt.logs.length -1].address; //Last log is the ST creation let newTokenABI = abis.securityToken(); @@ -298,25 +294,25 @@ async function step_launch_STs(tokens, securityTokenRegistry) { new web3.utils.BN(gmtEvent.returnValues._expiryTime), gmtEvent.returnValues._canBuyFromSTO ); - let modifyWhitelistReceipt = await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); + let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); totalGas = totalGas.add(new web3.utils.BN(modifyWhitelistReceipt.gasUsed)); } // Minting tokens for (const mintedEvent of t.mintedEvents) { let mintAction = newToken.methods.mint(mintedEvent.returnValues.to, new web3.utils.BN(mintedEvent.returnValues.value)); - let mintReceipt = await common.sendTransaction(Issuer, mintAction, defaultGasPrice); + let mintReceipt = await common.sendTransaction(mintAction); totalGas = totalGas.add(new web3.utils.BN(mintReceipt.gasUsed)); } } // Transferring onweship to the original owner let transferOwnershipAction = newToken.methods.transferOwnership(t.owner); - let transferOwnershipReceipt = await common.sendTransaction(Issuer, transferOwnershipAction, defaultGasPrice); + let transferOwnershipReceipt = await common.sendTransaction(transferOwnershipAction); totalGas = totalGas.add(new web3.utils.BN(transferOwnershipReceipt.gasUsed)); // Adding 2.0.0 Security Token to SecurityTokenRegistry let modifySecurityTokenAction = securityTokenRegistry.methods.modifySecurityToken(t.name, t.ticker, t.owner, newTokenAddress, t.details, t.deployedAt); - let modifySecurityTokenReceipt = await common.sendTransaction(Issuer, modifySecurityTokenAction, defaultGasPrice); + let modifySecurityTokenReceipt = await common.sendTransaction(modifySecurityTokenAction); totalGas = totalGas.add(new web3.utils.BN(modifySecurityTokenReceipt.gasUsed)); succeed.push(t); @@ -360,7 +356,7 @@ ${failed.map(ticker => chalk.red(`${ticker.ticker}`)).join('\n')} } async function getABIfromEtherscan(_address) { - let urlDomain = network == 'kovan' ? 'api-kovan' : 'api'; + let urlDomain = remoteNetwork == 'kovan' ? 'api-kovan' : 'api'; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { @@ -377,7 +373,7 @@ async function getABIfromEtherscan(_address) { } module.exports = { - executeApp: async function(toStrAddress, fromTrAddress, fromStrAddress, remoteNetwork) { - return executeApp(toStrAddress, fromTrAddress, fromStrAddress, remoteNetwork); + executeApp: async function(toStrAddress, fromTrAddress, fromStrAddress) { + return executeApp(toStrAddress, fromTrAddress, fromStrAddress); } }; \ No newline at end of file diff --git a/CLI/commands/transfer.js b/CLI/commands/transfer.js index 48fbb79e5..5bd6d1859 100644 --- a/CLI/commands/transfer.js +++ b/CLI/commands/transfer.js @@ -1,5 +1,4 @@ var common = require('./common/common_functions'); -var global = require('./common/global'); /////////////////////////////ARTIFACTS////////////////////////////////////////// var contracts = require('./helpers/contract_addresses'); @@ -14,13 +13,11 @@ let securityToken; //////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// -async function startScript(tokenSymbol, transferTo, transferAmount, remoteNetwork) { +async function startScript(tokenSymbol, transferTo, transferAmount) { _tokenSymbol = tokenSymbol; _transferTo = transferTo; _transferAmount = transferAmount; - await global.initialize(remoteNetwork); - try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -46,7 +43,7 @@ async function transfer() { try{ let transferAction = securityToken.methods.transfer(_transferTo,web3.utils.toWei(_transferAmount,"ether")); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice); + let receipt = await common.sendTransaction(transferAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` Account ${event.from} @@ -61,7 +58,7 @@ async function transfer() { }; module.exports = { - executeApp: async function(tokenSymbol, transferTo, transferAmount, remoteNetwork) { - return startScript(tokenSymbol, transferTo, transferAmount, remoteNetwork); + executeApp: async function(tokenSymbol, transferTo, transferAmount) { + return startScript(tokenSymbol, transferTo, transferAmount); } } diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index df06c68f4..eb5eb1a26 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1,8 +1,6 @@ var readlineSync = require('readline-sync'); var chalk = require('chalk'); -var moment = require('moment'); var common = require('./common/common_functions'); -var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); @@ -11,8 +9,7 @@ let tokenSymbol; let securityToken; let securityTokenRegistry; -async function executeApp(remoteNetwork) { - await global.initialize(remoteNetwork); +async function executeApp() { common.logAsciiBull(); console.log("*********************************************"); @@ -71,7 +68,7 @@ async function start_explorer() { case 'Disable controller': if (readlineSync.keyInYNStrict()) { let disableControllerAction = securityToken.methods.disableController(); - await common.sendTransaction(Issuer, disableControllerAction, defaultGasPrice); + await common.sendTransaction(disableControllerAction); console.log(chalk.green(`Forced transfers have been disabled permanently`)); } break; @@ -84,7 +81,7 @@ async function start_explorer() { defaultInput: Issuer.address }); let setControllerAction = securityToken.methods.setController(controllerAddress); - let setControllerReceipt = await common.sendTransaction(Issuer, setControllerAction, defaultGasPrice); + let setControllerReceipt = await common.sendTransaction(setControllerAction); let setControllerEvent = common.getEventFromLogs(securityToken._jsonInterface, setControllerReceipt.logs, 'SetController'); console.log(chalk.green(`New controller is ${setControllerEvent._newController}`)); break; @@ -114,7 +111,7 @@ async function start_explorer() { let data = readlineSync.question('Enter the data to indicate validation: '); let log = readlineSync.question('Enter the data attached to the transfer by controller to emit in event: '); let forceTransferAction = securityToken.methods.forceTransfer(from, to, web3.utils.toWei(amount), web3.utils.asciiToHex(data), web3.utils.asciiToHex(log)); - let forceTransferReceipt = await common.sendTransaction(Issuer, forceTransferAction, defaultGasPrice, 0, 1.5); + let forceTransferReceipt = await common.sendTransaction(forceTransferAction, {factor: 1.5}); let forceTransferEvent = common.getEventFromLogs(securityToken._jsonInterface, forceTransferReceipt.logs, 'ForceTransfer'); console.log(chalk.green(` ${forceTransferEvent._controller} has successfully forced a transfer of ${web3.utils.fromWei(forceTransferEvent._value)} ${tokenSymbol} from ${forceTransferEvent._from} to ${forceTransferEvent._to} @@ -138,7 +135,7 @@ async function start_explorer() { } module.exports = { - executeApp: async function(type, remoteNetwork) { - return executeApp(type, remoteNetwork); + executeApp: async function(type) { + return executeApp(type); } } \ No newline at end of file diff --git a/CLI/commands/transfer_ownership.js b/CLI/commands/transfer_ownership.js index 68ca7eb7a..99e12b80f 100644 --- a/CLI/commands/transfer_ownership.js +++ b/CLI/commands/transfer_ownership.js @@ -1,6 +1,5 @@ var chalk = require('chalk'); var common = require('./common/common_functions'); -var global = require('./common/global'); /////////////////////////////ARTIFACTS////////////////////////////////////////// var abis = require('./helpers/contract_abis') @@ -8,8 +7,7 @@ var abis = require('./helpers/contract_abis') let contract; //////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// -async function startScript(contractAddress, transferTo, remoteNetwork) { - await global.initialize(remoteNetwork); +async function startScript(contractAddress, transferTo) { if (!web3.utils.isAddress(contractAddress) || !web3.utils.isAddress(transferTo)) { console.log(chlak.red(`Please enter valid addresses`)); @@ -28,14 +26,14 @@ async function transferOwnership(transferTo) { console.log(chalk.red(`You are not the current owner ot this contract. Current owner is ${currentOwner}.`)); } else { let transferOwnershipAction = contract.methods.transferOwnership(transferTo); - let receipt = await common.sendTransaction(Issuer, transferOwnershipAction, defaultGasPrice); + let receipt = await common.sendTransaction(transferOwnershipAction); let event = common.getEventFromLogs(contract._jsonInterface, receipt.logs, 'OwnershipTransferred'); console.log(chalk.green(`Ownership transferred successfully. New owner is ${event.newOwner}`)); } }; module.exports = { - executeApp: async function(contractAddress, transferTo, remoteNetwork) { - return startScript(contractAddress, transferTo, remoteNetwork); + executeApp: async function(contractAddress, transferTo) { + return startScript(contractAddress, transferTo); } } diff --git a/CLI/commands/whitelist.js b/CLI/commands/whitelist.js index 4750adffa..5ef201195 100644 --- a/CLI/commands/whitelist.js +++ b/CLI/commands/whitelist.js @@ -167,7 +167,7 @@ async function setInvestors() { //toTimes is ability to buy coins TOwards your account (3rd row in csv, 3rd parameter in modifyWhiteList() ) //expiryTime is time at which KYC of investor get expired (4th row in csv, 4rd parameter in modifyWhiteList() ) let modifyWhitelistMultiAction = generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); - let r = await common.sendTransaction(Issuer, modifyWhitelistMultiAction, defaultGasPrice); + let r = await common.sendTransaction(modifyWhitelistMultiAction); console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Whitelist transaxction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 608182dfd..4de51588e 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -13,6 +13,7 @@ var contract_manager = require('./commands/contract_manager'); var strMigrator = require('./commands/strMigrator'); var permission_manager = require('./commands/permission_manager'); var program = require('commander'); +var gbl = require('./commands/common/global'); const yaml = require('js-yaml'); const fs = require('fs'); @@ -31,7 +32,8 @@ program .option('-D, --divisible [div]', 'If token is divisible or not [true]', /^(true|false)/, 'true') .description('Wizard-like script that will guide technical users in the creation and deployment of an ST-20 token') .action(async function(cmd) { - await st20generator.executeApp(cmd.ticker, cmd.transferOwnership, cmd.tokenName, cmd.details, cmd.divisible, program.remoteNode); + await gbl.initialize(program.remoteNode); + await st20generator.executeApp(cmd.ticker, cmd.transferOwnership, cmd.tokenName, cmd.details, cmd.divisible); }); program @@ -39,15 +41,17 @@ program .alias('f') .description('Poly faucet for local private netwtorks') .action(async function(beneficiary, amount) { - await faucet.executeApp(beneficiary, amount, program.remoteNode); + await gbl.initialize(program.remoteNode); + await faucet.executeApp(beneficiary, amount); }); program - .command('investor_portal [investor] [symbol] [currency] [amount]') + .command('investor_portal [investor] [privateKey] [symbol] [currency] [amount]') .alias('i') .description('Participate in any STO you have been whitelisted for') - .action(async function(investor, symbol, currency, amount) { - await investor_portal.executeApp(investor, symbol, currency, amount, program.remoteNode); + .action(async function(investor, privateKey, symbol, currency, amount) { + await gbl.initialize(program.remoteNode); + await investor_portal.executeApp(investor, privateKey, symbol, currency, amount); }); program @@ -55,7 +59,8 @@ program .alias('mm') .description('View modules attached to a token and their status') .action(async function() { - await module_manager.executeApp(program.remoteNode); + await gbl.initialize(program.remoteNode); + await module_manager.executeApp(); }); program @@ -63,6 +68,7 @@ program .alias('mi') .description('Distribute tokens to previously whitelisted investors') .action(async function(tokenSymbol, batchSize) { + await gbl.initialize(program.remoteNode); shell.exec(`${__dirname}/commands/scripts/script.sh Multimint ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; }); @@ -71,7 +77,8 @@ program .alias('t') .description('Transfer ST tokens to another account') .action(async function(tokenSymbol, transferTo, transferAmount) { - await transfer.executeApp(tokenSymbol, transferTo, transferAmount, program.remoteNode); + await gbl.initialize(program.remoteNode); + await transfer.executeApp(tokenSymbol, transferTo, transferAmount); }); program @@ -79,7 +86,8 @@ program .alias('to') .description('Transfer Ownership of an own contract to another account') .action(async function(contractAddress, transferTo) { - await transfer_ownership.executeApp(contractAddress, transferTo, program.remoteNode); + await gbl.initialize(program.remoteNode); + await transfer_ownership.executeApp(contractAddress, transferTo); }); program @@ -87,6 +95,7 @@ program .alias('w') .description('Mass-update a whitelist of allowed/known investors') .action(async function(tokenSymbol, batchSize) { + await gbl.initialize(program.remoteNode); shell.exec(`${__dirname}/commands/scripts/script.sh Whitelist ${tokenSymbol} ${batchSize} ${program.remoteNode}`); }); @@ -95,7 +104,8 @@ program .alias('dm') .description('Runs dividends_manager') .action(async function(dividendsType) { - await dividends_manager.executeApp(dividendsType, program.remoteNode); + await gbl.initialize(program.remoteNode); + await dividends_manager.executeApp(dividendsType); }); program @@ -103,7 +113,8 @@ program .alias('tm') .description('Runs transfer_manager') .action(async function() { - await transfer_manager.executeApp(program.remoteNode); + await gbl.initialize(program.remoteNode); + await transfer_manager.executeApp(); }); program @@ -111,7 +122,8 @@ program .alias('cm') .description('Runs contract_manager') .action(async function() { - await contract_manager.executeApp(program.remoteNode); + await gbl.initialize(program.remoteNode); + await contract_manager.executeApp(); }); program @@ -119,6 +131,7 @@ program .alias('a') .description('Runs accredit') .action(async function(tokenSymbol, batchSize) { + await gbl.initialize(program.remoteNode); shell.exec(`${__dirname}/commands/scripts/script.sh Accredit ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; }); @@ -127,6 +140,7 @@ program .alias('nal') .description('Runs changeNonAccreditedLimit') .action(async function(tokenSymbol, batchSize) { + await gbl.initialize(program.remoteNode); shell.exec(`${__dirname}/commands/scripts/script.sh NonAccreditedLimit ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; }); @@ -135,7 +149,8 @@ program .alias('str') .description('Runs STR Migrator') .action(async function(toStrAddress, fromTrAddress, fromStrAddress) { - await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress, program.remoteNode); + await gbl.initialize(program.remoteNode); + await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress); }); program @@ -143,7 +158,8 @@ program .alias('pm') .description('Runs permission_manager') .action(async function() { - await permission_manager.executeApp(program.remoteNode); + await gbl.initialize(program.remoteNode); + await permission_manager.executeApp(); }); program.parse(process.argv); diff --git a/README.md b/README.md index 98173db84..64ff0d251 100644 --- a/README.md +++ b/README.md @@ -169,6 +169,35 @@ node CLI/polymath-cli dividends_manager ``` # Setting up Polymath Core + +### v2.0.0 KOVAN + + ----------------------- Polymath Network Smart Contracts: ----------------------- + PolymathRegistry: 0xad09dc7939f09601674c69a07132bc642abeeb10 + SecurityTokenRegistry (Proxy): 0xef600e4904fe0a2f4587ae94bcbed4c9e9aeb37a + ModuleRegistry (Proxy): 0xe8e30fd7d65a5e3b1134ce29d3afb49cc27b7086 + FeatureRegistry: 0x35a8f211763be879541656d692f057d108eec9aa + + ETHOracle: 0xCE5551FC9d43E9D2CC255139169FC889352405C8 + POLYOracle: 0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C + + STFactory: 0x1f08b1473fbb5bfc2bbaea99520291b6120be529 + GeneralTransferManagerFactory: 0xc100ec8f8e397b426a52a5c7acc02892e1d92a53 + GeneralPermissionManagerFactory: 0x96d7d693edd4a2ae773e4dd9739d997f0c38738f + + CappedSTOFactory: 0xfde869904bbc1e881601b2ebde4a77ba3808dfad + USDTieredSTOFactory: 0x01c17f387224148931ce03788e61836e7fe5d753 + USDTieredSTOProxyFactory: 0x63d0371a3dfa419a50670770b55618f6b5269057 + + CountTransferManagerFactory: 0x6691d4e4f8e48c7a3df04c25088169cb101b2882 + PercentageTransferManagerFactory: 0x62dd693e8864874d3d806286983e9da41cd5a035 + ManualApprovalTransferManagerFactory: 0x20ba9fd6907ff42f033df5cfdbaced6426b5e682 + EtherDividendCheckpointFactory: 0xceba16202ce878d1c01a1f5bf3f219b58d712d5f + ERC20DividendCheckpointFactory: 0x5c0051ffdc9655ae7b87a8a79542178be2e973e4 + --------------------------------------------------------------------------------- + + + ## Mainnet ### v1.3.0 (TORO Release) diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index c8e8a42bf..9f2b50b60 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -8,7 +8,7 @@ contract Migrations { uint public lastCompletedMigration; modifier restricted() { - require(msg.sender == owner); + require(msg.sender == owner, "Sender must be owner"); _; } diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 4aa1fff74..b2f1fbba5 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -166,7 +166,10 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { // NB - here we index by the first type of the module. uint8 moduleType = moduleFactory.getTypes()[0]; set(Encoder.getKey("registry", _moduleFactory), uint256(moduleType)); - set(Encoder.getKey("moduleListIndex", _moduleFactory), uint256(getArrayAddress(Encoder.getKey("moduleList", uint256(moduleType))).length)); + set( + Encoder.getKey("moduleListIndex", _moduleFactory), + uint256(getArrayAddress(Encoder.getKey("moduleList", uint256(moduleType))).length) + ); pushArray(Encoder.getKey("moduleList", uint256(moduleType)), _moduleFactory); emit ModuleRegistered (_moduleFactory, IOwnable(_moduleFactory).owner()); } @@ -179,8 +182,10 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { uint256 moduleType = getUint(Encoder.getKey("registry", _moduleFactory)); require(moduleType != 0, "Module factory should be registered"); - require(msg.sender == IOwnable(_moduleFactory).owner() || msg.sender == owner(),"msg.sender must be the Module Factory owner or registry curator"); - + require( + msg.sender == IOwnable(_moduleFactory).owner() || msg.sender == owner(), + "msg.sender must be the Module Factory owner or registry curator" + ); uint256 index = getUint(Encoder.getKey("moduleListIndex", _moduleFactory)); uint256 last = getArrayAddress(Encoder.getKey("moduleList", moduleType)).length - 1; address temp = getArrayAddress(Encoder.getKey("moduleList", moduleType))[last]; @@ -331,7 +336,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @notice Reclaim all ERC20Basic compatible tokens + * @notice Reclaims all ERC20Basic compatible tokens * @param _tokenContract The address of the token contract */ function reclaimERC20(address _tokenContract) external onlyOwner { @@ -346,6 +351,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { */ function pause() external whenNotPaused onlyOwner { set(Encoder.getKey("paused"), true); + /*solium-disable-next-line security/no-block-members*/ emit Pause(now); } @@ -354,6 +360,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { */ function unpause() external whenPaused onlyOwner { set(Encoder.getKey("paused"), false); + /*solium-disable-next-line security/no-block-members*/ emit Unpause(now); } @@ -368,7 +375,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @notice Get the owner of the contract + * @notice Gets the owner of the contract * @return address owner */ function owner() public view returns(address) { @@ -376,7 +383,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @notice Check whether the contract operations is paused or not + * @notice Checks whether the contract operations is paused or not * @return bool */ function isPaused() public view returns(bool) { diff --git a/contracts/Pausable.sol b/contracts/Pausable.sol index b542396c3..fe4a3ca28 100644 --- a/contracts/Pausable.sol +++ b/contracts/Pausable.sol @@ -27,18 +27,20 @@ contract Pausable { } /** - * @notice called by the owner to pause, triggers stopped state + * @notice Called by the owner to pause, triggers stopped state */ - function _pause() whenNotPaused internal { + function _pause() internal whenNotPaused { paused = true; + /*solium-disable-next-line security/no-block-members*/ emit Pause(now); } /** - * @notice called by the owner to unpause, returns to normal state + * @notice Called by the owner to unpause, returns to normal state */ - function _unpause() whenPaused internal { + function _unpause() internal whenPaused { paused = false; + /*solium-disable-next-line security/no-block-members*/ emit Unpause(now); } diff --git a/contracts/PolymathRegistry.sol b/contracts/PolymathRegistry.sol index d33ad68f4..0d6a6ac92 100644 --- a/contracts/PolymathRegistry.sol +++ b/contracts/PolymathRegistry.sol @@ -12,18 +12,18 @@ contract PolymathRegistry is ReclaimTokens { event ChangeAddress(string _nameKey, address indexed _oldAddress, address indexed _newAddress); /** - * @notice Get the contract address + * @notice Gets the contract address * @param _nameKey is the key for the contract address mapping * @return address */ - function getAddress(string _nameKey) view external returns(address) { + function getAddress(string _nameKey) external view returns(address) { bytes32 key = keccak256(bytes(_nameKey)); require(storedAddresses[key] != address(0), "Invalid address key"); return storedAddresses[key]; } /** - * @notice change the contract address + * @notice Changes the contract address * @param _nameKey is the key for the contract address mapping * @param _newAddress is the new contract address */ diff --git a/contracts/ReclaimTokens.sol b/contracts/ReclaimTokens.sol index f6ce15641..767442829 100644 --- a/contracts/ReclaimTokens.sol +++ b/contracts/ReclaimTokens.sol @@ -13,9 +13,9 @@ contract ReclaimTokens is Ownable { * @param _tokenContract The address of the token contract */ function reclaimERC20(address _tokenContract) external onlyOwner { - require(_tokenContract != address(0)); + require(_tokenContract != address(0), "Invalid address"); IERC20 token = IERC20(_tokenContract); uint256 balance = token.balanceOf(address(this)); - require(token.transfer(owner, balance)); + require(token.transfer(owner, balance), "Transfer failed"); } } diff --git a/contracts/RegistryUpdater.sol b/contracts/RegistryUpdater.sol index 2ec9a1045..ee325b1cf 100644 --- a/contracts/RegistryUpdater.sol +++ b/contracts/RegistryUpdater.sol @@ -12,11 +12,11 @@ contract RegistryUpdater is Ownable { address public polyToken; constructor (address _polymathRegistry) public { - require(_polymathRegistry != address(0)); + require(_polymathRegistry != address(0), "Invalid address"); polymathRegistry = _polymathRegistry; } - function updateFromRegistry() onlyOwner public { + function updateFromRegistry() public onlyOwner { moduleRegistry = PolymathRegistry(polymathRegistry).getAddress("ModuleRegistry"); securityTokenRegistry = PolymathRegistry(polymathRegistry).getAddress("SecurityTokenRegistry"); featureRegistry = PolymathRegistry(polymathRegistry).getAddress("FeatureRegistry"); diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index fe47915d6..a9642cc20 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -156,7 +156,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { ///////////////////////////// /** - * @notice initializes instance of STR + * @notice Initializes instance of STR * @param _polymathRegistry is the address of the Polymath Registry * @param _STFactory is the address of the Proxy contract for Security Tokens * @param _stLaunchFee is the fee in POLY required to launch a token @@ -164,9 +164,22 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _polyToken is the address of the POLY ERC20 token * @param _owner is the owner of the STR */ - function initialize(address _polymathRegistry, address _STFactory, uint256 _stLaunchFee, uint256 _tickerRegFee, address _polyToken, address _owner) payable external { + function initialize( + address _polymathRegistry, + address _STFactory, + uint256 _stLaunchFee, + uint256 _tickerRegFee, + address _polyToken, + address _owner + ) + external + payable + { require(!getBool(INITIALIZE),"already initialized"); - require(_STFactory != address(0) && _polyToken != address(0) && _owner != address(0) && _polymathRegistry != address(0), "Invalid address"); + require( + _STFactory != address(0) && _polyToken != address(0) && _owner != address(0) && _polymathRegistry != address(0), + "Invalid address" + ); require(_stLaunchFee != 0 && _tickerRegFee != 0, "Fees should not be 0"); set(POLYTOKEN, _polyToken); set(STLAUNCHFEE, _stLaunchFee); @@ -205,6 +218,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { if (previousOwner != address(0)) { _deleteTickerOwnership(previousOwner, ticker); } + /*solium-disable-next-line security/no-block-members*/ _addTicker(_owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false, tickerFee); } @@ -292,6 +306,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { _deleteTickerOwnership(owner, ticker); set(Encoder.getKey("tickerToSecurityToken", ticker), address(0)); _storeTickerDetails(ticker, address(0), 0, 0, "", false); + /*solium-disable-next-line security/no-block-members*/ emit TickerRemoved(ticker, now, msg.sender); } @@ -302,6 +317,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function _tickerAvailable(string _ticker) internal view returns(bool) { if (_tickerOwner(_ticker) != address(0)) { + /*solium-disable-next-line security/no-block-members*/ if ((now > getUint(Encoder.getKey("registeredTickers_expiryDate", _ticker))) && !_tickerStatus(_ticker)) { return true; } else @@ -414,6 +430,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { bytes32[] memory tempList = new bytes32[](tickers.length); for (uint i = 0; i < tickers.length; i++) { string memory ticker = Util.bytes32ToString(tickers[i]); + /*solium-disable-next-line security/no-block-members*/ if (getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now || _tickerStatus(ticker)) { tempList[counter] = tickers[i]; counter ++; @@ -477,6 +494,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { string memory ticker = Util.upper(_ticker); bool tickerStatus = _tickerStatus(ticker); uint256 expiryDate = getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)); + /*solium-disable-next-line security/no-block-members*/ if ((tickerStatus == true) || (expiryDate > now)) { return ( @@ -508,6 +526,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(!getBool(statusKey), "Already deployed"); set(statusKey, true); require(_tickerOwner(ticker) == msg.sender, "Not authorised"); + /*solium-disable-next-line security/no-block-members*/ require(getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now, "Ticker gets expired"); uint256 launchFee = getSecurityTokenLaunchFee(); @@ -524,8 +543,10 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { getAddress(POLYMATHREGISTRY) ); + /*solium-disable-next-line security/no-block-members*/ _storeSecurityTokenData(newSecurityTokenAddress, ticker, _tokenDetails, now); set(Encoder.getKey("tickerToSecurityToken", ticker), newSecurityTokenAddress); + /*solium-disable-next-line security/no-block-members*/ emit NewSecurityToken(ticker, _name, newSecurityTokenAddress, msg.sender, now, msg.sender, false, launchFee); } @@ -538,7 +559,17 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _tokenDetails is the off-chain details of the token * @param _deployedAt is the timestamp at which the security token is deployed */ - function modifySecurityToken(string _name, string _ticker, address _owner, address _securityToken, string _tokenDetails, uint256 _deployedAt) external onlyOwner { + function modifySecurityToken( + string _name, + string _ticker, + address _owner, + address _securityToken, + string _tokenDetails, + uint256 _deployedAt + ) + external + onlyOwner + { require(bytes(_name).length > 0 && bytes(_ticker).length > 0, "String length > 0"); require(bytes(_ticker).length <= 10, "Ticker length range (0,10]"); require(_deployedAt != 0 && _owner != address(0), "0 value params not allowed"); @@ -547,6 +578,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { uint256 registrationTime = getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)); uint256 expiryTime = getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)); if (registrationTime == 0) { + /*solium-disable-next-line security/no-block-members*/ registrationTime = now; expiryTime = registrationTime.add(getExpiryLimit()); } @@ -610,24 +642,26 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _newOwner The address to transfer ownership to. */ function transferOwnership(address _newOwner) external onlyOwner { - require(_newOwner != address(0)); + require(_newOwner != address(0), "Invalid address"); emit OwnershipTransferred(getAddress(OWNER), _newOwner); set(OWNER, _newOwner); } /** - * @notice called by the owner to pause, triggers stopped state + * @notice Called by the owner to pause, triggers stopped state */ function pause() external whenNotPaused onlyOwner { set(PAUSED, true); + /*solium-disable-next-line security/no-block-members*/ emit Pause(now); } /** - * @notice called by the owner to unpause, returns to normal state + * @notice Called by the owner to unpause, returns to normal state */ function unpause() external whenPaused onlyOwner { set(PAUSED, false); + /*solium-disable-next-line security/no-block-members*/ emit Unpause(now); } @@ -637,7 +671,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function changeTickerRegistrationFee(uint256 _tickerRegFee) external onlyOwner { uint256 fee = getUint(TICKERREGFEE); - require(fee != _tickerRegFee); + require(fee != _tickerRegFee, "Fee not changed"); emit ChangeTickerRegistrationFee(fee, _tickerRegFee); set(TICKERREGFEE, _tickerRegFee); } @@ -648,7 +682,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function changeSecurityLaunchFee(uint256 _stLaunchFee) external onlyOwner { uint256 fee = getUint(STLAUNCHFEE); - require(fee != _stLaunchFee); + require(fee != _stLaunchFee, "Fee not changed"); emit ChangeSecurityLaunchFee(fee, _stLaunchFee); set(STLAUNCHFEE, _stLaunchFee); } @@ -658,10 +692,10 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _tokenContract is the address of the token contract */ function reclaimERC20(address _tokenContract) external onlyOwner { - require(_tokenContract != address(0)); + require(_tokenContract != address(0), "Invalid address"); IERC20 token = IERC20(_tokenContract); uint256 balance = token.balanceOf(address(this)); - require(token.transfer(owner(), balance)); + require(token.transfer(owner(), balance), "Transfer failed"); } /** @@ -700,7 +734,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { } /** - * @notice get Protocol version + * @notice Gets Protocol version */ function getProtocolVersion() public view returns(uint8[]) { return VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))); @@ -711,7 +745,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _newAddress is the address of the polytoken. */ function updatePolyTokenAddress(address _newAddress) external onlyOwner { - require(_newAddress != address(0)); + require(_newAddress != address(0), "Invalid address"); set(POLYTOKEN, _newAddress); } diff --git a/contracts/external/IMedianizer.sol b/contracts/external/IMedianizer.sol index f75804703..755d54a0f 100644 --- a/contracts/external/IMedianizer.sol +++ b/contracts/external/IMedianizer.sol @@ -1,3 +1,4 @@ +/* solium-disable */ pragma solidity ^0.4.24; /** diff --git a/contracts/external/oraclizeAPI.sol b/contracts/external/oraclizeAPI.sol index ee4b3cd17..c8d7a8f18 100644 --- a/contracts/external/oraclizeAPI.sol +++ b/contracts/external/oraclizeAPI.sol @@ -20,7 +20,7 @@ THE SOFTWARE. */ // This api is currently targeted at 0.4.18, please import oraclizeAPI_pre0.4.sol or oraclizeAPI_0.4 where necessary - +/* solium-disable */ pragma solidity >=0.4.18;// Incompatible compiler version... please select one stated within pragma solidity or use different oraclizeAPI version contract OraclizeI { diff --git a/contracts/helpers/PolyToken.sol b/contracts/helpers/PolyToken.sol index aea5f200d..d8f3d48ec 100644 --- a/contracts/helpers/PolyToken.sol +++ b/contracts/helpers/PolyToken.sol @@ -84,40 +84,40 @@ contract PolyToken is IERC20 { * @dev Assigns the totalSupply to the PolyDistribution contract */ constructor (address _polyDistributionContractAddress) public { - require(_polyDistributionContractAddress != address(0)); + require(_polyDistributionContractAddress != address(0), "Invalid address"); balances[_polyDistributionContractAddress] = totalSupply; emit Transfer(address(0), _polyDistributionContractAddress, totalSupply); } /** - * @dev Gets the balance of the specified address. - * @param _owner The address to query the the balance of. - * @return An uint256 representing the amount owned by the passed address. + * @dev Returns the balance of the specified address + * @param _owner The address to query the the balance of + * @return An uint256 representing the amount owned by the passed address */ function balanceOf(address _owner) public view returns (uint256 balance) { return balances[_owner]; } /** - * @dev Function to check the amount of tokens that an owner allowed to a spender. - * @param _owner address The address which owns the funds. - * @param _spender address The address which will spend the funds. - * @return A uint256 specifying the amount of tokens still available for the spender. + * @dev Function to check the amount of tokens a spender is allowed to spend + * @param _owner address The address which owns the tokens + * @param _spender address The address which will spend the tokens + * @return A uint256 specifying the amount of tokens left available for the spender */ function allowance(address _owner, address _spender) public view returns (uint256) { return allowed[_owner][_spender]; } /** - * @dev transfer token for a specified address - * @param _to The address to transfer to. - * @param _value The amount to be transferred. + * @dev Transfer token to a specified address + * @param _to The address to transfer tokens to + * @param _value The amount to be transferred */ function transfer(address _to, uint256 _value) public returns (bool) { - require(_to != address(0)); - require(_value <= balances[msg.sender]); + require(_to != address(0), "Invalid address"); + require(_value <= balances[msg.sender], "Insufficient tokens transferable"); - // SafeMath.sub will throw if there is not enough balance. + // SafeMath.sub will throw if the balance is not enough balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); emit Transfer(msg.sender, _to, _value); @@ -125,15 +125,15 @@ contract PolyToken is IERC20 { } /** - * @dev Transfer tokens from one address to another - * @param _from address The address which you want to send tokens from - * @param _to address The address which you want to transfer to - * @param _value uint256 the amount of tokens to be transferred + * @dev Transfers tokens from one address to another + * @param _from address The address to transfer tokens from + * @param _to address The address to transfer tokens to + * @param _value uint256 The amount of tokens to be transferred */ function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { - require(_to != address(0)); - require(_value <= balances[_from]); - require(_value <= allowed[_from][msg.sender]); + require(_to != address(0), "Invalid address"); + require(_value <= balances[_from], "Insufficient tokens transferable"); + require(_value <= allowed[_from][msg.sender], "Insufficient tokens allowable"); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); @@ -143,14 +143,14 @@ contract PolyToken is IERC20 { } /** - * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. + * @dev Approves the passed address to spend the specified amount of tokens on behalf of msg.sender * * Beware that changing an allowance with this method brings the risk that someone may use both the old * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this - * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * race condition is to reduce the spender's allowance to 0 first and set the desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * @param _spender The address which will spend the funds. - * @param _value The amount of tokens to be spent. + * @param _spender The address which will spend the funds + * @param _value The amount of tokens to be spent */ function approve(address _spender, uint256 _value) public returns (bool) { allowed[msg.sender][_spender] = _value; @@ -159,10 +159,10 @@ contract PolyToken is IERC20 { } /** - * @dev Increase the amount of tokens that an owner allowed to a spender. + * @dev Increases the amount of tokens that an owner has allowed a spender to spend * * approve should be called when allowed[_spender] == 0. To increment - * allowed value is better to use this function to avoid 2 calls (and wait until + * allowed value, it is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * @param _spender The address which will spend the funds. @@ -175,21 +175,21 @@ contract PolyToken is IERC20 { } /** - * @dev Decrease the amount of tokens that an owner allowed to a spender. + * @dev Decreases the amount of tokens that an owner has allowed a spender to spend * * approve should be called when allowed[_spender] == 0. To decrement - * allowed value is better to use this function to avoid 2 calls (and wait until + * allowed value, it is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol - * @param _spender The address which will spend the funds. - * @param _subtractedValue The amount of tokens to decrease the allowance by. + * @param _spender The address which will spend the funds + * @param _subtractedValue The amount of tokens to decrease the allowance by */ function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) { uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; } else { - allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); + allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; diff --git a/contracts/interfaces/IModule.sol b/contracts/interfaces/IModule.sol index 763e693fd..bc5140ae2 100644 --- a/contracts/interfaces/IModule.sol +++ b/contracts/interfaces/IModule.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; /** - * @title Interface that any module contract should implement + * @title Interface that every module contract should implement */ interface IModule { @@ -11,12 +11,12 @@ interface IModule { function getInitFunction() external pure returns (bytes4); /** - * @notice Return the permissions flag that are associated with a module + * @notice Return the permission flags that are associated with a module */ function getPermissions() external view returns(bytes32[]); /** - * @notice used to withdraw the fee by the factory owner + * @notice Used to withdraw the fee by the factory owner */ function takeFee(uint256 _amount) external returns(bool); diff --git a/contracts/interfaces/IModuleFactory.sol b/contracts/interfaces/IModuleFactory.sol index 9cf834069..9c2ad6bf2 100644 --- a/contracts/interfaces/IModuleFactory.sol +++ b/contracts/interfaces/IModuleFactory.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; /** - * @title Interface that any module factory contract should implement + * @title Interface that every module factory contract should implement */ interface IModuleFactory { @@ -31,21 +31,6 @@ interface IModuleFactory { */ function getName() external view returns(bytes32); - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string); - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string); - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string); - /** * @notice Returns the instructions associated with the module */ @@ -57,44 +42,44 @@ interface IModuleFactory { function getTags() external view returns (bytes32[]); /** - * @notice used to change the fee of the setup cost - * @param _newSetupCost new setup cost + * @notice Used to change the setup fee + * @param _newSetupCost New setup fee */ function changeFactorySetupFee(uint256 _newSetupCost) external; /** - * @notice used to change the fee of the usage cost - * @param _newUsageCost new usage cost + * @notice Used to change the usage fee + * @param _newUsageCost New usage fee */ function changeFactoryUsageFee(uint256 _newUsageCost) external; /** - * @notice used to change the fee of the subscription cost - * @param _newSubscriptionCost new subscription cost + * @notice Used to change the subscription fee + * @param _newSubscriptionCost New subscription fee */ function changeFactorySubscriptionFee(uint256 _newSubscriptionCost) external; /** * @notice Function use to change the lower and upper bound of the compatible version st * @param _boundType Type of bound - * @param _newVersion new version array + * @param _newVersion New version array */ function changeSTVersionBounds(string _boundType, uint8[] _newVersion) external; - /** + /** * @notice Get the setup cost of the module */ function getSetupCost() external view returns (uint256); /** - * @notice use to get the lower bound - * @return lower bound + * @notice Used to get the lower bound + * @return Lower bound */ function getLowerSTVersionBounds() external view returns(uint8[]); /** - * @notice use to get the upper bound - * @return upper bound + * @notice Used to get the upper bound + * @return Upper bound */ function getUpperSTVersionBounds() external view returns(uint8[]); diff --git a/contracts/interfaces/IPolymathRegistry.sol b/contracts/interfaces/IPolymathRegistry.sol index cb2de8d02..4601253fa 100644 --- a/contracts/interfaces/IPolymathRegistry.sol +++ b/contracts/interfaces/IPolymathRegistry.sol @@ -4,11 +4,11 @@ pragma solidity ^0.4.24; interface IPolymathRegistry { /** - * @notice Get the contract address + * @notice Returns the contract address * @param _nameKey is the key for the contract address mapping * @return address */ - function getAddress(string _nameKey) view external returns(address); + function getAddress(string _nameKey) external view returns(address); } \ No newline at end of file diff --git a/contracts/interfaces/ISTFactory.sol b/contracts/interfaces/ISTFactory.sol index a352fb2cb..7b7d6dd77 100644 --- a/contracts/interfaces/ISTFactory.sol +++ b/contracts/interfaces/ISTFactory.sol @@ -6,7 +6,7 @@ pragma solidity ^0.4.24; interface ISTFactory { /** - * @notice deploys the token and adds default modules like permission manager and transfer manager. + * @notice Deploys the token and adds default modules like permission manager and transfer manager. * Future versions of the proxy can attach different modules or pass some other paramters. * @param _name is the name of the Security token * @param _symbol is the symbol of the Security Token @@ -16,6 +16,15 @@ interface ISTFactory { * @param _divisible whether the token is divisible or not * @param _polymathRegistry is the address of the Polymath Registry contract */ - function deployToken(string _name, string _symbol, uint8 _decimals, string _tokenDetails, address _issuer, bool _divisible, address _polymathRegistry) - external returns (address); + function deployToken( + string _name, + string _symbol, + uint8 _decimals, + string _tokenDetails, + address _issuer, + bool _divisible, + address _polymathRegistry + ) + external + returns (address); } diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index c845cc30d..f280d6c19 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -18,38 +18,38 @@ interface ISecurityToken { event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); - //transfer, transferFrom must respect use respect the result of verifyTransfer + //transfer, transferFrom must respect the result of verifyTransfer function verifyTransfer(address _from, address _to, uint256 _value) external returns (bool success); /** - * @notice mints new tokens and assigns them to the target _investor. + * @notice Mints new tokens and assigns them to the target _investor. * Can only be called by the STO attached to the token (Or by the ST owner if there's no STO attached yet) - * @param _investor address the tokens will be minted to + * @param _investor Address the tokens will be minted to * @param _value is the amount of tokens that will be minted to the investor */ function mint(address _investor, uint256 _value) external returns (bool success); /** - * @notice mints new tokens and assigns them to the target _investor. + * @notice Mints new tokens and assigns them to the target _investor. * Can only be called by the STO attached to the token (Or by the ST owner if there's no STO attached yet) - * @param _investor address the tokens will be minted to - * @param _value is the amount of tokens that will be minted to the investor - * @param _data data to indicate validation + * @param _investor Address the tokens will be minted to + * @param _value is The amount of tokens that will be minted to the investor + * @param _data Data to indicate validation */ function mintWithData(address _investor, uint256 _value, bytes _data) external returns (bool success); /** - * @notice Burn function used to burn the securityToken on behalf of someone else + * @notice Used to burn the securityToken on behalf of someone else * @param _from Address for whom to burn tokens - * @param _value No. of token that get burned - * @param _data data to indicate validation + * @param _value No. of tokens to be burned + * @param _data Data to indicate validation */ function burnFromWithData(address _from, uint256 _value, bytes _data) external; /** - * @notice Burn function used to burn the securityToken - * @param _value No. of tokens that get burned - * @param _data data to indicate validation + * @notice Used to burn the securityToken + * @param _value No. of tokens to be burned + * @param _data Data to indicate validation */ function burnWithData(uint256 _value, bytes _data) external; @@ -63,29 +63,29 @@ interface ISecurityToken { /** * @notice Returns module list for a module type - * @param _module address of the module - * @return bytes32 name - * @return address module address - * @return address module factory address - * @return bool module archived - * @return uint8 module type - * @return uint256 module index - * @return uint256 name index + * @param _module Address of the module + * @return bytes32 Name + * @return address Module address + * @return address Module factory address + * @return bool Module archived + * @return uint8 Module type + * @return uint256 Module index + * @return uint256 Name index */ function getModule(address _module) external view returns(bytes32, address, address, bool, uint8, uint256, uint256); /** - * @notice returns module list for a module name - * @param _name name of the module - * @return address[] list of modules with this name + * @notice Returns module list for a module name + * @param _name Name of the module + * @return address[] List of modules with this name */ function getModulesByName(bytes32 _name) external view returns (address[]); /** - * @notice returns module list for a module type - * @param _type type of the module - * @return address[] list of modules with this type + * @notice Returns module list for a module type + * @param _type Type of the module + * @return address[] List of modules with this type */ function getModulesByType(uint8 _type) external view returns (address[]); @@ -96,7 +96,7 @@ interface ISecurityToken { function totalSupplyAt(uint256 _checkpointId) external view returns (uint256); /** - * @notice Queries balances at a specified checkpoint + * @notice Queries balance at a specified checkpoint * @param _investor Investor to query balance for * @param _checkpointId Checkpoint ID to query as of */ @@ -108,81 +108,98 @@ interface ISecurityToken { function createCheckpoint() external returns (uint256); /** - * @notice gets length of investors array + * @notice Gets length of investors array * NB - this length may differ from investorCount if the list has not been pruned of zero-balance investors - * @return length + * @return Length */ function getInvestors() external view returns (address[]); /** - * @notice gets current checkpoint ID - * @return id - */ + * @notice returns an array of investors at a given checkpoint + * NB - this length may differ from investorCount as it contains all investors that ever held tokens + * @param _checkpointId Checkpoint id at which investor list is to be populated + * @return list of investors + */ + function getInvestorsAt(uint256 _checkpointId) external view returns(address[]); + + /** + * @notice generates subset of investors + * NB - can be used in batches if investor list is large + * @param _start Position of investor to start iteration from + * @param _end Position of investor to stop iteration at + * @return list of investors + */ + function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[]); + + /** + * @notice Gets current checkpoint ID + * @return Id + */ function currentCheckpointId() external view returns (uint256); /** - * @notice gets an investor at a particular index - * @param _index index to return address from - * @return investor address + * @notice Gets an investor at a particular index + * @param _index Index to return address from + * @return Investor address */ function investors(uint256 _index) external view returns (address); /** - * @notice allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token. + * @notice Allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token. * @dev Owner can transfer POLY to the ST which will be used to pay for modules that require a POLY fee. * @param _tokenContract Address of the ERC20Basic compliance token - * @param _value amount of POLY to withdraw + * @param _value Amount of POLY to withdraw */ function withdrawERC20(address _tokenContract, uint256 _value) external; /** - * @notice allows owner to approve more POLY to one of the modules - * @param _module module address - * @param _budget new budget + * @notice Allows owner to approve more POLY to one of the modules + * @param _module Module address + * @param _budget New budget */ function changeModuleBudget(address _module, uint256 _budget) external; /** - * @notice changes the tokenDetails + * @notice Changes the tokenDetails * @param _newTokenDetails New token details */ function updateTokenDetails(string _newTokenDetails) external; /** - * @notice allows owner to change token granularity - * @param _granularity granularity level of the token + * @notice Allows the owner to change token granularity + * @param _granularity Granularity level of the token */ function changeGranularity(uint256 _granularity) external; /** - * @notice removes addresses with zero balances from the investors list - * @param _start Index in investor list at which to start removing zero balances + * @notice Removes addresses with zero balances from the investors list + * @param _start Index in investors list at which to start removing zero balances * @param _iters Max number of iterations of the for loop * NB - pruning this list will mean you may not be able to iterate over investors on-chain as of a historical checkpoint */ function pruneInvestors(uint256 _start, uint256 _iters) external; /** - * @notice freeze all the transfers + * @notice Freezes all the transfers */ function freezeTransfers() external; /** - * @notice un-freeze all the transfers + * @notice Un-freezes all the transfers */ function unfreezeTransfers() external; /** - * @notice End token minting period permanently + * @notice Ends token minting period permanently */ function freezeMinting() external; /** - * @notice mints new tokens and assigns them to the target investors. + * @notice Mints new tokens and assigns them to the target investors. * Can only be called by the STO attached to the token or by the Issuer (Security Token contract owner) * @param _investors A list of addresses to whom the minted tokens will be delivered * @param _values A list of the amount of tokens to mint to corresponding addresses from _investor[] list - * @return success + * @return Success */ function mintMulti(address[] _investors, uint256[] _values) external returns (bool success); @@ -223,13 +240,13 @@ interface ISecurityToken { function removeModule(address _module) external; /** - * @notice Use by the issuer to set the controller addresses + * @notice Used by the issuer to set the controller addresses * @param _controller address of the controller */ function setController(address _controller) external; /** - * @notice Use by a controller to execute a forced transfer + * @notice Used by a controller to execute a forced transfer * @param _from address from which to take tokens * @param _to address where to send tokens * @param _value amount of tokens to transfer @@ -239,7 +256,7 @@ interface ISecurityToken { function forceTransfer(address _from, address _to, uint256 _value, bytes _data, bytes _log) external; /** - * @notice Use by a controller to execute a foced burn + * @notice Used by a controller to execute a foced burn * @param _from address from which to take tokens * @param _value amount of tokens to transfer * @param _data data to indicate validation @@ -248,18 +265,18 @@ interface ISecurityToken { function forceBurn(address _from, uint256 _value, bytes _data, bytes _log) external; /** - * @notice Use by the issuer to permanently disable controller functionality + * @notice Used by the issuer to permanently disable controller functionality * @dev enabled via feature switch "disableControllerAllowed" */ function disableController() external; /** - * @notice Use to get the version of the securityToken + * @notice Used to get the version of the securityToken */ function getVersion() external view returns(uint8[]); /** - * @notice gets the investor count + * @notice Gets the investor count */ function getInvestorCount() external view returns(uint256); @@ -281,10 +298,10 @@ interface ISecurityToken { * @return bool success */ function transferFromWithData(address _from, address _to, uint256 _value, bytes _data) external returns(bool); - + /** - * @notice Provide the granularity of the token - * @return uint256 + * @notice Provides the granularity of the token + * @return uint256 */ function granularity() external view returns(uint256); } diff --git a/contracts/interfaces/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index 2bacd39d7..8db01f8ad 100644 --- a/contracts/interfaces/ISecurityTokenRegistry.sol +++ b/contracts/interfaces/ISecurityTokenRegistry.sol @@ -9,8 +9,8 @@ interface ISecurityTokenRegistry { * @notice Creates a new Security Token and saves it to the registry * @param _name Name of the token * @param _ticker Ticker ticker of the security token - * @param _tokenDetails off-chain details of the token - * @param _divisible whether the token is divisible or not + * @param _tokenDetails Off-chain details of the token + * @param _divisible Whether the token is divisible or not */ function generateSecurityToken(string _name, string _ticker, string _tokenDetails, bool _divisible) external; @@ -20,17 +20,25 @@ interface ISecurityTokenRegistry { * @param _ticker Ticker of the security token * @param _owner Owner of the token * @param _securityToken Address of the securityToken - * @param _tokenDetails off-chain details of the token + * @param _tokenDetails Off-chain details of the token * @param _deployedAt Timestamp at which security token comes deployed on the ethereum blockchain */ - function modifySecurityToken(string _name, string _ticker, address _owner, address _securityToken, string _tokenDetails, uint256 _deployedAt) external; + function modifySecurityToken( + string _name, + string _ticker, + address _owner, + address _securityToken, + string _tokenDetails, + uint256 _deployedAt + ) + external; /** - * @notice Register the token ticker for its particular owner - * @notice Once the token ticker is registered to its owner then no other issuer can claim + * @notice Registers the token ticker for its particular owner + * @notice once the token ticker is registered to its owner then no other issuer can claim * @notice its ownership. If the ticker expires and its issuer hasn't used it, then someone else can take it. * @param _owner Address of the owner of the token - * @param _ticker token ticker + * @param _ticker Token ticker * @param _tokenName Name of the token */ function registerTicker(address _owner, string _ticker, string _tokenName) external; @@ -82,12 +90,12 @@ interface ISecurityTokenRegistry { function getSTFactoryAddress() external view returns(address); /** - * @notice get Protocol version + * @notice Get Protocol version */ function getProtocolVersion() external view returns(uint8[]); /** - * @notice Use to get the ticker list as per the owner + * @notice Used to get the ticker list as per the owner * @param _owner Address which owns the list of tickers */ function getTickersByOwner(address _owner) external view returns(bytes32[]); @@ -111,45 +119,53 @@ interface ISecurityTokenRegistry { function getTickerDetails(string _ticker) external view returns (address, uint256, uint256, string, bool); /** - * @notice Modify the ticker details. Only polymath account has the ability + * @notice Modifies the ticker details. Only polymath account has the ability * to do so. Only allowed to modify the tickers which are not yet deployed * @param _owner Owner of the token - * @param _ticker token ticker + * @param _ticker Token ticker * @param _tokenName Name of the token * @param _registrationDate Date on which ticker get registered * @param _expiryDate Expiry date of the ticker * @param _status Token deployed status */ - function modifyTicker(address _owner, string _ticker, string _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status) external; + function modifyTicker( + address _owner, + string _ticker, + string _tokenName, + uint256 _registrationDate, + uint256 _expiryDate, + bool _status + ) + external; /** - * @notice Remove the ticker details and associated ownership & security token mapping - * @param _ticker token ticker + * @notice Removes the ticker details and associated ownership & security token mapping + * @param _ticker Token ticker */ function removeTicker(string _ticker) external; /** - * @notice Transfer the ownership of the ticker + * @notice Transfers the ownership of the ticker * @dev _newOwner Address whom ownership to transfer * @dev _ticker Ticker */ function transferTickerOwnership(address _newOwner, string _ticker) external; /** - * @notice Change the expiry time for the token ticker - * @param _newExpiry new time period for token ticker expiry + * @notice Changes the expiry time for the token ticker + * @param _newExpiry New time period for token ticker expiry */ function changeExpiryLimit(uint256 _newExpiry) external; /** - * @notice set the ticker registration fee in POLY tokens - * @param _tickerRegFee registration fee in POLY tokens (base 18 decimals) + * @notice Sets the ticker registration fee in POLY tokens + * @param _tickerRegFee Registration fee in POLY tokens (base 18 decimals) */ function changeTickerRegistrationFee(uint256 _tickerRegFee) external; /** - * @notice set the ticker registration fee in POLY tokens - * @param _stLaunchFee registration fee in POLY tokens (base 18 decimals) + * @notice Sets the ticker registration fee in POLY tokens + * @param _stLaunchFee Registration fee in POLY tokens (base 18 decimals) */ function changeSecurityLaunchFee(uint256 _stLaunchFee) external; @@ -178,7 +194,7 @@ interface ISecurityTokenRegistry { function getExpiryLimit() external view returns(uint256); /** - * @notice Check whether the registry is paused or not + * @notice Checks whether the registry is paused or not * @return bool */ function isPaused() external view returns(bool); diff --git a/contracts/interfaces/IUSDTieredSTOProxy.sol b/contracts/interfaces/IUSDTieredSTOProxy.sol index 1f0526d5d..3aec141a0 100644 --- a/contracts/interfaces/IUSDTieredSTOProxy.sol +++ b/contracts/interfaces/IUSDTieredSTOProxy.sol @@ -6,16 +6,16 @@ pragma solidity ^0.4.24; interface IUSDTieredSTOProxy { /** - * @notice deploys the STO. + * @notice Deploys the STO. * @param _securityToken Contract address of the securityToken - * @param _polyAddress Contract address of the PolyToken. + * @param _polyAddress Contract address of the PolyToken * @param _factoryAddress Contract address of the factory * @return address Address of the deployed STO */ function deploySTO(address _securityToken, address _polyAddress, address _factoryAddress) external returns (address); /** - * @notice Use to get the init function signature + * @notice Used to get the init function signature * @param _contractAddress Address of the STO contract * @return bytes4 */ diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index b7eeca7f4..42e5bebff 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -25,7 +25,7 @@ library TokenLib { } struct InvestorDataStorage { - // List of investors (may not be pruned to remove old investors with current zero balances) + // List of investors who have ever held a non-zero token balance mapping (address => bool) investorListed; // List of token holders address[] investors; @@ -40,29 +40,31 @@ library TokenLib { /** * @notice Archives a module attached to the SecurityToken - * @param _moduleData storage data - * @param _module address of module to archive + * @param _moduleData Storage data + * @param _module Address of module to archive */ function archiveModule(ModuleData storage _moduleData, address _module) public { require(!_moduleData.isArchived, "Module archived"); require(_moduleData.module != address(0), "Module missing"); + /*solium-disable-next-line security/no-block-members*/ emit ModuleArchived(_moduleData.moduleTypes, _module, now); _moduleData.isArchived = true; } /** * @notice Unarchives a module attached to the SecurityToken - * @param _moduleData storage data - * @param _module address of module to unarchive + * @param _moduleData Storage data + * @param _module Address of module to unarchive */ function unarchiveModule(ModuleData storage _moduleData, address _module) public { require(_moduleData.isArchived, "Module unarchived"); + /*solium-disable-next-line security/no-block-members*/ emit ModuleUnarchived(_moduleData.moduleTypes, _module, now); _moduleData.isArchived = false; } /** - * @notice Validate permissions with PermissionManager if it exists. If there's no permission return false + * @notice Validates permissions with PermissionManager if it exists. If there's no permission return false * @dev Note that IModule withPerm will allow ST owner all permissions by default * @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions) * @param _modules is the modules to check permissions on @@ -150,13 +152,13 @@ library TokenLib { } /** - * @notice keeps track of the number of non-zero token holders + * @notice Keeps track of the number of non-zero token holders * @param _investorData Date releated to investor metrics - * @param _from sender of transfer - * @param _to receiver of transfer - * @param _value value of transfer - * @param _balanceTo balance of the _to address - * @param _balanceFrom balance of the _from address + * @param _from Sender of transfer + * @param _to Receiver of transfer + * @param _value Value of transfer + * @param _balanceTo Balance of the _to address + * @param _balanceFrom Balance of the _from address */ function adjustInvestorCount( InvestorDataStorage storage _investorData, @@ -185,16 +187,4 @@ library TokenLib { } - /** - * @notice removes addresses with zero balances from the investors list - * @param _investorData is the date related to investor metrics - * @param _index is the index in investor list - * NB - pruning this list will mean you may not be able to iterate over investors on-chain as of a historical checkpoint - */ - function pruneInvestors(InvestorDataStorage storage _investorData, uint256 _index) public { - _investorData.investorListed[_investorData.investors[_index]] = false; - _investorData.investors[_index] = _investorData.investors[_investorData.investors.length - 1]; - _investorData.investors.length--; - } - } diff --git a/contracts/libraries/Util.sol b/contracts/libraries/Util.sol index 4e60c9c59..5d4cce83e 100644 --- a/contracts/libraries/Util.sol +++ b/contracts/libraries/Util.sol @@ -6,8 +6,8 @@ pragma solidity ^0.4.24; library Util { /** - * @notice changes a string to upper case - * @param _base string to change + * @notice Changes a string to upper case + * @param _base String to change */ function upper(string _base) internal pure returns (string) { bytes memory _baseBytes = bytes(_base); @@ -22,16 +22,16 @@ library Util { } /** - * @notice changes the string into bytes32 + * @notice Changes the string into bytes32 * @param _source String that need to convert into bytes32 */ - /// Notice - Maximum length for _source will be 32 chars otherwise returned bytes32 value will have lossy value. + /// Notice - Maximum Length for _source will be 32 chars otherwise returned bytes32 value will have lossy value. function stringToBytes32(string memory _source) internal pure returns (bytes32) { return bytesToBytes32(bytes(_source), 0); } /** - * @notice changes bytes into bytes32 + * @notice Changes bytes into bytes32 * @param _b Bytes that need to convert into bytes32 * @param _offset Offset from which to begin conversion */ @@ -67,8 +67,8 @@ library Util { } /** - * @notice Get function signature from _data - * @param _data passed data + * @notice Gets function signature from _data + * @param _data Passed data * @return bytes4 sig */ function getSig(bytes _data) internal pure returns (bytes4 sig) { diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 2650913ce..71376aa45 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -46,15 +46,15 @@ library VersionUtils { } /** - * @notice This function use to compare the lower bound with the latest version + * @notice Used to compare the lower bound with the latest version * @param _version1 Array holds the lower bound of the version * @param _version2 Array holds the latest version of the ST * @return bool */ function compareLowerBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) { - require(_version1.length == _version2.length); + require(_version1.length == _version2.length, "Input length mismatch"); uint counter = 0; - for (uint8 j = 0; j< _version1.length; j++) { + for (uint8 j = 0; j < _version1.length; j++) { if (_version1[j] == 0) counter ++; } @@ -77,15 +77,15 @@ library VersionUtils { } /** - * @notice This function use to compare the upper bound with the latest version + * @notice Used to compare the upper bound with the latest version * @param _version1 Array holds the upper bound of the version * @param _version2 Array holds the latest version of the ST * @return bool */ function compareUpperBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) { - require(_version1.length == _version2.length); + require(_version1.length == _version2.length, "Input length mismatch"); uint counter = 0; - for (uint8 j = 0; j< _version1.length; j++) { + for (uint8 j = 0; j < _version1.length; j++) { if (_version1[j] == 0) counter ++; } @@ -109,7 +109,7 @@ library VersionUtils { /** - * @notice Use to pack the uint8[] array data into uint24 value + * @notice Used to pack the uint8[] array data into uint24 value * @param _major Major version * @param _minor Minor version * @param _patch Patch version @@ -119,7 +119,7 @@ library VersionUtils { } /** - * @notice Use to convert packed data into uint8 array + * @notice Used to convert packed data into uint8 array * @param _packedVersion Packed data */ function unpack(uint24 _packedVersion) internal pure returns (uint8[]) { diff --git a/contracts/mocks/MockBurnFactory.sol b/contracts/mocks/MockBurnFactory.sol index c21b474f1..6c0e47c3d 100644 --- a/contracts/mocks/MockBurnFactory.sol +++ b/contracts/mocks/MockBurnFactory.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "./MockRedemptionManager.sol"; -import "../modules/Burn/TrackedRedemptionFactory.sol"; +import "../modules/Experimental/Burn/TrackedRedemptionFactory.sol"; /** * @title Mock Contract Not fit for production environment @@ -19,14 +19,15 @@ contract MockBurnFactory is TrackedRedemptionFactory { } /** - * @notice used to launch the Module with the help of factory - * @return address Contract address of the Module + * @notice Used to launch the Module with the help of factory + * @return Address Contract address of the Module */ function deploy(bytes /*_data*/) external returns(address) { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Unable to pay setup cost"); //Check valid bytes - can only call module init function MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(mockRedemptionManager), getName(), address(this), msg.sender, setupCost, now); return address(mockRedemptionManager); } diff --git a/contracts/mocks/MockModuleRegistry.sol b/contracts/mocks/MockModuleRegistry.sol index 23af59d58..5711108c1 100644 --- a/contracts/mocks/MockModuleRegistry.sol +++ b/contracts/mocks/MockModuleRegistry.sol @@ -11,7 +11,7 @@ contract MockModuleRegistry is ModuleRegistry { /// Alert! Alert! Do not use it for the mainnet release function addMoreReputation(address _moduleFactory, address[] _tokens) public onlyOwner { for (uint8 i = 0; i < _tokens.length; i++) { - pushArray(Encoder.getKey('reputation', _moduleFactory), _tokens[i]); + pushArray(Encoder.getKey("reputation", _moduleFactory), _tokens[i]); } } diff --git a/contracts/mocks/MockRedemptionManager.sol b/contracts/mocks/MockRedemptionManager.sol index a2a0a6f7c..02fbb2e81 100644 --- a/contracts/mocks/MockRedemptionManager.sol +++ b/contracts/mocks/MockRedemptionManager.sol @@ -1,12 +1,12 @@ pragma solidity ^0.4.24; -import "../modules/Burn/TrackedRedemption.sol"; +import "../modules/Experimental/Burn/TrackedRedemption.sol"; /** * @title Burn module for burning tokens and keeping track of burnt amounts */ contract MockRedemptionManager is TrackedRedemption { - + mapping (address => uint256) tokenToRedeem; event RedeemedTokenByOwner(address _investor, address _byWhoom, uint256 _value, uint256 _timestamp); @@ -22,7 +22,7 @@ contract MockRedemptionManager is TrackedRedemption { } /** - * @notice Transfer tokens to Module to burn + * @notice Transfers tokens to Module to burn * @param _value The number of tokens to redeem */ function transferToRedeem(uint256 _value) public { @@ -31,14 +31,15 @@ contract MockRedemptionManager is TrackedRedemption { } /** - * @notice use to redeem tokens by the module + * @notice Used to redeem tokens by the module * @param _value The number of tokens to redeem */ function redeemTokenByOwner(uint256 _value) public { - require(tokenToRedeem[msg.sender] >= _value); + require(tokenToRedeem[msg.sender] >= _value, "Insufficient tokens redeemable"); tokenToRedeem[msg.sender] = tokenToRedeem[msg.sender].sub(_value); redeemedTokens[msg.sender] = redeemedTokens[msg.sender].add(_value); ISecurityToken(securityToken).burnWithData(_value, ""); + /*solium-disable-next-line security/no-block-members*/ emit RedeemedTokenByOwner(msg.sender, address(this), _value, now); } diff --git a/contracts/mocks/PolyTokenFaucet.sol b/contracts/mocks/PolyTokenFaucet.sol index 4a30fe861..76f1a5596 100644 --- a/contracts/mocks/PolyTokenFaucet.sol +++ b/contracts/mocks/PolyTokenFaucet.sol @@ -30,7 +30,7 @@ contract PolyTokenFaucet { /* Token faucet - Not part of the ERC20 standard */ function getTokens(uint256 _amount, address _recipient) public returns (bool) { - require(_amount <= 1000000 * uint256(10)**decimals, "Amount can not be more than 1 million"); + require(_amount <= 1000000 * uint256(10)**decimals, "Amount should not exceed 1 million"); require(_recipient != address(0), "Recipient address can not be empty"); balances[_recipient] = balances[_recipient].add(_amount); totalSupply_ = totalSupply_.add(_amount); @@ -39,7 +39,7 @@ contract PolyTokenFaucet { } /** - * @notice send `_value` token to `_to` from `msg.sender` + * @notice Sends `_value` tokens to `_to` from `msg.sender` * @param _to The address of the recipient * @param _value The amount of token to be transferred * @return Whether the transfer was successful or not @@ -52,16 +52,16 @@ contract PolyTokenFaucet { } /** - * @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` + * @notice sends `_value` tokens to `_to` from `_from` with the condition it is approved by `_from` * @param _from The address of the sender * @param _to The address of the recipient * @param _value The amount of token to be transferred * @return Whether the transfer was successful or not */ function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { - require(_to != address(0)); - require(_value <= balances[_from]); - require(_value <= allowed[_from][msg.sender]); + require(_to != address(0), "Invalid address"); + require(_value <= balances[_from], "Insufficient tokens transferable"); + require(_value <= allowed[_from][msg.sender], "Insufficient tokens allowable"); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); @@ -71,7 +71,7 @@ contract PolyTokenFaucet { } /** - * @notice `balanceOf` function to get the balance of token holders + * @notice Returns the balance of a token holder * @param _owner The address from which the balance will be retrieved * @return The balance */ @@ -80,7 +80,7 @@ contract PolyTokenFaucet { } /** - * @notice `msg.sender` approves `_spender` to spend `_value` tokens + * @notice Used by `msg.sender` to approve `_spender` to spend `_value` tokens * @param _spender The address of the account able to transfer the tokens * @param _value The amount of tokens to be approved for transfer * @return Whether the approval was successful or not @@ -94,7 +94,7 @@ contract PolyTokenFaucet { /** * @param _owner The address of the account owning tokens * @param _spender The address of the account able to transfer the tokens - * @return Amount of remaining tokens allowed to spent + * @return Amount of remaining tokens allowed to be spent */ function allowance(address _owner, address _spender) public view returns (uint256 remaining) { return allowed[_owner][_spender]; @@ -105,9 +105,9 @@ contract PolyTokenFaucet { } /** - * @dev Increase the amount of tokens that an owner allowed to a spender. + * @dev Increases the amount of tokens that an owner allowed to a spender. * approve should be called when allowed[_spender] == 0. To increment - * allowed value is better to use this function to avoid 2 calls (and wait until + * allowed value, it is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * @param _spender The address which will spend the funds. @@ -130,7 +130,7 @@ contract PolyTokenFaucet { * @dev Decrease the amount of tokens that an owner allowed to a spender. * * approve should be called when allowed[_spender] == 0. To decrement - * allowed value is better to use this function to avoid 2 calls (and wait until + * allowed value, it is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * @param _spender The address which will spend the funds. diff --git a/contracts/mocks/SecurityTokenRegistryMock.sol b/contracts/mocks/SecurityTokenRegistryMock.sol index 78faa60d1..d0a6de099 100644 --- a/contracts/mocks/SecurityTokenRegistryMock.sol +++ b/contracts/mocks/SecurityTokenRegistryMock.sol @@ -7,7 +7,7 @@ import "../SecurityTokenRegistry.sol"; */ contract SecurityTokenRegistryMock is SecurityTokenRegistry { - /// @notice It is dummy functionality + /// @notice It is a dummy function /// Alert! Alert! Do not use it for the mainnet release function changeTheDeployedAddress(string _ticker, address _newSecurityTokenAddress) public { set(Encoder.getKey("tickerToSecurityToken", _ticker), _newSecurityTokenAddress); diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index eb26bd922..a8bcbbeb6 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -27,7 +27,7 @@ contract TestSTOFactory is DummySTOFactory { } /** - * @notice Get the tags related to the module factory + * @notice Gets the tags related to the module factory */ function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](4); diff --git a/contracts/modules/Burn/IBurn.sol b/contracts/modules/Burn/IBurn.sol index 3af836f40..7a84a802b 100644 --- a/contracts/modules/Burn/IBurn.sol +++ b/contracts/modules/Burn/IBurn.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.24; /** * @title Interface to be implemented by all checkpoint modules */ +/*solium-disable-next-line no-empty-blocks*/ interface IBurn { } diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 4199d06f8..452a48b13 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -1,3 +1,10 @@ +/** + * DISCLAIMER: Under certain conditions, the function pushDividendPayment + * may fail due to block gas limits. + * If the total number of investors that ever held tokens is greater than ~15,000 then + * the function may fail. If this happens investors can pull their dividends, or the Issuer + * can use pushDividendPaymentToAddresses to provide an explict address list in batches + */ pragma solidity ^0.4.24; import "./ICheckpoint.sol"; @@ -22,7 +29,8 @@ contract DividendCheckpoint is ICheckpoint, Module { uint256 checkpointId; uint256 created; // Time at which the dividend was created uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass - uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - set to very high value to bypass + uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - + // set to very high value to bypass uint256 amount; // Dividend amount in WEI uint256 claimedAmount; // Amount of dividend claimed so far uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) @@ -53,7 +61,9 @@ contract DividendCheckpoint is ICheckpoint, Module { modifier validDividendIndex(uint256 _dividendIndex) { require(_dividendIndex < dividends.length, "Invalid dividend"); require(!dividends[_dividendIndex].reclaimed, "Dividend reclaimed"); + /*solium-disable-next-line security/no-block-members*/ require(now >= dividends[_dividendIndex].maturity, "Dividend maturity in future"); + /*solium-disable-next-line security/no-block-members*/ require(now < dividends[_dividendIndex].expiry, "Dividend expiry in past"); _; } @@ -84,7 +94,7 @@ contract DividendCheckpoint is ICheckpoint, Module { /** * @notice Function to clear and set list of excluded addresses used for future dividends - * @param _excluded addresses of investor + * @param _excluded Addresses of investors */ function setDefaultExcluded(address[] _excluded) public withPerm(MANAGE) { require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many excluded addresses"); @@ -95,16 +105,18 @@ contract DividendCheckpoint is ICheckpoint, Module { } } excluded = _excluded; + /*solium-disable-next-line security/no-block-members*/ emit SetDefaultExcludedAddresses(excluded, now); } /** * @notice Function to set withholding tax rates for investors - * @param _investors addresses of investor - * @param _withholding withholding tax for individual investors (multiplied by 10**16) + * @param _investors Addresses of investors + * @param _withholding Withholding tax for individual investors (multiplied by 10**16) */ function setWithholding(address[] _investors, uint256[] _withholding) public withPerm(MANAGE) { require(_investors.length == _withholding.length, "Mismatched input lengths"); + /*solium-disable-next-line security/no-block-members*/ emit SetWithholding(_investors, _withholding, now); for (uint256 i = 0; i < _investors.length; i++) { require(_withholding[i] <= 10**18, "Incorrect withholding tax"); @@ -114,11 +126,12 @@ contract DividendCheckpoint is ICheckpoint, Module { /** * @notice Function to set withholding tax rates for investors - * @param _investors addresses of investor - * @param _withholding withholding tax for all investors (multiplied by 10**16) + * @param _investors Addresses of investor + * @param _withholding Withholding tax for all investors (multiplied by 10**16) */ function setWithholdingFixed(address[] _investors, uint256 _withholding) public withPerm(MANAGE) { require(_withholding <= 10**18, "Incorrect withholding tax"); + /*solium-disable-next-line security/no-block-members*/ emit SetWithholdingFixed(_investors, _withholding, now); for (uint256 i = 0; i < _investors.length; i++) { withholdingTax[_investors[i]] = _withholding; @@ -130,7 +143,14 @@ contract DividendCheckpoint is ICheckpoint, Module { * @param _dividendIndex Dividend to push * @param _payees Addresses to which to push the dividend */ - function pushDividendPaymentToAddresses(uint256 _dividendIndex, address[] _payees) public withPerm(DISTRIBUTE) validDividendIndex(_dividendIndex) { + function pushDividendPaymentToAddresses( + uint256 _dividendIndex, + address[] _payees + ) + public + withPerm(DISTRIBUTE) + validDividendIndex(_dividendIndex) + { Dividend storage dividend = dividends[_dividendIndex]; for (uint256 i = 0; i < _payees.length; i++) { if ((!dividend.claimed[_payees[i]]) && (!dividend.dividendExcluded[_payees[i]])) { @@ -145,7 +165,15 @@ contract DividendCheckpoint is ICheckpoint, Module { * @param _start Index in investor list at which to start pushing dividends * @param _iterations Number of addresses to push dividends for */ - function pushDividendPayment(uint256 _dividendIndex, uint256 _start, uint256 _iterations) public withPerm(DISTRIBUTE) validDividendIndex(_dividendIndex) { + function pushDividendPayment( + uint256 _dividendIndex, + uint256 _start, + uint256 _iterations + ) + public + withPerm(DISTRIBUTE) + validDividendIndex(_dividendIndex) + { Dividend storage dividend = dividends[_dividendIndex]; address[] memory investors = ISecurityToken(securityToken).getInvestors(); uint256 numberInvestors = Math.min256(investors.length, _start.add(_iterations)); @@ -171,8 +199,8 @@ contract DividendCheckpoint is ICheckpoint, Module { /** * @notice Internal function for paying dividends - * @param _payee address of investor - * @param _dividend storage with previously issued dividends + * @param _payee Address of investor + * @param _dividend Storage with previously issued dividends * @param _dividendIndex Dividend to pay */ function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index a23e87c0f..1f7f25cd5 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -12,11 +12,37 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { // Mapping to token address for each dividend mapping (uint256 => address) public dividendTokens; - - event ERC20DividendDeposited(address indexed _depositor, uint256 _checkpointId, uint256 _created, uint256 _maturity, uint256 _expiry, address indexed _token, uint256 _amount, uint256 _totalSupply, uint256 _dividendIndex, bytes32 indexed _name); - event ERC20DividendClaimed(address indexed _payee, uint256 _dividendIndex, address indexed _token, uint256 _amount, uint256 _withheld); - event ERC20DividendReclaimed(address indexed _claimer, uint256 _dividendIndex, address indexed _token, uint256 _claimedAmount); - event ERC20DividendWithholdingWithdrawn(address indexed _claimer, uint256 _dividendIndex, address indexed _token, uint256 _withheldAmount); + event ERC20DividendDeposited( + address indexed _depositor, + uint256 _checkpointId, + uint256 _created, + uint256 _maturity, + uint256 _expiry, + address indexed _token, + uint256 _amount, + uint256 _totalSupply, + uint256 _dividendIndex, + bytes32 indexed _name + ); + event ERC20DividendClaimed( + address indexed _payee, + uint256 _dividendIndex, + address indexed _token, + uint256 _amount, + uint256 _withheld + ); + event ERC20DividendReclaimed( + address indexed _claimer, + uint256 _dividendIndex, + address indexed _token, + uint256 _claimedAmount + ); + event ERC20DividendWithholdingWithdrawn( + address indexed _claimer, + uint256 _dividendIndex, + address indexed _token, + uint256 _withheldAmount + ); /** * @notice Constructor @@ -34,9 +60,18 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer * @param _token Address of ERC20 token in which dividend is to be denominated * @param _amount Amount of specified token for dividend - * @param _name name/title for identification + * @param _name Name/Title for identification */ - function createDividend(uint256 _maturity, uint256 _expiry, address _token, uint256 _amount, bytes32 _name) external withPerm(MANAGE) { + function createDividend( + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + bytes32 _name + ) + external + withPerm(MANAGE) + { createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name); } @@ -47,9 +82,19 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _token Address of ERC20 token in which dividend is to be denominated * @param _amount Amount of specified token for dividend * @param _checkpointId Checkpoint id from which to create dividends - * @param _name name/title for identification + * @param _name Name/Title for identification */ - function createDividendWithCheckpoint(uint256 _maturity, uint256 _expiry, address _token, uint256 _amount, uint256 _checkpointId, bytes32 _name) external withPerm(MANAGE) { + function createDividendWithCheckpoint( + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, + bytes32 _name + ) + external + withPerm(MANAGE) + { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, excluded, _name); } @@ -60,9 +105,19 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _token Address of ERC20 token in which dividend is to be denominated * @param _amount Amount of specified token for dividend * @param _excluded List of addresses to exclude - * @param _name name/title for identification + * @param _name Name/Title for identification */ - function createDividendWithExclusions(uint256 _maturity, uint256 _expiry, address _token, uint256 _amount, address[] _excluded, bytes32 _name) public withPerm(MANAGE) { + function createDividendWithExclusions( + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + address[] _excluded, + bytes32 _name + ) + public + withPerm(MANAGE) + { uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, checkpointId, _excluded, _name); } @@ -75,7 +130,7 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _amount Amount of specified token for dividend * @param _checkpointId Checkpoint id from which to create dividends * @param _excluded List of addresses to exclude - * @param _name name/title for identification + * @param _name Name/Title for identification */ function createDividendWithCheckpointAndExclusions( uint256 _maturity, @@ -100,7 +155,7 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _amount Amount of specified token for dividend * @param _checkpointId Checkpoint id from which to create dividends * @param _excluded List of addresses to exclude - * @param _name name/title for identification + * @param _name Name/Title for identification */ function _createDividendWithCheckpointAndExclusions( uint256 _maturity, @@ -116,6 +171,7 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { ISecurityToken securityTokenInstance = ISecurityToken(securityToken); require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); require(_expiry > _maturity, "Expiry before maturity"); + /*solium-disable-next-line security/no-block-members*/ require(_expiry > now, "Expiry in past"); require(_amount > 0, "No dividend sent"); require(_token != address(0), "Invalid token"); @@ -128,7 +184,7 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { dividends.push( Dividend( _checkpointId, - now, + now, /*solium-disable-line security/no-block-members*/ _maturity, _expiry, _amount, @@ -154,17 +210,29 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { } /** - * @notice emits the ERC20DividendDeposited event. + * @notice Emits the ERC20DividendDeposited event. * Seperated into a different function as a workaround for stack too deep error */ - function _emitERC20DividendDepositedEvent(uint256 _checkpointId, uint256 _maturity, uint256 _expiry, address _token, uint256 _amount, uint256 currentSupply, uint256 dividendIndex, bytes32 _name) internal { + function _emitERC20DividendDepositedEvent( + uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 currentSupply, + uint256 dividendIndex, + bytes32 _name + ) + internal + { + /*solium-disable-next-line security/no-block-members*/ emit ERC20DividendDeposited(msg.sender, _checkpointId, now, _maturity, _expiry, _token, _amount, currentSupply, dividendIndex, _name); } /** * @notice Internal function for paying dividends - * @param _payee address of investor - * @param _dividend storage with previously issued dividends + * @param _payee Address of investor + * @param _dividend Storage with previously issued dividends * @param _dividendIndex Dividend to pay */ function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { @@ -186,6 +254,7 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { */ function reclaimDividend(uint256 _dividendIndex) external withPerm(MANAGE) { require(_dividendIndex < dividends.length, "Invalid dividend"); + /*solium-disable-next-line security/no-block-members*/ require(now >= dividends[_dividendIndex].expiry, "Dividend expiry in future"); require(!dividends[_dividendIndex].reclaimed, "already claimed"); dividends[_dividendIndex].reclaimed = true; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 669382c15..5fd158c26 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -27,13 +27,14 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { } /** - * @notice used to launch the Module with the help of factory - * @return address Contract address of the Module + * @notice Used to launch the Module with the help of factory + * @return Address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "insufficent allowance"); address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return erc20DividendCheckpoint; } @@ -47,41 +48,6 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index f70935993..4def51468 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -8,8 +8,17 @@ import "../../interfaces/IOwnable.sol"; */ contract EtherDividendCheckpoint is DividendCheckpoint { using SafeMath for uint256; - - event EtherDividendDeposited(address indexed _depositor, uint256 _checkpointId, uint256 _created, uint256 _maturity, uint256 _expiry, uint256 _amount, uint256 _totalSupply, uint256 _dividendIndex, bytes32 indexed _name); + event EtherDividendDeposited( + address indexed _depositor, + uint256 _checkpointId, + uint256 _created, + uint256 _maturity, + uint256 _expiry, + uint256 _amount, + uint256 _totalSupply, + uint256 _dividendIndex, + bytes32 indexed _name + ); event EtherDividendClaimed(address indexed _payee, uint256 _dividendIndex, uint256 _amount, uint256 _withheld); event EtherDividendReclaimed(address indexed _claimer, uint256 _dividendIndex, uint256 _claimedAmount); event EtherDividendClaimFailed(address indexed _payee, uint256 _dividendIndex, uint256 _amount, uint256 _withheld); @@ -29,9 +38,9 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @notice Creates a dividend and checkpoint for the dividend, using global list of excluded addresses * @param _maturity Time from which dividend can be paid * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer - * @param _name name/title for identification + * @param _name Name/title for identification */ - function createDividend(uint256 _maturity, uint256 _expiry, bytes32 _name) payable external withPerm(MANAGE) { + function createDividend(uint256 _maturity, uint256 _expiry, bytes32 _name) external payable withPerm(MANAGE) { createDividendWithExclusions(_maturity, _expiry, excluded, _name); } @@ -40,9 +49,18 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _maturity Time from which dividend can be paid * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer * @param _checkpointId Id of the checkpoint from which to issue dividend - * @param _name name/title for identification + * @param _name Name/title for identification */ - function createDividendWithCheckpoint(uint256 _maturity, uint256 _expiry, uint256 _checkpointId, bytes32 _name) payable external withPerm(MANAGE) { + function createDividendWithCheckpoint( + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + bytes32 _name + ) + external + payable + withPerm(MANAGE) + { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _checkpointId, excluded, _name); } @@ -51,9 +69,18 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _maturity Time from which dividend can be paid * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer * @param _excluded List of addresses to exclude - * @param _name name/title for identification + * @param _name Name/title for identification */ - function createDividendWithExclusions(uint256 _maturity, uint256 _expiry, address[] _excluded, bytes32 _name) payable public withPerm(MANAGE) { + function createDividendWithExclusions( + uint256 _maturity, + uint256 _expiry, + address[] _excluded, + bytes32 _name + ) + public + payable + withPerm(MANAGE) + { uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); _createDividendWithCheckpointAndExclusions(_maturity, _expiry, checkpointId, _excluded, _name); } @@ -64,7 +91,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer * @param _checkpointId Id of the checkpoint from which to issue dividend * @param _excluded List of addresses to exclude - * @param _name name/title for identification + * @param _name Name/title for identification */ function createDividendWithCheckpointAndExclusions( uint256 _maturity, @@ -72,10 +99,10 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _checkpointId, address[] _excluded, bytes32 _name - ) - payable - public - withPerm(MANAGE) + ) + public + payable + withPerm(MANAGE) { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _checkpointId, _excluded, _name); } @@ -86,7 +113,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer * @param _checkpointId Id of the checkpoint from which to issue dividend * @param _excluded List of addresses to exclude - * @param _name name/title for identification + * @param _name Name/title for identification */ function _createDividendWithCheckpointAndExclusions( uint256 _maturity, @@ -99,6 +126,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { { require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); require(_expiry > _maturity, "Expiry is before maturity"); + /*solium-disable-next-line security/no-block-members*/ require(_expiry > now, "Expiry is in the past"); require(msg.value > 0, "No dividend sent"); require(_checkpointId <= ISecurityToken(securityToken).currentCheckpointId()); @@ -109,7 +137,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { dividends.push( Dividend( _checkpointId, - now, + now, /*solium-disable-line security/no-block-members*/ _maturity, _expiry, msg.value, @@ -129,6 +157,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { dividends[dividendIndex].dividendExcluded[_excluded[j]] = true; } dividends[dividendIndex].totalSupply = currentSupply.sub(excludedSupply); + /*solium-disable-next-line security/no-block-members*/ emit EtherDividendDeposited(msg.sender, _checkpointId, now, _maturity, _expiry, msg.value, currentSupply, dividendIndex, _name); } @@ -143,6 +172,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { _dividend.claimed[_payee] = true; uint256 claimAfterWithheld = claim.sub(withheld); if (claimAfterWithheld > 0) { + /*solium-disable-next-line security/no-send*/ if (_payee.send(claimAfterWithheld)) { _dividend.claimedAmount = _dividend.claimedAmount.add(claim); _dividend.dividendWithheld = _dividend.dividendWithheld.add(withheld); @@ -161,8 +191,9 @@ contract EtherDividendCheckpoint is DividendCheckpoint { */ function reclaimDividend(uint256 _dividendIndex) external withPerm(MANAGE) { require(_dividendIndex < dividends.length, "Incorrect dividend index"); + /*solium-disable-next-line security/no-block-members*/ require(now >= dividends[_dividendIndex].expiry, "Dividend expiry is in the future"); - require(!dividends[_dividendIndex].reclaimed, "Dividend already claimed"); + require(!dividends[_dividendIndex].reclaimed, "Dividend is already claimed"); Dividend storage dividend = dividends[_dividendIndex]; dividend.reclaimed = true; uint256 remainingAmount = dividend.amount.sub(dividend.claimedAmount); diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index cebc79571..315760be1 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -27,13 +27,14 @@ contract EtherDividendCheckpointFactory is ModuleFactory { } /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent allowance or balance"); address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return ethDividendCheckpoint; } @@ -47,46 +48,11 @@ contract EtherDividendCheckpointFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ function getInstructions() external view returns(string) { - return "Create a dividend which will be paid out to token holders proportional to their balances at the point the dividend is created"; + return "Create a dividend which will be paid out to token holders proportionally according to their balances at the point the dividend is created"; } /** diff --git a/contracts/modules/Checkpoint/ICheckpoint.sol b/contracts/modules/Checkpoint/ICheckpoint.sol index 3e567ba7b..f2a7417b2 100644 --- a/contracts/modules/Checkpoint/ICheckpoint.sol +++ b/contracts/modules/Checkpoint/ICheckpoint.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.24; /** * @title Interface to be implemented by all checkpoint modules */ +/*solium-disable-next-line no-empty-blocks*/ interface ICheckpoint { } diff --git a/contracts/modules/Burn/TrackedRedemption.sol b/contracts/modules/Experimental/Burn/TrackedRedemption.sol similarity index 81% rename from contracts/modules/Burn/TrackedRedemption.sol rename to contracts/modules/Experimental/Burn/TrackedRedemption.sol index 60745f778..bc06a99e9 100644 --- a/contracts/modules/Burn/TrackedRedemption.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemption.sol @@ -1,8 +1,8 @@ pragma solidity ^0.4.24; -import "./IBurn.sol"; -import "../Module.sol"; -import "../../interfaces/ISecurityToken.sol"; +import "../../Burn/IBurn.sol"; +import "../../Module.sol"; +import "../../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** @@ -33,17 +33,18 @@ contract TrackedRedemption is IBurn, Module { } /** - * @notice Redeem tokens and track redemptions + * @notice To redeem tokens and track redemptions * @param _value The number of tokens to redeem */ function redeemTokens(uint256 _value) public { ISecurityToken(securityToken).burnFromWithData(msg.sender, _value, ""); redeemedTokens[msg.sender] = redeemedTokens[msg.sender].add(_value); + /*solium-disable-next-line security/no-block-members*/ emit Redeemed(msg.sender, _value, now); } - + /** - * @notice Return the permissions flag that are associated with CountTransferManager + * @notice Returns the permissions flag that are associated with CountTransferManager */ function getPermissions() public view returns(bytes32[]) { bytes32[] memory allPermissions = new bytes32[](0); diff --git a/contracts/modules/Burn/TrackedRedemptionFactory.sol b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol similarity index 68% rename from contracts/modules/Burn/TrackedRedemptionFactory.sol rename to contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol index 6b0761865..d1fa010b7 100644 --- a/contracts/modules/Burn/TrackedRedemptionFactory.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "./TrackedRedemption.sol"; -import "../ModuleFactory.sol"; +import "../../ModuleFactory.sol"; /** * @title Factory for deploying GeneralTransferManager module @@ -27,13 +27,14 @@ contract TrackedRedemptionFactory is ModuleFactory { } /** - * @notice used to launch the Module with the help of factory - * @return address Contract address of the Module + * @notice Used to launch the Module with the help of factory + * @return Address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent allowance or balance"); address trackedRedemption = new TrackedRedemption(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(trackedRedemption), getName(), address(this), msg.sender, setupCost, now); return address(trackedRedemption); } @@ -47,41 +48,6 @@ contract TrackedRedemptionFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol new file mode 100644 index 000000000..097a44f50 --- /dev/null +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol @@ -0,0 +1,155 @@ +pragma solidity ^0.4.24; + +import "./../../Checkpoint/ICheckpoint.sol"; +import "../../TransferManager/ITransferManager.sol"; +import "../../../interfaces/ISecurityToken.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/** + * @title Burn module for burning tokens and keeping track of burnt amounts + */ +contract ScheduledCheckpoint is ICheckpoint, ITransferManager { + using SafeMath for uint256; + + struct Schedule { + bytes32 name; + uint256 startTime; + uint256 nextTime; + uint256 interval; + uint256 index; + uint256[] checkpointIds; + uint256[] timestamps; + uint256[] periods; + } + + bytes32[] public names; + + mapping (bytes32 => Schedule) public schedules; + + event AddSchedule(bytes32 _name, uint256 _startTime, uint256 _interval, uint256 _timestamp); + event RemoveSchedule(bytes32 _name, uint256 _timestamp); + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) public + Module(_securityToken, _polyAddress) + { + } + + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(0); + } + + /** + * @notice adds a new schedule for checkpoints + * @param _name name of the new schedule (must be unused) + * @param _startTime start time of the schedule (first checkpoint) + * @param _interval interval at which checkpoints should be created + */ + function addSchedule(bytes32 _name, uint256 _startTime, uint256 _interval) external onlyOwner { + require(_startTime > now, "Start time must be in the future"); + require(schedules[_name].name == bytes32(0), "Name already in use"); + schedules[_name].name = _name; + schedules[_name].startTime = _startTime; + schedules[_name].nextTime = _startTime; + schedules[_name].interval = _interval; + schedules[_name].index = names.length; + names.push(_name); + emit AddSchedule(_name, _startTime, _interval, now); + } + + /** + * @notice removes a schedule for checkpoints + * @param _name name of the schedule to be removed + */ + function removeSchedule(bytes32 _name) external onlyOwner { + require(schedules[_name].name == _name, "Name does not exist"); + uint256 index = schedules[_name].index; + names[index] = names[names.length - 1]; + names.length--; + if (index != names.length) { + schedules[names[index]].index = index; + } + delete schedules[_name]; + emit RemoveSchedule(_name, now); + } + + + /** + * @notice Used to create checkpoints that correctly reflect balances + * @param _isTransfer whether or not an actual transfer is occuring + * @return always returns Result.NA + */ + function verifyTransfer(address /* _from */, address /* _to */, uint256 /* _amount */, bytes /* _data */, bool _isTransfer) public returns(Result) { + require(_isTransfer == false || msg.sender == securityToken, "Sender is not owner"); + if (paused || !_isTransfer) { + return Result.NA; + } + _updateAll(); + return Result.NA; + } + + /** + * @notice gets schedule details + * @param _name name of the schedule + */ + function getSchedule(bytes32 _name) view external returns(bytes32, uint256, uint256, uint256, uint256[], uint256[], uint256[]) { + return ( + schedules[_name].name, + schedules[_name].startTime, + schedules[_name].nextTime, + schedules[_name].interval, + schedules[_name].checkpointIds, + schedules[_name].timestamps, + schedules[_name].periods + ); + } + + /** + * @notice manually triggers update outside of transfer request for named schedule (can be used to reduce user gas costs) + * @param _name name of the schedule + */ + function update(bytes32 _name) external onlyOwner { + _update(_name); + } + + function _update(bytes32 _name) internal { + Schedule storage schedule = schedules[_name]; + if (schedule.nextTime <= now) { + uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); + uint256 periods = now.sub(schedule.nextTime).div(schedule.interval).add(1); + schedule.timestamps.push(schedule.nextTime); + schedule.nextTime = periods.mul(schedule.interval).add(schedule.nextTime); + schedule.checkpointIds.push(checkpointId); + schedule.periods.push(periods); + } + } + + /** + * @notice manually triggers update outside of transfer request for all schedules (can be used to reduce user gas costs) + */ + function updateAll() onlyOwner external { + _updateAll(); + } + + function _updateAll() internal { + uint256 i; + for (i = 0; i < names.length; i++) { + _update(names[i]); + } + } + + /** + * @notice Return the permissions flag that are associated with CountTransferManager + */ + function getPermissions() view external returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](0); + return allPermissions; + } +} diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol new file mode 100644 index 000000000..1b5daac29 --- /dev/null +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol @@ -0,0 +1,102 @@ +pragma solidity ^0.4.24; + +import "./ScheduledCheckpoint.sol"; +import "../../ModuleFactory.sol"; + +/** + * @title Factory for deploying EtherDividendCheckpoint module + */ +contract ScheduledCheckpointFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _subscriptionCost Subscription cost of the module + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "ScheduledCheckpoint"; + title = "Schedule Checkpoints"; + description = "Allows you to schedule checkpoints in the future"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + } + + /** + * @notice used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes /* _data */) external returns(address) { + if(setupCost > 0) + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + address scheduledCheckpoint = new ScheduledCheckpoint(msg.sender, address(polyToken)); + emit GenerateModuleFromFactory(scheduledCheckpoint, getName(), address(this), msg.sender, setupCost, now); + return scheduledCheckpoint; + } + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](2); + res[0] = 4; + res[1] = 2; + return res; + } + + /** + * @notice Get the name of the Module + */ + function getName() public view returns(bytes32) { + return name; + } + + /** + * @notice Get the description of the Module + */ + function getDescription() external view returns(string) { + return description; + } + + /** + * @notice Get the title of the Module + */ + function getTitle() external view returns(string) { + return title; + } + + /** + * @notice Get the version of the Module + */ + function getVersion() external view returns(string) { + return version; + } + + /** + * @notice Get the setup cost of the module + */ + function getSetupCost() external view returns (uint256) { + return setupCost; + } + + /** + * @notice Get the Instructions that helped to used the module + */ + function getInstructions() external view returns(string) { + return "Schedule a series of future checkpoints by specifying a start time and interval of each checkpoint"; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() external view returns(bytes32[]) { + bytes32[] memory availableTags = new bytes32[](2); + availableTags[0] = "Scheduled"; + availableTags[1] = "Checkpoint"; + return availableTags; + } +} diff --git a/contracts/modules/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol similarity index 96% rename from contracts/modules/TransferManager/LockupVolumeRestrictionTM.sol rename to contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index 4ddb43f29..80f44cdb6 100644 --- a/contracts/modules/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; +import "./../../TransferManager/ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -96,6 +96,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { // if a startTime of 0 is passed in, then start now. if (startTime == 0) { + /*solium-disable-next-line security/no-block-members*/ startTime = now; } @@ -127,9 +128,9 @@ contract LockupVolumeRestrictionTM is ITransferManager { uint[] _totalAmounts ) external withPerm(ADMIN) { require( - _userAddresses.length == _lockUpPeriodsSeconds.length && - _userAddresses.length == _releaseFrequenciesSeconds.length && - _userAddresses.length == _startTimes.length && + _userAddresses.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _startTimes.length && _userAddresses.length == _totalAmounts.length, "Input array length mismatch" ); @@ -190,6 +191,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { uint256 startTime = _startTime; // if a startTime of 0 is passed in, then start now. if (startTime == 0) { + /*solium-disable-next-line security/no-block-members*/ startTime = now; } @@ -272,12 +274,15 @@ contract LockupVolumeRestrictionTM is ITransferManager { uint allowedAmountForThisLockup = 0; // check if lockup has entirely passed + /*solium-disable-next-line security/no-block-members*/ if (now >= aLockUp.startTime.add(aLockUp.lockUpPeriodSeconds)) { // lockup has passed, or not started yet. allow all. allowedAmountForThisLockup = aLockUp.totalAmount.sub(aLockUp.alreadyWithdrawn); + /*solium-disable-next-line security/no-block-members*/ } else if (now >= aLockUp.startTime) { // lockup is active. calculate how many to allow to be withdrawn right now // calculate how many periods have elapsed already + /*solium-disable-next-line security/no-block-members*/ uint elapsedPeriods = (now.sub(aLockUp.startTime)).div(aLockUp.releaseFrequencySeconds); // calculate the total number of periods, overall uint totalPeriods = aLockUp.lockUpPeriodSeconds.div(aLockUp.releaseFrequencySeconds); @@ -396,7 +401,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { } /** - * @notice Return the permissions flag that are associated with Percentage transfer Manager + * @notice Returns the permissions flag that are associated with Percentage transfer Manager */ function getPermissions() public view returns(bytes32[]) { bytes32[] memory allPermissions = new bytes32[](1); diff --git a/contracts/modules/TransferManager/LockupVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol similarity index 75% rename from contracts/modules/TransferManager/LockupVolumeRestrictionTMFactory.sol rename to contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol index 9d0e0fa26..5be77b6e0 100644 --- a/contracts/modules/TransferManager/LockupVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; +import "./../../ModuleFactory.sol"; import "./LockupVolumeRestrictionTM.sol"; -import "../ModuleFactory.sol"; /** * @title Factory for deploying ManualApprovalTransferManager module @@ -27,13 +27,14 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { } /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); LockupVolumeRestrictionTM lockupVolumeRestrictionTransferManager = new LockupVolumeRestrictionTM(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(lockupVolumeRestrictionTransferManager), getName(), address(this), msg.sender, now); return address(lockupVolumeRestrictionTransferManager); } @@ -47,42 +48,7 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { res[0] = 2; return res; } - - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - + /** * @notice Returns the instructions associated with the module */ diff --git a/contracts/modules/TransferManager/SingleTradeVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol similarity index 90% rename from contracts/modules/TransferManager/SingleTradeVolumeRestrictionTM.sol rename to contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol index f9d260fac..b92272167 100644 --- a/contracts/modules/TransferManager/SingleTradeVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol @@ -1,5 +1,6 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; + +import "./../../TransferManager/ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** @@ -56,7 +57,16 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { * @param _from Address of the sender * @param _amount The amount of tokens to transfer */ - function verifyTransfer(address _from, address /* _to */, uint256 _amount, bytes /* _data */, bool /* _isTransfer */) public returns(Result) { + function verifyTransfer( + address _from, + address /* _to */, + uint256 _amount, + bytes /* _data */, + bool /* _isTransfer */ + ) + public + returns(Result) + { bool validTransfer; if (exemptWallets[_from] || paused) return Result.NA; @@ -102,12 +112,13 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice sets whether or not to consider primary issuance transfers + * @notice Sets whether or not to consider primary issuance transfers * @param _allowPrimaryIssuance whether to allow all primary issuance transfers */ function setAllowPrimaryIssuance(bool _allowPrimaryIssuance) public withPerm(ADMIN) { require(_allowPrimaryIssuance != allowPrimaryIssuance, "Must change setting"); allowPrimaryIssuance = _allowPrimaryIssuance; + /*solium-disable-next-line security/no-block-members*/ emit SetAllowPrimaryIssuance(_allowPrimaryIssuance, now); } @@ -135,7 +146,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { emit TransferLimitChangedToTokens(); } /** - * @notice Change the global transfer limit + * @notice Changes the global transfer limit * @param _newGlobalTransferLimitInTokens new transfer limit in tokens * @dev This function can be used only when The manager is configured to use limits in tokens */ @@ -148,7 +159,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice Change the global transfer limit + * @notice Changes the global transfer limit * @param _newGlobalTransferLimitInPercentage new transfer limit in percentage. * Multiply the percentage by 10^16. Eg 22% will be 22*10^16 * @dev This function can be used only when The manager is configured to use limits in percentage @@ -162,7 +173,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice add an exempt wallet + * @notice Adds an exempt wallet * @param _wallet exempt wallet address */ function addExemptWallet(address _wallet) public withPerm(ADMIN) { @@ -172,7 +183,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice remove an exempt wallet + * @notice Removes an exempt wallet * @param _wallet exempt wallet address */ function removeExemptWallet(address _wallet) public withPerm(ADMIN) { @@ -182,7 +193,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice adds an array of exempt wallet + * @notice Adds an array of exempt wallet * @param _wallets array of exempt wallet addresses */ function addExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) { @@ -193,7 +204,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice removes an array of exempt wallet + * @notice Removes an array of exempt wallet * @param _wallets array of exempt wallet addresses */ function removeExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) { @@ -204,7 +215,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice set transfer limit per wallet + * @notice Sets transfer limit per wallet * @param _wallet wallet address * @param _transferLimit transfer limit for the wallet in tokens * @dev the manager has to be configured to use limits in tokens @@ -217,7 +228,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice set transfer limit for a wallet + * @notice Sets transfer limit for a wallet * @param _wallet wallet address * @param _transferLimitInPercentage transfer limit for the wallet in percentage. * Multiply the percentage by 10^16. Eg 22% will be 22*10^16 @@ -232,7 +243,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { /** - * @notice removes transfer limit set in percentage for a wallet + * @notice Removes transfer limit set in percentage for a wallet * @param _wallet wallet address */ function removeTransferLimitInPercentage(address _wallet) public withPerm(ADMIN) { @@ -242,7 +253,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice removes transfer limit set in tokens for a wallet + * @notice Removes transfer limit set in tokens for a wallet * @param _wallet wallet address */ function removeTransferLimitInTokens(address _wallet) public withPerm(ADMIN) { @@ -252,21 +263,21 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice sets transfer limits for an array of wallet + * @notice Sets transfer limits for an array of wallet * @param _wallets array of wallet addresses * @param _transferLimits array of transfer limits for each wallet in tokens * @dev The manager has to be configured to use tokens as limit */ function setTransferLimitInTokensMulti(address[] _wallets, uint[] _transferLimits) public withPerm(ADMIN) { require(_wallets.length > 0, "Wallets cannot be empty"); - require(_wallets.length == _transferLimits.length); + require(_wallets.length == _transferLimits.length, "Wallets don't match to transfer limits"); for (uint256 i = 0; i < _wallets.length; i++ ) { setTransferLimitInTokens(_wallets[i], _transferLimits[i]); } } /** - * @notice sets transfer limits for an array of wallet + * @notice Sets transfer limits for an array of wallet * @param _wallets array of wallet addresses * @param _transferLimitsInPercentage array of transfer limits for each wallet in percentages * The percentage has to be multipled by 10 ** 16. Eg: 20% would be 20 * 10 ** 16 @@ -274,14 +285,14 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { */ function setTransferLimitInPercentageMulti(address[] _wallets, uint[] _transferLimitsInPercentage) public withPerm(ADMIN) { require(_wallets.length > 0, "Wallets cannot be empty"); - require(_wallets.length == _transferLimitsInPercentage.length); + require(_wallets.length == _transferLimitsInPercentage.length, "Wallets don't match to percentage limits"); for (uint256 i = 0; i < _wallets.length; i++) { setTransferLimitInPercentage(_wallets[i], _transferLimitsInPercentage[i]); } } /** - * @notice removes transfer limits set in tokens for an array of wallet + * @notice Removes transfer limits set in tokens for an array of wallet * @param _wallets array of wallet addresses */ function removeTransferLimitInTokensMulti(address[] _wallets) public withPerm(ADMIN) { @@ -292,7 +303,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice removes transfer limits set in percentage for an array of wallet + * @notice Removes transfer limits set in percentage for an array of wallet * @param _wallets array of wallet addresses */ function removeTransferLimitInPercentageMulti(address[] _wallets) public withPerm(ADMIN) { @@ -310,11 +321,11 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { } /** - * @notice Return the permissions flag that are associated with SingleTradeVolumeRestrictionManager + * @notice Returns the permissions flag that are associated with SingleTradeVolumeRestrictionManager */ function getPermissions() public view returns(bytes32[]) { bytes32[] memory allPermissions = new bytes32[](1); allPermissions[0] = ADMIN; return allPermissions; } -} \ No newline at end of file +} diff --git a/contracts/modules/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol similarity index 75% rename from contracts/modules/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol rename to contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol index d5795647c..e6d8ed2be 100644 --- a/contracts/modules/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol @@ -1,8 +1,9 @@ pragma solidity ^0.4.24; -import "./../ModuleFactory.sol"; +import "./../../ModuleFactory.sol"; import "./SingleTradeVolumeRestrictionTM.sol"; -import "../../libraries/Util.sol"; +import "../../../libraries/Util.sol"; + /** * @title Factory for deploying SingleTradeVolumeRestrictionManager */ @@ -28,7 +29,7 @@ contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { } /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { @@ -37,7 +38,9 @@ contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { SingleTradeVolumeRestrictionTM singleTradeVolumeRestrictionManager = new SingleTradeVolumeRestrictionTM(msg.sender, address(polyToken)); require(Util.getSig(_data) == singleTradeVolumeRestrictionManager.getInitFunction(), "Provided data is not valid"); + /*solium-disable-next-line security/no-low-level-calls*/ require(address(singleTradeVolumeRestrictionManager).call(_data), "Unsuccessful call"); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(singleTradeVolumeRestrictionManager), getName(), address(this), msg.sender, setupCost, now); return address(singleTradeVolumeRestrictionManager); } @@ -52,53 +55,15 @@ contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - * @return bytes32 - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - * @return string - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - * @return string - */ - function getTitle() external view returns(string) { - return title; - } - /** * @notice Get the Instructions that help to use the module * @return string */ function getInstructions() external view returns(string) { + /*solium-disable-next-line max-len*/ return "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens"; } - /** - * @notice Get the version of the Module - * @return string - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - * return uint256 - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } /** * @notice Get the tags related to the module factory * @return bytes32[] diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index a330bd0ea..aca262621 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -12,9 +12,10 @@ import "../libraries/VersionUtils.sol"; contract ModuleFactory is IModuleFactory, Ownable { IERC20 public polyToken; - uint256 public setupCost; uint256 public usageCost; uint256 public monthlySubscriptionCost; + + uint256 public setupCost; string public description; string public version; bytes32 public name; @@ -30,7 +31,13 @@ contract ModuleFactory is IModuleFactory, Ownable { event ChangeFactorySetupFee(uint256 _oldSetupCost, uint256 _newSetupCost, address _moduleFactory); event ChangeFactoryUsageFee(uint256 _oldUsageCost, uint256 _newUsageCost, address _moduleFactory); event ChangeFactorySubscriptionFee(uint256 _oldSubscriptionCost, uint256 _newMonthlySubscriptionCost, address _moduleFactory); - event GenerateModuleFromFactory(address _module, bytes32 indexed _moduleName, address indexed _moduleFactory, address _creator, uint256 _timestamp); + event GenerateModuleFromFactory( + address _module, + bytes32 indexed _moduleName, + address indexed _moduleFactory, + address _creator, + uint256 _timestamp + ); event ChangeSTVersionBound(string _boundType, uint8 _major, uint8 _minor, uint8 _patch); /** @@ -45,7 +52,7 @@ contract ModuleFactory is IModuleFactory, Ownable { } /** - * @notice used to change the fee of the setup cost + * @notice Used to change the fee of the setup cost * @param _newSetupCost new setup cost */ function changeFactorySetupFee(uint256 _newSetupCost) public onlyOwner { @@ -54,7 +61,7 @@ contract ModuleFactory is IModuleFactory, Ownable { } /** - * @notice used to change the fee of the usage cost + * @notice Used to change the fee of the usage cost * @param _newUsageCost new usage cost */ function changeFactoryUsageFee(uint256 _newUsageCost) public onlyOwner { @@ -63,7 +70,7 @@ contract ModuleFactory is IModuleFactory, Ownable { } /** - * @notice used to change the fee of the subscription cost + * @notice Used to change the fee of the subscription cost * @param _newSubscriptionCost new subscription cost */ function changeFactorySubscriptionFee(uint256 _newSubscriptionCost) public onlyOwner { @@ -73,7 +80,7 @@ contract ModuleFactory is IModuleFactory, Ownable { } /** - * @notice Update the title of the ModuleFactory + * @notice Updates the title of the ModuleFactory * @param _newTitle New Title that will replace the old one. */ function changeTitle(string _newTitle) public onlyOwner { @@ -82,7 +89,7 @@ contract ModuleFactory is IModuleFactory, Ownable { } /** - * @notice Update the description of the ModuleFactory + * @notice Updates the description of the ModuleFactory * @param _newDesc New description that will replace the old one. */ function changeDescription(string _newDesc) public onlyOwner { @@ -91,7 +98,7 @@ contract ModuleFactory is IModuleFactory, Ownable { } /** - * @notice Update the name of the ModuleFactory + * @notice Updates the name of the ModuleFactory * @param _newName New name that will replace the old one. */ function changeName(bytes32 _newName) public onlyOwner { @@ -100,7 +107,7 @@ contract ModuleFactory is IModuleFactory, Ownable { } /** - * @notice Update the version of the ModuleFactory + * @notice Updates the version of the ModuleFactory * @param _newVersion New name that will replace the old one. */ function changeVersion(string _newVersion) public onlyOwner { @@ -114,8 +121,11 @@ contract ModuleFactory is IModuleFactory, Ownable { * @param _newVersion new version array */ function changeSTVersionBounds(string _boundType, uint8[] _newVersion) external onlyOwner { - require(keccak256(abi.encodePacked(_boundType)) == keccak256(abi.encodePacked("lowerBound")) || keccak256(abi.encodePacked(_boundType)) == keccak256(abi.encodePacked("upperBound")), - "Must be a valid bound type"); + require( + keccak256(abi.encodePacked(_boundType)) == keccak256(abi.encodePacked("lowerBound")) || + keccak256(abi.encodePacked(_boundType)) == keccak256(abi.encodePacked("upperBound")), + "Must be a valid bound type" + ); require(_newVersion.length == 3); if (compatibleSTVersionRange[_boundType] != uint24(0)) { uint8[] memory _currentVersion = VersionUtils.unpack(compatibleSTVersionRange[_boundType]); @@ -126,19 +136,33 @@ contract ModuleFactory is IModuleFactory, Ownable { } /** - * @notice use to get the lower bound + * @notice Used to get the lower bound * @return lower bound */ function getLowerSTVersionBounds() external view returns(uint8[]) { - return VersionUtils.unpack(compatibleSTVersionRange["lowerBound"]); + return VersionUtils.unpack(compatibleSTVersionRange["lowerBound"]); } /** - * @notice use to get the upper bound + * @notice Used to get the upper bound * @return upper bound */ function getUpperSTVersionBounds() external view returns(uint8[]) { return VersionUtils.unpack(compatibleSTVersionRange["upperBound"]); } + /** + * @notice Get the setup cost of the module + */ + function getSetupCost() external view returns (uint256) { + return setupCost; + } + + /** + * @notice Get the name of the Module + */ + function getName() public view returns(bytes32) { + return name; + } + } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 0257da6ec..f85abf675 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -21,7 +21,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { /// Event emitted after any permission get changed for the delegate event ChangePermission(address indexed _delegate, address _module, bytes32 _perm, bool _valid, uint256 _timestamp); - /// Use to notify when delegate is added in permission manager contract + /// Used to notify when delegate is added in permission manager contract event AddDelegate(address indexed _delegate, bytes32 _details, uint256 _timestamp); @@ -40,7 +40,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { } /** - * @notice Use to check the permission on delegate corresponds to module contract address + * @notice Used to check the permission on delegate corresponds to module contract address * @param _delegate Ethereum address of the delegate * @param _module Ethereum contract address of the module * @param _perm Permission flag @@ -54,7 +54,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { } /** - * @notice Use to add a delegate + * @notice Used to add a delegate * @param _delegate Ethereum address of the delegate * @param _details Details about the delegate i.e `Belongs to financial firm` */ @@ -64,6 +64,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { require(delegateDetails[_delegate] == bytes32(0), "Already present"); delegateDetails[_delegate] = _details; allDelegates.push(_delegate); + /*solium-disable-next-line security/no-block-members*/ emit AddDelegate(_delegate, _details, now); } @@ -83,12 +84,12 @@ contract GeneralPermissionManager is IPermissionManager, Module { } /** - * @notice use to check if an address is a delegate or not + * @notice Used to check if an address is a delegate or not * @param _potentialDelegate the address of potential delegate * @return bool */ function checkDelegate(address _potentialDelegate) external view returns(bool) { - require(_potentialDelegate != address(0)); + require(_potentialDelegate != address(0), "Invalid address"); if (delegateDetails[_potentialDelegate] != bytes32(0)) { return true; @@ -97,7 +98,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { } /** - * @notice Use to provide/change the permission to the delegate corresponds to the module contract + * @notice Used to provide/change the permission to the delegate corresponds to the module contract * @param _delegate Ethereum address of the delegate * @param _module Ethereum contract address of the module * @param _perm Permission flag @@ -118,7 +119,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { } /** - * @notice Use to change one or more permissions for a single delegate at once + * @notice Used to change one or more permissions for a single delegate at once * @param _delegate Ethereum address of the delegate * @param _modules Multiple module matching the multiperms, needs to be same length * @param _perms Multiple permission flag needs to be changed @@ -144,7 +145,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { } /** - * @notice use to return all delegates with a given permission and module + * @notice Used to return all delegates with a given permission and module * @param _module Ethereum contract address of the module * @param _perm Permission flag * @return address[] @@ -169,7 +170,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { } /** - * @notice use to return all permission of a single or multiple module + * @notice Used to return all permission of a single or multiple module * @dev possible that function get out of gas is there are lot of modules and perm related to them * @param _delegate Ethereum address of the delegate * @param _types uint8[] of types @@ -203,8 +204,8 @@ contract GeneralPermissionManager is IPermissionManager, Module { _allModulePerms = IModule(_currentTypeModules[j]).getPermissions(); for (k = 0; k < _allModulePerms.length; k++) { if (perms[_currentTypeModules[j]][_delegate][_allModulePerms[k]]) { - _allModules[counter]= _currentTypeModules[j]; - _allPerms[counter]=_allModulePerms[k]; + _allModules[counter] = _currentTypeModules[j]; + _allPerms[counter] = _allModulePerms[k]; counter++; } } @@ -215,7 +216,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { } /** - * @notice Use to provide/change the permission to the delegate corresponds to the module contract + * @notice Used to provide/change the permission to the delegate corresponds to the module contract * @param _delegate Ethereum address of the delegate * @param _module Ethereum contract address of the module * @param _perm Permission flag @@ -231,11 +232,12 @@ contract GeneralPermissionManager is IPermissionManager, Module { internal { perms[_module][_delegate][_perm] = _valid; + /*solium-disable-next-line security/no-block-members*/ emit ChangePermission(_delegate, _module, _perm, _valid, now); } /** - * @notice use to get all delegates + * @notice Used to get all delegates * @return address[] */ function getAllDelegates() external view returns(address[]) { diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index 7988cc4d7..bfdc73801 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -24,13 +24,14 @@ contract GeneralPermissionManagerFactory is ModuleFactory { } /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance provided"); address permissionManager = new GeneralPermissionManager(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(permissionManager), getName(), address(this), msg.sender, setupCost, now); return permissionManager; } @@ -44,46 +45,12 @@ contract GeneralPermissionManagerFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ function getInstructions() external view returns(string) { - return "Add and remove permissions for the SecurityToken and associated modules. Permission types should be encoded as bytes32 values, and attached using the withPerm modifier to relevant functions.No initFunction required."; + /*solium-disable-next-line max-len*/ + return "Add and remove permissions for the SecurityToken and associated modules. Permission types should be encoded as bytes32 values and attached using withPerm modifier to relevant functions. No initFunction required."; } /** diff --git a/contracts/modules/PermissionManager/IPermissionManager.sol b/contracts/modules/PermissionManager/IPermissionManager.sol index 00afeb3e7..d9b78944d 100644 --- a/contracts/modules/PermissionManager/IPermissionManager.sol +++ b/contracts/modules/PermissionManager/IPermissionManager.sol @@ -6,7 +6,7 @@ pragma solidity ^0.4.24; interface IPermissionManager { /** - * @notice Use to check the permission on delegate corresponds to module contract address + * @notice Used to check the permission on delegate corresponds to module contract address * @param _delegate Ethereum address of the delegate * @param _module Ethereum contract address of the module * @param _perm Permission flag @@ -15,7 +15,7 @@ interface IPermissionManager { function checkPermission(address _delegate, address _module, bytes32 _perm) external view returns(bool); /** - * @notice Use to add a delegate + * @notice Used to add a delegate * @param _delegate Ethereum address of the delegate * @param _details Details about the delegate i.e `Belongs to financial firm` */ @@ -28,14 +28,14 @@ interface IPermissionManager { function deleteDelegate(address _delegate) external; /** - * @notice use to check if an address is a delegate or not + * @notice Used to check if an address is a delegate or not * @param _potentialDelegate the address of potential delegate * @return bool */ function checkDelegate(address _potentialDelegate) external view returns(bool); /** - * @notice Use to provide/change the permission to the delegate corresponds to the module contract + * @notice Used to provide/change the permission to the delegate corresponds to the module contract * @param _delegate Ethereum address of the delegate * @param _module Ethereum contract address of the module * @param _perm Permission flag @@ -51,7 +51,7 @@ interface IPermissionManager { external; /** - * @notice Use to change one or more permissions for a single delegate at once + * @notice Used to change one or more permissions for a single delegate at once * @param _delegate Ethereum address of the delegate * @param _modules Multiple module matching the multiperms, needs to be same length * @param _perms Multiple permission flag needs to be changed @@ -67,7 +67,7 @@ interface IPermissionManager { external; /** - * @notice use to return all delegates with a given permission and module + * @notice Used to return all delegates with a given permission and module * @param _module Ethereum contract address of the module * @param _perm Permission flag * @return address[] @@ -75,7 +75,7 @@ interface IPermissionManager { function getAllDelegatesWithPerm(address _module, bytes32 _perm) external view returns(address[]); /** - * @notice use to return all permission of a single or multiple module + * @notice Used to return all permission of a single or multiple module * @dev possible that function get out of gas is there are lot of modules and perm related to them * @param _delegate Ethereum address of the delegate * @param _types uint8[] of types @@ -85,13 +85,13 @@ interface IPermissionManager { function getAllModulesAndPermsFromTypes(address _delegate, uint8[] _types) external view returns(address[], bytes32[]); /** - * @notice Use to get the Permission flag related the `this` contract + * @notice Used to get the Permission flag related the `this` contract * @return Array of permission flags */ function getPermissions() external view returns(bytes32[]); /** - * @notice use to get all delegates + * @notice Used to get all delegates * @return address[] */ function getAllDelegates() external view returns(address[]); diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 5bd481280..60373ae37 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -66,6 +66,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { { require(_rate > 0, "Rate of token should be greater than 0"); require(_fundsReceiver != address(0), "Zero address is not permitted"); + /*solium-disable-next-line security/no-block-members*/ require(_startTime >= now && _endTime > _startTime, "Date parameters are not valid"); require(_cap > 0, "Cap should be greater than 0"); require(_fundRaiseTypes.length == 1, "It only selects single fund raise type"); @@ -95,16 +96,16 @@ contract CappedSTO is ISTO, ReentrancyGuard { } /** - * @notice low level token purchase ***DO NOT OVERRIDE*** + * @notice Low level token purchase ***DO NOT OVERRIDE*** * @param _beneficiary Address performing the token purchase */ function buyTokens(address _beneficiary) public payable nonReentrant { if (!allowBeneficialInvestments) { - require(_beneficiary == msg.sender, "Beneficiary must match funding provider"); + require(_beneficiary == msg.sender, "Beneficiary address does not match msg.sender"); } - require(!paused); - require(fundRaiseTypes[uint8(FundRaiseType.ETH)], "ETH should be the mode of investment"); + require(!paused, "Should not be paused"); + require(fundRaiseTypes[uint8(FundRaiseType.ETH)], "Mode of investment is not ETH"); uint256 weiAmount = msg.value; _processTx(_beneficiary, weiAmount); @@ -118,8 +119,8 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @param _investedPOLY Amount of POLY invested */ function buyTokensWithPoly(uint256 _investedPOLY) public nonReentrant{ - require(!paused); - require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "POLY should be the mode of investment"); + require(!paused, "Should not be paused"); + require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "Mode of investment is not POLY"); _processTx(msg.sender, _investedPOLY); _forwardPoly(msg.sender, wallet, _investedPOLY); _postValidatePurchase(msg.sender, _investedPOLY); @@ -150,6 +151,13 @@ contract CappedSTO is ISTO, ReentrancyGuard { /** * @notice Return the STO details + * @return Unixtimestamp at which offering gets start. + * @return Unixtimestamp at which offering ends. + * @return Number of tokens this STO will be allowed to sell to investors. + * @return Amount of funds raised + * @return Number of individual investors this STO have. + * @return Amount of tokens get sold. + * @return Boolean value to justify whether the fund raise type is POLY or not, i.e true for POLY. */ function getSTODetails() public view returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool) { return ( @@ -202,6 +210,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { require(_beneficiary != address(0), "Beneficiary address should not be 0x"); require(_investedAmount != 0, "Amount invested should not be equal to 0"); require(totalTokensSold.add(_getTokenAmount(_investedAmount)) <= cap, "Investment more than cap is not allowed"); + /*solium-disable-next-line security/no-block-members*/ require(now >= startTime && now <= endTime, "Offering is closed/Not yet started"); } @@ -238,7 +247,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { } /** - * @notice Override for extensions that require an internal state to check for validity + * @notice Overrides for extensions that require an internal state to check for validity (current user contributions, etc.) */ function _updatePurchasingState(address /*_beneficiary*/, uint256 /*_investedAmount*/) internal pure { @@ -246,7 +255,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { } /** - * @notice Override to extend the way in which ether is converted to tokens. + * @notice Overrides to extend the way in which ether is converted to tokens. * @param _investedAmount Value in wei to be converted into tokens * @return Number of tokens that can be purchased with the specified _investedAmount */ diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 2c17bb299..89f3311d2 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -25,7 +25,7 @@ contract CappedSTOFactory is ModuleFactory { } /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { @@ -35,7 +35,9 @@ contract CappedSTOFactory is ModuleFactory { CappedSTO cappedSTO = new CappedSTO(msg.sender, address(polyToken)); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == cappedSTO.getInitFunction(), "Invalid data"); + /*solium-disable-next-line security/no-low-level-calls*/ require(address(cappedSTO).call(_data), "Unsuccessfull call"); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(cappedSTO), getName(), address(this), msg.sender, setupCost, now); return address(cappedSTO); } @@ -49,45 +51,11 @@ contract CappedSTOFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ function getInstructions() external view returns(string) { + /*solium-disable-next-line max-len*/ return "Initialises a capped STO. Init parameters are _startTime (time STO starts), _endTime (time STO ends), _cap (cap in tokens for STO), _rate (POLY/ETH to token rate), _fundRaiseType (whether you are raising in POLY or ETH), _polyToken (address of POLY token), _fundsReceiver (address which will receive funds)"; } diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index 8e7640d94..1b44d2e9b 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -56,7 +56,7 @@ contract DummySTO is ISTO { * @param _amount Amount of ETH or Poly invested by the investor */ function generateTokens(address _investor, uint256 _amount) public withPerm(ADMIN) { - require(!paused); + require(!paused, "Should not be paused"); require(_amount > 0, "Amount should be greater than 0"); ISecurityToken(securityToken).mint(_investor, _amount); if (investors[_investor] == 0) { @@ -68,21 +68,21 @@ contract DummySTO is ISTO { } /** - * @notice Return the total no. of investors + * @notice Returns the total no. of investors */ function getNumberInvestors() public view returns (uint256) { return investorCount; } /** - * @notice Return the total no. of investors + * @notice Returns the total no. of investors */ function getTokensSold() public view returns (uint256) { return 0; } /** - * @notice Return the permissions flag that are associated with STO + * @notice Returns the permissions flag that are associated with STO */ function getPermissions() public view returns(bytes32[]) { bytes32[] memory allPermissions = new bytes32[](1); diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index 94aa9516b..04640ac58 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -24,7 +24,7 @@ contract DummySTOFactory is ModuleFactory { compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { @@ -34,7 +34,9 @@ contract DummySTOFactory is ModuleFactory { DummySTO dummySTO = new DummySTO(msg.sender, address(polyToken)); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == dummySTO.getInitFunction(), "Invalid data"); + /*solium-disable-next-line security/no-low-level-calls*/ require(address(dummySTO).call(_data), "Unsuccessfull call"); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(dummySTO), getName(), address(this), msg.sender, setupCost, now); return address(dummySTO); } @@ -48,41 +50,6 @@ contract DummySTOFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ diff --git a/contracts/modules/STO/ISTO.sol b/contracts/modules/STO/ISTO.sol index 7205ca2a8..6ed1d5ba1 100644 --- a/contracts/modules/STO/ISTO.sol +++ b/contracts/modules/STO/ISTO.sol @@ -32,39 +32,40 @@ contract ISTO is Module, Pausable { event SetFundRaiseTypes(FundRaiseType[] _fundRaiseTypes); /** - * @notice Reclaim ERC20Basic compatible tokens + * @notice Reclaims ERC20Basic compatible tokens * @dev We duplicate here due to the overriden owner & onlyOwner * @param _tokenContract The address of the token contract */ function reclaimERC20(address _tokenContract) external onlyOwner { - require(_tokenContract != address(0)); + require(_tokenContract != address(0), "Invalid address"); IERC20 token = IERC20(_tokenContract); uint256 balance = token.balanceOf(address(this)); - require(token.transfer(msg.sender, balance)); + require(token.transfer(msg.sender, balance), "Transfer failed"); } /** - * @notice Return funds raised by the STO + * @notice Returns funds raised by the STO */ function getRaised(FundRaiseType _fundRaiseType) public view returns (uint256) { return fundsRaised[uint8(_fundRaiseType)]; } /** - * @notice Return the total no. of tokens sold + * @notice Returns the total no. of tokens sold */ function getTokensSold() public view returns (uint256); /** - * @notice pause (overridden function) + * @notice Pause (overridden function) */ function pause() public onlyOwner { - require(now < endTime); + /*solium-disable-next-line security/no-block-members*/ + require(now < endTime, "STO has been finalized"); super._pause(); } /** - * @notice unpause (overridden function) + * @notice Unpause (overridden function) */ function unpause() public onlyOwner { super._unpause(); @@ -72,7 +73,7 @@ contract ISTO is Module, Pausable { function _setFundRaiseType(FundRaiseType[] _fundRaiseTypes) internal { // FundRaiseType[] parameter type ensures only valid values for _fundRaiseTypes - require(_fundRaiseTypes.length > 0, "Raise type not specified"); + require(_fundRaiseTypes.length > 0, "Raise type is not specified"); fundRaiseTypes[uint8(FundRaiseType.ETH)] = false; fundRaiseTypes[uint8(FundRaiseType.POLY)] = false; fundRaiseTypes[uint8(FundRaiseType.DAI)] = false; diff --git a/contracts/modules/STO/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index 5e518bea0..7378fb06b 100644 --- a/contracts/modules/STO/PreSaleSTO.sol +++ b/contracts/modules/STO/PreSaleSTO.sol @@ -43,21 +43,21 @@ contract PreSaleSTO is ISTO { } /** - * @notice Return the total no. of investors + * @notice Returns the total no. of investors */ function getNumberInvestors() public view returns (uint256) { return investorCount; } /** - * @notice Return the total no. of tokens sold + * @notice Returns the total no. of tokens sold */ function getTokensSold() public view returns (uint256) { return totalTokensSold; } /** - * @notice Return the permissions flag that are associated with STO + * @notice Returns the permissions flag that are associated with STO */ function getPermissions() public view returns(bytes32[]) { bytes32[] memory allPermissions = new bytes32[](1); @@ -72,9 +72,17 @@ contract PreSaleSTO is ISTO { * @param _etherContributed How much ETH was contributed * @param _polyContributed How much POLY was contributed */ - function allocateTokens(address _investor, uint256 _amount, uint256 _etherContributed, uint256 _polyContributed) public withPerm(PRE_SALE_ADMIN) + function allocateTokens( + address _investor, + uint256 _amount, + uint256 _etherContributed, + uint256 _polyContributed + ) + public + withPerm(PRE_SALE_ADMIN) { - require(now <= endTime, "Current time should less than the endTime"); + /*solium-disable-next-line security/no-block-members*/ + require(now <= endTime, "Already passed Endtime"); require(_amount > 0, "No. of tokens provided should be greater the zero"); ISecurityToken(securityToken).mint(_investor, _amount); if (investors[_investor] == uint256(0)) { @@ -94,11 +102,18 @@ contract PreSaleSTO is ISTO { * @param _etherContributed Array of amount of ETH contributed by each investor * @param _polyContributed Array of amount of POLY contributed by each investor */ - function allocateTokensMulti(address[] _investors, uint256[] _amounts, uint256[] _etherContributed, uint256[] _polyContributed) public withPerm(PRE_SALE_ADMIN) + function allocateTokensMulti( + address[] _investors, + uint256[] _amounts, + uint256[] _etherContributed, + uint256[] _polyContributed + ) + public + withPerm(PRE_SALE_ADMIN) { - require(_investors.length == _amounts.length, "Mis-match in the length of the arrays"); - require(_etherContributed.length == _polyContributed.length, "Mis-match in the length of the arrays"); - require(_etherContributed.length == _investors.length, "Mis-match in the length of the arrays"); + require(_investors.length == _amounts.length, "Mis-match in length of the arrays"); + require(_etherContributed.length == _polyContributed.length, "Mis-match in length of the arrays"); + require(_etherContributed.length == _investors.length, "Mis-match in length of the arrays"); for (uint256 i = 0; i < _investors.length; i++) { allocateTokens(_investors[i], _amounts[i], _etherContributed[i], _polyContributed[i]); } diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index b4faf07a9..035c4bad5 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -25,7 +25,7 @@ contract PreSaleSTOFactory is ModuleFactory { } /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @param _data Data used for the intialization of the module factory variables * @return address Contract address of the Module */ @@ -37,7 +37,9 @@ contract PreSaleSTOFactory is ModuleFactory { PreSaleSTO preSaleSTO = new PreSaleSTO(msg.sender, address(polyToken)); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == preSaleSTO.getInitFunction(), "Invalid data"); + /*solium-disable-next-line security/no-low-level-calls*/ require(address(preSaleSTO).call(_data), "Unsuccessfull call"); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(preSaleSTO), getName(), address(this), msg.sender, setupCost, now); return address(preSaleSTO); } @@ -50,42 +52,7 @@ contract PreSaleSTOFactory is ModuleFactory { res[0] = 3; return res; } - - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - + /** * @notice Returns the instructions associated with the module */ diff --git a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol index 1f241d8cc..d9a48b87d 100644 --- a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol +++ b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol @@ -10,7 +10,7 @@ contract USDTieredSTOProxyFactory is IUSDTieredSTOProxy { } /** - * @notice deploys the STO. + * @notice Deploys the STO. * @param _securityToken Contract address of the securityToken * @param _polyAddress Contract address of the PolyToken. * @param _factoryAddress Contract address of the factory @@ -22,7 +22,7 @@ contract USDTieredSTOProxyFactory is IUSDTieredSTOProxy { } /** - * @notice Use to get the init function signature + * @notice Used to get the init function signature * @param _contractAddress Address of the STO contract * @return bytes4 */ diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index b7db53bfd..894744451 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -91,9 +91,31 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { event SetAllowBeneficialInvestments(bool _allowed); event SetNonAccreditedLimit(address _investor, uint256 _limit); event SetAccredited(address _investor, bool _accredited); - event TokenPurchase(address indexed _purchaser, address indexed _beneficiary, uint256 _tokens, uint256 _usdAmount, uint256 _tierPrice, uint8 _tier); - event FundsReceived(address indexed _purchaser, address indexed _beneficiary, uint256 _usdAmount, FundRaiseType _fundRaiseType, uint256 _receivedValue, uint256 _spentValue, uint256 _rate); - event FundsReceivedPOLY(address indexed _purchaser, address indexed _beneficiary, uint256 _usdAmount, uint256 _receivedValue, uint256 _spentValue, uint256 _rate); + event TokenPurchase( + address indexed _purchaser, + address indexed _beneficiary, + uint256 _tokens, + uint256 _usdAmount, + uint256 _tierPrice, + uint8 _tier + ); + event FundsReceived( + address indexed _purchaser, + address indexed _beneficiary, + uint256 _usdAmount, + FundRaiseType _fundRaiseType, + uint256 _receivedValue, + uint256 _spentValue, + uint256 _rate + ); + event FundsReceivedPOLY( + address indexed _purchaser, + address indexed _beneficiary, + uint256 _usdAmount, + uint256 _receivedValue, + uint256 _spentValue, + uint256 _rate + ); event ReserveTokenMint(address indexed _owner, address indexed _wallet, uint256 _tokens, uint8 _latestTier); event SetAddresses( @@ -122,18 +144,18 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { modifier validETH { require(_getOracle(bytes32("ETH"), bytes32("USD")) != address(0), "Invalid ETHUSD Oracle"); - require(fundRaiseTypes[uint8(FundRaiseType.ETH)]); + require(fundRaiseTypes[uint8(FundRaiseType.ETH)], "Fund raise in ETH should be allowed"); _; } modifier validPOLY { require(_getOracle(bytes32("POLY"), bytes32("USD")) != address(0), "Invalid POLYUSD Oracle"); - require(fundRaiseTypes[uint8(FundRaiseType.POLY)]); + require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "Fund raise in POLY should be allowed"); _; } modifier validDAI { - require(fundRaiseTypes[uint8(FundRaiseType.DAI)]); + require(fundRaiseTypes[uint8(FundRaiseType.DAI)], "Fund raise in DAI should be allowed"); _; } @@ -185,7 +207,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } function modifyFunding(FundRaiseType[] _fundRaiseTypes) public onlyFactoryOrOwner { - require(now < startTime); + /*solium-disable-next-line security/no-block-members*/ + require(now < startTime, "STO shouldn't be started"); _setFundRaiseType(_fundRaiseTypes); uint256 length = getNumberOfTiers(); mintedPerTierTotal = new uint256[](length); @@ -199,7 +222,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD ) public onlyFactoryOrOwner { - require(now < startTime); + /*solium-disable-next-line security/no-block-members*/ + require(now < startTime, "STO shouldn't be started"); minimumInvestmentUSD = _minimumInvestmentUSD; nonAccreditedLimitUSD = _nonAccreditedLimitUSD; emit SetLimits(minimumInvestmentUSD, nonAccreditedLimitUSD); @@ -211,15 +235,16 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256[] _tokensPerTierTotal, uint256[] _tokensPerTierDiscountPoly ) public onlyFactoryOrOwner { - require(now < startTime); - require(_tokensPerTierTotal.length > 0); + /*solium-disable-next-line security/no-block-members*/ + require(now < startTime, "STO shouldn't be started"); + require(_tokensPerTierTotal.length > 0, "Length should be > 0"); require(_ratePerTier.length == _tokensPerTierTotal.length, "Mismatch b/w rates & tokens / tier"); require(_ratePerTierDiscountPoly.length == _tokensPerTierTotal.length, "Mismatch b/w discount rates & tokens / tier"); require(_tokensPerTierDiscountPoly.length == _tokensPerTierTotal.length, "Mismatch b/w discount tokens / tier & tokens / tier"); for (uint8 i = 0; i < _ratePerTier.length; i++) { require(_ratePerTier[i] > 0, "Rate > 0"); require(_tokensPerTierTotal[i] > 0, "Tokens per tier > 0"); - require(_tokensPerTierDiscountPoly[i] <= _tokensPerTierTotal[i], "Discounted tokens / tier <= to tokens / tier"); + require(_tokensPerTierDiscountPoly[i] <= _tokensPerTierTotal[i], "Discounted tokens / tier <= tokens / tier"); require(_ratePerTierDiscountPoly[i] <= _ratePerTier[i], "Discounted rate / tier <= rate / tier"); } ratePerTier = _ratePerTier; @@ -233,7 +258,9 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _startTime, uint256 _endTime ) public onlyFactoryOrOwner { - require((startTime == 0) || (now < startTime)); + /*solium-disable-next-line security/no-block-members*/ + require((startTime == 0) || (now < startTime), "Invalid startTime"); + /*solium-disable-next-line security/no-block-members*/ require((_endTime > _startTime) && (_startTime > now), "Invalid times"); startTime = _startTime; endTime = _endTime; @@ -245,10 +272,11 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { address _reserveWallet, address _usdToken ) public onlyFactoryOrOwner { - require(now < startTime); - require(_wallet != address(0) && _reserveWallet != address(0), "0x address is not allowed"); + /*solium-disable-next-line security/no-block-members*/ + require(now < startTime, "STO shouldn't be started"); + require(_wallet != address(0) && _reserveWallet != address(0), "Invalid address"); if (fundRaiseTypes[uint8(FundRaiseType.DAI)]) { - require(_usdToken != address(0), "0x usdToken address is not allowed"); + require(_usdToken != address(0), "Invalid address"); } wallet = _wallet; reserveWallet = _reserveWallet; @@ -261,11 +289,11 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { //////////////////// /** - * @notice Finalize the STO and mint remaining tokens to reserve address + * @notice Finalizes the STO and mint remaining tokens to reserve address * @notice Reserve address must be whitelisted to successfully finalize */ function finalize() public onlyOwner { - require(!isFinalized); + require(!isFinalized, "STO is already finalized"); isFinalized = true; uint256 tempReturned; uint256 tempSold; @@ -285,12 +313,12 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } /** - * @notice Modify the list of accredited addresses + * @notice Modifies the list of accredited addresses * @param _investors Array of investor addresses to modify * @param _accredited Array of bools specifying accreditation status */ function changeAccredited(address[] _investors, bool[] _accredited) public onlyOwner { - require(_investors.length == _accredited.length); + require(_investors.length == _accredited.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { accredited[_investors[i]] = _accredited[i]; emit SetAccredited(_investors[i], _accredited[i]); @@ -298,15 +326,15 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } /** - * @notice Modify the list of overrides for non-accredited limits in USD + * @notice Modifies the list of overrides for non-accredited limits in USD * @param _investors Array of investor addresses to modify * @param _nonAccreditedLimit Array of uints specifying non-accredited limits */ function changeNonAccreditedLimit(address[] _investors, uint256[] _nonAccreditedLimit) public onlyOwner { //nonAccreditedLimitUSDOverride - require(_investors.length == _nonAccreditedLimit.length); + require(_investors.length == _nonAccreditedLimit.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { - require(_nonAccreditedLimit[i] > 0, "Limit can't be 0"); + require(_nonAccreditedLimit[i] > 0, "Limit can not be 0"); nonAccreditedLimitUSDOverride[_investors[i]] = _nonAccreditedLimit[i]; emit SetNonAccreditedLimit(_investors[i], _nonAccreditedLimit[i]); } @@ -377,7 +405,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { fundsRaised[uint8(_fundRaiseType)] = fundsRaised[uint8(_fundRaiseType)].add(spentValue); // Forward DAI to issuer wallet IERC20 token = _fundRaiseType == FundRaiseType.POLY ? polyToken : usdToken; - require(token.transferFrom(msg.sender, wallet, spentValue)); + require(token.transferFrom(msg.sender, wallet, spentValue), "Transfer failed"); emit FundsReceived(msg.sender, _beneficiary, spentUSD, _fundRaiseType, _tokenAmount, spentValue, rate); } @@ -387,9 +415,19 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @param _investmentValue Amount of POLY, ETH or DAI invested * @param _fundRaiseType Fund raise type (POLY, ETH, DAI) */ - function _buyTokens(address _beneficiary, uint256 _investmentValue, uint256 _rate, FundRaiseType _fundRaiseType) internal nonReentrant whenNotPaused returns(uint256, uint256) { + function _buyTokens( + address _beneficiary, + uint256 _investmentValue, + uint256 _rate, + FundRaiseType _fundRaiseType + ) + internal + nonReentrant + whenNotPaused + returns(uint256, uint256) + { if (!allowBeneficialInvestments) { - require(_beneficiary == msg.sender, "Beneficiary must match funder"); + require(_beneficiary == msg.sender, "Beneficiary does not match funder"); } require(isOpen(), "STO is not open"); @@ -442,7 +480,15 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { return (spentUSD, spentValue); } - function _calculateTier(address _beneficiary, uint8 _tier, uint256 _investedUSD, FundRaiseType _fundRaiseType) internal returns(uint256) { + function _calculateTier( + address _beneficiary, + uint8 _tier, + uint256 _investedUSD, + FundRaiseType _fundRaiseType + ) + internal + returns(uint256) + { // First purchase any discounted tokens if POLY investment uint256 spentUSD; uint256 tierSpentUSD; @@ -471,7 +517,16 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { return spentUSD; } - function _purchaseTier(address _beneficiary, uint256 _tierPrice, uint256 _tierRemaining, uint256 _investedUSD, uint8 _tier) internal returns(uint256, uint256) { + function _purchaseTier( + address _beneficiary, + uint256 _tierPrice, + uint256 _tierRemaining, + uint256 _investedUSD, + uint8 _tier + ) + internal + returns(uint256, uint256) + { uint256 maximumTokens = DecimalMath.div(_investedUSD, _tierPrice); uint256 spentUSD; uint256 purchasedTokens; @@ -502,8 +557,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { function isOpen() public view returns(bool) { if (isFinalized) return false; + /*solium-disable-next-line security/no-block-members*/ if (now < startTime) return false; + /*solium-disable-next-line security/no-block-members*/ if (now >= endTime) return false; if (capReached()) diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 4c4274ff8..adc3ba628 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -23,13 +23,14 @@ contract USDTieredSTOFactory is ModuleFactory { version = "1.0.0"; name = "USDTieredSTO"; title = "USD Tiered STO"; - description = "USD Tiered STO"; + /*solium-disable-next-line max-len*/ + description = "It allows both accredited and non-accredited investors to contribute into the STO. Non-accredited investors will be capped at a maximum investment limit (as a default or specific to their jurisdiction). Tokens will be sold according to tiers sequentially & each tier has its own price and volume of tokens to sell. Upon receipt of funds (ETH, POLY or DAI), security tokens will automatically transfer to investor’s wallet address"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { @@ -40,7 +41,9 @@ contract USDTieredSTOFactory is ModuleFactory { address usdTieredSTO = IUSDTieredSTOProxy(USDTieredSTOProxyAddress).deploySTO(msg.sender, address(polyToken), address(this)); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == IUSDTieredSTOProxy(USDTieredSTOProxyAddress).getInitFunction(usdTieredSTO), "Invalid data"); + /*solium-disable-next-line security/no-low-level-calls*/ require(address(usdTieredSTO).call(_data), "Unsuccessfull call"); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(usdTieredSTO, getName(), address(this), msg.sender, setupCost, now); return address(usdTieredSTO); } @@ -54,41 +57,6 @@ contract USDTieredSTOFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index 7d8edaf58..b54870251 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -28,7 +28,16 @@ contract CountTransferManager is ITransferManager { /** @notice Used to verify the transfer transaction and prevent a transfer if it passes the allowed amount of token holders * @param _to Address of the receiver */ - function verifyTransfer(address /* _from */, address _to, uint256 /* _amount */, bytes /* _data */, bool /* _isTransfer */) public returns(Result) { + function verifyTransfer( + address /* _from */, + address _to, + uint256 /* _amount */, + bytes /* _data */, + bool /* _isTransfer */ + ) + public + returns(Result) + { if (!paused) { if (maxHolderCount < ISecurityToken(securityToken).getInvestorCount()) { // Allow transfers to existing maxHolders @@ -51,7 +60,7 @@ contract CountTransferManager is ITransferManager { } /** - * @notice sets the cap for the amount of token holders there can be + * @notice Sets the cap for the amount of token holders there can be * @param _maxHolderCount is the new maximum amount of token holders */ function changeHolderCount(uint256 _maxHolderCount) public withPerm(ADMIN) { @@ -67,7 +76,7 @@ contract CountTransferManager is ITransferManager { } /** - * @notice Return the permissions flag that are associated with CountTransferManager + * @notice Returns the permissions flag that are associated with CountTransferManager */ function getPermissions() public view returns(bytes32[]) { bytes32[] memory allPermissions = new bytes32[](1); diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index 7469667bb..d9b1328f7 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -25,16 +25,18 @@ contract CountTransferManagerFactory is ModuleFactory { } /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @param _data Data used for the intialization of the module factory variables * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance provided"); CountTransferManager countTransferManager = new CountTransferManager(msg.sender, address(polyToken)); require(Util.getSig(_data) == countTransferManager.getInitFunction(), "Provided data is not valid"); + /*solium-disable-next-line security/no-low-level-calls*/ require(address(countTransferManager).call(_data), "Unsuccessful call"); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(countTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(countTransferManager); @@ -49,41 +51,6 @@ contract CountTransferManagerFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 92bdcdce2..814d54d7b 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -30,6 +30,8 @@ contract GeneralTransferManager is ITransferManager { // An address can only send / receive tokens once their corresponding uint256 > block.number // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) mapping (address => TimeRestriction) public whitelist; + // Map of used nonces by customer + mapping(address => mapping(uint256 => bool)) public nonceMap; //If true, there are no transfer restrictions, for any addresses bool public allowAllTransfers = false; @@ -144,7 +146,7 @@ contract GeneralTransferManager is ITransferManager { } /** - * @notice default implementation of verifyTransfer used by SecurityToken + * @notice Default implementation of verifyTransfer used by SecurityToken * If the transfer request comes from the STO, it only checks that the investor is in the whitelist * If the transfer request comes from a token holder, it checks that: * a) Both are on the whitelist @@ -173,28 +175,39 @@ contract GeneralTransferManager is ITransferManager { return _onWhitelist(_to) ? Result.VALID : Result.NA; } //Anyone on the whitelist can transfer provided the blocknumber is large enough + /*solium-disable-next-line security/no-block-members*/ return ((_onWhitelist(_from) && whitelist[_from].fromTime <= now) && - (_onWhitelist(_to) && whitelist[_to].toTime <= now)) ? Result.VALID : Result.NA; + (_onWhitelist(_to) && whitelist[_to].toTime <= now)) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } /** - * @notice adds or removes addresses from the whitelist. + * @notice Adds or removes addresses from the whitelist. * @param _investor is the address to whitelist * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others * @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC * @param _canBuyFromSTO is used to know whether the investor is restricted investor or not. */ - function modifyWhitelist(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO) public withPerm(WHITELIST) { + function modifyWhitelist( + address _investor, + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, + bool _canBuyFromSTO + ) + public + withPerm(WHITELIST) + { //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); + /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** - * @notice adds or removes addresses from the whitelist. + * @notice Adds or removes addresses from the whitelist. * @param _investors List of the addresses to whitelist * @param _fromTimes An array of the moment when the sale lockup period ends and the investor can freely sell his tokens * @param _toTimes An array of the moment when the purchase lockup period ends and the investor can freely purchase tokens from others @@ -218,7 +231,7 @@ contract GeneralTransferManager is ITransferManager { } /** - * @notice adds or removes addresses from the whitelist - can be called by anyone with a valid signature + * @notice Adds or removes addresses from the whitelist - can be called by anyone with a valid signature * @param _investor is the address to whitelist * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others @@ -226,6 +239,7 @@ contract GeneralTransferManager is ITransferManager { * @param _canBuyFromSTO is used to know whether the investor is restricted investor or not. * @param _validFrom is the time that this signature is valid from * @param _validTo is the time that this signature is valid until + * @param _nonce nonce of signature (avoid replay attack) * @param _v issuer signature * @param _r issuer signature * @param _s issuer signature @@ -238,21 +252,29 @@ contract GeneralTransferManager is ITransferManager { bool _canBuyFromSTO, uint256 _validFrom, uint256 _validTo, + uint256 _nonce, uint8 _v, bytes32 _r, bytes32 _s ) public { + /*solium-disable-next-line security/no-block-members*/ require(_validFrom <= now, "ValidFrom is too early"); + /*solium-disable-next-line security/no-block-members*/ require(_validTo >= now, "ValidTo is too late"); - bytes32 hash = keccak256(abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo)); + require(!nonceMap[_investor][_nonce], "Already used signature"); + nonceMap[_investor][_nonce] = true; + bytes32 hash = keccak256( + abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) + ); _checkSig(hash, _v, _r, _s); //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); + /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** - * @notice used to verify the signature + * @notice Used to verify the signature */ function _checkSig(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal view { //Check that the signature is valid @@ -268,7 +290,7 @@ contract GeneralTransferManager is ITransferManager { */ function _onWhitelist(address _investor) internal view returns(bool) { return (((whitelist[_investor].fromTime != 0) || (whitelist[_investor].toTime != 0)) && - (whitelist[_investor].expiryTime >= now)); + (whitelist[_investor].expiryTime >= now)); /*solium-disable-line security/no-block-members*/ } /** diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 5ef1953b4..c15eb52aa 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -25,13 +25,14 @@ contract GeneralTransferManagerFactory is ModuleFactory { /** - * @notice used to launch the Module with the help of factory + * @notice Used to launch the Module with the help of factory * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); address generalTransferManager = new GeneralTransferManager(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(generalTransferManager); } @@ -46,53 +47,19 @@ contract GeneralTransferManagerFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ function getInstructions() external view returns(string) { - return "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist, and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters."; + /*solium-disable-next-line max-len*/ + return "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters."; } /** * @notice Get the tags related to the module factory */ function getTags() public view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](2); + bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "General"; availableTags[1] = "Transfer Restriction"; return availableTags; diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 1dcc9f4cd..fd888680a 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -35,30 +35,30 @@ contract ManualApprovalTransferManager is ITransferManager { mapping (address => mapping (address => ManualBlocking)) public manualBlockings; event AddManualApproval( - address _from, - address _to, + address indexed _from, + address indexed _to, uint256 _allowance, uint256 _expiryTime, - address _addedBy + address indexed _addedBy ); event AddManualBlocking( - address _from, - address _to, + address indexed _from, + address indexed _to, uint256 _expiryTime, - address _addedBy + address indexed _addedBy ); event RevokeManualApproval( - address _from, - address _to, - address _addedBy + address indexed _from, + address indexed _to, + address indexed _addedBy ); event RevokeManualBlocking( - address _from, - address _to, - address _addedBy + address indexed _from, + address indexed _to, + address indexed _addedBy ); /** @@ -87,12 +87,14 @@ contract ManualApprovalTransferManager is ITransferManager { */ function verifyTransfer(address _from, address _to, uint256 _amount, bytes /* _data */, bool _isTransfer) public returns(Result) { // function must only be called by the associated security token if _isTransfer == true - require(_isTransfer == false || msg.sender == securityToken, "Sender is not owner"); + require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); // manual blocking takes precidence over manual approval if (!paused) { + /*solium-disable-next-line security/no-block-members*/ if (manualBlockings[_from][_to].expiryTime >= now) { return Result.INVALID; } + /*solium-disable-next-line security/no-block-members*/ if ((manualApprovals[_from][_to].expiryTime >= now) && (manualApprovals[_from][_to].allowance >= _amount)) { if (_isTransfer) { manualApprovals[_from][_to].allowance = manualApprovals[_from][_to].allowance.sub(_amount); @@ -104,7 +106,7 @@ contract ManualApprovalTransferManager is ITransferManager { } /** - * @notice adds a pair of addresses to manual approvals + * @notice Adds a pair of addresses to manual approvals * @param _from is the address from which transfers are approved * @param _to is the address to which transfers are approved * @param _allowance is the approved amount of tokens @@ -113,6 +115,7 @@ contract ManualApprovalTransferManager is ITransferManager { function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); + /*solium-disable-next-line security/no-block-members*/ require(_expiryTime > now, "Invalid expiry time"); require(manualApprovals[_from][_to].allowance == 0, "Approval already exists"); manualApprovals[_from][_to] = ManualApproval(_allowance, _expiryTime); @@ -120,7 +123,7 @@ contract ManualApprovalTransferManager is ITransferManager { } /** - * @notice adds a pair of addresses to manual blockings + * @notice Adds a pair of addresses to manual blockings * @param _from is the address from which transfers are blocked * @param _to is the address to which transfers are blocked * @param _expiryTime is the time until which the transfer is blocked @@ -128,6 +131,7 @@ contract ManualApprovalTransferManager is ITransferManager { function addManualBlocking(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); + /*solium-disable-next-line security/no-block-members*/ require(_expiryTime > now, "Invalid expiry time"); require(manualBlockings[_from][_to].expiryTime == 0, "Blocking already exists"); manualBlockings[_from][_to] = ManualBlocking(_expiryTime); @@ -135,7 +139,7 @@ contract ManualApprovalTransferManager is ITransferManager { } /** - * @notice removes a pairs of addresses from manual approvals + * @notice Removes a pairs of addresses from manual approvals * @param _from is the address from which transfers are approved * @param _to is the address to which transfers are approved */ @@ -147,7 +151,7 @@ contract ManualApprovalTransferManager is ITransferManager { } /** - * @notice removes a pairs of addresses from manual approvals + * @notice Removes a pairs of addresses from manual approvals * @param _from is the address from which transfers are approved * @param _to is the address to which transfers are approved */ @@ -159,7 +163,7 @@ contract ManualApprovalTransferManager is ITransferManager { } /** - * @notice Return the permissions flag that are associated with ManualApproval transfer manager + * @notice Returns the permissions flag that are associated with ManualApproval transfer manager */ function getPermissions() public view returns(bytes32[]) { bytes32[] memory allPermissions = new bytes32[](1); diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 4de95959a..f634b33e9 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -34,6 +34,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); address manualTransferManager = new ManualApprovalTransferManager(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(manualTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(manualTransferManager); } @@ -47,45 +48,11 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ function getInstructions() external view returns(string) { + /*solium-disable-next-line max-len*/ return "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters."; } diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index 4238cff14..162b090de 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -92,7 +92,7 @@ contract PercentageTransferManager is ITransferManager { * @notice sets the maximum percentage that an individual token holder can hold * @param _maxHolderPercentage is the new maximum percentage (multiplied by 10**16) */ - function changeHolderPercentage(uint256 _maxHolderPercentage) public onlyOwner { + function changeHolderPercentage(uint256 _maxHolderPercentage) public withPerm(ADMIN) { emit ModifyHolderPercentage(maxHolderPercentage, _maxHolderPercentage); maxHolderPercentage = _maxHolderPercentage; } @@ -104,6 +104,7 @@ contract PercentageTransferManager is ITransferManager { */ function modifyWhitelist(address _investor, bool _valid) public withPerm(WHITELIST) { whitelist[_investor] = _valid; + /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _valid); } @@ -126,6 +127,7 @@ contract PercentageTransferManager is ITransferManager { function setAllowPrimaryIssuance(bool _allowPrimaryIssuance) public withPerm(ADMIN) { require(_allowPrimaryIssuance != allowPrimaryIssuance, "Must change setting"); allowPrimaryIssuance = _allowPrimaryIssuance; + /*solium-disable-next-line security/no-block-members*/ emit SetAllowPrimaryIssuance(_allowPrimaryIssuance, now); } diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 9d6523651..1702b6f08 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -34,7 +34,9 @@ contract PercentageTransferManagerFactory is ModuleFactory { require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); PercentageTransferManager percentageTransferManager = new PercentageTransferManager(msg.sender, address(polyToken)); require(Util.getSig(_data) == percentageTransferManager.getInitFunction(), "Provided data is not valid"); + /*solium-disable-next-line security/no-low-level-calls*/ require(address(percentageTransferManager).call(_data), "Unsuccessful call"); + /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(percentageTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(percentageTransferManager); @@ -50,41 +52,6 @@ contract PercentageTransferManagerFactory is ModuleFactory { return res; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ @@ -96,7 +63,7 @@ contract PercentageTransferManagerFactory is ModuleFactory { * @notice Get the tags related to the module factory */ function getTags() external view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](2); + bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Percentage"; availableTags[1] = "Transfer Restriction"; return availableTags; diff --git a/contracts/oracles/MakerDAOOracle.sol b/contracts/oracles/MakerDAOOracle.sol index 5ed3d02c7..51773cd7d 100644 --- a/contracts/oracles/MakerDAOOracle.sol +++ b/contracts/oracles/MakerDAOOracle.sol @@ -13,6 +13,7 @@ contract MakerDAOOracle is IOracle, Ownable { bool public manualOverride; uint256 public manualPrice; + /*solium-disable-next-line security/no-block-members*/ event ChangeMedianizer(address _newMedianizer, address _oldMedianizer, uint256 _now); event SetManualPrice(uint256 _oldPrice, uint256 _newPrice, uint256 _time); event SetManualOverride(bool _override, uint256 _time); @@ -35,6 +36,7 @@ contract MakerDAOOracle is IOracle, Ownable { */ function changeMedianier(address _medianizer) public onlyOwner { require(_medianizer != address(0), "0x not allowed"); + /*solium-disable-next-line security/no-block-members*/ emit ChangeMedianizer(_medianizer, medianizer, now); medianizer = _medianizer; } @@ -78,6 +80,7 @@ contract MakerDAOOracle is IOracle, Ownable { * @param _price Price to set */ function setManualPrice(uint256 _price) public onlyOwner { + /*solium-disable-next-line security/no-block-members*/ emit SetManualPrice(manualPrice, _price, now); manualPrice = _price; } @@ -88,6 +91,7 @@ contract MakerDAOOracle is IOracle, Ownable { */ function setManualOverride(bool _override) public onlyOwner { manualOverride = _override; + /*solium-disable-next-line security/no-block-members*/ emit SetManualOverride(_override, now); } diff --git a/contracts/oracles/PolyOracle.sol b/contracts/oracles/PolyOracle.sol index 2bcf2b8d1..d46242929 100644 --- a/contracts/oracles/PolyOracle.sol +++ b/contracts/oracles/PolyOracle.sol @@ -8,7 +8,8 @@ import "../interfaces/IOracle.sol"; contract PolyOracle is usingOraclize, IOracle, Ownable { using SafeMath for uint256; - string public oracleURL = '[URL] json(https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?id=2496&convert=USD&CMC_PRO_API_KEY=${[decrypt] BCA0Bqxmn3jkSENepaHxQv09Z/vGdEO9apO+B9RplHyV3qOL/dw5Indlei3hoXrGk9G14My8MFpHJycB7UoVnl+4mlzEsjTlS2UBAYVrl0fAepfiSyM30/GMZAoJmDagY+0YyNZvpkgXn86Q/59Bi48PWEet}).data."2496".quote.USD.price'; + /*solium-disable-next-line max-len*/ + string public oracleURL = "[URL] json(https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?id=2496&convert=USD&CMC_PRO_API_KEY=${[decrypt] BCA0Bqxmn3jkSENepaHxQv09Z/vGdEO9apO+B9RplHyV3qOL/dw5Indlei3hoXrGk9G14My8MFpHJycB7UoVnl+4mlzEsjTlS2UBAYVrl0fAepfiSyM30/GMZAoJmDagY+0YyNZvpkgXn86Q/59Bi48PWEet}).data.\"2496\".quote.USD.price"; string public oracleQueryType = "nested"; uint256 public sanityBounds = 20*10**16; uint256 public gasLimit = 100000; @@ -59,12 +60,13 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { return; } require(requestIds[_requestId] >= latestUpdate, "Result is stale"); + /*solium-disable-next-line security/no-block-members*/ require(requestIds[_requestId] <= now + oraclizeTimeTolerance, "Result is early"); uint256 newPOLYUSD = parseInt(_result, 18); uint256 bound = POLYUSD.mul(sanityBounds).div(10**18); if (latestUpdate != 0) { - require(newPOLYUSD <= POLYUSD.add(bound), "Result is too large"); - require(newPOLYUSD >= POLYUSD.sub(bound), "Result is too small"); + require(newPOLYUSD <= POLYUSD.add(bound), "Result is too large"); + require(newPOLYUSD >= POLYUSD.sub(bound), "Result is too small"); } latestUpdate = requestIds[_requestId]; emit PriceUpdated(newPOLYUSD, POLYUSD, _requestId, latestUpdate); @@ -75,18 +77,22 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice Allows owner to schedule future Oraclize calls * @param _times UNIX timestamps to schedule Oraclize calls as of. Empty list means trigger an immediate query. */ - function schedulePriceUpdatesFixed(uint256[] _times) payable isAdminOrOwner public { + function schedulePriceUpdatesFixed(uint256[] _times) public payable isAdminOrOwner { bytes32 requestId; uint256 maximumScheduledUpdated; if (_times.length == 0) { require(oraclize_getPrice(oracleQueryType, gasLimit) <= address(this).balance, "Insufficient Funds"); requestId = oraclize_query(oracleQueryType, oracleURL, gasLimit); + /*solium-disable-next-line security/no-block-members*/ requestIds[requestId] = now; + /*solium-disable-next-line security/no-block-members*/ maximumScheduledUpdated = now; + /*solium-disable-next-line security/no-block-members*/ emit NewOraclizeQuery(now, requestId, oracleURL); } else { require(oraclize_getPrice(oracleQueryType, gasLimit) * _times.length <= address(this).balance, "Insufficient Funds"); for (uint256 i = 0; i < _times.length; i++) { + /*solium-disable-next-line security/no-block-members*/ require(_times[i] >= now, "Past scheduling is not allowed and scheduled time should be absolute timestamp"); requestId = oraclize_query(_times[i], oracleQueryType, oracleURL, gasLimit); requestIds[requestId] = _times[i]; @@ -107,10 +113,11 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @param _interval how long (in seconds) between each subsequent Oraclize query * @param _iters the number of Oraclize queries to schedule. */ - function schedulePriceUpdatesRolling(uint256 _startTime, uint256 _interval, uint256 _iters) payable isAdminOrOwner public { + function schedulePriceUpdatesRolling(uint256 _startTime, uint256 _interval, uint256 _iters) public payable isAdminOrOwner { bytes32 requestId; require(_interval > 0, "Interval between scheduled time should be greater than zero"); require(_iters > 0, "No iterations specified"); + /*solium-disable-next-line security/no-block-members*/ require(_startTime >= now, "Past scheduling is not allowed and scheduled time should be absolute timestamp"); require(oraclize_getPrice(oracleQueryType, gasLimit) * _iters <= address(this).balance, "Insufficient Funds"); for (uint256 i = 0; i < _iters; i++) { @@ -128,9 +135,11 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice Allows owner to manually set POLYUSD price * @param _price POLYUSD price */ - function setPOLYUSD(uint256 _price) onlyOwner public { + function setPOLYUSD(uint256 _price) public onlyOwner { + /*solium-disable-next-line security/no-block-members*/ emit PriceUpdated(_price, POLYUSD, 0, now); POLYUSD = _price; + /*solium-disable-next-line security/no-block-members*/ latestUpdate = now; } @@ -138,7 +147,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice Allows owner to set oracle to ignore all Oraclize pricce updates * @param _frozen true to freeze updates, false to reenable updates */ - function setFreezeOracle(bool _frozen) onlyOwner public { + function setFreezeOracle(bool _frozen) public onlyOwner { freezeOracle = _frozen; } @@ -146,7 +155,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice Allows owner to set URL used in Oraclize queries * @param _oracleURL URL to use */ - function setOracleURL(string _oracleURL) onlyOwner public { + function setOracleURL(string _oracleURL) public onlyOwner { oracleURL = _oracleURL; } @@ -154,7 +163,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice Allows owner to set type used in Oraclize queries * @param _oracleQueryType to use */ - function setOracleQueryType(string _oracleQueryType) onlyOwner public { + function setOracleQueryType(string _oracleQueryType) public onlyOwner { oracleQueryType = _oracleQueryType; } @@ -162,7 +171,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice Allows owner to set new sanity bounds for price updates * @param _sanityBounds sanity bounds as a percentage * 10**16 */ - function setSanityBounds(uint256 _sanityBounds) onlyOwner public { + function setSanityBounds(uint256 _sanityBounds) public onlyOwner { sanityBounds = _sanityBounds; } @@ -171,7 +180,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice NB - this will only impact newly scheduled Oraclize queries, not future queries which have already been scheduled * @param _gasPrice gas price to use for Oraclize callbacks */ - function setGasPrice(uint256 _gasPrice) onlyOwner public { + function setGasPrice(uint256 _gasPrice) public onlyOwner { oraclize_setCustomGasPrice(_gasPrice); } @@ -180,7 +189,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @return latest POLYUSD price * @return timestamp of latest price update */ - function getPriceAndTime() view public returns(uint256, uint256) { + function getPriceAndTime() public view returns(uint256, uint256) { return (POLYUSD, latestUpdate); } @@ -189,7 +198,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice NB - this will only impact newly scheduled Oraclize queries, not future queries which have already been scheduled * @param _gasLimit gas limit to use for Oraclize callbacks */ - function setGasLimit(uint256 _gasLimit) isAdminOrOwner public { + function setGasLimit(uint256 _gasLimit) public isAdminOrOwner { gasLimit = _gasLimit; } @@ -197,7 +206,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice Allows owner to set time after which price is considered stale * @param _staleTime elapsed time after which price is considered stale */ - function setStaleTime(uint256 _staleTime) onlyOwner public { + function setStaleTime(uint256 _staleTime) public onlyOwner { staleTime = _staleTime; } @@ -206,7 +215,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @param _requestIds Oraclize queryIds (as logged out when Oraclize query is scheduled) * @param _ignore whether or not they should be ignored */ - function setIgnoreRequestIds(bytes32[] _requestIds, bool[] _ignore) onlyOwner public { + function setIgnoreRequestIds(bytes32[] _requestIds, bool[] _ignore) public onlyOwner { require(_requestIds.length == _ignore.length, "Incorrect parameter lengths"); for (uint256 i = 0; i < _requestIds.length; i++) { ignoreRequestIds[_requestIds[i]] = _ignore[i]; @@ -218,8 +227,9 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @param _admin Admin address * @param _valid Whether address should be added or removed from admin list */ - function setAdmin(address _admin, bool _valid) onlyOwner public { + function setAdmin(address _admin, bool _valid) public onlyOwner { admin[_admin] = _valid; + /*solium-disable-next-line security/no-block-members*/ emit AdminSet(_admin, _valid, now); } @@ -227,7 +237,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice Allows owner to set new time tolerance on Oraclize queries * @param _oraclizeTimeTolerance amount of time in seconds that an Oraclize query can be early */ - function setOraclizeTimeTolerance(uint256 _oraclizeTimeTolerance) onlyOwner public { + function setOraclizeTimeTolerance(uint256 _oraclizeTimeTolerance) public onlyOwner { oraclizeTimeTolerance = _oraclizeTimeTolerance; } @@ -256,7 +266,8 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @notice Returns price - should throw if not valid */ function getPrice() external view returns(uint256) { - require(latestUpdate >= now - staleTime); + /*solium-disable-next-line security/no-block-members*/ + require(latestUpdate >= now - staleTime, "Invalid price"); return POLYUSD; } diff --git a/contracts/proxy/ModuleRegistryProxy.sol b/contracts/proxy/ModuleRegistryProxy.sol index ae77cd6b2..aea5a70c5 100644 --- a/contracts/proxy/ModuleRegistryProxy.sol +++ b/contracts/proxy/ModuleRegistryProxy.sol @@ -10,6 +10,7 @@ import "./OwnedUpgradeabilityProxy.sol"; * Besides, it allows upgrading the contract's behaviour towards further implementations, and provides basic * authorization control functionalities */ +/*solium-disable-next-line no-empty-blocks*/ contract ModuleRegistryProxy is EternalStorage, OwnedUpgradeabilityProxy { } \ No newline at end of file diff --git a/contracts/proxy/OwnedUpgradeabilityProxy.sol b/contracts/proxy/OwnedUpgradeabilityProxy.sol index 81a634ec8..7ec520630 100644 --- a/contracts/proxy/OwnedUpgradeabilityProxy.sol +++ b/contracts/proxy/OwnedUpgradeabilityProxy.sol @@ -110,8 +110,9 @@ contract OwnedUpgradeabilityProxy is UpgradeabilityProxy { * @param _data represents the msg.data to bet sent in the low level call. This parameter may include the function * signature of the implementation to be called with the needed payload */ - function upgradeToAndCall(string _newVersion, address _newImplementation, bytes _data) payable external ifOwner { + function upgradeToAndCall(string _newVersion, address _newImplementation, bytes _data) external payable ifOwner { _upgradeTo(_newVersion, _newImplementation); + /*solium-disable-next-line security/no-call-value*/ require(address(this).call.value(msg.value)(_data), "Fail in executing the function of implementation contract"); } diff --git a/contracts/proxy/Proxy.sol b/contracts/proxy/Proxy.sol index adcfc8f46..6cfbce44f 100644 --- a/contracts/proxy/Proxy.sol +++ b/contracts/proxy/Proxy.sol @@ -25,6 +25,7 @@ contract Proxy { * This function will return whatever the implementation call returns */ function _delegate(address implementation) internal { + /*solium-disable-next-line security/no-inline-assembly*/ assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the diff --git a/contracts/proxy/SecurityTokenRegistryProxy.sol b/contracts/proxy/SecurityTokenRegistryProxy.sol index 3ffb3c32e..6acc6e38f 100644 --- a/contracts/proxy/SecurityTokenRegistryProxy.sol +++ b/contracts/proxy/SecurityTokenRegistryProxy.sol @@ -10,6 +10,7 @@ import "./OwnedUpgradeabilityProxy.sol"; * Besides, it allows to upgrade the SecurityTokenRegistry's behaviour towards further implementations, and provides basic * authorization control functionalities */ +/*solium-disable-next-line no-empty-blocks*/ contract SecurityTokenRegistryProxy is EternalStorage, OwnedUpgradeabilityProxy { } \ No newline at end of file diff --git a/contracts/proxy/UpgradeabilityProxy.sol b/contracts/proxy/UpgradeabilityProxy.sol index 52bc121a9..0f7806b71 100644 --- a/contracts/proxy/UpgradeabilityProxy.sol +++ b/contracts/proxy/UpgradeabilityProxy.sol @@ -28,10 +28,13 @@ contract UpgradeabilityProxy is Proxy { * @param _newImplementation representing the address of the new implementation to be set */ function _upgradeTo(string _newVersion, address _newImplementation) internal { - require(__implementation != _newImplementation && _newImplementation != address(0), "Old address is not allowed and implementation address should not be 0x"); + require( + __implementation != _newImplementation && _newImplementation != address(0), + "Old address is not allowed and implementation address should not be 0x" + ); require(AddressUtils.isContract(_newImplementation), "Cannot set a proxy implementation to a non-contract address"); require(bytes(_newVersion).length > 0, "Version should not be empty string"); - require(keccak256(abi.encodePacked(__version)) != keccak256(abi.encodePacked(_newVersion))); + require(keccak256(abi.encodePacked(__version)) != keccak256(abi.encodePacked(_newVersion)), "New version equals to current"); __version = _newVersion; __implementation = _newImplementation; emit Upgraded(_newVersion, _newImplementation); diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 2015ab1c7..cfa24baa1 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -38,7 +38,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr SemanticVersion securityTokenVersion; - // off-chain data + // off-chain data string public tokenDetails; uint8 constant PERMISSION_KEY = 1; @@ -58,10 +58,10 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr // Used to permanently halt all minting bool public mintingFrozen; - // Use to permanently halt controller actions + // Used to permanently halt controller actions bool public controllerDisabled; - // address whitelisted by issuer as controller + // Address whitelisted by issuer as controller address public controller; // Records added modules - module list should be order agnostic! @@ -111,20 +111,31 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr event CheckpointCreated(uint256 indexed _checkpointId, uint256 _timestamp); // Emit when is permanently frozen by the issuer event FreezeMinting(uint256 _timestamp); - // Change the STR address in the event of a upgrade - event ChangeSTRAddress(address indexed _oldAddress, address indexed _newAddress); // Events to log minting and burning event Minted(address indexed _to, uint256 _value); event Burnt(address indexed _from, uint256 _value); // Events to log controller actions event SetController(address indexed _oldController, address indexed _newController); - event ForceTransfer(address indexed _controller, address indexed _from, address indexed _to, uint256 _value, bool _verifyTransfer, bytes _data); - event ForceBurn(address indexed _controller, address indexed _from, uint256 _value, bool _verifyTransfer, bytes _data); + event ForceTransfer( + address indexed _controller, + address indexed _from, + address indexed _to, + uint256 _value, + bool _verifyTransfer, + bytes _data + ); + event ForceBurn( + address indexed _controller, + address indexed _from, + uint256 _value, + bool _verifyTransfer, + bytes _data + ); event DisableController(uint256 _timestamp); function _isModule(address _module, uint8 _type) internal view returns (bool) { - require(modulesToData[_module].module == _module, "Address mismatch"); + require(modulesToData[_module].module == _module, "Wrong address"); require(!modulesToData[_module].isArchived, "Module archived"); for (uint256 i = 0; i < modulesToData[_module].moduleTypes.length; i++) { if (modulesToData[_module].moduleTypes[i] == _type) { @@ -151,7 +162,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } modifier checkGranularity(uint256 _value) { - require(_value % granularity == 0, "Incorrect granularity"); + require(_value % granularity == 0, "Invalid granularity"); _; } @@ -222,14 +233,14 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); uint8[] memory moduleTypes = moduleFactory.getTypes(); uint256 moduleCost = moduleFactory.getSetupCost(); - require(moduleCost <= _maxCost, "Cost too high"); + require(moduleCost <= _maxCost, "Invalid cost"); //Approve fee for module - require(ERC20(polyToken).approve(_moduleFactory, moduleCost), "Insufficient funds"); + ERC20(polyToken).approve(_moduleFactory, moduleCost); //Creates instance of module from factory address module = moduleFactory.deploy(_data); require(modulesToData[module].module == address(0), "Module exists"); //Approve ongoing budget - require(ERC20(polyToken).approve(module, _budget), "Insufficient funds"); + ERC20(polyToken).approve(module, _budget); //Add to SecurityToken module map bytes32 moduleName = moduleFactory.getName(); uint256[] memory moduleIndexes = new uint256[](moduleTypes.length); @@ -238,9 +249,12 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr moduleIndexes[i] = modules[moduleTypes[i]].length; modules[moduleTypes[i]].push(module); } - modulesToData[module] = TokenLib.ModuleData(moduleName, module, _moduleFactory, false, moduleTypes, moduleIndexes, names[moduleName].length); + modulesToData[module] = TokenLib.ModuleData( + moduleName, module, _moduleFactory, false, moduleTypes, moduleIndexes, names[moduleName].length + ); names[moduleName].push(module); //Emit log event + /*solium-disable-next-line security/no-block-members*/ emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, now); } @@ -265,8 +279,9 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _module address of module to unarchive */ function removeModule(address _module) external onlyOwner { - require(modulesToData[_module].isArchived, "Module archived"); + require(modulesToData[_module].isArchived, "Not archived"); require(modulesToData[_module].module != address(0), "Module missing"); + /*solium-disable-next-line security/no-block-members*/ emit ModuleRemoved(modulesToData[_module].moduleTypes, _module, now); // Remove from module type list uint8[] memory moduleTypes = modulesToData[_module].moduleTypes; @@ -324,7 +339,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice returns a list of modules that match the provided name + * @notice Returns a list of modules that match the provided name * @param _name name of the module * @return address[] list of modules with this name */ @@ -333,7 +348,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice returns a list of modules that match the provided module type + * @notice Returns a list of modules that match the provided module type * @param _type type of the module * @return address[] list of modules with this type */ @@ -342,7 +357,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token. + * @notice Allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token. * @dev Owner can transfer POLY to the ST which will be used to pay for modules that require a POLY fee. * @param _tokenContract Address of the ERC20Basic compliance token * @param _value amount of POLY to withdraw @@ -354,19 +369,24 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice allows owner to approve more POLY to one of the modules + + * @notice allows owner to increase/decrease POLY approval of one of the modules * @param _module module address - * @param _budget new budget + * @param _change change in allowance + * @param _increase true if budget has to be increased, false if decrease */ - function changeModuleBudget(address _module, uint256 _budget) external onlyOwner { + function changeModuleBudget(address _module, uint256 _change, bool _increase) external onlyOwner { require(modulesToData[_module].module != address(0), "Module missing"); - uint256 _currentAllowance = IERC20(polyToken).allowance(address(this), _module); - if (_budget < _currentAllowance) { - require(IERC20(polyToken).decreaseApproval(_module, _currentAllowance.sub(_budget)), "Insufficient balance"); + uint256 currentAllowance = IERC20(polyToken).allowance(address(this), _module); + uint256 newAllowance; + if (_increase) { + require(IERC20(polyToken).increaseApproval(_module, _change), "IncreaseApproval fail"); + newAllowance = currentAllowance.add(_change); } else { - require(IERC20(polyToken).increaseApproval(_module, _budget.sub(_currentAllowance)), "Insufficient balance"); + require(IERC20(polyToken).decreaseApproval(_module, _change), "Insufficient allowance"); + newAllowance = currentAllowance.sub(_change); } - emit ModuleBudgetChanged(modulesToData[_module].moduleTypes, _module, _currentAllowance, _budget); + emit ModuleBudgetChanged(modulesToData[_module].moduleTypes, _module, currentAllowance, newAllowance); } /** @@ -379,17 +399,17 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice allows owner to change token granularity + * @notice Allows owner to change token granularity * @param _granularity granularity level of the token */ function changeGranularity(uint256 _granularity) external onlyOwner { - require(_granularity != 0, "Incorrect granularity"); + require(_granularity != 0, "Invalid granularity"); emit GranularityChanged(granularity, _granularity); granularity = _granularity; } /** - * @notice keeps track of the number of non-zero token holders + * @notice Keeps track of the number of non-zero token holders * @param _from sender of transfer * @param _to receiver of transfer * @param _value value of transfer @@ -399,30 +419,60 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice removes addresses with zero balances from the investors list - * @param _start Index in investor list at which to start removing zero balances - * @param _iters Max number of iterations of the for loop - * NB - pruning this list will mean you may not be able to iterate over investors on-chain as of a historical checkpoint - */ - function pruneInvestors(uint256 _start, uint256 _iters) external onlyOwner { - for (uint256 i = _start; i < Math.min256(_start.add(_iters), investorData.investors.length); i++) { - if ((i < investorData.investors.length) && (balanceOf(investorData.investors[i]) == 0)) { - TokenLib.pruneInvestors(investorData, i); + * @notice returns an array of investors + * NB - this length may differ from investorCount as it contains all investors that ever held tokens + * @return list of addresses + */ + function getInvestors() external view returns(address[]) { + return investorData.investors; + } + + /** + * @notice returns an array of investors at a given checkpoint + * NB - this length may differ from investorCount as it contains all investors that ever held tokens + * @param _checkpointId Checkpoint id at which investor list is to be populated + * @return list of investors + */ + function getInvestorsAt(uint256 _checkpointId) external view returns(address[]) { + uint256 count = 0; + uint256 i; + for (i = 0; i < investorData.investors.length; i++) { + if (balanceOfAt(investorData.investors[i], _checkpointId) > 0) { + count++; + } + } + address[] memory investors = new address[](count); + count = 0; + for (i = 0; i < investorData.investors.length; i++) { + if (balanceOfAt(investorData.investors[i], _checkpointId) > 0) { + investors[count] = investorData.investors[i]; + count++; } } + return investors; } /** - * @notice returns an array of investors - * NB - this length may differ from investorCount if list has not been pruned of zero balance investors - * @return length + * @notice generates subset of investors + * NB - can be used in batches if investor list is large + * @param _start Position of investor to start iteration from + * @param _end Position of investor to stop iteration at + * @return list of investors */ - function getInvestors() external view returns(address[]) { - return investorData.investors; + function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[]) { + require(_end <= investorData.investors.length, "Invalid end"); + address[] memory investors = new address[](_end.sub(_start)); + uint256 index = 0; + for (uint256 i = _start; i < _end; i++) { + investors[index] = investorData.investors[i]; + index++; + } + return investors; } /** - * @notice returns the investor count + * @notice Returns the investor count + * @return Investor count */ function getInvestorCount() external view returns(uint256) { return investorData.investorCount; @@ -434,15 +484,17 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function freezeTransfers() external onlyOwner { require(!transfersFrozen, "Already frozen"); transfersFrozen = true; + /*solium-disable-next-line security/no-block-members*/ emit FreezeTransfers(true, now); } /** - * @notice unfreeze transfers + * @notice Unfreeze transfers */ function unfreezeTransfers() external onlyOwner { require(transfersFrozen, "Not frozen"); transfersFrozen = false; + /*solium-disable-next-line security/no-block-members*/ emit FreezeTransfers(false, now); } @@ -479,7 +531,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @return bool success */ function transferWithData(address _to, uint256 _value, bytes _data) public returns (bool success) { - require(_updateTransfer(msg.sender, _to, _value, _data), "Transfer not valid"); + require(_updateTransfer(msg.sender, _to, _value, _data), "Transfer invalid"); require(super.transfer(_to, _value)); return true; } @@ -504,7 +556,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @return bool success */ function transferFromWithData(address _from, address _to, uint256 _value, bytes _data) public returns(bool) { - require(_updateTransfer(_from, _to, _value, _data), "Transfer not valid"); + require(_updateTransfer(_from, _to, _value, _data), "Transfer invalid"); require(super.transferFrom(_from, _to, _value)); return true; } @@ -517,20 +569,28 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _data data to indicate validation * @return bool success */ - function _updateTransfer(address _from, address _to, uint256 _value, bytes _data) internal returns(bool) { + function _updateTransfer(address _from, address _to, uint256 _value, bytes _data) internal nonReentrant returns(bool) { + // NB - the ordering in this function implies the following: + // - investor counts are updated before transfer managers are called - i.e. transfer managers will see + //investor counts including the current transfer. + // - checkpoints are updated after the transfer managers are called. This allows TMs to create + //checkpoints as though they have been created before the current transactions, + // - to avoid the situation where a transfer manager transfers tokens, and this function is called recursively, + //the function is marked as nonReentrant. This means that no TM can transfer (or mint / burn) tokens. _adjustInvestorCount(_from, _to, _value); + bool verified = _verifyTransfer(_from, _to, _value, _data, true); _adjustBalanceCheckpoints(_from); _adjustBalanceCheckpoints(_to); - return _verifyTransfer(_from, _to, _value, _data, true); + return verified; } /** - * @notice validate transfer with TransferManager module if it exists + * @notice Validate transfer with TransferManager module if it exists * @dev TransferManager module has a key of 2 - * @dev _isTransfer boolean flag is the deciding factor for whether the + * @dev _isTransfer boolean flag is the deciding factor for whether the * state variables gets modified or not within the different modules. i.e isTransfer = true * leads to change in the modules environment otherwise _verifyTransfer() works as a read-only - * function (no change in the state). + * function (no change in the state). * @param _from sender of transfer * @param _to receiver of transfer * @param _value value of transfer @@ -544,28 +604,23 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr uint256 _value, bytes _data, bool _isTransfer - ) internal checkGranularity(_value) returns (bool) { + ) internal checkGranularity(_value) returns (bool) { if (!transfersFrozen) { - if (modules[TRANSFER_KEY].length == 0) { - return true; - } bool isInvalid = false; bool isValid = false; bool isForceValid = false; bool unarchived = false; address module; - for (uint8 i = 0; i < modules[TRANSFER_KEY].length; i++) { + for (uint256 i = 0; i < modules[TRANSFER_KEY].length; i++) { module = modules[TRANSFER_KEY][i]; if (!modulesToData[module].isArchived) { unarchived = true; ITransferManager.Result valid = ITransferManager(module).verifyTransfer(_from, _to, _value, _data, _isTransfer); if (valid == ITransferManager.Result.INVALID) { isInvalid = true; - } - if (valid == ITransferManager.Result.VALID) { + } else if (valid == ITransferManager.Result.VALID) { isValid = true; - } - if (valid == ITransferManager.Result.FORCE_VALID) { + } else if (valid == ITransferManager.Result.FORCE_VALID) { isForceValid = true; } } @@ -577,7 +632,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice validates a transfer with a TransferManager module if it exists + * @notice Validates a transfer with a TransferManager module if it exists * @dev TransferManager module has a key of 2 * @param _from sender of transfer * @param _to receiver of transfer @@ -595,11 +650,12 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr */ function freezeMinting() external isMintingAllowed() isEnabled("freezeMintingAllowed") onlyOwner { mintingFrozen = true; + /*solium-disable-next-line security/no-block-members*/ emit FreezeMinting(now); } /** - * @notice mints new tokens and assigns them to the target _investor. + * @notice Mints new tokens and assigns them to the target _investor. * @dev Can only be called by the issuer or STO attached to the token * @param _investor Address where the minted tokens will be delivered * @param _value Number of tokens be minted @@ -623,7 +679,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr bytes _data ) public onlyModuleOrOwner(MINT_KEY) isMintingAllowed() returns (bool success) { require(_investor != address(0), "Investor is 0"); - require(_updateTransfer(address(0), _investor, _value, _data), "Transfer not valid"); + require(_updateTransfer(address(0), _investor, _value, _data), "Transfer invalid"); _adjustTotalSupplyCheckpoints(); totalSupply_ = totalSupply_.add(_value); balances[_investor] = balances[_investor].add(_value); @@ -633,13 +689,13 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice mints new tokens and assigns them to the target _investor. + * @notice Mints new tokens and assigns them to the target _investor. * @dev Can only be called by the issuer or STO attached to the token. * @param _investors A list of addresses to whom the minted tokens will be dilivered * @param _values A list of number of tokens get minted and transfer to corresponding address of the investor from _investor[] list * @return success */ - function mintMulti(address[] _investors, uint256[] _values) external onlyModuleOrOwner(MINT_KEY) returns (bool success) { + function mintMulti(address[] _investors, uint256[] _values) external returns (bool success) { require(_investors.length == _values.length, "Incorrect inputs"); for (uint256 i = 0; i < _investors.length; i++) { mint(_investors[i], _values[i]); @@ -681,7 +737,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _data data to indicate validation */ function burnWithData(uint256 _value, bytes _data) public onlyModule(BURN_KEY) { - require(_burn(msg.sender, _value, _data), "Burn not valid"); + require(_burn(msg.sender, _value, _data), "Burn invalid"); } /** @@ -693,7 +749,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function burnFromWithData(address _from, uint256 _value, bytes _data) public onlyModule(BURN_KEY) { require(_value <= allowed[_from][msg.sender], "Value too high"); allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); - require(_burn(_from, _value, _data), "Burn not valid"); + require(_burn(_from, _value, _data), "Burn invalid"); } /** @@ -703,7 +759,9 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function createCheckpoint() external onlyModuleOrOwner(CHECKPOINT_KEY) returns(uint256) { require(currentCheckpointId < 2**256 - 1); currentCheckpointId = currentCheckpointId + 1; + /*solium-disable-next-line security/no-block-members*/ checkpointTimes.push(now); + /*solium-disable-next-line security/no-block-members*/ emit CheckpointCreated(currentCheckpointId, now); return currentCheckpointId; } @@ -741,24 +799,25 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _controller address of the controller */ function setController(address _controller) public onlyOwner { - require(!controllerDisabled,"Controller disabled"); + require(!controllerDisabled); emit SetController(controller, _controller); controller = _controller; } /** - * @notice Use by the issuer to permanently disable controller functionality + * @notice Used by the issuer to permanently disable controller functionality * @dev enabled via feature switch "disableControllerAllowed" */ function disableController() external isEnabled("disableControllerAllowed") onlyOwner { - require(!controllerDisabled,"Controller disabled"); + require(!controllerDisabled); controllerDisabled = true; delete controller; + /*solium-disable-next-line security/no-block-members*/ emit DisableController(now); } /** - * @notice Use by a controller to execute a forced transfer + * @notice Used by a controller to execute a forced transfer * @param _from address from which to take tokens * @param _to address where to send tokens * @param _value amount of tokens to transfer @@ -776,7 +835,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice Use by a controller to execute a forced burn + * @notice Used by a controller to execute a forced burn * @param _from address from which to take tokens * @param _value amount of tokens to transfer * @param _data data to indicate validation diff --git a/docs/permissions_list.md b/docs/permissions_list.md index 4592474ea..b49c95a0e 100644 --- a/docs/permissions_list.md +++ b/docs/permissions_list.md @@ -199,11 +199,10 @@ setAllowPrimaryIssuance() - withPerm(ADMIN) + withPerm(ADMIN) changeHolderPercentage() - onlyOwner() LockupVolumeRestrictionTM diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 0994e249e..694fdf03e 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -59,7 +59,7 @@ module.exports = function (deployer, network, accounts) { } else if (network === 'kovan') { web3 = new Web3(new Web3.providers.HttpProvider('https://kovan.infura.io/g5xfoQ0jFSE9S5LwM1Ei')) PolymathAccount = accounts[0] - PolyToken = '0xb06d72a24df50d4e2cac133b320c5e7de3ef94cb' // PolyToken Kovan Faucet Address + PolyToken = '0xb347b9f5b56b431b2cf4e1d90a5995f7519ca792' // PolyToken Kovan Faucet Address POLYOracle = '0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C' // Poly Oracle Kovan Address ETHOracle = '0xCE5551FC9d43E9D2CC255139169FC889352405C8' // ETH Oracle Kovan Address } else if (network === 'mainnet') { diff --git a/package.json b/package.json index 8c322e8c0..b350b4ac6 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "lint:all": "npm run lint && npm run lint:sol", "lint:all:fix": "npm run lint:fix && npm run lint:sol:fix", "compile": "truffle compile --optimize-runs 200", - "ganache-cli": "node_modules/.bin/ganache-cli -i 15 --gasLimit 90000000", + "ganache-cli": "node_modules/.bin/ganache-cli -i 15 --gasLimit 8000000", "migrate:local": "truffle migrate --network=development --reset --all", "migrate:ropsten": "truffle migrate --network=ropsten --reset --all", "migrate:kovan": "truffle migrate --network=kovan --reset --all", @@ -28,7 +28,9 @@ "flatten-token": "sol-merger './contracts/tokens/*.sol' ./flat/tokens", "flatten-mocks": "sol-merger './contracts/mocks/*.sol' ./flat/mocks", "flatten-oracles": "sol-merger './contracts/oracles/*.sol' ./flat/oracles", + "flatten-proxies": "sol-merger './contracts/proxy/*.sol' ./flat/proxy", "flatten": "sol-merger './contracts/*.sol' ./flat", + "flatten-all": "npm run flatten-modules && npm run flatten-token && npm run flatten-mocks && npm run flatten-oracles && npm run flatten-proxies && npm run flatten", "ethereum-bridge": "node_modules/.bin/ethereum-bridge -H localhost:8545 -a 9 --dev", "st20generator": "node demo/ST20Generator", "pretty": "prettier --write --print-width 140 --tab-width 4 \"**/*.js\"" @@ -93,5 +95,10 @@ "solium": "^1.1.6", "truffle": "^4.1.13", "truffle-wallet-provider": "0.0.5" + }, + "greenkeeper": { + "ignore": [ + "openzeppelin-solidity" + ] } } diff --git a/scripts/tokenInfo.js b/scripts/tokenInfo.js new file mode 100644 index 000000000..e8a59ca1a --- /dev/null +++ b/scripts/tokenInfo.js @@ -0,0 +1,72 @@ +const Web3 = require("web3"); +const fs = require("fs"); +const async = require("async"); +const path = require("path"); +const web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/")); + +const securityTokenRegistryABI = JSON.parse(require('fs').readFileSync('../build/contracts/SecurityTokenRegistry.json').toString()).abi; +const securityTokenABI = JSON.parse(require('fs').readFileSync('../build/contracts/SecurityToken.json').toString()).abi; +const generalTransferManagerABI = JSON.parse(require('fs').readFileSync('../build/contracts/GeneralTransferManager.json').toString()).abi; +const securityTokenRegistryAddress = "0xEf58491224958d978fACF55D2120c55A24516B98"; +const securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); + +async function getTokens() { + let strEvents = await web3.eth.getPastLogs({fromBlock:'0x5C5C18', address:securityTokenRegistry.address, topics: ["0x2510d802a0818e71139a7680a6388bcffcd3fa686e02a0f7319488c5bdb38fcb"]}); + for (let i = 0; i < strEvents.length; i++) { + let tokenAddress = '0x' + strEvents[i].topics[1].slice(26,66) + try { + await getInfo(tokenAddress); + } catch(exception) { + console.log('Failed to load info of', tokenAddress, exception); + } + } +} + +async function getInfo(tokenAddress) { + let token = new web3.eth.Contract(securityTokenABI, tokenAddress); + console.log("Token - " + tokenAddress); + console.log("----------------------"); + console.log("Owner: " + await token.methods.owner().call()); + console.log("Name: " + await token.methods.name().call()); + console.log("Symbol: " + await token.methods.symbol().call()); + console.log("Total Supply: " + await token.methods.totalSupply().call()); + console.log("Frozen: " + await token.methods.freeze().call()); + console.log("Investors: " + await token.methods.investorCount().call()); + console.log("Latest Checkpoint: " + await token.methods.currentCheckpointId().call()); + console.log("Finished Issuer Minting: " + await token.methods.finishedIssuerMinting().call()); + console.log("Finished STO Minting: " + await token.methods.finishedSTOMinting().call()); + let gtmRes = await token.methods.modules(2, 0).call(); + let gtmEvents = await web3.eth.getPastLogs({fromBlock:'0x5C5C18', address:gtmRes.moduleAddress}); + console.log("Count of GeneralTransferManager Events: " + gtmEvents.length); + console.log("Modules Attached (TransferManager):"); + await getModules(2, token); + console.log("Modules Attached (PermissionManager):"); + await getModules(1, token); + console.log("Modules Attached (STO):"); + await getModules(3, token); + console.log("Modules Attached (Checkpoint):"); + await getModules(4, token); + console.log("") + console.log(); + console.log(); +} + +async function getModules(type, token) { + let index = 0; + while (true) { + try { + let res = await token.methods.modules(type, index).call(); + console.log(" Name: " + web3.utils.toAscii(res.name)); + console.log(" Address: " + res.moduleAddress); + } catch (err) { + // console.log(err); + if (index == 0) { + console.log(" None"); + } + return; + } + index = index + 1; + } +} + +getTokens(); diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 58d2335d3..d89fe6eba 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -850,15 +850,15 @@ contract("CappedSTO", accounts => { describe("Test cases for the CappedSTOFactory", async () => { it("should get the exact details of the factory", async () => { - assert.equal((await I_CappedSTOFactory.setupCost.call()).toNumber(), cappedSTOSetupCost); + assert.equal((await I_CappedSTOFactory.getSetupCost.call()).toNumber(), cappedSTOSetupCost); assert.equal((await I_CappedSTOFactory.getTypes.call())[0], 3); assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), "CappedSTO", "Wrong Module added"); assert.equal( - await I_CappedSTOFactory.getDescription.call(), + await I_CappedSTOFactory.description.call(), "Use to collects the funds and once the cap is reached then investment will be no longer entertained", "Wrong Module added" ); - assert.equal(await I_CappedSTOFactory.getTitle.call(), "Capped STO", "Wrong Module added"); + assert.equal(await I_CappedSTOFactory.title.call(), "Capped STO", "Wrong Module added"); assert.equal( await I_CappedSTOFactory.getInstructions.call(), "Initialises a capped STO. Init parameters are _startTime (time STO starts), _endTime (time STO ends), _cap (cap in tokens for STO), _rate (POLY/ETH to token rate), _fundRaiseType (whether you are raising in POLY or ETH), _polyToken (address of POLY token), _fundsReceiver (address which will receive funds)", @@ -866,7 +866,7 @@ contract("CappedSTO", accounts => { ); let tags = await I_CappedSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "Capped"); - assert.equal(await I_CappedSTOFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_CappedSTOFactory.version.call(), "1.0.0"); }); it("Should fail to change the title -- bad owner", async () => { @@ -879,7 +879,7 @@ contract("CappedSTO", accounts => { it("Should successfully change the title", async () => { await I_CappedSTOFactory.changeTitle("STO Capped", { from: token_owner }); - assert.equal(await I_CappedSTOFactory.getTitle.call(), "STO Capped", "Title doesn't get changed"); + assert.equal(await I_CappedSTOFactory.title.call(), "STO Capped", "Title doesn't get changed"); }); it("Should fail to change the description -- bad owner", async () => { @@ -892,7 +892,7 @@ contract("CappedSTO", accounts => { it("Should successfully change the description", async () => { await I_CappedSTOFactory.changeDescription("It is only a STO", { from: token_owner }); - assert.equal(await I_CappedSTOFactory.getDescription.call(), "It is only a STO", "Description doesn't get changed"); + assert.equal(await I_CappedSTOFactory.description.call(), "It is only a STO", "Description doesn't get changed"); }); it("Should fail to change the name -- bad owner", async () => { diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 6db725c74..1a1e7717a 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -350,7 +350,7 @@ contract("CountTransferManager", accounts => { describe("Test cases for the factory", async () => { it("should get the exact details of the factory", async () => { - assert.equal(await I_CountTransferManagerFactory.setupCost.call(), 0); + assert.equal(await I_CountTransferManagerFactory.getSetupCost.call(), 0); assert.equal((await I_CountTransferManagerFactory.getTypes.call())[0], 2); assert.equal( web3.utils.toAscii(await I_CountTransferManagerFactory.getName.call()).replace(/\u0000/g, ""), @@ -358,11 +358,11 @@ contract("CountTransferManager", accounts => { "Wrong Module added" ); assert.equal( - await I_CountTransferManagerFactory.getDescription.call(), + await I_CountTransferManagerFactory.description.call(), "Restrict the number of investors", "Wrong Module added" ); - assert.equal(await I_CountTransferManagerFactory.getTitle.call(), "Count Transfer Manager", "Wrong Module added"); + assert.equal(await I_CountTransferManagerFactory.title.call(), "Count Transfer Manager", "Wrong Module added"); assert.equal( await I_CountTransferManagerFactory.getInstructions.call(), "Allows an issuer to restrict the total number of non-zero token holders", @@ -424,7 +424,7 @@ contract("CountTransferManager", accounts => { it("Should successfully change the version of the fatory", async() => { await I_CountTransferManagerFactory.changeVersion("5.0.0", {from: account_polymath}); - assert.equal(await I_CountTransferManagerFactory.getVersion.call(), "5.0.0"); + assert.equal(await I_CountTransferManagerFactory.version.call(), "5.0.0"); }); }) diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index f2186845d..b832bcee2 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -1103,20 +1103,20 @@ contract("ERC20DividendCheckpoint", accounts => { describe("Test cases for the ERC20DividendCheckpointFactory", async () => { it("should get the exact details of the factory", async () => { - assert.equal((await I_ERC20DividendCheckpointFactory.setupCost.call()).toNumber(), 0); + assert.equal((await I_ERC20DividendCheckpointFactory.getSetupCost.call()).toNumber(), 0); assert.equal((await I_ERC20DividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(await I_ERC20DividendCheckpointFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_ERC20DividendCheckpointFactory.version.call(), "1.0.0"); assert.equal( web3.utils.toAscii(await I_ERC20DividendCheckpointFactory.getName.call()).replace(/\u0000/g, ""), "ERC20DividendCheckpoint", "Wrong Module added" ); assert.equal( - await I_ERC20DividendCheckpointFactory.getDescription.call(), + await I_ERC20DividendCheckpointFactory.description.call(), "Create ERC20 dividends for token holders at a specific checkpoint", "Wrong Module added" ); - assert.equal(await I_ERC20DividendCheckpointFactory.getTitle.call(), "ERC20 Dividend Checkpoint", "Wrong Module added"); + assert.equal(await I_ERC20DividendCheckpointFactory.title.call(), "ERC20 Dividend Checkpoint", "Wrong Module added"); assert.equal( await I_ERC20DividendCheckpointFactory.getInstructions.call(), "Create ERC20 dividend to be paid out to token holders based on their balances at dividend creation time", diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 1e6884e39..b4e5bbf2b 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -952,23 +952,23 @@ contract("EtherDividendCheckpoint", accounts => { describe("Test cases for the EtherDividendCheckpointFactory", async () => { it("should get the exact details of the factory", async () => { - assert.equal((await I_EtherDividendCheckpointFactory.setupCost.call()).toNumber(), 0); + assert.equal((await I_EtherDividendCheckpointFactory.getSetupCost.call()).toNumber(), 0); assert.equal((await I_EtherDividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(await I_EtherDividendCheckpointFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_EtherDividendCheckpointFactory.version.call(), "1.0.0"); assert.equal( web3.utils.toAscii(await I_EtherDividendCheckpointFactory.getName.call()).replace(/\u0000/g, ""), "EtherDividendCheckpoint", "Wrong Module added" ); assert.equal( - await I_EtherDividendCheckpointFactory.getDescription.call(), + await I_EtherDividendCheckpointFactory.description.call(), "Create ETH dividends for token holders at a specific checkpoint", "Wrong Module added" ); - assert.equal(await I_EtherDividendCheckpointFactory.getTitle.call(), "Ether Dividend Checkpoint", "Wrong Module added"); + assert.equal(await I_EtherDividendCheckpointFactory.title.call(), "Ether Dividend Checkpoint", "Wrong Module added"); assert.equal( await I_EtherDividendCheckpointFactory.getInstructions.call(), - "Create a dividend which will be paid out to token holders proportional to their balances at the point the dividend is created", + "Create a dividend which will be paid out to token holders proportionally according to their balances at the point the dividend is created", "Wrong Module added" ); let tags = await I_EtherDividendCheckpointFactory.getTags.call(); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index 29da205b3..d554891ee 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -392,23 +392,23 @@ contract('GeneralPermissionManager', accounts => { describe("General Permission Manager Factory test cases", async () => { it("should get the exact details of the factory", async () => { - assert.equal(await I_GeneralPermissionManagerFactory.setupCost.call(), 0); + assert.equal(await I_GeneralPermissionManagerFactory.getSetupCost.call(), 0); assert.equal((await I_GeneralPermissionManagerFactory.getTypes.call())[0], 1); - assert.equal(await I_GeneralPermissionManagerFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_GeneralPermissionManagerFactory.version.call(), "1.0.0"); assert.equal( web3.utils.toAscii(await I_GeneralPermissionManagerFactory.getName.call()).replace(/\u0000/g, ""), "GeneralPermissionManager", "Wrong Module added" ); assert.equal( - await I_GeneralPermissionManagerFactory.getDescription.call(), + await I_GeneralPermissionManagerFactory.description.call(), "Manage permissions within the Security Token and attached modules", "Wrong Module added" ); - assert.equal(await I_GeneralPermissionManagerFactory.getTitle.call(), "General Permission Manager", "Wrong Module added"); + assert.equal(await I_GeneralPermissionManagerFactory.title.call(), "General Permission Manager", "Wrong Module added"); assert.equal( await I_GeneralPermissionManagerFactory.getInstructions.call(), - "Add and remove permissions for the SecurityToken and associated modules. Permission types should be encoded as bytes32 values, and attached using the withPerm modifier to relevant functions.No initFunction required.", + "Add and remove permissions for the SecurityToken and associated modules. Permission types should be encoded as bytes32 values and attached using withPerm modifier to relevant functions. No initFunction required.", "Wrong Module added" ); }); @@ -419,7 +419,7 @@ contract('GeneralPermissionManager', accounts => { }); it("Should ge the version of the factory", async() => { - let version = await I_GeneralPermissionManagerFactory.getVersion.call(); + let version = await I_GeneralPermissionManagerFactory.version.call(); assert.equal(version, "1.0.0"); }) }); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index c40809d8b..3e060c288 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -352,6 +352,7 @@ contract("GeneralTransferManager", accounts => { //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk let validFrom = latestTime(); let validTo = latestTime() + duration.days(5); + let nonce = 5; const sig = signData( account_investor2, account_investor2, @@ -361,6 +362,7 @@ contract("GeneralTransferManager", accounts => { true, validFrom, validTo, + nonce, token_owner_pk ); @@ -377,6 +379,7 @@ contract("GeneralTransferManager", accounts => { true, validFrom, validTo, + nonce, v, r, s, @@ -393,6 +396,7 @@ contract("GeneralTransferManager", accounts => { //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk let validFrom = latestTime() - 100; let validTo = latestTime() - 1; + let nonce = 5; const sig = signData( I_GeneralTransferManager.address, account_investor2, @@ -402,6 +406,7 @@ contract("GeneralTransferManager", accounts => { true, validFrom, validTo, + nonce, token_owner_pk ); @@ -418,6 +423,7 @@ contract("GeneralTransferManager", accounts => { true, validFrom, validTo, + nonce, v, r, s, @@ -434,7 +440,7 @@ contract("GeneralTransferManager", accounts => { //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk let validFrom = latestTime(); let validTo = latestTime() + 60 * 60; - + let nonce = 5; const sig = signData( account_investor2, account_investor2, @@ -444,6 +450,7 @@ contract("GeneralTransferManager", accounts => { true, validFrom, validTo, + nonce, "2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200" ); @@ -460,6 +467,7 @@ contract("GeneralTransferManager", accounts => { true, validFrom, validTo, + nonce, v, r, s, @@ -476,6 +484,7 @@ contract("GeneralTransferManager", accounts => { //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk let validFrom = latestTime(); let validTo = latestTime() + duration.days(5); + let nonce = 5; const sig = signData( I_GeneralTransferManager.address, account_investor2, @@ -485,12 +494,14 @@ contract("GeneralTransferManager", accounts => { true, validFrom, validTo, + nonce, token_owner_pk ); const r = `0x${sig.r.toString("hex")}`; const s = `0x${sig.s.toString("hex")}`; const v = sig.v; + let tx = await I_GeneralTransferManager.modifyWhitelistSigned( account_investor2, latestTime(), @@ -499,6 +510,7 @@ contract("GeneralTransferManager", accounts => { true, validFrom, validTo, + nonce, v, r, s, @@ -523,6 +535,49 @@ contract("GeneralTransferManager", accounts => { assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("1", "ether")); }); + it("Should fail if the txn is generated with same nonce", async() => { + // Add the Investor in to the whitelist + //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + let validFrom = latestTime(); + let validTo = latestTime() + duration.days(5); + let nonce = 5; + const sig = signData( + I_GeneralTransferManager.address, + account_investor2, + latestTime(), + latestTime() + duration.days(80), + expiryTime + duration.days(200), + true, + validFrom, + validTo, + nonce, + token_owner_pk + ); + + const r = `0x${sig.r.toString("hex")}`; + const s = `0x${sig.s.toString("hex")}`; + const v = sig.v; + + await catchRevert(I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + latestTime(), + latestTime() + duration.days(80), + expiryTime + duration.days(200), + true, + validFrom, + validTo, + nonce, + v, + r, + s, + { + from: account_investor2, + gas: 6000000 + } + ) + ); + }) + it("Should fail in changing the signing address", async () => { await catchRevert(I_GeneralTransferManager.changeSigningAddress(account_polymath, { from: account_investor4 })); }); @@ -554,7 +609,7 @@ contract("GeneralTransferManager", accounts => { }); it("Should set a budget for the GeneralTransferManager", async () => { - await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, 10 * Math.pow(10, 18), { from: token_owner }); + await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, 10 * Math.pow(10, 18), true, { from: token_owner }); await catchRevert(I_GeneralTransferManager.takeFee(web3.utils.toWei("1", "ether"), { from: token_owner })); await I_PolyToken.getTokens(10 * Math.pow(10, 18), token_owner); @@ -706,7 +761,7 @@ contract("GeneralTransferManager", accounts => { describe("General Transfer Manager Factory test cases", async () => { it("Should get the exact details of the factory", async () => { - assert.equal(await I_GeneralTransferManagerFactory.setupCost.call(), 0); + assert.equal(await I_GeneralTransferManagerFactory.getSetupCost.call(), 0); assert.equal((await I_GeneralTransferManagerFactory.getTypes.call())[0], 2); assert.equal( web3.utils.toAscii(await I_GeneralTransferManagerFactory.getName.call()).replace(/\u0000/g, ""), @@ -714,17 +769,17 @@ contract("GeneralTransferManager", accounts => { "Wrong Module added" ); assert.equal( - await I_GeneralTransferManagerFactory.getDescription.call(), + await I_GeneralTransferManagerFactory.description.call(), "Manage transfers using a time based whitelist", "Wrong Module added" ); - assert.equal(await I_GeneralTransferManagerFactory.getTitle.call(), "General Transfer Manager", "Wrong Module added"); + assert.equal(await I_GeneralTransferManagerFactory.title.call(), "General Transfer Manager", "Wrong Module added"); assert.equal( await I_GeneralTransferManagerFactory.getInstructions.call(), - "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist, and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters.", + "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters.", "Wrong Module added" ); - assert.equal(await I_GeneralPermissionManagerFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_GeneralPermissionManagerFactory.version.call(), "1.0.0"); }); it("Should get the tags of the factory", async () => { @@ -735,15 +790,15 @@ contract("GeneralTransferManager", accounts => { describe("Dummy STO Factory test cases", async () => { it("should get the exact details of the factory", async () => { - assert.equal(await I_DummySTOFactory.setupCost.call(), 0); + assert.equal(await I_DummySTOFactory.getSetupCost.call(), 0); assert.equal((await I_DummySTOFactory.getTypes.call())[0], 3); assert.equal( web3.utils.toAscii(await I_DummySTOFactory.getName.call()).replace(/\u0000/g, ""), "DummySTO", "Wrong Module added" ); - assert.equal(await I_DummySTOFactory.getDescription.call(), "Dummy STO", "Wrong Module added"); - assert.equal(await I_DummySTOFactory.getTitle.call(), "Dummy STO", "Wrong Module added"); + assert.equal(await I_DummySTOFactory.description.call(), "Dummy STO", "Wrong Module added"); + assert.equal(await I_DummySTOFactory.title.call(), "Dummy STO", "Wrong Module added"); assert.equal(await I_DummySTOFactory.getInstructions.call(), "Dummy STO - you can mint tokens at will", "Wrong Module added"); }); @@ -753,7 +808,7 @@ contract("GeneralTransferManager", accounts => { }); it("Should get the version of factory", async() => { - let version = await I_DummySTOFactory.getVersion.call(); + let version = await I_DummySTOFactory.version.call(); assert.equal(version, "1.0.0"); }); }); diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index f72ab54e3..2021d350e 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -14,6 +14,7 @@ const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApproval const SingleTradeVolumeRestrictionManagerFactory = artifacts.require('./SingleTradeVolumeRestrictionTMFactory.sol'); const TrackedRedemptionFactory = artifacts.require("./TrackedRedemptionFactory.sol"); const PercentageTransferManagerFactory = artifacts.require("./PercentageTransferManagerFactory.sol"); +const ScheduledCheckpointFactory = artifacts.require('./ScheduledCheckpointFactory.sol'); const USDTieredSTOFactory = artifacts.require("./USDTieredSTOFactory.sol"); const USDTieredSTOProxyFactory = artifacts.require("./USDTieredSTOProxyFactory"); const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); @@ -37,6 +38,7 @@ const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); let I_USDTieredSTOProxyFactory; let I_USDTieredSTOFactory; let I_TrackedRedemptionFactory; +let I_ScheduledCheckpointFactory; let I_MockBurnFactory; let I_MockWrongTypeBurnFactory; let I_SingleTradeVolumeRestrictionManagerFactory; @@ -265,6 +267,18 @@ export async function deploySingleTradeVolumeRMAndVerified(accountPolymath, MRPr return new Array(I_SingleTradeVolumeRestrictionManagerFactory); } +export async function deployScheduleCheckpointAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { + I_ScheduledCheckpointFactory = await ScheduledCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + assert.notEqual( + I_ScheduledCheckpointFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "ScheduledCheckpointFactory contract was not deployed" + ); + + await registerAndVerifyByMR(I_ScheduledCheckpointFactory.address, accountPolymath, MRProxyInstance); + return new Array(I_ScheduledCheckpointFactory); +} + /// Deploy the Permission Manager export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { @@ -311,7 +325,7 @@ export async function deployCappedSTOAndVerifyed(accountPolymath, MRProxyInstanc export async function deployPresaleSTOAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { I_PreSaleSTOFactory = await PreSaleSTOFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); - + assert.notEqual( I_PreSaleSTOFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -326,14 +340,14 @@ export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInst I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({from: accountPolymath}); I_USDTieredSTOFactory = await USDTieredSTOFactory.new(polyToken, setupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: accountPolymath }); - + assert.notEqual( I_USDTieredSTOFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", "USDTieredSTOFactory contract was not deployed" ); - await registerAndVerifyByMR(I_USDTieredSTOFactory.address, accountPolymath, MRProxyInstance); + await registerAndVerifyByMR(I_USDTieredSTOFactory.address, accountPolymath, MRProxyInstance); return new Array(I_USDTieredSTOFactory); } @@ -419,4 +433,4 @@ function mergeReturn(returnData) { } } return returnArray; -} \ No newline at end of file +} diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 9d8b33380..ea7476cc3 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -3,11 +3,11 @@ const utils = ethers.utils; const ethUtil = require("ethereumjs-util"); //this, _investor, _fromTime, _toTime, _validTo -function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, pk) { +function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce, pk) { let packedData = utils .solidityKeccak256( - ["address", "address", "uint256", "uint256", "uint256", "bool", "uint256", "uint256"], - [tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo] + ["address", "address", "uint256", "uint256", "uint256", "bool", "uint256", "uint256", "uint256"], + [tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce] ) .slice(2); packedData = new Buffer(packedData, "hex"); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 0a1346f31..709991b92 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -536,13 +536,13 @@ contract("ManualApprovalTransferManager", accounts => { describe("ManualApproval Transfer Manager Factory test cases", async () => { it("Should get the exact details of the factory", async () => { - assert.equal(await I_ManualApprovalTransferManagerFactory.setupCost.call(), 0); + assert.equal(await I_ManualApprovalTransferManagerFactory.getSetupCost.call(), 0); assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0], 2); let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); assert.equal(name, "ManualApprovalTransferManager", "Wrong Module added"); - let desc = await I_ManualApprovalTransferManagerFactory.getDescription.call(); + let desc = await I_ManualApprovalTransferManagerFactory.description.call(); assert.equal(desc, "Manage transfers using single approvals / blocking", "Wrong Module added"); - let title = await I_ManualApprovalTransferManagerFactory.getTitle.call(); + let title = await I_ManualApprovalTransferManagerFactory.title.call(); assert.equal(title, "Manual Approval Transfer Manager", "Wrong Module added"); let inst = await I_ManualApprovalTransferManagerFactory.getInstructions.call(); assert.equal( @@ -550,7 +550,7 @@ contract("ManualApprovalTransferManager", accounts => { "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.", "Wrong Module added" ); - assert.equal(await I_ManualApprovalTransferManagerFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "1.0.0"); }); it("Should get the tags of the factory", async () => { diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index 3a62463ac..b15ee41a0 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -22,6 +22,7 @@ contract("PercentageTransferManager", accounts => { let account_investor2; let account_investor3; let account_investor4; + let account_delegate; // investor Details let fromTime = latestTime(); @@ -57,6 +58,7 @@ contract("PercentageTransferManager", accounts => { const tokenDetails = "This is equity type of issuance"; const decimals = 18; const contact = "team@polymath.network"; + const delegateDetails = "Hello I am legit delegate"; // Module key const delegateManagerKey = 1; @@ -92,6 +94,7 @@ contract("PercentageTransferManager", accounts => { account_investor1 = accounts[7]; account_investor2 = accounts[8]; account_investor3 = accounts[9]; + account_delegate = accounts[6]; let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -166,6 +169,18 @@ contract("PercentageTransferManager", accounts => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); + + it("Should successfully attach the General permission manager factory with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "GeneralPermissionManager", + "GeneralPermissionManagerFactory module was not added" + ); + I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); + }); + }); describe("Buy tokens using on-chain whitelist", async () => { @@ -333,10 +348,32 @@ contract("PercentageTransferManager", accounts => { ) }); + it("Should not be able to modify holder percentage to 100 - Unauthorized msg.sender", async () => { + await catchRevert( + I_PercentageTransferManager.changeHolderPercentage(100 * 10 ** 16, { from: account_delegate }) + ) + }); + + it("Should successfully add the delegate", async() => { + let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); + assert.equal(tx.logs[0].args._delegate, account_delegate); + }); + + it("Should provide the permission", async() => { + let tx = await I_GeneralPermissionManager.changePermission( + account_delegate, + I_PercentageTransferManager.address, + "ADMIN", + true, + {from: token_owner} + ); + assert.equal(tx.logs[0].args._delegate, account_delegate); + }); + it("Modify holder percentage to 100", async () => { // Add the Investor in to the whitelist // Mint some tokens - await I_PercentageTransferManager.changeHolderPercentage(100 * 10 ** 16, { from: token_owner }); + await I_PercentageTransferManager.changeHolderPercentage(100 * 10 ** 16, { from: account_delegate }); assert.equal((await I_PercentageTransferManager.maxHolderPercentage()).toNumber(), 100 * 10 ** 16); }); @@ -372,7 +409,7 @@ contract("PercentageTransferManager", accounts => { describe("Percentage Transfer Manager Factory test cases", async () => { it("Should get the exact details of the factory", async () => { - assert.equal(await I_PercentageTransferManagerFactory.setupCost.call(), 0); + assert.equal(await I_PercentageTransferManagerFactory.getSetupCost.call(), 0); assert.equal((await I_PercentageTransferManagerFactory.getTypes.call())[0], 2); assert.equal( web3.utils.toAscii(await I_PercentageTransferManagerFactory.getName.call()).replace(/\u0000/g, ""), @@ -380,17 +417,17 @@ contract("PercentageTransferManager", accounts => { "Wrong Module added" ); assert.equal( - await I_PercentageTransferManagerFactory.getDescription.call(), + await I_PercentageTransferManagerFactory.description.call(), "Restrict the number of investors", "Wrong Module added" ); - assert.equal(await I_PercentageTransferManagerFactory.getTitle.call(), "Percentage Transfer Manager", "Wrong Module added"); + assert.equal(await I_PercentageTransferManagerFactory.title.call(), "Percentage Transfer Manager", "Wrong Module added"); assert.equal( await I_PercentageTransferManagerFactory.getInstructions.call(), "Allows an issuer to restrict the total number of non-zero token holders", "Wrong Module added" ); - assert.equal(await I_PercentageTransferManagerFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_PercentageTransferManagerFactory.version.call(), "1.0.0"); }); it("Should get the tags of the factory", async () => { diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index e21ac6df3..a89932dc4 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -413,7 +413,7 @@ contract("PreSaleSTO", accounts => { describe("Test cases for the PresaleSTOFactory", async () => { it("should get the exact details of the factory", async () => { - assert.equal(await I_PreSaleSTOFactory.setupCost.call(), 0); + assert.equal(await I_PreSaleSTOFactory.getSetupCost.call(), 0); assert.equal((await I_PreSaleSTOFactory.getTypes.call())[0], 3); assert.equal( web3.utils.toAscii(await I_PreSaleSTOFactory.getName.call()).replace(/\u0000/g, ""), @@ -421,11 +421,11 @@ contract("PreSaleSTO", accounts => { "Wrong Module added" ); assert.equal( - await I_PreSaleSTOFactory.getDescription.call(), + await I_PreSaleSTOFactory.description.call(), "Allows Issuer to configure pre-sale token allocations", "Wrong Module added" ); - assert.equal(await I_PreSaleSTOFactory.getTitle.call(), "PreSale STO", "Wrong Module added"); + assert.equal(await I_PreSaleSTOFactory.title.call(), "PreSale STO", "Wrong Module added"); assert.equal( await I_PreSaleSTOFactory.getInstructions.call(), "Configure and track pre-sale token allocations", diff --git a/test/o_security_token.js b/test/o_security_token.js index 619b80035..52521181e 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -3,7 +3,7 @@ import { duration, ensureException, promisifyLogWatch, latestBlock } from "./hel import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; -import { +import { setUpPolymathNetwork, deployGPMAndVerifyed, deployCappedSTOAndVerifyed, @@ -68,7 +68,6 @@ contract("SecurityToken", accounts => { let I_MockRedemptionManagerFactory; let I_MockRedemptionManager; - // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; const symbol = "DET"; @@ -481,27 +480,31 @@ contract("SecurityToken", accounts => { }); it("Should change the budget of the module - fail incorrect address", async () => { - await catchRevert(I_SecurityToken.changeModuleBudget(0, 100 * Math.pow(10, 18), { from: token_owner })); + await catchRevert(I_SecurityToken.changeModuleBudget(0, 100 * Math.pow(10, 18), true, { from: token_owner })); }); it("Should change the budget of the module", async () => { - let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, 100 * Math.pow(10, 18), { from: token_owner }); + let budget = await I_PolyToken.allowance.call(I_SecurityToken.address, I_CappedSTO.address); + let increaseAmount = 100 * Math.pow(10, 18); + let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, increaseAmount, true, { from: token_owner }); assert.equal(tx.logs[1].args._moduleTypes[0], stoKey); assert.equal(tx.logs[1].args._module, I_CappedSTO.address); - assert.equal(tx.logs[1].args._budget.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); + assert.equal(tx.logs[1].args._budget.toNumber(), budget.plus(increaseAmount).toNumber()); }); it("Should change the budget of the module (decrease it)", async() => { - let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, 50 * Math.pow(10, 18), { from: token_owner }); + let budget = await I_PolyToken.allowance.call(I_SecurityToken.address, I_CappedSTO.address); + let decreaseAmount = 100 * Math.pow(10, 18); + let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, decreaseAmount, false, { from: token_owner }); assert.equal(tx.logs[1].args._moduleTypes[0], stoKey); assert.equal(tx.logs[1].args._module, I_CappedSTO.address); - assert.equal(tx.logs[1].args._budget.dividedBy(new BigNumber(10).pow(18)).toNumber(), 50); + assert.equal(tx.logs[1].args._budget.toNumber(), budget.minus(decreaseAmount).toNumber()); }); it("Should fail to get the total supply -- because checkpoint id is greater than present", async() => { await catchRevert( I_SecurityToken.totalSupplyAt.call(50) - ); + ); }) }); @@ -854,11 +857,10 @@ contract("SecurityToken", accounts => { assert.equal(newInvestorCount.toNumber() + 1, currentInvestorCount.toNumber(), "Investor count drops by one"); }); - it("Should prune investor length", async () => { - await I_SecurityToken.pruneInvestors(0, 10, { from: token_owner }); - // Hardcode list of expected accounts based on transfers above - - let investors = await I_SecurityToken.getInvestors.call(); + it("Should use getInvestorsAt to determine balances now", async () => { + await I_SecurityToken.createCheckpoint({ from: token_owner }); + let investors = await I_SecurityToken.getInvestorsAt.call(1); + console.log("Filtered investors:" + investors); let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1]; for (let i = 0; i < expectedAccounts.length; i++) { assert.equal(investors[i], expectedAccounts[i]); @@ -866,6 +868,54 @@ contract("SecurityToken", accounts => { assert.equal(investors.length, 3); }); + it("Should prune investor length test #2", async () => { + let balance = await I_SecurityToken.balanceOf(account_affiliate2); + let balance2 = await I_SecurityToken.balanceOf(account_investor1); + await I_SecurityToken.transfer(account_affiliate1, balance, { from: account_affiliate2}); + await I_SecurityToken.transfer(account_affiliate1, balance2, { from: account_investor1}); + await I_SecurityToken.createCheckpoint({ from: token_owner }); + let investors = await I_SecurityToken.getInvestors.call(); + console.log("All investors:" + investors); + let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1, account_temp]; + for (let i = 0; i < expectedAccounts.length; i++) { + assert.equal(investors[i], expectedAccounts[i]); + } + assert.equal(investors.length, 4); + investors = await I_SecurityToken.getInvestorsAt.call(2); + console.log("Filtered investors:" + investors); + expectedAccounts = [account_affiliate1]; + for (let i = 0; i < expectedAccounts.length; i++) { + assert.equal(investors[i], expectedAccounts[i]); + } + assert.equal(investors.length, 1); + await I_SecurityToken.transfer(account_affiliate2, balance, { from: account_affiliate1}); + await I_SecurityToken.transfer(account_investor1, balance2, { from: account_affiliate1}); + }); + + it("Should get filtered investors", async () => { + let investors = await I_SecurityToken.getInvestors.call(); + console.log("All Investors: " + investors); + let filteredInvestors = await I_SecurityToken.iterateInvestors.call(0, 1); + console.log("Filtered Investors (0, 1): " + filteredInvestors); + assert.equal(filteredInvestors[0], investors[0]); + assert.equal(filteredInvestors.length, 1); + filteredInvestors = await I_SecurityToken.iterateInvestors.call(2, 4); + console.log("Filtered Investors (2, 4): " + filteredInvestors); + assert.equal(filteredInvestors[0], investors[2]); + assert.equal(filteredInvestors[1], investors[3]); + assert.equal(filteredInvestors.length, 2); + filteredInvestors = await I_SecurityToken.iterateInvestors.call(0, 4); + console.log("Filtered Investors (0, 4): " + filteredInvestors); + assert.equal(filteredInvestors[0], investors[0]); + assert.equal(filteredInvestors[1], investors[1]); + assert.equal(filteredInvestors[2], investors[2]); + assert.equal(filteredInvestors[3], investors[3]); + assert.equal(filteredInvestors.length, 4); + await catchRevert( + I_SecurityToken.iterateInvestors(0, 5) + ); + }); + it("Should check the balance of investor at checkpoint", async () => { await catchRevert(I_SecurityToken.balanceOfAt(account_investor1, 5)); }); @@ -877,7 +927,7 @@ contract("SecurityToken", accounts => { }); describe("Test cases for the Mock TrackedRedeemption", async() => { - + it("Should add the tracked redeemption module successfully", async() => { [I_MockRedemptionManagerFactory] = await deployMockRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "", 0, 0, {from: token_owner }); @@ -943,7 +993,7 @@ contract("SecurityToken", accounts => { await I_SecurityToken.approve(I_MockRedemptionManager.address, web3.utils.toWei("500"), {from: account_investor1}); // Transfer the tokens to module (Burn) await I_MockRedemptionManager.transferToRedeem(web3.utils.toWei("500"), { from: account_investor1}); - + await catchRevert( // Redeem tokens I_MockRedemptionManager.redeemTokenByOwner(web3.utils.toWei("250"), {from: account_investor1}) @@ -1089,4 +1139,4 @@ contract("SecurityToken", accounts => { }); }); -}); \ No newline at end of file +}); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 62cd4cc05..5332700b4 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -4303,13 +4303,15 @@ contract("USDTieredSTO", accounts => { describe("Test cases for the USDTieredSTOFactory", async () => { it("should get the exact details of the factory", async () => { - assert.equal((await I_USDTieredSTOFactory.setupCost.call()).toNumber(), STOSetupCost); + assert.equal((await I_USDTieredSTOFactory.getSetupCost.call()).toNumber(), STOSetupCost); assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0], 3); assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), "USDTieredSTO", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.getDescription.call(), "USD Tiered STO", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.getTitle.call(), "USD Tiered STO", "Wrong Module added"); + assert.equal(await I_USDTieredSTOFactory.description.call(), + "It allows both accredited and non-accredited investors to contribute into the STO. Non-accredited investors will be capped at a maximum investment limit (as a default or specific to their jurisdiction). Tokens will be sold according to tiers sequentially & each tier has its own price and volume of tokens to sell. Upon receipt of funds (ETH, POLY or DAI), security tokens will automatically transfer to investor’s wallet address", + "Wrong Module added"); + assert.equal(await I_USDTieredSTOFactory.title.call(), "USD Tiered STO", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.getInstructions.call(), "Initialises a USD tiered STO.", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_USDTieredSTOFactory.version.call(), "1.0.0"); let tags = await I_USDTieredSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "USD"); assert.equal(web3.utils.hexToString(tags[1]), "Tiered"); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index a8a11f66d..159564651 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -265,16 +265,16 @@ contract("TrackedRedemption", accounts => { describe("Test cases for the TrackedRedemptionFactory", async () => { it("should get the exact details of the factory", async () => { - assert.equal((await I_TrackedRedemptionFactory.setupCost.call()).toNumber(), 0); + assert.equal((await I_TrackedRedemptionFactory.getSetupCost.call()).toNumber(), 0); assert.equal((await I_TrackedRedemptionFactory.getTypes.call())[0], 5); - assert.equal(await I_TrackedRedemptionFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_TrackedRedemptionFactory.version.call(), "1.0.0"); assert.equal( web3.utils.toAscii(await I_TrackedRedemptionFactory.getName.call()).replace(/\u0000/g, ""), "TrackedRedemption", "Wrong Module added" ); - assert.equal(await I_TrackedRedemptionFactory.getDescription.call(), "Track token redemptions", "Wrong Module added"); - assert.equal(await I_TrackedRedemptionFactory.getTitle.call(), "Tracked Redemption", "Wrong Module added"); + assert.equal(await I_TrackedRedemptionFactory.description.call(), "Track token redemptions", "Wrong Module added"); + assert.equal(await I_TrackedRedemptionFactory.title.call(), "Tracked Redemption", "Wrong Module added"); assert.equal( await I_TrackedRedemptionFactory.getInstructions.call(), "Allows an investor to redeem security tokens which are tracked by this module", diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index fda65be4f..fe06f3f5c 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -781,22 +781,22 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { describe("VolumeRestriction Transfer Manager Factory test cases", async() => { it("Should get the exact details of the factory", async() => { - assert.equal(await I_VolumeRestrictionTransferManagerFactory.setupCost.call(),0); + assert.equal(await I_VolumeRestrictionTransferManagerFactory.getSetupCost.call(),0); assert.equal((await I_VolumeRestrictionTransferManagerFactory.getTypes.call())[0],2); assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTransferManagerFactory.getName.call()) .replace(/\u0000/g, ''), "LockupVolumeRestrictionTM", "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getDescription.call(), + assert.equal(await I_VolumeRestrictionTransferManagerFactory.description.call(), "Manage transfers using lock ups over time", "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getTitle.call(), + assert.equal(await I_VolumeRestrictionTransferManagerFactory.title.call(), "Lockup Volume Restriction Transfer Manager", "Wrong Module added"); assert.equal(await I_VolumeRestrictionTransferManagerFactory.getInstructions.call(), "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getVersion.call(), "1.0.0"); + assert.equal(await I_VolumeRestrictionTransferManagerFactory.version.call(), "1.0.0"); }); it("Should get the tags of the factory", async() => { diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index a0e1fb3f0..15c01e68c 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -700,17 +700,17 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { describe("SingleTradeVolumeRestrictionManager Factory test cases", async () => { it("Should get the exact details of the factory", async () => { - assert.equal(await I_SingleTradeVolumeRestrictionManagerFactory.setupCost.call(), 0); + assert.equal(await I_SingleTradeVolumeRestrictionManagerFactory.getSetupCost.call(), 0); assert.equal((await I_SingleTradeVolumeRestrictionManagerFactory.getTypes.call())[0], 2); let name = web3.utils.toUtf8(await I_SingleTradeVolumeRestrictionManagerFactory.getName.call()); assert.equal(name, "SingleTradeVolumeRestrictionTM", "Wrong Module added"); - let desc = await I_SingleTradeVolumeRestrictionManagerFactory.getDescription.call(); + let desc = await I_SingleTradeVolumeRestrictionManagerFactory.description.call(); assert.equal(desc, "Imposes volume restriction on a single trade", "Wrong Module added"); - let title = await I_SingleTradeVolumeRestrictionManagerFactory.getTitle.call(); + let title = await I_SingleTradeVolumeRestrictionManagerFactory.title.call(); assert.equal(title, "Single Trade Volume Restriction Manager", "Wrong Module added"); let inst = await I_SingleTradeVolumeRestrictionManagerFactory.getInstructions.call(); assert.equal(inst, "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens", "Wrong Module added"); - let version = await I_SingleTradeVolumeRestrictionManagerFactory.getVersion.call(); + let version = await I_SingleTradeVolumeRestrictionManagerFactory.version.call(); assert.equal(version, "1.0.0", "Version not correct"); }); diff --git a/test/y_scheduled_checkpoints.js b/test/y_scheduled_checkpoints.js new file mode 100644 index 000000000..5fcc03a74 --- /dev/null +++ b/test/y_scheduled_checkpoints.js @@ -0,0 +1,389 @@ +import latestTime from './helpers/latestTime'; +import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; +import { setUpPolymathNetwork, deployScheduleCheckpointAndVerified } from "./helpers/createInstances"; + +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const ScheduledCheckpoint = artifacts.require('./ScheduledCheckpoint.sol'); + + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('ScheduledCheckpoint', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_ScheduledCheckpointFactory; + let I_GeneralPermissionManager; + let I_ScheduledCheckpoint; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_MRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[7]; + account_investor2 = accounts[8]; + account_investor3 = accounts[9]; + + // Step 1: Deploy the genral PM ecosystem + let instances = await setUpPolymathNetwork(account_polymath, token_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; + + // STEP 2: Deploy the ScheduleCheckpointModule + [I_ScheduledCheckpointFactory] = await deployScheduleCheckpointAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${I_PolymathRegistry.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistry: ${I_ModuleRegistry.address} + ModuleRegistryProxy: ${I_ModuleRegistryProxy.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + STFactory: ${I_STFactory.address} + GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + + + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + }); + + describe("Buy tokens using on-chain whitelist", async() => { + + it("Should successfully attach the ScheduledCheckpoint with the security token", async () => { + await I_SecurityToken.changeGranularity(1, {from: token_owner}); + const tx = await I_SecurityToken.addModule(I_ScheduledCheckpointFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), 4, "ScheduledCheckpoint doesn't get deployed"); + assert.equal(tx.logs[2].args._types[1].toNumber(), 2, "ScheduledCheckpoint doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "ScheduledCheckpoint", + "ScheduledCheckpoint module was not added" + ); + I_ScheduledCheckpoint = ScheduledCheckpoint.at(tx.logs[2].args._module); + }); + + let startTime; + let interval; + it("Should create a daily checkpoint", async () => { + startTime = latestTime() + 100; + interval = 24 * 60 * 60; + console.log("Creating scheduled CP: " + startTime, interval); + await I_ScheduledCheckpoint.addSchedule("CP1", startTime, interval, {from: token_owner}); + console.log("2: " + latestTime()); + }); + + it("Remove (temp) daily checkpoint", async () => { + let snap_Id = await takeSnapshot(); + await I_ScheduledCheckpoint.removeSchedule("CP1", {from: token_owner}); + await revertToSnapshot(snap_Id); + }); + + it("Should Buy the tokens for account_investor1", async() => { + // Add the Investor in to the whitelist + console.log("3: " + latestTime()); + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + console.log("4: " + latestTime()); + + await increaseTime(5000); + // We should be after the first scheduled checkpoint, and before the second + console.log("5: " + latestTime()); + + assert.isTrue(latestTime() > startTime); + assert.isTrue(latestTime() <= startTime + interval); + console.log("6: " + latestTime()); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should have checkpoint created with correct balances", async() => { + let cp1 = await I_ScheduledCheckpoint.getSchedule("CP1"); + checkSchedule(cp1, "CP1", startTime, startTime + interval, interval, [1], [startTime], [1]); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 1)).toNumber(), 0); + }); + + it("Should Buy some more tokens for account_investor2", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // We should be after the first scheduled checkpoint, and before the second + assert.isTrue(latestTime() > startTime); + assert.isTrue(latestTime() <= startTime + interval); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("No additional checkpoints created", async() => { + let cp1 = await I_ScheduledCheckpoint.getSchedule("CP1"); + checkSchedule(cp1, "CP1", startTime, startTime + interval, interval, [1], [startTime], [1]); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 1)).toNumber(), 0); + }); + + it("Add a new token holder - account_investor3", async() => { + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(interval); + // We should be after the first scheduled checkpoint, and before the second + assert.isTrue(latestTime() > startTime + interval); + assert.isTrue(latestTime() <= startTime + (2 * interval)); + + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + }); + + it("Should have new checkpoint created with correct balances", async() => { + let cp1 = await I_ScheduledCheckpoint.getSchedule("CP1"); + checkSchedule(cp1, "CP1", startTime, startTime + (2 * interval), interval, [1, 2], [startTime, startTime + interval], [1, 1]); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 1)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 2)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 1)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 2)).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 1)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 2)).toNumber(), web3.utils.toWei('1', 'ether')); + }); + + it("Should have correct balances for investor 3 after new checkpoint", async() => { + // Jump time + await increaseTime(2 * interval); + // We should be after the first scheduled checkpoint, and before the second + assert.isTrue(latestTime() > startTime + (3 * interval)); + assert.isTrue(latestTime() <= startTime + (4 * interval)); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('0.5', 'ether'), { from: account_investor1 }); + let cp1 = await I_ScheduledCheckpoint.getSchedule("CP1"); + checkSchedule(cp1, "CP1", startTime, startTime + (4 * interval), interval, [1, 2, 3], [startTime, startTime + interval, startTime + (2 * interval)], [1, 1, 2]); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 1)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 2)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 3)).toNumber(), web3.utils.toWei('1', 'ether')); + + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 1)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 2)).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 3)).toNumber(), web3.utils.toWei('1', 'ether')); + + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 1)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 2)).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 3)).toNumber(), web3.utils.toWei('1', 'ether')); + + }); + + it("Manually update checkpoints", async() => { + await increaseTime(interval); + await I_ScheduledCheckpoint.updateAll({from: token_owner}); + + let cp1 = await I_ScheduledCheckpoint.getSchedule("CP1"); + checkSchedule(cp1, "CP1", startTime, startTime + (5 * interval), interval, [1, 2, 3, 4], [startTime, startTime + interval, startTime + (2 * interval), startTime + (4 * interval)], [1, 1, 2, 1]); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 1)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 2)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 3)).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 4)).toNumber(), web3.utils.toWei('1.5', 'ether')); + + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 1)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 2)).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 3)).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 4)).toNumber(), web3.utils.toWei('1', 'ether')); + + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 0)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 1)).toNumber(), 0); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 2)).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 3)).toNumber(), web3.utils.toWei('1', 'ether')); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 4)).toNumber(), web3.utils.toWei('0.5', 'ether')); + + }); + + it("Should get the permission", async() => { + let perm = await I_ScheduledCheckpoint.getPermissions.call(); + assert.equal(perm.length, 0); + }); + + }); + +}); + +function checkSchedule(schedule, name, startTime, nextTime, interval, checkpoints, timestamps, periods) { + assert.equal(web3.utils.toAscii(schedule[0]).replace(/\u0000/g, ''), name); + assert.equal(schedule[1].toNumber(), startTime); + assert.equal(schedule[2].toNumber(), nextTime); + assert.equal(schedule[3].toNumber(), interval); + assert.equal(schedule[4].length, checkpoints.length); + for (let i = 0; i < checkpoints.length; i++) { + assert.equal(schedule[4][i].toNumber(), checkpoints[i]); + } + assert.equal(schedule[5].length, timestamps.length); + for (let i = 0; i < timestamps.length; i++) { + assert.equal(schedule[5][i].toNumber(), timestamps[i]); + } + assert.equal(schedule[6].length, periods.length); + for (let i = 0; i < periods.length; i++) { + assert.equal(schedule[6][i].toNumber(), periods[i]); + } +} From 18d770bb3bb119e8f33d22e886033e82b9d66143 Mon Sep 17 00:00:00 2001 From: Polymath Date: Mon, 12 Nov 2018 15:51:13 -0300 Subject: [PATCH 076/582] Whitelist refactor --- CLI/commands/OLD_whitelist.js | 302 ++++++++++++++++++++++++++++++++++ CLI/commands/whitelist.js | 266 ++++++++++++------------------ CLI/polymath-cli.js | 3 +- 3 files changed, 409 insertions(+), 162 deletions(-) create mode 100644 CLI/commands/OLD_whitelist.js diff --git a/CLI/commands/OLD_whitelist.js b/CLI/commands/OLD_whitelist.js new file mode 100644 index 000000000..5ef201195 --- /dev/null +++ b/CLI/commands/OLD_whitelist.js @@ -0,0 +1,302 @@ +var fs = require('fs'); +var csv = require('fast-csv'); +var BigNumber = require('bignumber.js'); +var common = require('./common/common_functions'); +var global = require('./common/global'); + +/////////////////////////////ARTIFACTS////////////////////////////////////////// +var contracts = require('./helpers/contract_addresses'); +var abis = require('./helpers/contract_abis'); + +////////////////////////////USER INPUTS////////////////////////////////////////// +let tokenSymbol = process.argv.slice(2)[0]; //token symbol +let BATCH_SIZE = process.argv.slice(2)[1]; //batch size +if (!BATCH_SIZE) BATCH_SIZE = 70; +let remoteNetwork = process.argv.slice(2)[2]; + +/////////////////////////GLOBAL VARS////////////////////////////////////////// + +//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] +let distribData = new Array(); +//allocData is a temporary array that stores up to the batch size, +//then gets push into distribData, then gets set to 0 to start another batch +let allocData = new Array(); +//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] +let fullFileData = new Array(); +let badData = new Array(); + +const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); + +//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// + +startScript(); + +async function startScript() { + if (remoteNetwork == 'undefined') remoteNetwork = undefined; + await global.initialize(remoteNetwork); + + try { + let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); + let securityTokenRegistryABI = abis.securityTokenRegistry(); + securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); + securityTokenRegistry.setProvider(web3.currentProvider); + + console.log("Processing investor CSV upload. Batch size is "+BATCH_SIZE+" accounts per transaction"); + readFile(); + } catch (err) { + console.log(err) + console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); + return; + } +} + +///////////////////////////FUNCTION READING THE CSV FILE +function readFile() { + var stream = fs.createReadStream("./CLI/data/whitelist_data.csv"); + + let index = 0; + let batch = 0; + console.log(` + -------------------------------------------- + ----------- Parsing the csv file ----------- + -------------------------------------------- + `); + + var csvStream = csv() + .on("data", function (data) { + // console.log(data[1]) + // console.log(data[2]) + // console.log(data[3]) + let isAddress = web3.utils.isAddress(data[0]); + let sellValid = isValidDate(data[1]) + let buyValid = isValidDate(data[2]) + let kycExpiryDate = isValidDate(data[3]) + let canBuyFromSTO = (typeof JSON.parse(data[4].toLowerCase())) == "boolean" ? JSON.parse(data[4].toLowerCase()) : "not-valid"; + + if (isAddress && sellValid && buyValid && kycExpiryDate && (canBuyFromSTO != "not-valid") ) { + let userArray = new Array() + let checksummedAddress = web3.utils.toChecksumAddress(data[0]); + + userArray.push(checksummedAddress) + userArray.push(sellValid) + userArray.push(buyValid) + userArray.push(kycExpiryDate) + userArray.push(canBuyFromSTO) + // console.log(userArray) + allocData.push(userArray); + fullFileData.push(userArray); + index++; + if (index >= BATCH_SIZE) { + distribData.push(allocData); + // console.log("DIS", distribData); + allocData = []; + // console.log("ALLOC", allocData); + index = 0; + } + + } else { + let userArray = new Array() + //dont need this here, as if it is NOT an address this function will fail + //let checksummedAddress = web3.utils.toChecksumAddress(data[1]); + userArray.push(data[0]) + userArray.push(sellValid) + userArray.push(buyValid) + userArray.push(kycExpiryDate); + userArray.push(canBuyFromSTO); + badData.push(userArray); + fullFileData.push(userArray) + } + }) + .on("end", function () { + //Add last remainder batch + distribData.push(allocData); + allocData = []; + + setInvestors(); + }); + + stream.pipe(csvStream); +} + +////////////////////////MAIN FUNCTION COMMUNICATING TO BLOCKCHAIN +async function setInvestors() { + let tokenDeployed = false; + let tokenDeployedAddress; + // Let's check if token has already been deployed, if it has, skip to STO + await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { + if (result != "0x0000000000000000000000000000000000000000") { + console.log('\x1b[32m%s\x1b[0m', "Token deployed at address " + result + "."); + tokenDeployedAddress = result; + tokenDeployed = true; + } + }); + if (tokenDeployed) { + let securityTokenABI = abis.securityToken(); + securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); + } + let gmtModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + let generalTransferManagerAddress = gmtModules[0]; + let generalTransferManagerABI = abis.generalTransferManager(); + let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, generalTransferManagerAddress); + + console.log(` + ------------------------------------------------------- + ----- Sending buy/sell restrictions to blockchain ----- + ------------------------------------------------------- + `); + + //this for loop will do the batches, so it should run 75, 75, 50 with 200 + for (let i = 0; i < distribData.length; i++) { + try { + let investorArray = []; + let fromTimesArray = []; + let toTimesArray = []; + let expiryTimeArray = []; + let canBuyFromSTOArray = []; + + //splitting the user arrays to be organized by input + for (let j = 0; j < distribData[i].length; j++) { + investorArray.push(distribData[i][j][0]) + fromTimesArray.push(distribData[i][j][1]) + toTimesArray.push(distribData[i][j][2]) + expiryTimeArray.push(distribData[i][j][3]) + canBuyFromSTOArray.push(distribData[i][j][4]) + } + + //fromTimes is ability to sell coin FROM your account (2nd row in csv, 2nd parameter in modifyWhiteList() ) + //toTimes is ability to buy coins TOwards your account (3rd row in csv, 3rd parameter in modifyWhiteList() ) + //expiryTime is time at which KYC of investor get expired (4th row in csv, 4rd parameter in modifyWhiteList() ) + let modifyWhitelistMultiAction = generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); + let r = await common.sendTransaction(modifyWhitelistMultiAction); + console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); + console.log("Whitelist transaxction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); + + } catch (err) { + console.log("ERROR:", err); + } + } + + console.log("Retrieving logs to determine investors have had their times uploaded correctly.\n\n") + + let totalInvestors = 0; + let updatedInvestors = 0; + + let investorData_Events = new Array(); + let investorObjectLookup = {}; + + let event_data = await generalTransferManager.getPastEvents('ModifyWhitelist', { + fromBlock: 0, + toBlock: 'latest' + }, function (error, events) { + //console.log(error); + }); + + for (var i = 0; i < event_data.length; i++) { + let combineArray = []; + + let investorAddress_Event = event_data[i].returnValues._investor; + let fromTime_Event = event_data[i].returnValues._fromTime + let toTime_Event = event_data[i].returnValues._toTime + let expiryTime_Event = event_data[i].returnValues._expiryTime + let canBuyFromSTO_Event = event_data[i].returnValues._canBuyFromSTO + let blockNumber = event_data[i].blockNumber + + combineArray.push(investorAddress_Event); + combineArray.push(fromTime_Event); + combineArray.push(toTime_Event); + combineArray.push(expiryTime_Event); + combineArray.push(canBuyFromSTO_Event); + combineArray.push(blockNumber) + + investorData_Events.push(combineArray) + + //we have already recorded it, so this is an update to our object + if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { + + //the block number form the event we are checking is bigger, so we gotta replace it + if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { + investorObjectLookup[investorAddress_Event] = { fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber }; + updatedInvestors += 1; + // investorAddress_Events.push(investorAddress_Event); not needed, because we start the obj with zero events + + } else { + //do nothing. so if we find an event, and it was an older block, its old, we dont care + } + //we have never recorded this address as an object key, so we need to add it to our list of investors updated by the csv + } else { + investorObjectLookup[investorAddress_Event] = { fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber }; + totalInvestors += 1; + // investorAddress_Events.push(investorAddress_Event); + } + } + let investorAddress_Events = Object.keys(investorObjectLookup) + + console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); + console.log(`A total of ${totalInvestors} investors have been whitelisted total, all time.\n`); + console.log(`This script in total sent ${fullFileData.length - badData.length} new investors and updated investors to the blockchain.\n`); + console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); + + // console.log("LIST OF ALL INVESTOR DATA FROM EVENTS:", investorData_Events) + // console.log(fullFileData) + console.log("************************************************************************************************"); + console.log("OBJECT WITH EVERY USER AND THEIR UPDATED TIMES: \n\n", investorObjectLookup) + console.log("************************************************************************************************"); + console.log("LIST OF ALL INVESTORS WHITELISTED: \n\n", investorAddress_Events) + + let missingDistribs = []; + for (let l = 0; l < fullFileData.length; l++) { + if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { + missingDistribs.push(fullFileData[l]) + } + } + + if (missingDistribs.length > 0) { + console.log("************************************************************************************************"); + console.log("-- No LogModifyWhitelist event was found for the following data arrays. Please review them manually --") + console.log(missingDistribs) + // for (var i = 0; i < missingDistribs.length; i++) { + // console.log('\x1b[31m%s\x1b[0m', `No Transfer event was found for account ${missingDistribs[i]}`); + // } + console.log("************************************************************************************************"); + } else { + console.log("\n************************************************************************************************"); + console.log("All accounts passed through from the CSV were successfully whitelisted, because we were able to read them all from events") + console.log("************************************************************************************************"); + } + // console.log(`Run 'node scripts/verify_airdrop.js ${polyDistribution.address} > scripts/data/review.csv' to get a log of all the accounts that were distributed the airdrop tokens.`) +} + +//will be deleted once DATES are updated +function isValidDayInput(days) { + let today = Date.now() / 1000 + let isValid = !isNaN(days) + if (isValid) { + let addedSeconds = days * 86400 + + let unixTimestamp = today + addedSeconds + console.log("unxitimestapm :" , (unixTimestamp)) + + return unixTimestamp + } else { + return false + } +} + +function isValidDate(date) { + var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(date); + if (matches == null) return false; + var d = matches[2]; + var m = matches[1] - 1; //not clear why this is -1, but it works after checking + var y = matches[3]; + var composedDate = new Date(y, m, d); + var timestampDate = composedDate.getTime() + + //note, some reason these timestamps are being recorded +4 hours UTC + if (composedDate.getDate() == d && composedDate.getMonth() == m && composedDate.getFullYear() == y) { + return timestampDate / 1000 + } else { + return false + } +} diff --git a/CLI/commands/whitelist.js b/CLI/commands/whitelist.js index 5ef201195..d176903ee 100644 --- a/CLI/commands/whitelist.js +++ b/CLI/commands/whitelist.js @@ -1,143 +1,97 @@ +var common = require('./common/common_functions'); var fs = require('fs'); var csv = require('fast-csv'); -var BigNumber = require('bignumber.js'); -var common = require('./common/common_functions'); -var global = require('./common/global'); - -/////////////////////////////ARTIFACTS////////////////////////////////////////// var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); +var BigNumber = require('bignumber.js'); -////////////////////////////USER INPUTS////////////////////////////////////////// -let tokenSymbol = process.argv.slice(2)[0]; //token symbol -let BATCH_SIZE = process.argv.slice(2)[1]; //batch size -if (!BATCH_SIZE) BATCH_SIZE = 70; -let remoteNetwork = process.argv.slice(2)[2]; - -/////////////////////////GLOBAL VARS////////////////////////////////////////// - -//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] let distribData = new Array(); -//allocData is a temporary array that stores up to the batch size, -//then gets push into distribData, then gets set to 0 to start another batch let allocData = new Array(); -//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] let fullFileData = new Array(); let badData = new Array(); +let BATCH_SIZE = 70; +let securityToken; +let generalTransferManager; -const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); +async function startScript(tokenSymbol, batchSize) { + if (batchSize) { + BATCH_SIZE = batchSize; + } -//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// + common.logAsciiBull(); -startScript(); + let STAddress = await checkST(tokenSymbol); + securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); + + await readCsv(); +}; -async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); +async function checkST(tokenSymbol) { + let securityTokenRegistry = await STConnect(); + return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { + if (result != "0x0000000000000000000000000000000000000000") { + return result + } else { + console.log("Token doesn't exist") + process.exit(0) + } + }); +} + +async function STConnect() { try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - - console.log("Processing investor CSV upload. Batch size is "+BATCH_SIZE+" accounts per transaction"); - readFile(); + let STRegistryAddress = await contracts.securityTokenRegistry(); + let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); + return STRegistry; } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); - return; + console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); + process.exit(0); } } -///////////////////////////FUNCTION READING THE CSV FILE -function readFile() { - var stream = fs.createReadStream("./CLI/data/whitelist_data.csv"); +async function readCsv() { + var CSV_STRING = fs.readFileSync("./CLI/data/whitelist_data.csv").toString(); + let i = 0; - let index = 0; - let batch = 0; - console.log(` - -------------------------------------------- - ----------- Parsing the csv file ----------- - -------------------------------------------- - `); + csv.fromString(CSV_STRING) + .on("data", (data) => { + let data_processed = whitelist_processing(data); + fullFileData.push(data_processed[1]); - var csvStream = csv() - .on("data", function (data) { - // console.log(data[1]) - // console.log(data[2]) - // console.log(data[3]) - let isAddress = web3.utils.isAddress(data[0]); - let sellValid = isValidDate(data[1]) - let buyValid = isValidDate(data[2]) - let kycExpiryDate = isValidDate(data[3]) - let canBuyFromSTO = (typeof JSON.parse(data[4].toLowerCase())) == "boolean" ? JSON.parse(data[4].toLowerCase()) : "not-valid"; - - if (isAddress && sellValid && buyValid && kycExpiryDate && (canBuyFromSTO != "not-valid") ) { - let userArray = new Array() - let checksummedAddress = web3.utils.toChecksumAddress(data[0]); - - userArray.push(checksummedAddress) - userArray.push(sellValid) - userArray.push(buyValid) - userArray.push(kycExpiryDate) - userArray.push(canBuyFromSTO) - // console.log(userArray) - allocData.push(userArray); - fullFileData.push(userArray); - index++; - if (index >= BATCH_SIZE) { + if (data_processed[0]) { + allocData.push(data_processed[1]); + i++; + if (i >= BATCH_SIZE) { distribData.push(allocData); - // console.log("DIS", distribData); allocData = []; - // console.log("ALLOC", allocData); - index = 0; + i = 0; } - } else { - let userArray = new Array() - //dont need this here, as if it is NOT an address this function will fail - //let checksummedAddress = web3.utils.toChecksumAddress(data[1]); - userArray.push(data[0]) - userArray.push(sellValid) - userArray.push(buyValid) - userArray.push(kycExpiryDate); - userArray.push(canBuyFromSTO); - badData.push(userArray); - fullFileData.push(userArray) + badData.push(data_processed[1]); } + }) - .on("end", function () { - //Add last remainder batch + .on("end", async () => { distribData.push(allocData); allocData = []; - setInvestors(); + await saveInBlockchain(); + await finalResults(); + return; }); - - stream.pipe(csvStream); } -////////////////////////MAIN FUNCTION COMMUNICATING TO BLOCKCHAIN -async function setInvestors() { - let tokenDeployed = false; - let tokenDeployedAddress; - // Let's check if token has already been deployed, if it has, skip to STO - await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { - if (result != "0x0000000000000000000000000000000000000000") { - console.log('\x1b[32m%s\x1b[0m', "Token deployed at address " + result + "."); - tokenDeployedAddress = result; - tokenDeployed = true; - } - }); - if (tokenDeployed) { - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); +async function saveInBlockchain() { + let gtmModules; + try { + gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + } catch (e) { + console.log("Please attach General Transfer module before launch this action.", e) + process.exit(0) } - let gmtModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); - let generalTransferManagerAddress = gmtModules[0]; - let generalTransferManagerABI = abis.generalTransferManager(); - let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, generalTransferManagerAddress); + + generalTransferManager = new web3.eth.Contract(abis.generalTransferManager(), gtmModules[0]); console.log(` ------------------------------------------------------- @@ -145,16 +99,11 @@ async function setInvestors() { ------------------------------------------------------- `); - //this for loop will do the batches, so it should run 75, 75, 50 with 200 for (let i = 0; i < distribData.length; i++) { try { - let investorArray = []; - let fromTimesArray = []; - let toTimesArray = []; - let expiryTimeArray = []; - let canBuyFromSTOArray = []; + let investorArray = [], fromTimesArray = [], toTimesArray = [], expiryTimeArray = [], canBuyFromSTOArray = []; - //splitting the user arrays to be organized by input + // Splitting the user arrays to be organized by input for (let j = 0; j < distribData[i].length; j++) { investorArray.push(distribData[i][j][0]) fromTimesArray.push(distribData[i][j][1]) @@ -163,40 +112,33 @@ async function setInvestors() { canBuyFromSTOArray.push(distribData[i][j][4]) } - //fromTimes is ability to sell coin FROM your account (2nd row in csv, 2nd parameter in modifyWhiteList() ) - //toTimes is ability to buy coins TOwards your account (3rd row in csv, 3rd parameter in modifyWhiteList() ) - //expiryTime is time at which KYC of investor get expired (4th row in csv, 4rd parameter in modifyWhiteList() ) let modifyWhitelistMultiAction = generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); - let r = await common.sendTransaction(modifyWhitelistMultiAction); + let tx = await common.sendTransaction(modifyWhitelistMultiAction); console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Whitelist transaxction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); + console.log("Whitelist transaxction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); } catch (err) { - console.log("ERROR:", err); + console.log("ERROR", err) + process.exit(0) } } - console.log("Retrieving logs to determine investors have had their times uploaded correctly.\n\n") + return; +} +async function finalResults() { let totalInvestors = 0; let updatedInvestors = 0; - - let investorData_Events = new Array(); let investorObjectLookup = {}; - - let event_data = await generalTransferManager.getPastEvents('ModifyWhitelist', { - fromBlock: 0, - toBlock: 'latest' - }, function (error, events) { - //console.log(error); - }); + let investorData_Events = new Array(); + let event_data = await generalTransferManager.getPastEvents('ModifyWhitelist', {fromBlock: 0, toBlock: 'latest'}, () => {}); for (var i = 0; i < event_data.length; i++) { let combineArray = []; - let investorAddress_Event = event_data[i].returnValues._investor; + let investorAddress_Event = event_data[i].returnValues._investor let fromTime_Event = event_data[i].returnValues._fromTime let toTime_Event = event_data[i].returnValues._toTime let expiryTime_Event = event_data[i].returnValues._expiryTime @@ -212,34 +154,25 @@ async function setInvestors() { investorData_Events.push(combineArray) - //we have already recorded it, so this is an update to our object + // We have already recorded it, so this is an update to our object if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { - - //the block number form the event we are checking is bigger, so we gotta replace it + // The block number form the event we are checking is bigger, so we gotta replace it if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { - investorObjectLookup[investorAddress_Event] = { fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber }; + investorObjectLookup[investorAddress_Event] = {fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber}; updatedInvestors += 1; - // investorAddress_Events.push(investorAddress_Event); not needed, because we start the obj with zero events - - } else { - //do nothing. so if we find an event, and it was an older block, its old, we dont care } - //we have never recorded this address as an object key, so we need to add it to our list of investors updated by the csv } else { - investorObjectLookup[investorAddress_Event] = { fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber }; + investorObjectLookup[investorAddress_Event] = {fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber}; totalInvestors += 1; - // investorAddress_Events.push(investorAddress_Event); } } + let investorAddress_Events = Object.keys(investorObjectLookup) console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); console.log(`A total of ${totalInvestors} investors have been whitelisted total, all time.\n`); console.log(`This script in total sent ${fullFileData.length - badData.length} new investors and updated investors to the blockchain.\n`); console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); - - // console.log("LIST OF ALL INVESTOR DATA FROM EVENTS:", investorData_Events) - // console.log(fullFileData) console.log("************************************************************************************************"); console.log("OBJECT WITH EVERY USER AND THEIR UPDATED TIMES: \n\n", investorObjectLookup) console.log("************************************************************************************************"); @@ -256,31 +189,34 @@ async function setInvestors() { console.log("************************************************************************************************"); console.log("-- No LogModifyWhitelist event was found for the following data arrays. Please review them manually --") console.log(missingDistribs) - // for (var i = 0; i < missingDistribs.length; i++) { - // console.log('\x1b[31m%s\x1b[0m', `No Transfer event was found for account ${missingDistribs[i]}`); - // } console.log("************************************************************************************************"); } else { console.log("\n************************************************************************************************"); console.log("All accounts passed through from the CSV were successfully whitelisted, because we were able to read them all from events") console.log("************************************************************************************************"); } - // console.log(`Run 'node scripts/verify_airdrop.js ${polyDistribution.address} > scripts/data/review.csv' to get a log of all the accounts that were distributed the airdrop tokens.`) + } -//will be deleted once DATES are updated -function isValidDayInput(days) { - let today = Date.now() / 1000 - let isValid = !isNaN(days) - if (isValid) { - let addedSeconds = days * 86400 +function whitelist_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let sellValid = isValidDate(csv_line[1]) + let buyValid = isValidDate(csv_line[2]) + let kycExpiryDate = isValidDate(csv_line[3]) + let canBuyFromSTO = (typeof JSON.parse(csv_line[4].toLowerCase())) == "boolean" ? JSON.parse(csv_line[4].toLowerCase()) : "not-valid"; - let unixTimestamp = today + addedSeconds - console.log("unxitimestapm :" , (unixTimestamp)) + if (isAddress && + sellValid && + buyValid && + kycExpiryDate && + (canBuyFromSTO != "not-valid")) { + + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] - return unixTimestamp } else { - return false + + return [false, new Array(csv_line[0], sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] + } } @@ -288,15 +224,23 @@ function isValidDate(date) { var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(date); if (matches == null) return false; var d = matches[2]; - var m = matches[1] - 1; //not clear why this is -1, but it works after checking + var m = matches[1] - 1; var y = matches[3]; var composedDate = new Date(y, m, d); var timestampDate = composedDate.getTime() - //note, some reason these timestamps are being recorded +4 hours UTC - if (composedDate.getDate() == d && composedDate.getMonth() == m && composedDate.getFullYear() == y) { + // For some reason these timestamps are being recorded +4 hours UTC + if (composedDate.getDate() == d && + composedDate.getMonth() == m && + composedDate.getFullYear() == y) { return timestampDate / 1000 } else { return false } } + +module.exports = { + executeApp: async (tokenSymbol, batchSize) => { + return startScript(tokenSymbol, batchSize); + } +} \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index f802ab4c0..db0c02d9d 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -6,6 +6,7 @@ var investor_portal = require('./commands/investor_portal'); var module_manager = require('./commands/module_manager'); var st20generator = require('./commands/ST20Generator'); var transfer = require('./commands/transfer'); +var whitelist = require('./commands/whitelist'); var transfer_ownership = require('./commands/transfer_ownership'); var dividends_manager = require('./commands/dividends_manager'); var transfer_manager = require('./commands/transfer_manager'); @@ -101,7 +102,7 @@ program .description('Mass-update a whitelist of allowed/known investors') .action(async function(tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - shell.exec(`${__dirname}/commands/scripts/script.sh Whitelist ${tokenSymbol} ${batchSize} ${program.remoteNode}`); + await whitelist.executeApp(tokenSymbol, batchSize); }); program From 28f784b04867078e1eed61987d59415ac7f423a2 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 12 Nov 2018 23:46:54 +0200 Subject: [PATCH 077/582] added VestingEscrowWallet --- contracts/wallet/VestingEscrowWallet.sol | 109 +++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 contracts/wallet/VestingEscrowWallet.sol diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol new file mode 100644 index 000000000..4f178f289 --- /dev/null +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -0,0 +1,109 @@ +pragma solidity ^0.4.24; + +import "../../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol"; +import "../../node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../interfaces/IERC20.sol"; + +/** + * @title Wallet for core vesting escrow functionality + */ +contract VestingEscrowWallet is Ownable { + using SafeMath for uint256; + + struct VestingSchedule { + uint256 numberOfTokens; + uint256 vestingDuration; + uint256 vestingFrequency; + uint256 startDate; + } + + struct VestingData { + VestingSchedule[] schedules; + uint256 index; + } + + IERC20 public token; + address public treasury; + + uint256 public unassignedTokens; + + mapping (address => VestingData) internal schedules; + address[] users; + + event AddVestingSchedule( + address _user, + uint256 _numberOfTokens, + uint256 _vestingDuration, + uint256 _vestingFrequency, + uint256 _startDate, + uint256 _timestamp + ); + event RevokeVestingSchedules(address _user, uint256 _timestamp); + event RevokeVestingSchedule(address _user, uint256 index, uint256 _timestamp); + + constructor(address _tokenAddress, address _treasury) { + token = IERC20(_tokenAddress); + treasury = _treasury; + } + + function addVestingSchedule( + address _user, + uint256 _numberOfTokens, + uint256 _vestingDuration, + uint256 _vestingFrequency, + uint256 _startDate + ) + public + onlyOwner + { + //TODO validation + VestingSchedule schedule; + schedule.numberOfTokens = _numberOfTokens; + schedule.vestingDuration = _vestingDuration; + schedule.vestingFrequency = _vestingFrequency; + schedule.startDate = _startDate; + //add user to the schedule list only if adding first schedule + if (schedules[_user].schedules.length == 0) { + schedules[_user].index = users.length; + users.push(_user); + } + schedules[_user].schedules.push(schedule); + /*solium-disable-next-line security/no-block-members*/ + emit AddVestingSchedule(_user, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); + } + + function revokeVestingSchedule(address _user, uint256 index) public onlyOwner { + //TODO validation + + /*solium-disable-next-line security/no-block-members*/ + emit RevokeVestingSchedule(_user, index, now); + } + + function revokeVestingSchedules(address _user) public onlyOwner { + //TODO validation + uint256 index = schedules[_user].index; + users[index] = users[users.length - 1]; + users.length--; + if (index != users.length) { + schedules[users[index]].index = index; + } + delete schedules[_user]; + /*solium-disable-next-line security/no-block-members*/ + emit RevokeVestingSchedules(_user, now); + } + + function editVestingSchedule( + address _user, + uint256 index, + uint256 _numberOfTokens, + uint256 _vestingDuration, + uint256 _vestingFrequency, + uint256 _startDate + ) + public + onlyOwner + { + + } + +} From 34ef7e8c5476a626fe23fc7040089922a4860751 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 13 Nov 2018 10:59:15 +0530 Subject: [PATCH 078/582] Updated documentation --- CHANGELOG.md | 18 ++++++++++---- contracts/modules/STO/USDTieredSTO.sol | 33 +++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 869af0d8e..82d075303 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,26 @@ # Changelog All notable changes to this project will be documented in this file. -# v1.5.0 - Release Candidate +# v2.1.0 -[__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ +[__2.1.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-09-18__ ## Added * Added `getSTODetails` to USDTSTO. * Added an Array of Tiers that will hold data about every tier in USDTSTO. * Added `buyWithETHRateLimited`, `buyWithPOLYRateLimited` and `buyWithUSDRateLimited` to USDTSTO. + +##Changed +* `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. + +## Removed +* Individual mappings for tier data removed in UDSTSTO. + +# v1.5.0 - Release Candidate + +[__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ + +## Added * Added `getInvestorsAt` which returns the investors (non-zero balances) at a particular checkpoint * Added `iterateInvestors` to allow an a subset of `investors` to be returned from the security token in case `investors` is large. * `ChangeModuleBudget` in SecurityToken now takes in the change in budget rather than absoulte budget. Added boolean paramter to decide increase/decrease. @@ -37,7 +49,6 @@ All notable changes to this project will be documented in this file. * Add new function `modifyTickerDetails()`, To modify the details of undeployed ticker. #230 ## Fixed -* `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. * 0x0 and duplicate address in exclusions are no longer allowed in dividend modules. * All permissions are denied if no permission manager is active. * Generalize the STO varaible names and added them in `ISTO.sol` to use the common standard in all STOs. @@ -45,7 +56,6 @@ All notable changes to this project will be documented in this file. * Change the function name of `withdraPoly` to `withdrawERC20` and make the function generalize to extract tokens from the ST contract. parmeters are contract address and the value need to extract from the securityToken. ## Removed -* Individual mappings for tier data removed in UDSTSTO. * Removed investors list pruning * Remove `swarmHash` from the `registerTicker(), addCustomTicker(), generateSecurityToken(), addCustomSecurityToken()` functions of TickerRegistry.sol and SecurityTokenRegistry.sol. #230 * Remove `Log` prefix from all the event present in the ecosystem. diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index bd2df86c3..a210db45d 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -200,12 +200,21 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); } + /** + * @dev Modifies fund raise types + * @param _fundRaiseTypes Array of fund raise types to allow + */ function modifyFunding(FundRaiseType[] _fundRaiseTypes) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); _setFundRaiseType(_fundRaiseTypes); } + /** + * @dev modifies max non accredited invets limit and overall minimum investment limit + * @param _nonAccreditedLimitUSD max non accredited invets limit + * @param _minimumInvestmentUSD overall minimum investment limit + */ function modifyLimits( uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD @@ -215,6 +224,13 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); } + /** + * @dev modifiers STO tiers. All tiers must be passed, can not edit specific tiers. + * @param _ratePerTier Array of rates per tier + * @param _ratePerTierDiscountPoly Array of discounted poly rates per tier + * @param _tokensPerTierTotal Array of total tokens per tier + * @param _tokensPerTierDiscountPoly Array of discounted tokens per tier + */ function modifyTiers( uint256[] _ratePerTier, uint256[] _ratePerTierDiscountPoly, @@ -226,6 +242,11 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); } + /** + * @dev Modifies STO start and end times + * @param _startTime start time of sto + * @param _endTime end time of sto + */ function modifyTimes( uint256 _startTime, uint256 _endTime @@ -233,6 +254,12 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _modifyTimes(_startTime, _endTime); } + /** + * @dev Modifies addresses used as wallet, reserve wallet and usd token + * @param _wallet Address of wallet where funds are sent + * @param _reserveWallet Address of wallet where unsold tokens are sent + * @param _usdToken Address of usd token (DAI) + */ function modifyAddresses( address _wallet, address _reserveWallet, @@ -378,7 +405,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { buyWithETHRateLimited(msg.sender, 0); } - // For backwards compatibility + // Buy functions without rate restriction function buyWithETH(address _beneficiary) external payable { buyWithETHRateLimited(_beneficiary, 0); } @@ -620,6 +647,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { return (tiers[tiers.length - 1].mintedTotal == tiers[tiers.length - 1].tokenTotal); } + /** + * @dev returns current conversion rate of funds + * @param _fundRaiseType Fund raise type to get rate of + */ function getRate(FundRaiseType _fundRaiseType) public view returns (uint256) { if (_fundRaiseType == FundRaiseType.ETH) { return IOracle(_getOracle(bytes32("ETH"), bytes32("USD"))).getPrice(); From 937235bfaf92302fcdf3fcf80f6c23604f4025ec Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 13 Nov 2018 17:34:45 +0530 Subject: [PATCH 079/582] minor fix --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82d075303..f9ffcb644 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog All notable changes to this project will be documented in this file. -# v2.1.0 +# v2.1.0 - Release Candidate [__2.1.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-09-18__ @@ -16,7 +16,7 @@ All notable changes to this project will be documented in this file. ## Removed * Individual mappings for tier data removed in UDSTSTO. -# v1.5.0 - Release Candidate +# v1.5.0 [__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ @@ -63,7 +63,7 @@ All notable changes to this project will be documented in this file. ====== -# v1.4.1 - Release Candidate +# v1.4.1 [__1.4.1__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-08-18__ @@ -87,7 +87,7 @@ All notable changes to this project will be documented in this file. * Fix #238: make beneficial investments optionally supported (default to not allowed) -# v1.4.0 - Release candidate +# v1.4.0 [__1.4.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-08-18__ From e2c426202542303a3026d04248218364aa3aea91 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 13 Nov 2018 17:52:13 +0530 Subject: [PATCH 080/582] ignore the certificate --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 14c03d06b..cf13bd2e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ cache: matrix: fast_finish: true before_install: + - export GIT_SSL_NO_VERIFY=1 - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum - sudo apt-get -y update - sudo apt-get -y install solc From 2c91dc14564b44719788fa5efcabf7537ee6d209 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 13 Nov 2018 17:55:57 +0530 Subject: [PATCH 081/582] Allow unauthenticated repos --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cf13bd2e2..6ce84961a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,8 @@ cache: matrix: fast_finish: true before_install: - - export GIT_SSL_NO_VERIFY=1 - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum - - sudo apt-get -y update + - sudo apt-get -y update --allow-unauthenticated - sudo apt-get -y install solc before_script: - truffle version From 261f2a85a1048bce441cdb904a73dfcfe9b0b9c0 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 13 Nov 2018 18:02:52 +0530 Subject: [PATCH 082/582] Removed travis before install --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6ce84961a..caddfc523 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,6 @@ cache: - node_modules matrix: fast_finish: true -before_install: - - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum - - sudo apt-get -y update --allow-unauthenticated - - sudo apt-get -y install solc before_script: - truffle version - wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js From d7abab239a3afdcf5df5c44d51f283c1bb992a6c Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 13 Nov 2018 18:18:30 +0530 Subject: [PATCH 083/582] revamp the lockup --- .../LockupVolumeRestrictionTM.sol | 440 +++++++++--------- 1 file changed, 213 insertions(+), 227 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index 80f44cdb6..514f9f18f 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "./../../TransferManager/ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - contract LockupVolumeRestrictionTM is ITransferManager { using SafeMath for uint256; @@ -13,11 +12,10 @@ contract LockupVolumeRestrictionTM is ITransferManager { // a per-user lockup struct LockUp { - uint lockUpPeriodSeconds; // total period of lockup (seconds) - uint releaseFrequencySeconds; // how often to release a tranche of tokens (seconds) - uint startTime; // when this lockup starts (seconds) - uint totalAmount; // total amount of locked up tokens - uint alreadyWithdrawn; // amount already withdrawn for this lockup + uint256 lockupAmount; // Amount to be locked + uint256 startTime; // when this lockup starts (seconds) + uint256 lockUpPeriodSeconds; // total period of lockup (seconds) + uint256 releaseFrequencySeconds; // how often to release a tranche of tokens (seconds) } // maps user addresses to an array of lockups for that user @@ -25,29 +23,32 @@ contract LockupVolumeRestrictionTM is ITransferManager { event AddNewLockUp( address indexed userAddress, - uint lockUpPeriodSeconds, - uint releaseFrequencySeconds, - uint startTime, - uint totalAmount, - uint indexed addedIndex + uint256 lockupAmount, + uint256 startTime, + uint256 lockUpPeriodSeconds, + uint256 releaseFrequencySeconds, + uint256 indexed lockupIndex ); event RemoveLockUp( address indexed userAddress, - uint lockUpPeriodSeconds, - uint releaseFrequencySeconds, - uint startTime, - uint totalAmount, - uint indexed removedIndex + uint256 indexed lockupIndex ); event ModifyLockUp( address indexed userAddress, - uint lockUpPeriodSeconds, - uint releaseFrequencySeconds, - uint startTime, - uint totalAmount, - uint indexed modifiedIndex + uint256 lockupAmount, + uint256 startTime, + uint256 lockUpPeriodSeconds, + uint256 releaseFrequencySeconds, + uint256 indexed lockupIndex + ); + + event ChangeLockupIndex( + address indexed _userAddress, + uint256 indexed _oldLockupIndex, + uint256 indexed _newLockupIndex, + uint256 _timestamp ); /** @@ -61,17 +62,16 @@ contract LockupVolumeRestrictionTM is ITransferManager { { } - /** @notice Used to verify the transfer transaction and prevent locked up tokens from being transferred * @param _from Address of the sender * @param _amount The amount of tokens to transfer * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable */ - function verifyTransfer(address _from, address /* _to*/, uint256 _amount, bytes /* _data */, bool _isTransfer) public returns(Result) { + function verifyTransfer(address _from, address /* _to*/, uint256 _amount, bytes /* _data */, bool /*_isTransfer*/) public returns(Result) { // only attempt to verify the transfer if the token is unpaused, this isn't a mint txn, and there exists a lockup for this user - if (!paused && _from != address(0) && lockUps[_from].length != 0) { + if (!paused && _from != address(0) && lockUps[_from].length != 0) { // check if this transfer is valid - return _checkIfValidTransfer(_from, _amount, _isTransfer); + return _checkIfValidTransfer(_from, _amount); } return Result.NA; } @@ -79,64 +79,65 @@ contract LockupVolumeRestrictionTM is ITransferManager { /** * @notice Lets the admin create a volume restriction lockup for a given address. * @param _userAddress Address of the user whose tokens should be locked up + * @param _lockupAmount Amount of tokens that need to lock. + * @param _startTime When this lockup starts (seconds) * @param _lockUpPeriodSeconds Total period of lockup (seconds) * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) - * @param _startTime When this lockup starts (seconds) - * @param _totalAmount Total amount of locked up tokens */ function addLockUp( address _userAddress, - uint _lockUpPeriodSeconds, - uint _releaseFrequencySeconds, - uint _startTime, - uint _totalAmount - ) public withPerm(ADMIN) { - uint256 startTime = _startTime; - _checkLockUpParams(_lockUpPeriodSeconds, _releaseFrequencySeconds, _totalAmount); - - // if a startTime of 0 is passed in, then start now. - if (startTime == 0) { - /*solium-disable-next-line security/no-block-members*/ - startTime = now; - } - - lockUps[_userAddress].push(LockUp(_lockUpPeriodSeconds, _releaseFrequencySeconds, startTime, _totalAmount, 0)); + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds + ) + public + withPerm(ADMIN) + { + /*solium-disable-next-line security/no-block-members*/ + require(_startTime >= now, "start time is in past"); + _checkLockUpParams(_userAddress, _lockupAmount, _lockUpPeriodSeconds, _releaseFrequencySeconds); + + lockUps[_userAddress].push(LockUp(_lockupAmount, _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds)); emit AddNewLockUp( _userAddress, + _lockupAmount, + _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds, - startTime, - _totalAmount, - lockUps[_userAddress].length - 1 + lockUps[_userAddress].length -1 ); } /** * @notice Lets the admin create multiple volume restriction lockups for multiple given addresses. * @param _userAddresses Array of address of the user whose tokens should be locked up + * @param _lockupAmounts Array of the amounts that need to be locked for the different addresses. + * @param _startTimes Array of When this lockup starts (seconds) * @param _lockUpPeriodsSeconds Array of total periods of lockup (seconds) * @param _releaseFrequenciesSeconds Array of how often to release a tranche of tokens (seconds) - * @param _startTimes Array of When this lockup starts (seconds) - * @param _totalAmounts Array of total amount of locked up tokens */ function addLockUpMulti( address[] _userAddresses, - uint[] _lockUpPeriodsSeconds, - uint[] _releaseFrequenciesSeconds, - uint[] _startTimes, - uint[] _totalAmounts - ) external withPerm(ADMIN) { + uint256[] _lockupAmounts, + uint256[] _startTimes, + uint256[] _lockUpPeriodsSeconds, + uint256[] _releaseFrequenciesSeconds + ) + external + withPerm(ADMIN) + { require( _userAddresses.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ _userAddresses.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _startTimes.length && - _userAddresses.length == _totalAmounts.length, + _userAddresses.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _lockupAmounts.length, "Input array length mismatch" ); for (uint i = 0; i < _userAddresses.length; i++) { - addLockUp(_userAddresses[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i], _startTimes[i], _totalAmounts[i]); + addLockUp(_userAddresses[i], _lockupAmounts[i], _startTimes[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i]); } } @@ -144,76 +145,129 @@ contract LockupVolumeRestrictionTM is ITransferManager { /** * @notice Lets the admin remove a user's lock up * @param _userAddress Address of the user whose tokens are locked up - * @param _lockUpIndex The index of the LockUp to remove for the given userAddress + * @param _lockupIndex Index of the lockup need to be removed. */ - function removeLockUp(address _userAddress, uint _lockUpIndex) public withPerm(ADMIN) { - LockUp[] storage userLockUps = lockUps[_userAddress]; - require(_lockUpIndex < userLockUps.length, "Array out of bounds exception"); - - LockUp memory toRemove = userLockUps[_lockUpIndex]; + function removeLockUp(address _userAddress, uint256 _lockupIndex) public withPerm(ADMIN) { + require(lockUps[_userAddress].length > _lockupIndex, "Invalid index"); + LockUp[] storage userLockup = lockUps[_userAddress]; emit RemoveLockUp( _userAddress, - toRemove.lockUpPeriodSeconds, - toRemove.releaseFrequencySeconds, - toRemove.startTime, - toRemove.totalAmount, - _lockUpIndex + _lockupIndex ); - if (_lockUpIndex < userLockUps.length - 1) { + if (_lockupIndex != userLockup.length - 1) { // move the last element in the array into the index that is desired to be removed. - userLockUps[_lockUpIndex] = userLockUps[userLockUps.length - 1]; + userLockup[_lockupIndex] = userLockup[userLockup.length - 1]; + /*solium-disable-next-line security/no-block-members*/ + emit ChangeLockupIndex(_userAddress, userLockup.length - 1, _lockupIndex, now); + } + userLockup.length--; + } + + /** + * @notice Use to remove the lockup for multiple users + * @param _userAddresses Array of addresses of the user whose tokens are locked up + * @param _lockupIndexes Array of the indexes to the lockup that needs to be removed. + */ + function removeLockUpMulti(address[] _userAddresses, uint256[] _lockupIndexes) external withPerm(ADMIN) { + require(_userAddresses.length == _lockupIndexes.length, "Array length mismatch"); + for (uint i = 0; i < _userAddresses.length; i++) { + removeLockUp(_userAddresses[i], _lockupIndexes[i]); } - // delete the last element - userLockUps.length--; } /** * @notice Lets the admin modify a volume restriction lockup for a given address. * @param _userAddress Address of the user whose tokens should be locked up - * @param _lockUpIndex The index of the LockUp to edit for the given userAddress + * @param _lockupAmount Amount of tokens that needs to be locked + * @param _startTime When this lockup starts (seconds) * @param _lockUpPeriodSeconds Total period of lockup (seconds) * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) - * @param _startTime When this lockup starts (seconds) - * @param _totalAmount Total amount of locked up tokens + * @param _lockupIndex Index of the lockup that needs to be modified. */ function modifyLockUp( address _userAddress, - uint _lockUpIndex, - uint _lockUpPeriodSeconds, - uint _releaseFrequencySeconds, - uint _startTime, - uint _totalAmount - ) public withPerm(ADMIN) { - require(_lockUpIndex < lockUps[_userAddress].length, "Array out of bounds exception"); - - uint256 startTime = _startTime; - // if a startTime of 0 is passed in, then start now. - if (startTime == 0) { + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + uint256 _lockupIndex + ) + public + withPerm(ADMIN) + { + require(lockUps[_userAddress].length > _lockupIndex, "Invalid index"); + + // Get the lockup from the master list and edit it + LockUp[] storage userLockup = lockUps[_userAddress]; + // If _startTime is equal to the previous startTime then it only allow to modify + // when there is no tokens gets unlocked from the lockup + if (_startTime == userLockup[_lockupIndex].startTime) { + require(_getUnlockedAmountForLockup(userLockup, _lockupIndex) == uint256(0)); + } else { /*solium-disable-next-line security/no-block-members*/ - startTime = now; + require(_startTime >= now, "start time is in past"); } - - _checkLockUpParams(_lockUpPeriodSeconds, _releaseFrequencySeconds, _totalAmount); - - // Get the lockup from the master list and edit it - lockUps[_userAddress][_lockUpIndex] = LockUp( + _checkLockUpParams( + _userAddress, + _lockupAmount, _lockUpPeriodSeconds, - _releaseFrequencySeconds, - startTime, - _totalAmount, - lockUps[_userAddress][_lockUpIndex].alreadyWithdrawn + _releaseFrequencySeconds ); + userLockup[_lockupIndex] = LockUp( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds + ); + emit ModifyLockUp( _userAddress, + _lockupAmount, + _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds, - startTime, - _totalAmount, - _lockUpIndex + _lockupIndex + ); + } + + /** + * @notice Lets the admin modify a volume restriction lockup for a multiple address. + * @param _userAddresses Array of address of the user whose tokens should be locked up + * @param _lockupAmounts Array of the amount of tokens that needs to be locked for the respective addresses. + * @param _startTimes Array of the start time of the lockups (seconds) + * @param _lockUpPeriodsSeconds Array of unix timestamp for the list of lockups (seconds). + * @param _releaseFrequenciesSeconds How often to release a tranche of tokens (seconds) + * @param _lockupIndexes Array of the lockup indexes that needs to be modified + */ + function modifyLockUpMulti( + address[] _userAddresses, + uint256[] _lockupAmounts, + uint256[] _startTimes, + uint256[] _lockUpPeriodsSeconds, + uint256[] _releaseFrequenciesSeconds, + uint256[] _lockupIndexes + ) public withPerm(ADMIN) { + require( + _userAddresses.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _lockupAmounts.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _lockupIndexes.length, + "Input array length mismatch" ); + for (uint256 i = 0; i < _userAddresses.length; i++) { + modifyLockUp( + _userAddresses[i], + _lockupAmounts[i], + _startTimes[i], + _lockUpPeriodsSeconds[i], + _releaseFrequenciesSeconds[i], + _lockupIndexes[i] + ); + } } /** @@ -229,164 +283,96 @@ contract LockupVolumeRestrictionTM is ITransferManager { * @param _userAddress Address of the user whose tokens should be locked up * @param _lockUpIndex The index of the LockUp to edit for the given userAddress */ - function getLockUp( - address _userAddress, - uint _lockUpIndex) - public view returns ( - uint lockUpPeriodSeconds, - uint releaseFrequencySeconds, - uint startTime, - uint totalAmount, - uint alreadyWithdrawn - ) { - require(_lockUpIndex < lockUps[_userAddress].length, "Array out of bounds exception"); - LockUp storage userLockUp = lockUps[_userAddress][_lockUpIndex]; + function getLockUp( address _userAddress, uint _lockUpIndex) public view returns ( + uint256 lockupAmount, + uint256 startTime, + uint256 lockUpPeriodSeconds, + uint256 releaseFrequencySeconds, + uint256 unlockedAmount + ) { + require(lockUps[_userAddress].length > _lockUpIndex, "Invalid index"); + LockUp[] memory userLockup = lockUps[_userAddress]; return ( - userLockUp.lockUpPeriodSeconds, - userLockUp.releaseFrequencySeconds, - userLockUp.startTime, - userLockUp.totalAmount, - userLockUp.alreadyWithdrawn + userLockup[_lockUpIndex].lockupAmount, + userLockup[_lockUpIndex].startTime, + userLockup[_lockUpIndex].lockUpPeriodSeconds, + userLockup[_lockUpIndex].releaseFrequencySeconds, + _getUnlockedAmountForLockup(userLockup, _lockUpIndex) ); } /** - * @notice Takes a userAddress as input, and returns a uint that represents the number of tokens allowed to be withdrawn right now - * @param userAddress Address of the user whose lock ups should be checked + * @notice Checks whether the transfer is allowed + * @param _userAddress Address of the user whose lock ups should be checked + * @param _amount Amount of tokens that need to transact */ - function _checkIfValidTransfer(address userAddress, uint amount, bool isTransfer) internal returns (Result) { - // get lock up array for this user - LockUp[] storage userLockUps = lockUps[userAddress]; - - // maps the index of userLockUps to the amount allowed in this transfer - uint[] memory allowedAmountPerLockup = new uint[](userLockUps.length); - - uint[3] memory tokenSums = [ - uint256(0), // allowed amount right now - uint256(0), // total locked up, ever - uint256(0) // already withdrawn, ever - ]; - - // loop over the user's lock ups - for (uint i = 0; i < userLockUps.length; i++) { - LockUp storage aLockUp = userLockUps[i]; - - uint allowedAmountForThisLockup = 0; - - // check if lockup has entirely passed - /*solium-disable-next-line security/no-block-members*/ - if (now >= aLockUp.startTime.add(aLockUp.lockUpPeriodSeconds)) { - // lockup has passed, or not started yet. allow all. - allowedAmountForThisLockup = aLockUp.totalAmount.sub(aLockUp.alreadyWithdrawn); - /*solium-disable-next-line security/no-block-members*/ - } else if (now >= aLockUp.startTime) { - // lockup is active. calculate how many to allow to be withdrawn right now - // calculate how many periods have elapsed already - /*solium-disable-next-line security/no-block-members*/ - uint elapsedPeriods = (now.sub(aLockUp.startTime)).div(aLockUp.releaseFrequencySeconds); - // calculate the total number of periods, overall - uint totalPeriods = aLockUp.lockUpPeriodSeconds.div(aLockUp.releaseFrequencySeconds); - // calculate how much should be released per period - uint amountPerPeriod = aLockUp.totalAmount.div(totalPeriods); - // calculate the number of tokens that should be released, - // multiplied by the number of periods that have elapsed already - // and add it to the total tokenSums[0] - allowedAmountForThisLockup = amountPerPeriod.mul(elapsedPeriods).sub(aLockUp.alreadyWithdrawn); - - } - // tokenSums[0] is allowed sum - tokenSums[0] = tokenSums[0].add(allowedAmountForThisLockup); - // tokenSums[1] is total locked up - tokenSums[1] = tokenSums[1].add(aLockUp.totalAmount); - // tokenSums[2] is total already withdrawn - tokenSums[2] = tokenSums[2].add(aLockUp.alreadyWithdrawn); - - allowedAmountPerLockup[i] = allowedAmountForThisLockup; - } - - // tokenSums[0] is allowed sum - if (amount <= tokenSums[0]) { - // transfer is valid and will succeed. - if (!isTransfer) { - // if this isn't a real transfer, don't subtract the withdrawn amounts from the lockups. it's a "read only" txn - return Result.VALID; - } - - // we are going to write the withdrawn balances back to the lockups, so make sure that the person calling this function is the securityToken itself, since its public - require(msg.sender == securityToken, "Sender is not securityToken"); - - // subtract amounts so they are now known to be withdrawen - for (i = 0; i < userLockUps.length; i++) { - aLockUp = userLockUps[i]; - - // tokenSums[0] is allowed sum - if (allowedAmountPerLockup[i] >= tokenSums[0]) { - aLockUp.alreadyWithdrawn = aLockUp.alreadyWithdrawn.add(tokenSums[0]); - // we withdrew the entire tokenSums[0] from the lockup. We are done. - break; - } else { - // we have to split the tokenSums[0] across mutiple lockUps - aLockUp.alreadyWithdrawn = aLockUp.alreadyWithdrawn.add(allowedAmountPerLockup[i]); - // subtract the amount withdrawn from this lockup - tokenSums[0] = tokenSums[0].sub(allowedAmountPerLockup[i]); - } - - } - return Result.VALID; + function _checkIfValidTransfer(address _userAddress, uint256 _amount) internal view returns (Result) { + LockUp[] memory userLockup = lockUps[_userAddress]; + uint256 totalRemainingLockedAmount = 0; + for (uint256 i = 0; i < userLockup.length; i++) { + // Find out the remaining locked amount for a given lockup + uint256 remainingLockedAmount = userLockup[i].lockupAmount.sub(_getUnlockedAmountForLockup(userLockup, i)); + // aggregating all the remaining locked amount for all the lockups for a given address + totalRemainingLockedAmount = totalRemainingLockedAmount.add(remainingLockedAmount); } - - return _checkIfUnlockedTokenTransferIsPossible(userAddress, amount, tokenSums[1], tokenSums[2]); - } - - function _checkIfUnlockedTokenTransferIsPossible( - address userAddress, - uint amount, - uint totalSum, - uint alreadyWithdrawnSum - ) internal view returns (Result) { - // the amount the user wants to withdraw is greater than their allowed amounts according to the lockups. however, if the user has like, 10 tokens, but only 4 are locked up, we should let the transfer go through for those 6 that aren't locked up - uint currentUserBalance = ISecurityToken(securityToken).balanceOf(userAddress); - uint stillLockedAmount = totalSum.sub(alreadyWithdrawnSum); - if (currentUserBalance >= stillLockedAmount && amount <= currentUserBalance.sub(stillLockedAmount)) { - // the user has more tokens in their balance than are actually locked up. they should be allowed to withdraw the difference + // Present balance of the user + uint256 currentBalance = ISecurityToken(securityToken).balanceOf(_userAddress); + if ((currentBalance.sub(_amount)) >= totalRemainingLockedAmount) { return Result.VALID; } return Result.INVALID; } + /** + * @notice Provide the unlock amount for the given lockup for a particular user + */ + function _getUnlockedAmountForLockup(LockUp[] userLockup, uint256 _lockupIndex) internal view returns (uint256) { + // Calculate the no. of periods for a lockup + uint256 noOfPeriods = (userLockup[_lockupIndex].lockUpPeriodSeconds).div(userLockup[_lockupIndex].releaseFrequencySeconds); + // Calculate the transaction time lies in which period + uint256 elapsedPeriod = (now.sub(userLockup[_lockupIndex].startTime)).div(userLockup[_lockupIndex].releaseFrequencySeconds); + // Calculate the allowed unlocked amount per period + uint256 amountPerPeriod = (userLockup[_lockupIndex].lockupAmount).div(noOfPeriods); + // Find out the unlocked amount for a given lockup + uint256 unLockedAmount = elapsedPeriod.mul(amountPerPeriod); + return unLockedAmount; + } /** * @notice Parameter checking function for creating or editing a lockup. This function will cause an exception if any of the parameters are bad. - * @param lockUpPeriodSeconds Total period of lockup (seconds) - * @param releaseFrequencySeconds How often to release a tranche of tokens (seconds) - * @param totalAmount Total amount of locked up tokens + * @param _userAddress Address whom lockup is being applied + * @param _lockupAmount Amount that needs to be locked + * @param _lockUpPeriodSeconds Total period of lockup (seconds) + * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) */ - function _checkLockUpParams(uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint totalAmount) internal view { - require(lockUpPeriodSeconds != 0, "lockUpPeriodSeconds cannot be zero"); - require(releaseFrequencySeconds != 0, "releaseFrequencySeconds cannot be zero"); - require(totalAmount != 0, "totalAmount cannot be zero"); + function _checkLockUpParams( + address _userAddress, + uint256 _lockupAmount, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds + ) + internal + view + { + require(_userAddress != address(0), "Invalid address"); + require(_lockUpPeriodSeconds != 0, "lockUpPeriodSeconds cannot be zero"); + require(_releaseFrequencySeconds != 0, "releaseFrequencySeconds cannot be zero"); // check that the total amount to be released isn't too granular require( - totalAmount % ISecurityToken(securityToken).granularity() == 0, + _lockupAmount % ISecurityToken(securityToken).granularity() == 0, "The total amount to be released is more granular than allowed by the token" ); // check that releaseFrequencySeconds evenly divides lockUpPeriodSeconds require( - lockUpPeriodSeconds % releaseFrequencySeconds == 0, + _lockUpPeriodSeconds % _releaseFrequencySeconds == 0, "lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds" ); - // check that totalPeriods evenly divides totalAmount - uint totalPeriods = lockUpPeriodSeconds.div(releaseFrequencySeconds); - require( - totalAmount % totalPeriods == 0, - "The total amount being locked up must be evenly divisible by the number of total periods" - ); - // make sure the amount to be released per period is not too granular for the token - uint amountPerPeriod = totalAmount.div(totalPeriods); + uint256 totalPeriods = _lockUpPeriodSeconds.div(_releaseFrequencySeconds); + uint256 amountPerPeriod = _lockupAmount.div(totalPeriods); require( amountPerPeriod % ISecurityToken(securityToken).granularity() == 0, "The amount to be released per period is more granular than allowed by the token" From 018fee2d3137b48ea50a85805840cf03d4021e33 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 13 Nov 2018 18:49:03 +0530 Subject: [PATCH 084/582] Configuration by factory allowed only once --- contracts/modules/STO/USDTieredSTO.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index a210db45d..44569d469 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -192,6 +192,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { address _reserveWallet, address _usdToken ) public onlyFactory { + require(endTime == 0, "Already configured"); _modifyTimes(_startTime, _endTime); _modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); // NB - _setFundRaiseType must come before modifyAddresses From 2ee91c488223302f62d4847c74cae1c8e6851f00 Mon Sep 17 00:00:00 2001 From: Polymath Date: Tue, 13 Nov 2018 10:23:12 -0300 Subject: [PATCH 085/582] Multi mint refactor --- CLI/commands/OLD_multi_mint.js | 280 ++++++++++++++++++++++++++++++++ CLI/commands/multi_mint.js | 281 +++++++++++++++------------------ CLI/polymath-cli.js | 3 +- 3 files changed, 410 insertions(+), 154 deletions(-) create mode 100644 CLI/commands/OLD_multi_mint.js diff --git a/CLI/commands/OLD_multi_mint.js b/CLI/commands/OLD_multi_mint.js new file mode 100644 index 000000000..d550fcd3e --- /dev/null +++ b/CLI/commands/OLD_multi_mint.js @@ -0,0 +1,280 @@ +var fs = require('fs'); +var csv = require('fast-csv'); +var BigNumber = require('bignumber.js'); +const chalk = require('chalk'); +var common = require('./common/common_functions'); +var global = require('./common/global'); + +/////////////////////////////ARTIFACTS////////////////////////////////////////// +var contracts = require('./helpers/contract_addresses'); +var abis = require('./helpers/contract_abis'); + +const STO_KEY = 3; + +let securityToken; + +////////////////////////////USER INPUTS////////////////////////////////////////// +let tokenSymbol = process.argv.slice(2)[0]; //token symbol +let BATCH_SIZE = process.argv.slice(2)[1]; //batch size +if (!BATCH_SIZE) BATCH_SIZE = 75; +let remoteNetwork = process.argv.slice(2)[2]; + +/////////////////////////GLOBAL VARS////////////////////////////////////////// + +//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] +let distribData = new Array(); +//allocData is a temporary array that stores up to the batch size, +//then gets push into distribData, then gets set to 0 to start another batch +let allocData = new Array(); +//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] +let fullFileData = new Array(); +let badData = new Array(); + +//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// + +startScript(); + +async function startScript() { + if (remoteNetwork == 'undefined') remoteNetwork = undefined; + await global.initialize(remoteNetwork); + + try { + let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); + let securityTokenRegistryABI = abis.securityTokenRegistry(); + securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); + securityTokenRegistry.setProvider(web3.currentProvider); + + console.log("Processing investor CSV upload. Batch size is "+BATCH_SIZE+" accounts per transaction"); + readFile(); + } catch (err) { + console.log(err) + console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); + return; + } +} + +function readFile() { + var stream = fs.createReadStream("./CLI/data/multi_mint_data.csv"); + + let index = 0; + let batch = 0; + console.log(` + -------------------------------------------- + ----------- Parsing the csv file ----------- + -------------------------------------------- + `); + + var csvStream = csv() + .on("data", function (data) { + let isAddress = web3.utils.isAddress(data[0]); + let validToken = isvalidToken(data[1]); + + if (isAddress && validToken) { + let userArray = new Array() + let checksummedAddress = web3.utils.toChecksumAddress(data[0]); + + userArray.push(checksummedAddress) + userArray.push(validToken) + allocData.push(userArray); + fullFileData.push(userArray); + index++; + if (index >= 75) { + distribData.push(allocData); + allocData = []; + index = 0; + } + + } else { + let userArray = new Array() + //dont need this here, as if it is NOT an address this function will fail + //let checksummedAddress = web3.utils.toChecksumAddress(data[1]); + userArray.push(data[0]) + userArray.push(data[1]); + badData.push(userArray); + fullFileData.push(userArray) + } + }) + .on("end", function () { + //Add last remainder batch + distribData.push(allocData); + allocData = []; + + mint_tokens_for_affliliates(); + }); + + stream.pipe(csvStream); + } + + async function mint_tokens_for_affliliates() { + let tokenDeployed = false; + let tokenDeployedAddress; + // Let's check if token has already been deployed, if it has, skip to STO + await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { + if (result != "0x0000000000000000000000000000000000000000") { + console.log('\x1b[32m%s\x1b[0m', "Token deployed at address " + result + "."); + tokenDeployedAddress = result; + tokenDeployed = true; + } + }); + if (tokenDeployed) { + let securityTokenABI = abis.securityToken(); + securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); + } + let modules = await securityToken.methods.getModulesByType(STO_KEY).call(); + if (modules.length == 0) { + console.log("****************************************************************************************\n"); + console.log("*************" + chalk.red(" Minting of tokens is only allowed before the STO get attached ") + "************\n"); + console.log("****************************************************************************************\n"); + process.exit(0); + } + console.log(` + ------------------------------------------------------- + ------------ Mint the tokens to affiliates ------------ + ------------------------------------------------------- + `); + + let affiliatesFailedArray = []; + let affiliatesKYCInvalidArray = []; + //this for loop will do the batches, so it should run 75, 75, 50 with 200 + for (let i = 0; i < distribData.length; i++) { + try { + let affiliatesVerifiedArray = []; + let tokensVerifiedArray = []; + //splitting the user arrays to be organized by input + for (let j = 0; j < distribData[i].length; j++) { + let investorAccount = distribData[i][j][0]; + let tokenAmount = web3.utils.toWei((distribData[i][j][1]).toString(),"ether"); + let verifiedTransaction = await securityToken.methods.verifyTransfer("0x0000000000000000000000000000000000000000", investorAccount, tokenAmount, web3.utils.fromAscii('')).call(); + if (verifiedTransaction) { + affiliatesVerifiedArray.push(investorAccount); + tokensVerifiedArray.push(tokenAmount); + } else { + let gtmModule = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + let generalTransferManagerABI = abis.generalTransferManager(); + let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, gtmModule[0]); + let validKYC = (await generalTransferManager.methods.whitelist(Issuer.address).call()).expiryTime > Math.floor(Date.now()/1000); + if (validKYC) { + affiliatesFailedArray.push(investorAccount); + } else { + affiliatesKYCInvalidArray.push(investorAccount); + } + } + } + let mintMultiAction = securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); + let r = await common.sendTransaction(mintMultiAction); + console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); + console.log("Multi Mint transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); + + + } catch (err) { + console.log("ERROR:", err); + } + } + + console.log("Retrieving logs to determine investors have had their tokens correctly.\n\n") + + let totalInvestors = 0; + let updatedInvestors = 0; + + let investorData_Events = new Array(); + let investorObjectLookup = {}; + + let event_data = await securityToken.getPastEvents('Minted', { + fromBlock: 0, + toBlock: 'latest' + }, function (error, events) { + + }); + + for (var i = 0; i < event_data.length; i++) { + let combineArray = []; + + let investorAddress_Event = event_data[i].returnValues._to; + let amount_Event = event_data[i].returnValues._value; + let blockNumber = event_data[i].blockNumber + + combineArray.push(investorAddress_Event); + combineArray.push(amount_Event); + combineArray.push(blockNumber); + + investorData_Events.push(combineArray) + //we have already recorded it, so this is an update to our object + if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { + + //the block number form the event we are checking is bigger, so we gotta replace it + if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { + investorObjectLookup[investorAddress_Event] = { amount: amount_Event, recordedBlockNumber: blockNumber }; + updatedInvestors += 1; + // investorAddress_Events.push(investorAddress_Event); not needed, because we start the obj with zero events + + } else { + //do nothing. so if we find an event, and it was an older block, its old, we dont care + } + //we have never recorded this address as an object key, so we need to add it to our list of investors updated by the csv + } else { + investorObjectLookup[investorAddress_Event] = { amount: amount_Event, recordedBlockNumber: blockNumber }; + totalInvestors += 1; + // investorAddress_Events.push(investorAddress_Event); + } + } + let investorAddress_Events = Object.keys(investorObjectLookup) + + console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); + console.log(`A total of ${totalInvestors} affiliated investors get the token\n`); + console.log(`This script in total sent ${fullFileData.length - badData.length - affiliatesFailedArray.length - affiliatesKYCInvalidArray.length} new investors and updated investors to the blockchain.\n`); + console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); + console.log(`There were ${affiliatesKYCInvalidArray.length} accounts with invalid KYC.\n`); + console.log(`There were ${affiliatesFailedArray.length} accounts that didn't get sent to the blockchain as they would fail.\n`); + + console.log("************************************************************************************************"); + console.log("OBJECT WITH EVERY USER AND THEIR MINTED TOKEN: \n\n", investorObjectLookup) + console.log("************************************************************************************************"); + console.log("LIST OF ALL INVESTORS WHO GOT THE MINTED TOKENS: \n\n", investorAddress_Events) + + let missingDistribs = []; + let failedVerificationDistribs = []; + let invalidKYCDistribs = []; + for (let l = 0; l < fullFileData.length; l++) { + if (affiliatesKYCInvalidArray.includes(fullFileData[l][0])) { + invalidKYCDistribs.push(fullFileData[l]); + } else if (affiliatesFailedArray.includes(fullFileData[l][0])) { + failedVerificationDistribs.push(fullFileData[l]); + } else if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { + missingDistribs.push(fullFileData[l]); + } + } + + if (invalidKYCDistribs.length > 0) { + console.log("**************************************************************************************************************************"); + console.log("The following data arrays have an invalid KYC. Please review if these accounts are whitelisted and their KYC is not expired\n"); + console.log(invalidKYCDistribs); + console.log("**************************************************************************************************************************"); + } + if (failedVerificationDistribs.length > 0) { + console.log("*********************************************************************************************************"); + console.log("-- The following data arrays failed at verifyTransfer. Please review if these accounts are whitelisted --\n"); + console.log(failedVerificationDistribs); + console.log("*********************************************************************************************************"); + } + if (missingDistribs.length > 0) { + console.log("******************************************************************************************"); + console.log("-- No Minted event was found for the following data arrays. Please review them manually --\n"); + console.log(missingDistribs); + console.log("******************************************************************************************"); + } + if (missingDistribs.length == 0 && failedVerificationDistribs.length == 0 && invalidKYCDistribs.length == 0) { + console.log("\n**************************************************************************************************************************"); + console.log("All accounts passed through from the CSV were successfully get the tokens, because we were able to read them all from events"); + console.log("****************************************************************************************************************************"); + } +} + +function isvalidToken(token) { + var tokenAmount = parseInt(token); + if((tokenAmount % 1 == 0)) { + return tokenAmount; + } + return false; +} diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index b138ef849..4e83c4190 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -1,157 +1,118 @@ +var common = require('./common/common_functions'); var fs = require('fs'); var csv = require('fast-csv'); -var BigNumber = require('bignumber.js'); -const chalk = require('chalk'); -var common = require('./common/common_functions'); -var global = require('./common/global'); - -/////////////////////////////ARTIFACTS////////////////////////////////////////// var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); +var BigNumber = require('bignumber.js'); -const STO_KEY = 3; - -let securityToken; - -////////////////////////////USER INPUTS////////////////////////////////////////// -let tokenSymbol = process.argv.slice(2)[0]; //token symbol -let BATCH_SIZE = process.argv.slice(2)[1]; //batch size -if (!BATCH_SIZE) BATCH_SIZE = 75; -let remoteNetwork = process.argv.slice(2)[2]; - -/////////////////////////GLOBAL VARS////////////////////////////////////////// - -//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] let distribData = new Array(); -//allocData is a temporary array that stores up to the batch size, -//then gets push into distribData, then gets set to 0 to start another batch let allocData = new Array(); -//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] let fullFileData = new Array(); let badData = new Array(); +let BATCH_SIZE = 75; +let securityToken; +let affiliatesFailedArray = new Array(); +let affiliatesKYCInvalidArray = new Array(); -//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// +async function startScript(tokenSymbol, batchSize) { + if (batchSize) { + BATCH_SIZE = batchSize; + } + + common.logAsciiBull(); -startScript(); + let STAddress = await checkST(tokenSymbol); + securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); + + await readCsv(); +}; -async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); +async function checkST(tokenSymbol) { + let securityTokenRegistry = await STConnect(); - try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); + return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { + if (result != "0x0000000000000000000000000000000000000000") { + return result + } else { + console.log("Token doesn't exist") + process.exit(0) + } + }); +} - console.log("Processing investor CSV upload. Batch size is "+BATCH_SIZE+" accounts per transaction"); - readFile(); +async function STConnect() { + try { + let STRegistryAddress = await contracts.securityTokenRegistry(); + let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); + return STRegistry; } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); - return; + console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); + process.exit(0); } } -function readFile() { - var stream = fs.createReadStream("./CLI/data/multi_mint_data.csv"); - - let index = 0; - let batch = 0; - console.log(` - -------------------------------------------- - ----------- Parsing the csv file ----------- - -------------------------------------------- - `); - - var csvStream = csv() - .on("data", function (data) { - let isAddress = web3.utils.isAddress(data[0]); - let validToken = isvalidToken(data[1]); - - if (isAddress && validToken) { - let userArray = new Array() - let checksummedAddress = web3.utils.toChecksumAddress(data[0]); - - userArray.push(checksummedAddress) - userArray.push(validToken) - allocData.push(userArray); - fullFileData.push(userArray); - index++; - if (index >= 75) { - distribData.push(allocData); - allocData = []; - index = 0; - } - - } else { - let userArray = new Array() - //dont need this here, as if it is NOT an address this function will fail - //let checksummedAddress = web3.utils.toChecksumAddress(data[1]); - userArray.push(data[0]) - userArray.push(data[1]); - badData.push(userArray); - fullFileData.push(userArray) +async function readCsv() { + var CSV_STRING = fs.readFileSync("./CLI/data/multi_mint_data.csv").toString(); + let i = 0; + + csv.fromString(CSV_STRING) + .on("data", (data) => { + let data_processed = multimint_processing(data); + fullFileData.push(data_processed[1]); + + if (data_processed[0]) { + allocData.push(data_processed[1]); + i++; + if (i >= BATCH_SIZE) { + distribData.push(allocData); + allocData = []; + i = 0; } - }) - .on("end", function () { - //Add last remainder batch - distribData.push(allocData); - allocData = []; + } else { + badData.push(data_processed[1]); + } + + }) + .on("end", async () => { + distribData.push(allocData); + allocData = []; - mint_tokens_for_affliliates(); - }); + await saveInBlockchain(); + await finalResults(); + return; + }); +} - stream.pipe(csvStream); +async function saveInBlockchain() { + + try { + await securityToken.methods.getModulesByType(3).call(); + } catch (e) { + console.log("Minting of tokens is only allowed before the STO get attached", e) + process.exit(0) } - async function mint_tokens_for_affliliates() { - let tokenDeployed = false; - let tokenDeployedAddress; - // Let's check if token has already been deployed, if it has, skip to STO - await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { - if (result != "0x0000000000000000000000000000000000000000") { - console.log('\x1b[32m%s\x1b[0m', "Token deployed at address " + result + "."); - tokenDeployedAddress = result; - tokenDeployed = true; - } - }); - if (tokenDeployed) { - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); - } - let modules = await securityToken.methods.getModulesByType(STO_KEY).call(); - if (modules.length > 0) { - console.log("****************************************************************************************\n"); - console.log("*************" + chalk.red(" Minting of tokens is only allowed before the STO get attached ") + "************\n"); - console.log("****************************************************************************************\n"); - process.exit(0); - } - console.log(` - ------------------------------------------------------- - ------------ Mint the tokens to affiliates ------------ - ------------------------------------------------------- - `); - - let affiliatesFailedArray = []; - let affiliatesKYCInvalidArray = []; - //this for loop will do the batches, so it should run 75, 75, 50 with 200 + console.log(` + ----------------------------------------- + ----- Mint the tokens to affiliates ----- + ----------------------------------------- + `); + for (let i = 0; i < distribData.length; i++) { try { - let affiliatesVerifiedArray = []; - let tokensVerifiedArray = []; - //splitting the user arrays to be organized by input + let affiliatesVerifiedArray = [], tokensVerifiedArray = []; + + // Splitting the user arrays to be organized by input for (let j = 0; j < distribData[i].length; j++) { let investorAccount = distribData[i][j][0]; - let tokenAmount = web3.utils.toWei((distribData[i][j][1]).toString(),"ether"); + let tokenAmount = web3.utils.toWei((distribData[i][j][1]).toString(), "ether"); let verifiedTransaction = await securityToken.methods.verifyTransfer("0x0000000000000000000000000000000000000000", investorAccount, tokenAmount, web3.utils.fromAscii('')).call(); if (verifiedTransaction) { affiliatesVerifiedArray.push(investorAccount); tokensVerifiedArray.push(tokenAmount); } else { let gtmModule = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); - let generalTransferManagerABI = abis.generalTransferManager(); - let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, gtmModule[0]); + let generalTransferManager = new web3.eth.Contract(abis.generalTransferManager(), gtmModule[0]); let validKYC = (await generalTransferManager.methods.whitelist(Issuer.address).call()).expiryTime > Math.floor(Date.now()/1000); if (validKYC) { affiliatesFailedArray.push(investorAccount); @@ -160,65 +121,57 @@ function readFile() { } } } + let mintMultiAction = securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); - let r = await common.sendTransaction(mintMultiAction); + let tx = await common.sendTransaction(mintMultiAction); console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Multi Mint transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); + console.log("Multi Mint transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - } catch (err) { - console.log("ERROR:", err); + console.log("ERROR", err) + process.exit(0) } } - console.log("Retrieving logs to determine investors have had their tokens correctly.\n\n") + return; +} +async function finalResults() { let totalInvestors = 0; let updatedInvestors = 0; - - let investorData_Events = new Array(); let investorObjectLookup = {}; + let investorData_Events = new Array(); - let event_data = await securityToken.getPastEvents('Minted', { - fromBlock: 0, - toBlock: 'latest' - }, function (error, events) { - - }); + let event_data = await securityToken.getPastEvents('Minted', {fromBlock: 0, toBlock: 'latest'}, () => {}); for (var i = 0; i < event_data.length; i++) { let combineArray = []; let investorAddress_Event = event_data[i].returnValues._to; let amount_Event = event_data[i].returnValues._value; - let blockNumber = event_data[i].blockNumber + let blockNumber = event_data[i].blockNumber; combineArray.push(investorAddress_Event); combineArray.push(amount_Event); combineArray.push(blockNumber); investorData_Events.push(combineArray) - //we have already recorded it, so this is an update to our object - if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { - //the block number form the event we are checking is bigger, so we gotta replace it + // We have already recorded it, so this is an update to our object + if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { + // The block number form the event we are checking is bigger, so we gotta replace it if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { - investorObjectLookup[investorAddress_Event] = { amount: amount_Event, recordedBlockNumber: blockNumber }; + investorObjectLookup[investorAddress_Event] = {amount: amount_Event, recordedBlockNumber: blockNumber}; updatedInvestors += 1; - // investorAddress_Events.push(investorAddress_Event); not needed, because we start the obj with zero events - - } else { - //do nothing. so if we find an event, and it was an older block, its old, we dont care } - //we have never recorded this address as an object key, so we need to add it to our list of investors updated by the csv } else { - investorObjectLookup[investorAddress_Event] = { amount: amount_Event, recordedBlockNumber: blockNumber }; + investorObjectLookup[investorAddress_Event] = {amount: amount_Event, recordedBlockNumber: blockNumber}; totalInvestors += 1; - // investorAddress_Events.push(investorAddress_Event); } } + let investorAddress_Events = Object.keys(investorObjectLookup) console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); @@ -227,15 +180,12 @@ function readFile() { console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); console.log(`There were ${affiliatesKYCInvalidArray.length} accounts with invalid KYC.\n`); console.log(`There were ${affiliatesFailedArray.length} accounts that didn't get sent to the blockchain as they would fail.\n`); - console.log("************************************************************************************************"); console.log("OBJECT WITH EVERY USER AND THEIR MINTED TOKEN: \n\n", investorObjectLookup) console.log("************************************************************************************************"); console.log("LIST OF ALL INVESTORS WHO GOT THE MINTED TOKENS: \n\n", investorAddress_Events) - let missingDistribs = []; - let failedVerificationDistribs = []; - let invalidKYCDistribs = []; + let missingDistribs = [], failedVerificationDistribs = [], invalidKYCDistribs = []; for (let l = 0; l < fullFileData.length; l++) { if (affiliatesKYCInvalidArray.includes(fullFileData[l][0])) { invalidKYCDistribs.push(fullFileData[l]); @@ -264,17 +214,42 @@ function readFile() { console.log(missingDistribs); console.log("******************************************************************************************"); } - if (missingDistribs.length == 0 && failedVerificationDistribs.length == 0 && invalidKYCDistribs.length == 0) { + if (missingDistribs.length == 0 && + failedVerificationDistribs.length == 0 && + invalidKYCDistribs.length == 0) { console.log("\n**************************************************************************************************************************"); console.log("All accounts passed through from the CSV were successfully get the tokens, because we were able to read them all from events"); console.log("****************************************************************************************************************************"); } + +} + +function multimint_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let validToken = isValidToken(csv_line[1]); + + if (isAddress && + validToken) { + + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), validToken)] + + } else { + + return [false, new Array(csv_line[0], csv_line[1])] + + } } -function isvalidToken(token) { +function isValidToken(token) { var tokenAmount = parseInt(token); - if((tokenAmount % 1 == 0)) { + if ((tokenAmount % 1 == 0)) { return tokenAmount; } return false; } + +module.exports = { + executeApp: async (tokenSymbol, batchSize) => { + return startScript(tokenSymbol, batchSize); + } +} \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index db0c02d9d..43ec73dd8 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -7,6 +7,7 @@ var module_manager = require('./commands/module_manager'); var st20generator = require('./commands/ST20Generator'); var transfer = require('./commands/transfer'); var whitelist = require('./commands/whitelist'); +var multimint = require('./commands/multi_mint'); var transfer_ownership = require('./commands/transfer_ownership'); var dividends_manager = require('./commands/dividends_manager'); var transfer_manager = require('./commands/transfer_manager'); @@ -75,7 +76,7 @@ program .description('Distribute tokens to previously whitelisted investors') .action(async function(tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - shell.exec(`${__dirname}/commands/scripts/script.sh Multimint ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; + await multimint.executeApp(tokenSymbol, batchSize); }); program From eb5079a2211eb9858c4adc1929fbcbf44a276283 Mon Sep 17 00:00:00 2001 From: Polymath Date: Tue, 13 Nov 2018 11:51:42 -0300 Subject: [PATCH 086/582] Accredit refactor --- CLI/commands/OLD_accredit.js | 149 +++++++++++++++++++++++++ CLI/commands/accredit.js | 210 ++++++++++++++++++----------------- CLI/commands/multi_mint.js | 8 +- CLI/polymath-cli.js | 3 +- 4 files changed, 268 insertions(+), 102 deletions(-) create mode 100644 CLI/commands/OLD_accredit.js diff --git a/CLI/commands/OLD_accredit.js b/CLI/commands/OLD_accredit.js new file mode 100644 index 000000000..a0aa306a2 --- /dev/null +++ b/CLI/commands/OLD_accredit.js @@ -0,0 +1,149 @@ +var fs = require('fs'); +var csv = require('fast-csv'); +var BigNumber = require('bignumber.js'); +var chalk = require('chalk'); +var common = require('./common/common_functions'); +var global = require('./common/global'); +var contracts = require('./helpers/contract_addresses'); +var abis = require('./helpers/contract_abis') + +/////////////////////////////ARTIFACTS////////////////////////////////////////// +let securityTokenRegistry; +let securityToken; +let usdTieredSTO; + +////////////////////////////USER INPUTS////////////////////////////////////////// +let tokenSymbol = process.argv.slice(2)[0]; //token symbol +let BATCH_SIZE = process.argv.slice(2)[1]; //batch size +if (!BATCH_SIZE) BATCH_SIZE = 75; +let remoteNetwork = process.argv.slice(2)[2]; + +/////////////////////////GLOBAL VARS////////////////////////////////////////// +//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] +let distribData = new Array(); +//allocData is a temporary array that stores up to the batch size, +//then gets push into distribData, then gets set to 0 to start another batch +let allocData = new Array(); +//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] +let fullFileData = new Array(); +//baa data is an array that contains invalid entries +let badData = new Array(); + +//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// +startScript(); + +async function startScript() { + if (remoteNetwork == 'undefined') remoteNetwork = undefined; + await global.initialize(remoteNetwork); + + try { + let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); + let securityTokenRegistryABI = abis.securityTokenRegistry(); + securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); + securityTokenRegistry.setProvider(web3.currentProvider); + console.log("Processing investor CSV upload. Batch size is " + BATCH_SIZE + " accounts per transaction"); + readFile(); + } catch (err) { + console.log(err) + console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); + return; + } +} + +///////////////////////////FUNCTION READING THE CSV FILE +function readFile() { + var stream = fs.createReadStream("./CLI/data/accredited_data.csv"); + + let index = 0; + console.log(` + -------------------------------------------- + ----------- Parsing the csv file ----------- + -------------------------------------------- + `); + + var csvStream = csv() + .on("data", function (data) { + let isAddress = web3.utils.isAddress(data[0]); + let isAccredited = (typeof JSON.parse(data[1].toLowerCase())) == "boolean" ? JSON.parse(data[1].toLowerCase()) : "not-valid"; + + if (isAddress && (isAccredited != "not-valid") ) { + let userArray = new Array() + let checksummedAddress = web3.utils.toChecksumAddress(data[0]); + + userArray.push(checksummedAddress) + userArray.push(isAccredited) + + allocData.push(userArray); + fullFileData.push(userArray); + + index++; + if (index >= BATCH_SIZE) { + distribData.push(allocData); + allocData = []; + index = 0; + } + } else { + let userArray = new Array() + userArray.push(data[0]) + userArray.push(isAccredited); + + badData.push(userArray); + fullFileData.push(userArray) + } + }) + .on("end", function () { + //Add last remainder batch + distribData.push(allocData); + allocData = []; + + changeAccredited(); + }); + + stream.pipe(csvStream); +} + +// MAIN FUNCTION COMMUNICATING TO BLOCKCHAIN +async function changeAccredited() { + // Let's check if token has already been deployed, if it has, skip to STO + let tokenDeployedAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); + if (tokenDeployedAddress != "0x0000000000000000000000000000000000000000") { + let securityTokenABI = abis.securityToken(); + securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); + let result = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); + if (result.length > 0) { + let usdTieredSTOABI = abis.usdTieredSTO(); + usdTieredSTO = new web3.eth.Contract(usdTieredSTOABI, result[0]); + console.log(` +------------------------------------------------------- +----- Sending accreditation changes to blockchain ----- +------------------------------------------------------- + `); + //this for loop will do the batches, so it should run 75, 75, 50 with 200 + for (let i = 0; i < distribData.length; i++) { + try { + let investorArray = []; + let isAccreditedArray = []; + + //splitting the user arrays to be organized by input + for (let j = 0; j < distribData[i].length; j++) { + investorArray.push(distribData[i][j][0]) + isAccreditedArray.push(distribData[i][j][1]) + } + + let changeAccreditedAction = usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); + let r = await common.sendTransaction(changeAccreditedAction); + console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); + console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); + } catch (err) { + console.log("ERROR:", err); + } + } + } else { + console.log(chalk.red(`There is no USDTieredSTO module attached to the ${tokenSymbol.toUpperCase()} Token. No further actions can be taken.`)); + } + } else { + console.log(chalk.red(`Token symbol provided is not a registered Security Token.`)); + } +} diff --git a/CLI/commands/accredit.js b/CLI/commands/accredit.js index a0aa306a2..079e1040c 100644 --- a/CLI/commands/accredit.js +++ b/CLI/commands/accredit.js @@ -1,149 +1,159 @@ +var common = require('./common/common_functions'); var fs = require('fs'); var csv = require('fast-csv'); -var BigNumber = require('bignumber.js'); -var chalk = require('chalk'); -var common = require('./common/common_functions'); -var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis') - -/////////////////////////////ARTIFACTS////////////////////////////////////////// -let securityTokenRegistry; -let securityToken; -let usdTieredSTO; - -////////////////////////////USER INPUTS////////////////////////////////////////// -let tokenSymbol = process.argv.slice(2)[0]; //token symbol -let BATCH_SIZE = process.argv.slice(2)[1]; //batch size -if (!BATCH_SIZE) BATCH_SIZE = 75; -let remoteNetwork = process.argv.slice(2)[2]; +var abis = require('./helpers/contract_abis'); +var BigNumber = require('bignumber.js'); -/////////////////////////GLOBAL VARS////////////////////////////////////////// -//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] let distribData = new Array(); -//allocData is a temporary array that stores up to the batch size, -//then gets push into distribData, then gets set to 0 to start another batch let allocData = new Array(); -//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] let fullFileData = new Array(); -//baa data is an array that contains invalid entries let badData = new Array(); -//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// -startScript(); +let BATCH_SIZE = 70; +let securityToken; + +async function startScript(tokenSymbol, batchSize) { + if (batchSize) { + BATCH_SIZE = batchSize; + } + + common.logAsciiBull(); + + let STAddress = await checkST(tokenSymbol); + securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); + + await readCsv(); +}; -async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); +async function checkST(tokenSymbol) { + let securityTokenRegistry = await STConnect(); + return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { + if (result != "0x0000000000000000000000000000000000000000") { + return result + } else { + console.log("Token doesn't exist") + process.exit(0) + } + }); +} + +async function STConnect() { try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - console.log("Processing investor CSV upload. Batch size is " + BATCH_SIZE + " accounts per transaction"); - readFile(); + let STRegistryAddress = await contracts.securityTokenRegistry(); + let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); + return STRegistry; } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); - return; + console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); + process.exit(0); } } -///////////////////////////FUNCTION READING THE CSV FILE -function readFile() { - var stream = fs.createReadStream("./CLI/data/accredited_data.csv"); - - let index = 0; - console.log(` - -------------------------------------------- - ----------- Parsing the csv file ----------- - -------------------------------------------- - `); +async function readCsv() { + var CSV_STRING = fs.readFileSync("./CLI/data/accredited_data.csv").toString(); + let i = 0; - var csvStream = csv() - .on("data", function (data) { - let isAddress = web3.utils.isAddress(data[0]); - let isAccredited = (typeof JSON.parse(data[1].toLowerCase())) == "boolean" ? JSON.parse(data[1].toLowerCase()) : "not-valid"; + csv.fromString(CSV_STRING) + .on("data", (data) => { + let data_processed = accredit_processing(data); + fullFileData.push(data_processed[1]); - if (isAddress && (isAccredited != "not-valid") ) { - let userArray = new Array() - let checksummedAddress = web3.utils.toChecksumAddress(data[0]); - - userArray.push(checksummedAddress) - userArray.push(isAccredited) - - allocData.push(userArray); - fullFileData.push(userArray); - - index++; - if (index >= BATCH_SIZE) { + if (data_processed[0]) { + allocData.push(data_processed[1]); + i++; + if (i >= BATCH_SIZE) { distribData.push(allocData); allocData = []; - index = 0; + i = 0; } } else { - let userArray = new Array() - userArray.push(data[0]) - userArray.push(isAccredited); - - badData.push(userArray); - fullFileData.push(userArray) + badData.push(data_processed[1]); } + }) - .on("end", function () { - //Add last remainder batch + .on("end", async () => { distribData.push(allocData); allocData = []; - changeAccredited(); + await saveInBlockchain(); + return; }); - - stream.pipe(csvStream); } -// MAIN FUNCTION COMMUNICATING TO BLOCKCHAIN -async function changeAccredited() { - // Let's check if token has already been deployed, if it has, skip to STO - let tokenDeployedAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); - if (tokenDeployedAddress != "0x0000000000000000000000000000000000000000") { - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); - let result = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); - if (result.length > 0) { - let usdTieredSTOABI = abis.usdTieredSTO(); - usdTieredSTO = new web3.eth.Contract(usdTieredSTOABI, result[0]); - console.log(` -------------------------------------------------------- ------ Sending accreditation changes to blockchain ----- -------------------------------------------------------- - `); - //this for loop will do the batches, so it should run 75, 75, 50 with 200 +async function saveInBlockchain() { + let gtmModules; + try { + gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); + } catch (e) { + console.log("Please attach USDTieredSTO module before launch this action.", e) + process.exit(0) + } + + if (!gtmModules.length) { + console.log("Please attach USDTieredSTO module before launch this action.") + process.exit(0) + } + + let usdTieredSTO = new web3.eth.Contract(abis.usdTieredSTO(), gtmModules[0]); + + console.log(` + -------------------------------------------------------- + ----- Sending accreditation changes to blockchain ----- + -------------------------------------------------------- + `); + + for (let i = 0; i < distribData.length; i++) { + try { + + // Splitting the user arrays to be organized by input for (let i = 0; i < distribData.length; i++) { try { - let investorArray = []; - let isAccreditedArray = []; + let investorArray = [], isAccreditedArray = []; - //splitting the user arrays to be organized by input for (let j = 0; j < distribData[i].length; j++) { investorArray.push(distribData[i][j][0]) isAccreditedArray.push(distribData[i][j][1]) } let changeAccreditedAction = usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); - let r = await common.sendTransaction(changeAccreditedAction); + let tx = await common.sendTransaction(changeAccreditedAction); console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); + console.log("Change accredited transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); } catch (err) { console.log("ERROR:", err); } } - } else { - console.log(chalk.red(`There is no USDTieredSTO module attached to the ${tokenSymbol.toUpperCase()} Token. No further actions can be taken.`)); - } + + } catch (err) { + console.log("ERROR", err) + process.exit(0) + } + } + + return; +} + +function accredit_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let isAccredited = (typeof JSON.parse(csv_line[1].toLowerCase())) == "boolean" ? JSON.parse(csv_line[1].toLowerCase()) : "not-valid"; + + if (isAddress && + (isAccredited != "not-valid")) { + + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), isAccredited)] + } else { - console.log(chalk.red(`Token symbol provided is not a registered Security Token.`)); + + return [false, new Array(csv_line[0], isAccredited)] + } } + +module.exports = { + executeApp: async (tokenSymbol, batchSize) => { + return startScript(tokenSymbol, batchSize); + } +} \ No newline at end of file diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index 4e83c4190..723c2a34c 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -84,14 +84,20 @@ async function readCsv() { } async function saveInBlockchain() { + let gtmModules; try { - await securityToken.methods.getModulesByType(3).call(); + gtmModules = await securityToken.methods.getModulesByType(3).call(); } catch (e) { console.log("Minting of tokens is only allowed before the STO get attached", e) process.exit(0) } + if (!gtmModules.length) { + console.log("Minting of tokens is only allowed before the STO get attached") + process.exit(0) + } + console.log(` ----------------------------------------- ----- Mint the tokens to affiliates ----- diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 43ec73dd8..6d496cd00 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -8,6 +8,7 @@ var st20generator = require('./commands/ST20Generator'); var transfer = require('./commands/transfer'); var whitelist = require('./commands/whitelist'); var multimint = require('./commands/multi_mint'); +var accredit = require('./commands/accredit'); var transfer_ownership = require('./commands/transfer_ownership'); var dividends_manager = require('./commands/dividends_manager'); var transfer_manager = require('./commands/transfer_manager'); @@ -139,7 +140,7 @@ program .description('Runs accredit') .action(async function(tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - shell.exec(`${__dirname}/commands/scripts/script.sh Accredit ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; + await accredit.executeApp(tokenSymbol, batchSize); }); program From de2f1ebe0d20f1e4a82aa70fa395ba3fb8362a1c Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 13 Nov 2018 18:03:21 +0200 Subject: [PATCH 087/582] added z_vesting_escrow_wallet.js --- contracts/wallet/VestingEscrowWallet.sol | 16 ++--- test/helpers/createInstances.js | 14 ++++- test/z_vesting_escrow_wallet.js | 78 ++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 test/z_vesting_escrow_wallet.js diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 4f178f289..0c7897702 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -27,8 +27,8 @@ contract VestingEscrowWallet is Ownable { uint256 public unassignedTokens; - mapping (address => VestingData) internal schedules; - address[] users; + mapping (address => VestingData) public schedules; + address[] public users; event AddVestingSchedule( address _user, @@ -41,7 +41,7 @@ contract VestingEscrowWallet is Ownable { event RevokeVestingSchedules(address _user, uint256 _timestamp); event RevokeVestingSchedule(address _user, uint256 index, uint256 _timestamp); - constructor(address _tokenAddress, address _treasury) { + constructor(address _tokenAddress, address _treasury) public { token = IERC20(_tokenAddress); treasury = _treasury; } @@ -53,11 +53,11 @@ contract VestingEscrowWallet is Ownable { uint256 _vestingFrequency, uint256 _startDate ) - public + external onlyOwner { //TODO validation - VestingSchedule schedule; + VestingSchedule memory schedule; schedule.numberOfTokens = _numberOfTokens; schedule.vestingDuration = _vestingDuration; schedule.vestingFrequency = _vestingFrequency; @@ -72,14 +72,14 @@ contract VestingEscrowWallet is Ownable { emit AddVestingSchedule(_user, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); } - function revokeVestingSchedule(address _user, uint256 index) public onlyOwner { + function revokeVestingSchedule(address _user, uint256 index) external onlyOwner { //TODO validation /*solium-disable-next-line security/no-block-members*/ emit RevokeVestingSchedule(_user, index, now); } - function revokeVestingSchedules(address _user) public onlyOwner { + function revokeVestingSchedules(address _user) external onlyOwner { //TODO validation uint256 index = schedules[_user].index; users[index] = users[users.length - 1]; @@ -100,7 +100,7 @@ contract VestingEscrowWallet is Ownable { uint256 _vestingFrequency, uint256 _startDate ) - public + external onlyOwner { diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 2021d350e..319c61f51 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -30,6 +30,7 @@ const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); +const VestingEscrowWallet = artifacts.require("./VestingEscrowWallet.sol"); const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port @@ -65,6 +66,7 @@ let I_PolymathRegistry; let I_SecurityTokenRegistryProxy; let I_STRProxied; let I_MRProxied; +let I_VestingEscrowWallet; // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -97,7 +99,7 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { } -async function deployPolyRegistryAndPolyToken(account_polymath, token_owner) { +export async function deployPolyRegistryAndPolyToken(account_polymath, token_owner) { // Step 0: Deploy the PolymathRegistry I_PolymathRegistry = await PolymathRegistry.new({ from: account_polymath }); @@ -422,6 +424,16 @@ export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, return new Array(I_MockWrongTypeBurnFactory); } +export async function deployVestingEscrowWallet(accountPolymath, polyToken, treasury) { + I_VestingEscrowWallet = await VestingEscrowWallet.new(polyToken, treasury, { from: accountPolymath }); + assert.notEqual( + I_VestingEscrowWallet.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "VestingEscrowWallet contract was not deployed" + ); + + return new Array(I_VestingEscrowWallet); +} /// Helper function diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js new file mode 100644 index 000000000..565be8ce9 --- /dev/null +++ b/test/z_vesting_escrow_wallet.js @@ -0,0 +1,78 @@ +import {deployPolyRegistryAndPolyToken, deployVestingEscrowWallet} from "./helpers/createInstances"; +import latestTime from "./helpers/latestTime"; +import {duration} from "./helpers/utils"; + +const VestingEscrowWallet = artifacts.require('./VestingEscrowWallet.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));// Hardcoded development port + +contract('VestingEscrowWallet', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_user1; + let account_user2; + let account_user3; + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_VestingEscrowWallet; + let I_PolyToken; + let I_PolymathRegistry; + + before(async () => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_user1 = accounts[7]; + account_user2 = accounts[8]; + account_user3 = accounts[9]; + + // Step 1: Deploy the PolyToken + [I_PolymathRegistry, I_PolyToken] = await deployPolyRegistryAndPolyToken(account_polymath, token_owner); + + // STEP 2: Deploy the VestingEscrowWallet + [I_VestingEscrowWallet] = await deployVestingEscrowWallet(account_polymath, I_PolyToken.address, token_owner); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${I_PolymathRegistry.address} + PolyToken: ${I_PolyToken.address} + + VestingEscrowWalle: ${I_VestingEscrowWallet.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Adding Vesting Schedule", async () => { + + it("Should add Vesting Schedule to the user address", async () => { + const tx = await I_VestingEscrowWallet.addVestingSchedule(account_user1, 100000, duration.years(4), duration.years(1), latestTime(), {from: account_polymath}); + + console.log("====================================================="); + console.log(tx.logs); + console.log("====================================================="); + + // assert.equal(tx.logs[2].args._types[0].toNumber(), 4, "ScheduledCheckpoint doesn't get deployed"); + // assert.equal(tx.logs[2].args._types[1].toNumber(), 2, "ScheduledCheckpoint doesn't get deployed"); + // assert.equal( + // web3.utils.toAscii(tx.logs[2].args._name) + // .replace(/\u0000/g, ''), + // "ScheduledCheckpoint", + // "ScheduledCheckpoint module was not added" + // ); + }); + + + }); + +}); \ No newline at end of file From ae711879e667d7080c4d1619b4adc749face8d13 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Tue, 13 Nov 2018 14:05:11 -0300 Subject: [PATCH 088/582] token_manager command --- CLI/commands/helpers/contract_abis.js | 10 + CLI/commands/module_manager.js | 445 ------------------- CLI/commands/token_manager.js | 600 ++++++++++++++++++++++++++ CLI/polymath-cli.js | 10 +- 4 files changed, 615 insertions(+), 450 deletions(-) delete mode 100644 CLI/commands/module_manager.js create mode 100644 CLI/commands/token_manager.js diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index b6c58cc38..ba8ce2007 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -15,6 +15,8 @@ let erc20DividendCheckpointABI; let etherDividendCheckpointABI; let moduleInterfaceABI; let ownableABI; +let iSTOABI; +let iTransferManagerABI; let moduleFactoryABI; try { @@ -35,6 +37,8 @@ try { etherDividendCheckpointABI = JSON.parse(require('fs').readFileSync('./build/contracts/EtherDividendCheckpoint.json').toString()).abi; moduleInterfaceABI = JSON.parse(require('fs').readFileSync('./build/contracts/IModule.json').toString()).abi; ownableABI = JSON.parse(require('fs').readFileSync('./build/contracts/Ownable.json').toString()).abi; + iSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/ISTO.json').toString()).abi + iTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ITransferManager.json').toString()).abi moduleFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleFactory.json').toString()).abi; } catch (err) { console.log('\x1b[31m%s\x1b[0m',"Couldn't find contracts' artifacts. Make sure you ran truffle compile first"); @@ -93,6 +97,12 @@ module.exports = { ownable: function () { return ownableABI; }, + ISTO: function () { + return iSTOABI; + }, + ITransferManager: function () { + return iTransferManagerABI; + }, moduleFactory: function () { return moduleFactoryABI; } diff --git a/CLI/commands/module_manager.js b/CLI/commands/module_manager.js deleted file mode 100644 index 53f2a863a..000000000 --- a/CLI/commands/module_manager.js +++ /dev/null @@ -1,445 +0,0 @@ -// Libraries for terminal prompts -var readlineSync = require('readline-sync'); -var chalk = require('chalk'); -var common = require('./common/common_functions'); - -// Load contract artifacts -var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis'); - -let securityTokenRegistry; -let securityToken; -let polyToken; - -// Init token info -let STSymbol; -let STAddress; -let STDetails; -let validSymbol = false; - -// Init Module Info -let pmModules; -let tmModules; -let stoModules; -let cpModules; -let numPM; -let numTM; -let numSTO; -let numCP; - -async function setup() { - try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - - let polytokenAddress = await contracts.polyToken(); - let polytokenABI = abis.polyToken(); - polyToken = new web3.eth.Contract(polytokenABI, polytokenAddress); - polyToken.setProvider(web3.currentProvider); - }catch(err){ - console.log(err); - console.log(chalk.red(`There was a problem getting the contracts. Make sure they are deployed to the selected network.`)); - process.exit(0); - } -} - -// Start function -async function executeApp() { - - common.logAsciiBull(); - console.log(chalk.yellow(`******************************************`)); - console.log(chalk.yellow(`Welcome to the Command-Line Module Manager`)); - console.log(chalk.yellow(`******************************************`)); - - await setup(); - await showUserInfo(Issuer.address); - - while (!validSymbol) { - await getSecurityToken(); - } -}; - -// get token contract based on input symbol -async function getSecurityToken() { - STSymbol = readlineSync.question(chalk.yellow(`\nEnter the symbol of the registered security token you issued: `)); - STAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(STSymbol).call(); - if (STAddress == "0x0000000000000000000000000000000000000000") { - console.log(chalk.red(`\nToken symbol provided is not a registered Security Token. Please enter another symbol.`)); - return; - } - STDetails = await securityTokenRegistry.methods.getSecurityTokenData(STAddress).call(); - if (STDetails[1] != Issuer.address) { - console.log(chalk.red(`\nYou did not issue the Security Token associated with the symbol provided. Please enter another symbol.`)); - return; - } - validSymbol = true; - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, STAddress); - - await displayModules(); - -} - -// display module status -async function displayModules() { - - await showUserInfo(Issuer.address); - - // Security Token details - let displayTokenSymbol = await securityToken.methods.symbol().call(); - let displayTokenSupply = await securityToken.methods.totalSupply().call(); - let displayUserTokens = await securityToken.methods.balanceOf(Issuer.address).call(); - - console.log(` - ************** Security Token Information *************** - - Address: ${STAddress} - - Token symbol: ${displayTokenSymbol.toUpperCase()} - - Total supply: ${web3.utils.fromWei(displayTokenSupply)} ${displayTokenSymbol.toUpperCase()} - - User balance: ${web3.utils.fromWei(displayUserTokens)} ${displayTokenSymbol.toUpperCase()} - `); - - // Module Details - pmModules = await iterateModules(1); - tmModules = await iterateModules(2); - stoModules = await iterateModules(3); - cpModules = await iterateModules(4); - - // Module Counts - numPM = pmModules.length; - numTM = tmModules.length; - numSTO = stoModules.length; - numCP = cpModules.length; - - console.log(` - ****************** Module Information ******************* - - Permission Manager: ${(numPM > 0) ? numPM : 'None'} - - Transfer Manager: ${(numTM > 0) ? numTM : 'None'} - - STO: ${(numSTO > 0) ? numSTO : 'None'} - - Checkpoint: ${(numCP > 0) ? numCP : 'None'} - `); - - if (numPM) { - console.log(chalk.green(`\n Permission Manager Modules:`)); - for (i=0;i m.type == gbl.constants.MODULES_TYPES.PERMISSION); + let tmModules = allModules.filter(m => m.type == gbl.constants.MODULES_TYPES.TRANSFER); + let stoModules = allModules.filter(m => m.type == gbl.constants.MODULES_TYPES.STO); + let cpModules = allModules.filter(m => m.type == gbl.constants.MODULES_TYPES.DIVIDENDS); + let burnModules = allModules.filter(m => m.type == gbl.constants.MODULES_TYPES.BURN); + + // Module Counts + let numPM = pmModules.length; + let numTM = tmModules.length; + let numSTO = stoModules.length; + let numCP = cpModules.length; + let numBURN = burnModules.length; + + console.log(` +******************* Module Information ******************** +- Permission Manager: ${(numPM > 0) ? numPM : 'None'} +- Transfer Manager: ${(numTM > 0) ? numTM : 'None'} +- STO: ${(numSTO > 0) ? numSTO : 'None'} +- Checkpoint: ${(numCP > 0) ? numCP : 'None'} +- Burn: ${(numBURN > 0) ? numBURN : 'None'} + `); + + if (numPM) { + console.log(`Permission Manager Modules:`); + pmModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + } + + if (numTM) { + console.log(`Transfer Manager Modules:`); + tmModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + } + + if (numSTO) { + console.log(`STO Modules:`); + stoModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + } + + if (numCP) { + console.log(`Checkpoint Modules:`); + cpModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + } + + if (numBURN) { + console.log(` Burn Modules:`); + burnModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + } +} + +async function selectAction() { + let options = ['Update token details'/*, 'Change granularity'*/]; + + let transferFrozen = await securityToken.methods.transfersFrozen().call(); + if (transferFrozen) { + options.push('Unfreeze transfers'); + } else { + options.push('Freeze transfers'); + } + + let isMintingFrozen = await securityToken.methods.mintingFrozen().call(); + if (!isMintingFrozen) { + let isFreezeMintingAllowed = await featureRegistry.methods.getFeatureStatus('freezeMintingAllowed').call(); + if (isFreezeMintingAllowed) { + options.push('Freeze minting permanently'); + } + } + + options.push('Create a checkpoint', 'List investors') + + let currentCheckpointId = await securityToken.methods.currentCheckpointId().call(); + if (currentCheckpointId > 0) { + options.push('List investors at checkpoint') + } + + if (!isMintingFrozen) { + options.push('Mint tokens'); + } + + options.push('Manage modules', 'Withdraw tokens from contract'); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Exit'}); + let selected = index == -1 ? 'Exit' : options[index]; + console.log('Selected:', selected); + switch (selected) { + case 'Update token details': + let updatedDetails = readlineSync.question('Enter new off-chain details of the token (i.e. Dropbox folder url): '); + await updateTokenDetails(updatedDetails); + break; + case 'Change granularity': + //let granularity = readlineSync.questionInt('Enter ') + //await changeGranularity(); + break; + case 'Freeze transfers': + await freezeTransfers(); + break; + case 'Unfreeze transfers': + await unfreezeTransfers(); + break; + case 'Freeze minting permanently': + await freezeMinting(); + break; + case 'Create a checkpoint': + await createCheckpoint(); + break; + case 'List investors': + await listInvestors(); + break; + case 'List investors at checkpoint': + let checkpointId = readlineSync.questionInt('Enter the id of the checkpoint: ', { + limit: function (input) { + return input > 0 && input <= currentCheckpointId; + }, + limitMessage: `Must be greater than 0 and less than ${currentCheckpointId}` + }); + await listInvestorsAtCheckpoint(checkpointId); + break; + case 'Mint tokens': + await mintTokens(); + break; + case 'Manage modules': + await listModuleOptions(); + break; + case 'Withdraw tokens from contract': + let tokenAddress = readlineSync.question(`Enter the ERC20 token address (POLY ${polyToken.options.address}): `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: polyToken.options.address + }); + let value = readlineSync.questionFloat('Enter the value to withdraw: ', { + limit: function (input) { + return input > 0; + }, + limitMessage: "Must be a greater than 0" + }); + await withdrawFromContract(tokenAddress, web3.utils.toWei(new web3.utils.BN(value))); + break; + case 'Exit': + process.exit(); + break; + } +} + +// Token actions +async function updateTokenDetails(updatedDetails) { + let updateTokenDetailsAction = securityToken.methods.updateTokenDetails(updatedDetails); + await common.sendTransaction(updateTokenDetailsAction); + console.log(chalk.green(`Token details have been updated successfully!`)); +} + +async function freezeTransfers() { + let freezeTransfersAction = securityToken.methods.freezeTransfers(); + await common.sendTransaction(freezeTransfersAction); + console.log(chalk.green(`Transfers have been frozen successfully!`)); +} + +async function unfreezeTransfers() { + let unfreezeTransfersAction = securityToken.methods.unfreezeTransfers(); + await common.sendTransaction(unfreezeTransfersAction); + console.log(chalk.green(`Transfers have been unfrozen successfully!`)); +} + +async function freezeMinting() { + let freezeMintingAction = securityToken.methods.freezeMinting(); + await common.sendTransaction(freezeMintingAction); + console.log(chalk.green(`Minting has been frozen successfully!.`)); +} + +async function createCheckpoint() { + let createCheckpointAction = securityToken.methods.createCheckpoint(); + let receipt = await common.sendTransaction(createCheckpointAction); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'CheckpointCreated'); + console.log(chalk.green(`Checkpoint ${event._checkpointId} has been created successfully!`)); +} + +async function listInvestors() { + let investors = await securityToken.methods.getInvestors().call(); + console.log(); + if (investors.length > 0) { + console.log('***** List of investors *****'); + investors.map(i => console.log(i)); + } else { + console.log(chalk.yellow('There are no investors yet')); + } +} + +async function listInvestorsAtCheckpoint(checkpointId) { + let investors = await securityToken.methods.getInvestorsAt(checkpointId).call(); + console.log(); + if (investors.length > 0) { + console.log(`*** List of investors at checkpoint ${checkpointId} ***`); + investors.map(i => console.log(i)); + } else { + console.log(chalk.yellow(`There are no investors at checkpoint ${checkpointId}`)); + } + +} + +async function mintTokens() { + let options = ['Modify whitelist', 'Mint tokens to a single address', `Modify whitelist and mint tokens using data from 'whitelist_data.csv' and 'multi_mint_data.csv'`]; + let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Return'}); + let selected = index == -1 ? 'Return' : options[index]; + console.log('Selected:', selected); + switch (selected) { + case 'Modify whitelist': + let investor = readlineSync.question('Enter the address to whitelist: ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let fromTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); + let toTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); + let expiryTime = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); + let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); + await modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); + break; + case 'Mint tokens to a single address': + console.log(chalk.yellow(`Investor should be previously whitelisted.`)); + let receiver = readlineSync.question(`Enter the address to receive the tokens: `); + let amount = readlineSync.question(`Enter the amount of tokens to mint: `); + await mintToSingleAddress(receiver, amount); + break; + case `Modify whitelist and mint tokens using data from 'whitelist_data.csv' and 'multi_mint_data.csv'`: + await multi_mint_tokens(); + break; + } +} + +/// Mint actions +async function modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO) { + let gmtModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + let generalTransferManagerAddress = gmtModules[0]; + let generalTransferManagerABI = abis.generalTransferManager(); + let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, generalTransferManagerAddress); + + let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); + let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); + let modifyWhitelistEvent = common.getEventFromLogs(generalTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); + console.log(chalk.green(`${modifyWhitelistEvent._investor} has been whitelisted sucessfully!`)); +} + +async function mintToSingleAddress(_investor, _amount) { + try { + let mintAction = securityToken.methods.mint(_investor, web3.utils.toWei(_amount)); + let receipt = await common.sendTransaction(mintAction); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Minted'); + console.log(chalk.green(`${web3.utils.fromWei(event._value)} tokens have been minted to ${event._to} successfully.`)); + } + catch (e) { + console.log(e); + console.log(chalk.red(`Minting was not successful - Please make sure beneficiary address has been whitelisted`)); + } +} + +async function multi_mint_tokens() { + let tokenSymbol = await securityToken.methods.symbol().call(); + + shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${remoteNetwork}`); + console.log(chalk.green(`\nCongratulations! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); + console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); + + shell.exec(`${__dirname}/scripts//script.sh Multimint ${tokenSymbol} 75 ${remoteNetwork}`); + console.log(chalk.green(`\nCongratulations! Tokens get successfully Minted and transferred to token holders`)); +} +/// + +async function withdrawFromContract(erc20address, value) { + let withdrawAction = securityToken.methods.withdrawERC20(erc20address, value); + await common.sendTransaction(withdrawAction); + console.log(chalk.green(`Withdrawn has been successful!.`)); +} +/// + +async function listModuleOptions() { + let options = ['Add a module'] + + let unpausedModules = allModules.filter(m => m.paused == false); + if (unpausedModules.length > 0) { + options.push('Pause a module'); + } + + let pausedModules = allModules.filter(m => m.paused == true); + if (pausedModules.length > 0) { + options.push('Unpause a module'); + } + + let unarchivedModules = allModules.filter(m => !m.archived); + if (unarchivedModules.length > 0) { + options.push('Archive a module'); + } + + let archivedModules = allModules.filter(m => m.archived); + if (archivedModules.length > 0) { + options.push('Unarchive a module'); + } + + if (allModules.length > 0) { + options.push('Remove a module', 'Change module budget'); + } + + let index = readlineSync.keyInSelect(options, chalk.yellow('What do you want to do?'), {cancel: 'Return'}); + let selected = index == -1 ? 'Exit' : options[index]; + console.log('Selected:', selected); + switch (selected) { + case 'Add a module': + await addModule(); + break; + case 'Pause a module': + await pauseModule(unpausedModules); + break; + case 'Unpause a module': + await unpauseModule(pausedModules); + break; + case 'Archive a module': + await archiveModule(unarchivedModules); + break; + case 'Unarchive a module': + await unarchiveModule(archivedModules); + break; + case 'Remove a module': + await removeModule(allModules); + break; + case 'Change module budget': + await changeBudget(allModules); + break; + } +} + +// Modules a actions +async function addModule() { + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************`)); +} + +async function pauseModule(modules) { + let options = modules.map(m => `${m.name} (${m.address})`); + let index = readlineSync.keyInSelect(options, 'Which module whould you like to pause?'); + if (index != -1) { + console.log("\nSelected: ",options[index]); + let moduleABI; + if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { + moduleABI = abis.ISTO(); + } else if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { + moduleABI = abis.ITransferManager(); + } else { + console.log(chalk.red(`Only STO and TM modules can be paused/unpaused`)); + process.exit(0); + } + let pausableModule = new web3.eth.Contract(moduleABI, modules[index].address); + let pauseAction = pausableModule.methods.pause(); + await common.sendTransaction(pauseAction); + console.log(chalk.green(`${modules[index].name} has been paused successfully!`)); + } +} + +async function unpauseModule(modules) { + let options = modules.map(m => `${m.name} (${m.address})`); + let index = readlineSync.keyInSelect(options, 'Which module whould you like to pause?'); + if (index != -1) { + console.log("\nSelected: ",options[index]); + let moduleABI; + if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { + moduleABI = abis.ISTO(); + } else if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { + moduleABI = abis.ITransferManager(); + } else { + console.log(chalk.red(`Only STO and TM modules can be paused/unpaused`)); + process.exit(0); + } + let pausableModule = new web3.eth.Contract(moduleABI, modules[index].address); + let unpauseAction = pausableModule.methods.unpause(); + await common.sendTransaction(unpauseAction); + console.log(chalk.green(`${modules[index].name} has been unpaused successfully!`)); + } +} + +async function archiveModule(modules) { + let options = modules.map(m => `${m.name} (${m.address})`); + let index = readlineSync.keyInSelect(options, 'Which module would you like to archive?'); + if (index != -1) { + console.log("\nSelected: ",options[index]); + let archiveModuleAction = securityToken.methods.archiveModule(modules[index].address); + await common.sendTransaction(archiveModuleAction, {factor: 2}); + console.log(chalk.green(`${modules[index].name} has been archived successfully!`)); + } +} + +async function unarchiveModule(modules) { + let options = modules.map(m => `${m.name} (${m.address})`); + let index = readlineSync.keyInSelect(options, 'Which module whould you like to unarchive?'); + if (index != -1) { + console.log("\nSelected: ",options[index]); + let unarchiveModuleAction = securityToken.methods.unarchiveModule(modules[index].address); + await common.sendTransaction(unarchiveModuleAction, {factor: 2}); + console.log(chalk.green(`${modules[index].name} has been unarchived successfully!`)); + } +} + +async function removeModule(modules) { + let options = modules.map(m => `${m.name} (${m.address})`); + let index = readlineSync.keyInSelect(options, 'Which module whould you like to remove?'); + if (index != -1) { + console.log("\nSelected: ",options[index]); + let removeModuleAction = securityToken.methods.removeModule(modules[index].address); + await common.sendTransaction(removeModuleAction, {factor: 2}); + console.log(chalk.green(`${modules[index].name} has been removed successfully!`)); + } +} + +async function changeBudget() { + let options = modules.map(m => `${m.name} (${m.address})`); + let index = readlineSync.keyInSelect(options, 'Which module whould you like to remove?'); + if (index != -1) { + console.log("\nSelected: ",options[index]); + let increase = 0 == readlineSync.keyInSelect(['Increase', 'Decrease'], `Do you want to increase or decrease budget?`, {cancel: false}); + let amount = readlineSync.question(`Enter the amount of POLY to change in allowance`); + let changeModuleBudgetAction = securityToken.methods.changeModuleBudget(modules[index].address, web3.utils.toWei(amount), increase); + await common.sendTransaction(changeModuleBudgetAction); + console.log(chalk.green(`Module budget has been changed successfully!`)); + } +} + +// Helpers +async function showUserInfo(_user) { + console.log(` +******************** User Information ********************* +- Address: ${_user} +- POLY balance: ${web3.utils.fromWei(await polyToken.methods.balanceOf(_user).call())} +- ETH balance: ${web3.utils.fromWei(await web3.eth.getBalance(_user))} + `); +} + +async function getAllModules() { + function ModuleInfo(_moduleType, _name, _address, _factoryAddress, _archived, _paused) { + this.name = _name; + this.type = _moduleType; + this.address = _address; + this.factoryAddress = _factoryAddress; + this.archived = _archived; + this.paused = _paused; + } + + let modules = []; + + // Iterate over all module types + for (let type = 1; type <= 5; type++) { + let allModules = await securityToken.methods.getModulesByType(type).call(); + + // Iterate over all modules of each type + for (let i = 0; i < allModules.length; i++) { + try { + let details = await securityToken.methods.getModule(allModules[i]).call(); + let nameTemp = web3.utils.hexToUtf8(details[0]); + let pausedTemp = null; + if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER) { + let abiTemp = JSON.parse(require('fs').readFileSync(`./build/contracts/${nameTemp}.json`).toString()).abi; + let contractTemp = new web3.eth.Contract(abiTemp, details[1]); + pausedTemp = await contractTemp.methods.paused().call(); + } + modules.push(new ModuleInfo(type, nameTemp, details[1], details[2], details[3], pausedTemp)); + } catch(error) { + console.log(error); + console.log(chalk.red(` + ************************* + Unable to iterate over module type - unexpected error + *************************`)); + } + } + } + + return modules; +} + +module.exports = { + executeApp: async function() { + return executeApp(); + } +} diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 4de51588e..c21c9abad 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -3,7 +3,7 @@ const shell = require('shelljs'); var faucet = require('./commands/faucet'); var investor_portal = require('./commands/investor_portal'); -var module_manager = require('./commands/module_manager'); +var token_manager = require('./commands/token_manager'); var st20generator = require('./commands/ST20Generator'); var transfer = require('./commands/transfer'); var transfer_ownership = require('./commands/transfer_ownership'); @@ -55,12 +55,12 @@ program }); program - .command('module_manager') - .alias('mm') - .description('View modules attached to a token and their status') + .command('token_manager') + .alias('stm') + .description('Manage your Security Tokens, mint tokens, add modules and change config') .action(async function() { await gbl.initialize(program.remoteNode); - await module_manager.executeApp(); + await token_manager.executeApp(); }); program From ee2c89d441cec4bee183d25b09a8e9ea0592f855 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 13 Nov 2018 19:59:03 +0200 Subject: [PATCH 089/582] refactored add and revoke methods --- contracts/wallet/VestingEscrowWallet.sol | 82 ++++++++++++++++-------- test/z_vesting_escrow_wallet.js | 47 ++++++++------ 2 files changed, 82 insertions(+), 47 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 0c7897702..2e8ce15ab 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -28,18 +28,18 @@ contract VestingEscrowWallet is Ownable { uint256 public unassignedTokens; mapping (address => VestingData) public schedules; - address[] public users; + address[] public beneficiaries; event AddVestingSchedule( - address _user, + address _beneficiary, uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, uint256 _startDate, uint256 _timestamp ); - event RevokeVestingSchedules(address _user, uint256 _timestamp); - event RevokeVestingSchedule(address _user, uint256 index, uint256 _timestamp); + event RevokeVestingSchedules(address _beneficiary, uint256 _timestamp); + event RevokeVestingSchedule(address _beneficiary, uint256 index, uint256 _timestamp); constructor(address _tokenAddress, address _treasury) public { token = IERC20(_tokenAddress); @@ -47,7 +47,7 @@ contract VestingEscrowWallet is Ownable { } function addVestingSchedule( - address _user, + address _beneficiary, uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, @@ -56,44 +56,62 @@ contract VestingEscrowWallet is Ownable { external onlyOwner { + require(_beneficiary != address(0), "Invalid beneficiary address"); //TODO validation + VestingSchedule memory schedule; schedule.numberOfTokens = _numberOfTokens; schedule.vestingDuration = _vestingDuration; schedule.vestingFrequency = _vestingFrequency; schedule.startDate = _startDate; - //add user to the schedule list only if adding first schedule - if (schedules[_user].schedules.length == 0) { - schedules[_user].index = users.length; - users.push(_user); + //add beneficiary to the schedule list only if adding first schedule + if (schedules[_beneficiary].schedules.length == 0) { + schedules[_beneficiary].index = beneficiaries.length; + beneficiaries.push(_beneficiary); } - schedules[_user].schedules.push(schedule); + schedules[_beneficiary].schedules.push(schedule); /*solium-disable-next-line security/no-block-members*/ - emit AddVestingSchedule(_user, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); + emit AddVestingSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); } - function revokeVestingSchedule(address _user, uint256 index) external onlyOwner { - //TODO validation - + function revokeVestingSchedule(address _beneficiary, uint256 index) external onlyOwner { + require(_beneficiary != address(0), "Invalid beneficiary address"); + require(index < schedules[_beneficiary].schedules.length, "Schedule not found"); + VestingSchedule[] storage vestingSchedule = schedules[_beneficiary].schedules; + vestingSchedule[index] = vestingSchedule[vestingSchedule.length - 1]; + vestingSchedule.length--; + if (vestingSchedule.length == 0) { + _revokeVestingSchedules(_beneficiary); + } /*solium-disable-next-line security/no-block-members*/ - emit RevokeVestingSchedule(_user, index, now); + emit RevokeVestingSchedule(_beneficiary, index, now); } - function revokeVestingSchedules(address _user) external onlyOwner { - //TODO validation - uint256 index = schedules[_user].index; - users[index] = users[users.length - 1]; - users.length--; - if (index != users.length) { - schedules[users[index]].index = index; - } - delete schedules[_user]; + function revokeVestingSchedules(address _beneficiary) external onlyOwner { + require(_beneficiary != address(0), "Invalid beneficiary address"); + _revokeVestingSchedules(_beneficiary); /*solium-disable-next-line security/no-block-members*/ - emit RevokeVestingSchedules(_user, now); + emit RevokeVestingSchedules(_beneficiary, now); + } + + function getVestingSchedule(address _beneficiary, uint256 index) external onlyOwner returns(uint256, uint256, uint256, uint256) { + require(_beneficiary != address(0), "Invalid beneficiary address"); + require(index < schedules[_beneficiary].schedules.length, "Schedule not found"); + return ( + schedules[_beneficiary].schedules[index].numberOfTokens, + schedules[_beneficiary].schedules[index].vestingDuration, + schedules[_beneficiary].schedules[index].vestingFrequency, + schedules[_beneficiary].schedules[index].startDate + ); + } + + function getVestingScheduleCount(address _beneficiary, uint256 index) external onlyOwner returns(uint256) { + require(_beneficiary != address(0), "Invalid beneficiary address"); + return schedules[_beneficiary].schedules.length; } function editVestingSchedule( - address _user, + address _beneficiary, uint256 index, uint256 _numberOfTokens, uint256 _vestingDuration, @@ -103,7 +121,19 @@ contract VestingEscrowWallet is Ownable { external onlyOwner { + //TODO implement + } + + + function _revokeVestingSchedules(address _beneficiary) private { + uint256 index = schedules[_beneficiary].index; + beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; + beneficiaries.length--; + if (index != beneficiaries.length) { + schedules[beneficiaries[index]].index = index; + } + delete schedules[_beneficiary]; } } diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 565be8ce9..4b4b8adbb 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -14,9 +14,9 @@ contract('VestingEscrowWallet', accounts => { let account_polymath; let account_issuer; let token_owner; - let account_user1; - let account_user2; - let account_user3; + let account_beneficiary1; + let account_beneficiary2; + let account_beneficiary3; let message = "Transaction Should Fail!"; @@ -32,9 +32,9 @@ contract('VestingEscrowWallet', accounts => { token_owner = account_issuer; - account_user1 = accounts[7]; - account_user2 = accounts[8]; - account_user3 = accounts[9]; + account_beneficiary1 = accounts[7]; + account_beneficiary2 = accounts[8]; + account_beneficiary3 = accounts[9]; // Step 1: Deploy the PolyToken [I_PolymathRegistry, I_PolyToken] = await deployPolyRegistryAndPolyToken(account_polymath, token_owner); @@ -55,21 +55,26 @@ contract('VestingEscrowWallet', accounts => { describe("Adding Vesting Schedule", async () => { - it("Should add Vesting Schedule to the user address", async () => { - const tx = await I_VestingEscrowWallet.addVestingSchedule(account_user1, 100000, duration.years(4), duration.years(1), latestTime(), {from: account_polymath}); - - console.log("====================================================="); - console.log(tx.logs); - console.log("====================================================="); - - // assert.equal(tx.logs[2].args._types[0].toNumber(), 4, "ScheduledCheckpoint doesn't get deployed"); - // assert.equal(tx.logs[2].args._types[1].toNumber(), 2, "ScheduledCheckpoint doesn't get deployed"); - // assert.equal( - // web3.utils.toAscii(tx.logs[2].args._name) - // .replace(/\u0000/g, ''), - // "ScheduledCheckpoint", - // "ScheduledCheckpoint module was not added" - // ); + it("Should add Vesting Schedule to the beneficiary address", async () => { + let numberOfTokens = 100000; + let vestingDuration = duration.years(4); + let vestingFrequency = duration.years(1); + let startDate = latestTime(); + const tx = await I_VestingEscrowWallet.addVestingSchedule( + account_beneficiary1, + numberOfTokens, + vestingDuration, + vestingFrequency, + startDate, + {from: account_polymath} + ); + + let log = tx.logs[0]; + assert.equal(log.args._beneficiary, account_beneficiary1); + assert.equal(log.args._numberOfTokens, numberOfTokens); + assert.equal(log.args._vestingDuration, vestingDuration); + assert.equal(log.args._vestingFrequency, vestingFrequency); + assert.equal(log.args._startDate, startDate); }); From 508abe1bb64f2263839940fa54146400aae1fa78 Mon Sep 17 00:00:00 2001 From: Polymath Date: Tue, 13 Nov 2018 16:14:24 -0300 Subject: [PATCH 090/582] Non accredited limit refactor + delete old files and packages dependencies --- CLI/commands/OLD_accredit.js | 149 ----------- CLI/commands/OLD_multi_mint.js | 280 --------------------- CLI/commands/OLD_whitelist.js | 302 ----------------------- CLI/commands/changeNonAccreditedLimit.js | 212 ++++++++-------- CLI/commands/scripts/script.sh | 19 -- CLI/polymath-cli.js | 4 +- package.json | 1 - 7 files changed, 113 insertions(+), 854 deletions(-) delete mode 100644 CLI/commands/OLD_accredit.js delete mode 100644 CLI/commands/OLD_multi_mint.js delete mode 100644 CLI/commands/OLD_whitelist.js delete mode 100755 CLI/commands/scripts/script.sh diff --git a/CLI/commands/OLD_accredit.js b/CLI/commands/OLD_accredit.js deleted file mode 100644 index a0aa306a2..000000000 --- a/CLI/commands/OLD_accredit.js +++ /dev/null @@ -1,149 +0,0 @@ -var fs = require('fs'); -var csv = require('fast-csv'); -var BigNumber = require('bignumber.js'); -var chalk = require('chalk'); -var common = require('./common/common_functions'); -var global = require('./common/global'); -var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis') - -/////////////////////////////ARTIFACTS////////////////////////////////////////// -let securityTokenRegistry; -let securityToken; -let usdTieredSTO; - -////////////////////////////USER INPUTS////////////////////////////////////////// -let tokenSymbol = process.argv.slice(2)[0]; //token symbol -let BATCH_SIZE = process.argv.slice(2)[1]; //batch size -if (!BATCH_SIZE) BATCH_SIZE = 75; -let remoteNetwork = process.argv.slice(2)[2]; - -/////////////////////////GLOBAL VARS////////////////////////////////////////// -//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] -let distribData = new Array(); -//allocData is a temporary array that stores up to the batch size, -//then gets push into distribData, then gets set to 0 to start another batch -let allocData = new Array(); -//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] -let fullFileData = new Array(); -//baa data is an array that contains invalid entries -let badData = new Array(); - -//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// -startScript(); - -async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); - - try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - console.log("Processing investor CSV upload. Batch size is " + BATCH_SIZE + " accounts per transaction"); - readFile(); - } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); - return; - } -} - -///////////////////////////FUNCTION READING THE CSV FILE -function readFile() { - var stream = fs.createReadStream("./CLI/data/accredited_data.csv"); - - let index = 0; - console.log(` - -------------------------------------------- - ----------- Parsing the csv file ----------- - -------------------------------------------- - `); - - var csvStream = csv() - .on("data", function (data) { - let isAddress = web3.utils.isAddress(data[0]); - let isAccredited = (typeof JSON.parse(data[1].toLowerCase())) == "boolean" ? JSON.parse(data[1].toLowerCase()) : "not-valid"; - - if (isAddress && (isAccredited != "not-valid") ) { - let userArray = new Array() - let checksummedAddress = web3.utils.toChecksumAddress(data[0]); - - userArray.push(checksummedAddress) - userArray.push(isAccredited) - - allocData.push(userArray); - fullFileData.push(userArray); - - index++; - if (index >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - index = 0; - } - } else { - let userArray = new Array() - userArray.push(data[0]) - userArray.push(isAccredited); - - badData.push(userArray); - fullFileData.push(userArray) - } - }) - .on("end", function () { - //Add last remainder batch - distribData.push(allocData); - allocData = []; - - changeAccredited(); - }); - - stream.pipe(csvStream); -} - -// MAIN FUNCTION COMMUNICATING TO BLOCKCHAIN -async function changeAccredited() { - // Let's check if token has already been deployed, if it has, skip to STO - let tokenDeployedAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); - if (tokenDeployedAddress != "0x0000000000000000000000000000000000000000") { - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); - let result = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); - if (result.length > 0) { - let usdTieredSTOABI = abis.usdTieredSTO(); - usdTieredSTO = new web3.eth.Contract(usdTieredSTOABI, result[0]); - console.log(` -------------------------------------------------------- ------ Sending accreditation changes to blockchain ----- -------------------------------------------------------- - `); - //this for loop will do the batches, so it should run 75, 75, 50 with 200 - for (let i = 0; i < distribData.length; i++) { - try { - let investorArray = []; - let isAccreditedArray = []; - - //splitting the user arrays to be organized by input - for (let j = 0; j < distribData[i].length; j++) { - investorArray.push(distribData[i][j][0]) - isAccreditedArray.push(distribData[i][j][1]) - } - - let changeAccreditedAction = usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); - let r = await common.sendTransaction(changeAccreditedAction); - console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - } catch (err) { - console.log("ERROR:", err); - } - } - } else { - console.log(chalk.red(`There is no USDTieredSTO module attached to the ${tokenSymbol.toUpperCase()} Token. No further actions can be taken.`)); - } - } else { - console.log(chalk.red(`Token symbol provided is not a registered Security Token.`)); - } -} diff --git a/CLI/commands/OLD_multi_mint.js b/CLI/commands/OLD_multi_mint.js deleted file mode 100644 index d550fcd3e..000000000 --- a/CLI/commands/OLD_multi_mint.js +++ /dev/null @@ -1,280 +0,0 @@ -var fs = require('fs'); -var csv = require('fast-csv'); -var BigNumber = require('bignumber.js'); -const chalk = require('chalk'); -var common = require('./common/common_functions'); -var global = require('./common/global'); - -/////////////////////////////ARTIFACTS////////////////////////////////////////// -var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis'); - -const STO_KEY = 3; - -let securityToken; - -////////////////////////////USER INPUTS////////////////////////////////////////// -let tokenSymbol = process.argv.slice(2)[0]; //token symbol -let BATCH_SIZE = process.argv.slice(2)[1]; //batch size -if (!BATCH_SIZE) BATCH_SIZE = 75; -let remoteNetwork = process.argv.slice(2)[2]; - -/////////////////////////GLOBAL VARS////////////////////////////////////////// - -//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] -let distribData = new Array(); -//allocData is a temporary array that stores up to the batch size, -//then gets push into distribData, then gets set to 0 to start another batch -let allocData = new Array(); -//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] -let fullFileData = new Array(); -let badData = new Array(); - -//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// - -startScript(); - -async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); - - try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - - console.log("Processing investor CSV upload. Batch size is "+BATCH_SIZE+" accounts per transaction"); - readFile(); - } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); - return; - } -} - -function readFile() { - var stream = fs.createReadStream("./CLI/data/multi_mint_data.csv"); - - let index = 0; - let batch = 0; - console.log(` - -------------------------------------------- - ----------- Parsing the csv file ----------- - -------------------------------------------- - `); - - var csvStream = csv() - .on("data", function (data) { - let isAddress = web3.utils.isAddress(data[0]); - let validToken = isvalidToken(data[1]); - - if (isAddress && validToken) { - let userArray = new Array() - let checksummedAddress = web3.utils.toChecksumAddress(data[0]); - - userArray.push(checksummedAddress) - userArray.push(validToken) - allocData.push(userArray); - fullFileData.push(userArray); - index++; - if (index >= 75) { - distribData.push(allocData); - allocData = []; - index = 0; - } - - } else { - let userArray = new Array() - //dont need this here, as if it is NOT an address this function will fail - //let checksummedAddress = web3.utils.toChecksumAddress(data[1]); - userArray.push(data[0]) - userArray.push(data[1]); - badData.push(userArray); - fullFileData.push(userArray) - } - }) - .on("end", function () { - //Add last remainder batch - distribData.push(allocData); - allocData = []; - - mint_tokens_for_affliliates(); - }); - - stream.pipe(csvStream); - } - - async function mint_tokens_for_affliliates() { - let tokenDeployed = false; - let tokenDeployedAddress; - // Let's check if token has already been deployed, if it has, skip to STO - await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { - if (result != "0x0000000000000000000000000000000000000000") { - console.log('\x1b[32m%s\x1b[0m', "Token deployed at address " + result + "."); - tokenDeployedAddress = result; - tokenDeployed = true; - } - }); - if (tokenDeployed) { - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); - } - let modules = await securityToken.methods.getModulesByType(STO_KEY).call(); - if (modules.length == 0) { - console.log("****************************************************************************************\n"); - console.log("*************" + chalk.red(" Minting of tokens is only allowed before the STO get attached ") + "************\n"); - console.log("****************************************************************************************\n"); - process.exit(0); - } - console.log(` - ------------------------------------------------------- - ------------ Mint the tokens to affiliates ------------ - ------------------------------------------------------- - `); - - let affiliatesFailedArray = []; - let affiliatesKYCInvalidArray = []; - //this for loop will do the batches, so it should run 75, 75, 50 with 200 - for (let i = 0; i < distribData.length; i++) { - try { - let affiliatesVerifiedArray = []; - let tokensVerifiedArray = []; - //splitting the user arrays to be organized by input - for (let j = 0; j < distribData[i].length; j++) { - let investorAccount = distribData[i][j][0]; - let tokenAmount = web3.utils.toWei((distribData[i][j][1]).toString(),"ether"); - let verifiedTransaction = await securityToken.methods.verifyTransfer("0x0000000000000000000000000000000000000000", investorAccount, tokenAmount, web3.utils.fromAscii('')).call(); - if (verifiedTransaction) { - affiliatesVerifiedArray.push(investorAccount); - tokensVerifiedArray.push(tokenAmount); - } else { - let gtmModule = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); - let generalTransferManagerABI = abis.generalTransferManager(); - let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, gtmModule[0]); - let validKYC = (await generalTransferManager.methods.whitelist(Issuer.address).call()).expiryTime > Math.floor(Date.now()/1000); - if (validKYC) { - affiliatesFailedArray.push(investorAccount); - } else { - affiliatesKYCInvalidArray.push(investorAccount); - } - } - } - let mintMultiAction = securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); - let r = await common.sendTransaction(mintMultiAction); - console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Multi Mint transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - - - } catch (err) { - console.log("ERROR:", err); - } - } - - console.log("Retrieving logs to determine investors have had their tokens correctly.\n\n") - - let totalInvestors = 0; - let updatedInvestors = 0; - - let investorData_Events = new Array(); - let investorObjectLookup = {}; - - let event_data = await securityToken.getPastEvents('Minted', { - fromBlock: 0, - toBlock: 'latest' - }, function (error, events) { - - }); - - for (var i = 0; i < event_data.length; i++) { - let combineArray = []; - - let investorAddress_Event = event_data[i].returnValues._to; - let amount_Event = event_data[i].returnValues._value; - let blockNumber = event_data[i].blockNumber - - combineArray.push(investorAddress_Event); - combineArray.push(amount_Event); - combineArray.push(blockNumber); - - investorData_Events.push(combineArray) - //we have already recorded it, so this is an update to our object - if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { - - //the block number form the event we are checking is bigger, so we gotta replace it - if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { - investorObjectLookup[investorAddress_Event] = { amount: amount_Event, recordedBlockNumber: blockNumber }; - updatedInvestors += 1; - // investorAddress_Events.push(investorAddress_Event); not needed, because we start the obj with zero events - - } else { - //do nothing. so if we find an event, and it was an older block, its old, we dont care - } - //we have never recorded this address as an object key, so we need to add it to our list of investors updated by the csv - } else { - investorObjectLookup[investorAddress_Event] = { amount: amount_Event, recordedBlockNumber: blockNumber }; - totalInvestors += 1; - // investorAddress_Events.push(investorAddress_Event); - } - } - let investorAddress_Events = Object.keys(investorObjectLookup) - - console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); - console.log(`A total of ${totalInvestors} affiliated investors get the token\n`); - console.log(`This script in total sent ${fullFileData.length - badData.length - affiliatesFailedArray.length - affiliatesKYCInvalidArray.length} new investors and updated investors to the blockchain.\n`); - console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); - console.log(`There were ${affiliatesKYCInvalidArray.length} accounts with invalid KYC.\n`); - console.log(`There were ${affiliatesFailedArray.length} accounts that didn't get sent to the blockchain as they would fail.\n`); - - console.log("************************************************************************************************"); - console.log("OBJECT WITH EVERY USER AND THEIR MINTED TOKEN: \n\n", investorObjectLookup) - console.log("************************************************************************************************"); - console.log("LIST OF ALL INVESTORS WHO GOT THE MINTED TOKENS: \n\n", investorAddress_Events) - - let missingDistribs = []; - let failedVerificationDistribs = []; - let invalidKYCDistribs = []; - for (let l = 0; l < fullFileData.length; l++) { - if (affiliatesKYCInvalidArray.includes(fullFileData[l][0])) { - invalidKYCDistribs.push(fullFileData[l]); - } else if (affiliatesFailedArray.includes(fullFileData[l][0])) { - failedVerificationDistribs.push(fullFileData[l]); - } else if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { - missingDistribs.push(fullFileData[l]); - } - } - - if (invalidKYCDistribs.length > 0) { - console.log("**************************************************************************************************************************"); - console.log("The following data arrays have an invalid KYC. Please review if these accounts are whitelisted and their KYC is not expired\n"); - console.log(invalidKYCDistribs); - console.log("**************************************************************************************************************************"); - } - if (failedVerificationDistribs.length > 0) { - console.log("*********************************************************************************************************"); - console.log("-- The following data arrays failed at verifyTransfer. Please review if these accounts are whitelisted --\n"); - console.log(failedVerificationDistribs); - console.log("*********************************************************************************************************"); - } - if (missingDistribs.length > 0) { - console.log("******************************************************************************************"); - console.log("-- No Minted event was found for the following data arrays. Please review them manually --\n"); - console.log(missingDistribs); - console.log("******************************************************************************************"); - } - if (missingDistribs.length == 0 && failedVerificationDistribs.length == 0 && invalidKYCDistribs.length == 0) { - console.log("\n**************************************************************************************************************************"); - console.log("All accounts passed through from the CSV were successfully get the tokens, because we were able to read them all from events"); - console.log("****************************************************************************************************************************"); - } -} - -function isvalidToken(token) { - var tokenAmount = parseInt(token); - if((tokenAmount % 1 == 0)) { - return tokenAmount; - } - return false; -} diff --git a/CLI/commands/OLD_whitelist.js b/CLI/commands/OLD_whitelist.js deleted file mode 100644 index 5ef201195..000000000 --- a/CLI/commands/OLD_whitelist.js +++ /dev/null @@ -1,302 +0,0 @@ -var fs = require('fs'); -var csv = require('fast-csv'); -var BigNumber = require('bignumber.js'); -var common = require('./common/common_functions'); -var global = require('./common/global'); - -/////////////////////////////ARTIFACTS////////////////////////////////////////// -var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis'); - -////////////////////////////USER INPUTS////////////////////////////////////////// -let tokenSymbol = process.argv.slice(2)[0]; //token symbol -let BATCH_SIZE = process.argv.slice(2)[1]; //batch size -if (!BATCH_SIZE) BATCH_SIZE = 70; -let remoteNetwork = process.argv.slice(2)[2]; - -/////////////////////////GLOBAL VARS////////////////////////////////////////// - -//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] -let distribData = new Array(); -//allocData is a temporary array that stores up to the batch size, -//then gets push into distribData, then gets set to 0 to start another batch -let allocData = new Array(); -//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] -let fullFileData = new Array(); -let badData = new Array(); - -const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); - -//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// - -startScript(); - -async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); - - try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - - console.log("Processing investor CSV upload. Batch size is "+BATCH_SIZE+" accounts per transaction"); - readFile(); - } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); - return; - } -} - -///////////////////////////FUNCTION READING THE CSV FILE -function readFile() { - var stream = fs.createReadStream("./CLI/data/whitelist_data.csv"); - - let index = 0; - let batch = 0; - console.log(` - -------------------------------------------- - ----------- Parsing the csv file ----------- - -------------------------------------------- - `); - - var csvStream = csv() - .on("data", function (data) { - // console.log(data[1]) - // console.log(data[2]) - // console.log(data[3]) - let isAddress = web3.utils.isAddress(data[0]); - let sellValid = isValidDate(data[1]) - let buyValid = isValidDate(data[2]) - let kycExpiryDate = isValidDate(data[3]) - let canBuyFromSTO = (typeof JSON.parse(data[4].toLowerCase())) == "boolean" ? JSON.parse(data[4].toLowerCase()) : "not-valid"; - - if (isAddress && sellValid && buyValid && kycExpiryDate && (canBuyFromSTO != "not-valid") ) { - let userArray = new Array() - let checksummedAddress = web3.utils.toChecksumAddress(data[0]); - - userArray.push(checksummedAddress) - userArray.push(sellValid) - userArray.push(buyValid) - userArray.push(kycExpiryDate) - userArray.push(canBuyFromSTO) - // console.log(userArray) - allocData.push(userArray); - fullFileData.push(userArray); - index++; - if (index >= BATCH_SIZE) { - distribData.push(allocData); - // console.log("DIS", distribData); - allocData = []; - // console.log("ALLOC", allocData); - index = 0; - } - - } else { - let userArray = new Array() - //dont need this here, as if it is NOT an address this function will fail - //let checksummedAddress = web3.utils.toChecksumAddress(data[1]); - userArray.push(data[0]) - userArray.push(sellValid) - userArray.push(buyValid) - userArray.push(kycExpiryDate); - userArray.push(canBuyFromSTO); - badData.push(userArray); - fullFileData.push(userArray) - } - }) - .on("end", function () { - //Add last remainder batch - distribData.push(allocData); - allocData = []; - - setInvestors(); - }); - - stream.pipe(csvStream); -} - -////////////////////////MAIN FUNCTION COMMUNICATING TO BLOCKCHAIN -async function setInvestors() { - let tokenDeployed = false; - let tokenDeployedAddress; - // Let's check if token has already been deployed, if it has, skip to STO - await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { - if (result != "0x0000000000000000000000000000000000000000") { - console.log('\x1b[32m%s\x1b[0m', "Token deployed at address " + result + "."); - tokenDeployedAddress = result; - tokenDeployed = true; - } - }); - if (tokenDeployed) { - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); - } - let gmtModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); - let generalTransferManagerAddress = gmtModules[0]; - let generalTransferManagerABI = abis.generalTransferManager(); - let generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, generalTransferManagerAddress); - - console.log(` - ------------------------------------------------------- - ----- Sending buy/sell restrictions to blockchain ----- - ------------------------------------------------------- - `); - - //this for loop will do the batches, so it should run 75, 75, 50 with 200 - for (let i = 0; i < distribData.length; i++) { - try { - let investorArray = []; - let fromTimesArray = []; - let toTimesArray = []; - let expiryTimeArray = []; - let canBuyFromSTOArray = []; - - //splitting the user arrays to be organized by input - for (let j = 0; j < distribData[i].length; j++) { - investorArray.push(distribData[i][j][0]) - fromTimesArray.push(distribData[i][j][1]) - toTimesArray.push(distribData[i][j][2]) - expiryTimeArray.push(distribData[i][j][3]) - canBuyFromSTOArray.push(distribData[i][j][4]) - } - - //fromTimes is ability to sell coin FROM your account (2nd row in csv, 2nd parameter in modifyWhiteList() ) - //toTimes is ability to buy coins TOwards your account (3rd row in csv, 3rd parameter in modifyWhiteList() ) - //expiryTime is time at which KYC of investor get expired (4th row in csv, 4rd parameter in modifyWhiteList() ) - let modifyWhitelistMultiAction = generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); - let r = await common.sendTransaction(modifyWhitelistMultiAction); - console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Whitelist transaxction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - - } catch (err) { - console.log("ERROR:", err); - } - } - - console.log("Retrieving logs to determine investors have had their times uploaded correctly.\n\n") - - let totalInvestors = 0; - let updatedInvestors = 0; - - let investorData_Events = new Array(); - let investorObjectLookup = {}; - - let event_data = await generalTransferManager.getPastEvents('ModifyWhitelist', { - fromBlock: 0, - toBlock: 'latest' - }, function (error, events) { - //console.log(error); - }); - - for (var i = 0; i < event_data.length; i++) { - let combineArray = []; - - let investorAddress_Event = event_data[i].returnValues._investor; - let fromTime_Event = event_data[i].returnValues._fromTime - let toTime_Event = event_data[i].returnValues._toTime - let expiryTime_Event = event_data[i].returnValues._expiryTime - let canBuyFromSTO_Event = event_data[i].returnValues._canBuyFromSTO - let blockNumber = event_data[i].blockNumber - - combineArray.push(investorAddress_Event); - combineArray.push(fromTime_Event); - combineArray.push(toTime_Event); - combineArray.push(expiryTime_Event); - combineArray.push(canBuyFromSTO_Event); - combineArray.push(blockNumber) - - investorData_Events.push(combineArray) - - //we have already recorded it, so this is an update to our object - if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { - - //the block number form the event we are checking is bigger, so we gotta replace it - if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { - investorObjectLookup[investorAddress_Event] = { fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber }; - updatedInvestors += 1; - // investorAddress_Events.push(investorAddress_Event); not needed, because we start the obj with zero events - - } else { - //do nothing. so if we find an event, and it was an older block, its old, we dont care - } - //we have never recorded this address as an object key, so we need to add it to our list of investors updated by the csv - } else { - investorObjectLookup[investorAddress_Event] = { fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber }; - totalInvestors += 1; - // investorAddress_Events.push(investorAddress_Event); - } - } - let investorAddress_Events = Object.keys(investorObjectLookup) - - console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); - console.log(`A total of ${totalInvestors} investors have been whitelisted total, all time.\n`); - console.log(`This script in total sent ${fullFileData.length - badData.length} new investors and updated investors to the blockchain.\n`); - console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); - - // console.log("LIST OF ALL INVESTOR DATA FROM EVENTS:", investorData_Events) - // console.log(fullFileData) - console.log("************************************************************************************************"); - console.log("OBJECT WITH EVERY USER AND THEIR UPDATED TIMES: \n\n", investorObjectLookup) - console.log("************************************************************************************************"); - console.log("LIST OF ALL INVESTORS WHITELISTED: \n\n", investorAddress_Events) - - let missingDistribs = []; - for (let l = 0; l < fullFileData.length; l++) { - if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { - missingDistribs.push(fullFileData[l]) - } - } - - if (missingDistribs.length > 0) { - console.log("************************************************************************************************"); - console.log("-- No LogModifyWhitelist event was found for the following data arrays. Please review them manually --") - console.log(missingDistribs) - // for (var i = 0; i < missingDistribs.length; i++) { - // console.log('\x1b[31m%s\x1b[0m', `No Transfer event was found for account ${missingDistribs[i]}`); - // } - console.log("************************************************************************************************"); - } else { - console.log("\n************************************************************************************************"); - console.log("All accounts passed through from the CSV were successfully whitelisted, because we were able to read them all from events") - console.log("************************************************************************************************"); - } - // console.log(`Run 'node scripts/verify_airdrop.js ${polyDistribution.address} > scripts/data/review.csv' to get a log of all the accounts that were distributed the airdrop tokens.`) -} - -//will be deleted once DATES are updated -function isValidDayInput(days) { - let today = Date.now() / 1000 - let isValid = !isNaN(days) - if (isValid) { - let addedSeconds = days * 86400 - - let unixTimestamp = today + addedSeconds - console.log("unxitimestapm :" , (unixTimestamp)) - - return unixTimestamp - } else { - return false - } -} - -function isValidDate(date) { - var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(date); - if (matches == null) return false; - var d = matches[2]; - var m = matches[1] - 1; //not clear why this is -1, but it works after checking - var y = matches[3]; - var composedDate = new Date(y, m, d); - var timestampDate = composedDate.getTime() - - //note, some reason these timestamps are being recorded +4 hours UTC - if (composedDate.getDate() == d && composedDate.getMonth() == m && composedDate.getFullYear() == y) { - return timestampDate / 1000 - } else { - return false - } -} diff --git a/CLI/commands/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js index b4d5e3c6b..da3589f3d 100644 --- a/CLI/commands/changeNonAccreditedLimit.js +++ b/CLI/commands/changeNonAccreditedLimit.js @@ -1,149 +1,159 @@ +var common = require('./common/common_functions'); var fs = require('fs'); var csv = require('fast-csv'); -var BigNumber = require('bignumber.js'); -var chalk = require('chalk'); -var common = require('./common/common_functions'); -var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis') - -/////////////////////////////ARTIFACTS////////////////////////////////////////// -let securityTokenRegistry; -let securityToken; -let usdTieredSTO; - -////////////////////////////USER INPUTS////////////////////////////////////////// -let tokenSymbol = process.argv.slice(2)[0]; //token symbol -let BATCH_SIZE = process.argv.slice(2)[1]; //batch size -if (!BATCH_SIZE) BATCH_SIZE = 75; -let remoteNetwork = process.argv.slice(2)[2]; +var abis = require('./helpers/contract_abis'); +var BigNumber = require('bignumber.js'); -/////////////////////////GLOBAL VARS////////////////////////////////////////// -//distribData is an array of batches. i.e. if there are 200 entries, with batch sizes of 75, we get [[75],[75],[50]] let distribData = new Array(); -//allocData is a temporary array that stores up to the batch size, -//then gets push into distribData, then gets set to 0 to start another batch let allocData = new Array(); -//full file data is a single array that contains all arrays. i.e. if there are 200 entries we get [[200]] let fullFileData = new Array(); -//baa data is an array that contains invalid entries let badData = new Array(); -//////////////////////////////////////////ENTRY INTO SCRIPT////////////////////////////////////////// -startScript(); +let BATCH_SIZE = 70; +let securityToken; + +async function startScript(tokenSymbol, batchSize) { + if (batchSize) { + BATCH_SIZE = batchSize; + } + + common.logAsciiBull(); + + let STAddress = await checkST(tokenSymbol); + securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); + + await readCsv(); +}; -async function startScript() { - if (remoteNetwork == 'undefined') remoteNetwork = undefined; - await global.initialize(remoteNetwork); +async function checkST(tokenSymbol) { + let securityTokenRegistry = await STConnect(); + return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { + if (result != "0x0000000000000000000000000000000000000000") { + return result + } else { + console.log("Token doesn't exist") + process.exit(0) + } + }); +} + +async function STConnect() { try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - console.log("Processing investor CSV upload. Batch size is " + BATCH_SIZE + " accounts per transaction"); - readFile(); + let STRegistryAddress = await contracts.securityTokenRegistry(); + let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); + return STRegistry; } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); - return; + console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); + process.exit(0); } } -///////////////////////////FUNCTION READING THE CSV FILE -function readFile() { - var stream = fs.createReadStream("./CLI/data/nonAccreditedLimits_data.csv"); - - let index = 0; - console.log(` - -------------------------------------------- - ----------- Parsing the csv file ----------- - -------------------------------------------- - `); - - var csvStream = csv() - .on("data", function (data) { - let isAddress = web3.utils.isAddress(data[0]); - let isNumber = !isNaN(data[1]); - - if (isAddress && isNumber) { - let userArray = new Array(); - let checksummedAddress = web3.utils.toChecksumAddress(data[0]); +async function readCsv() { + var CSV_STRING = fs.readFileSync("./CLI/data/nonAccreditedLimits_data.csv").toString(); + let i = 0; - userArray.push(checksummedAddress); - userArray.push(data[1]); + csv.fromString(CSV_STRING) + .on("data", (data) => { + let data_processed = nonAccredited_processing(data); + fullFileData.push(data_processed[1]); - allocData.push(userArray); - fullFileData.push(userArray); - - index++; - if (index >= BATCH_SIZE) { + if (data_processed[0]) { + allocData.push(data_processed[1]); + i++; + if (i >= BATCH_SIZE) { distribData.push(allocData); allocData = []; - index = 0; + i = 0; } } else { - let userArray = new Array() - userArray.push(data[0]); - userArray.push(data[1]); - - badData.push(userArray); - fullFileData.push(userArray) + badData.push(data_processed[1]); } + }) - .on("end", function () { - //Add last remainder batch + .on("end", async () => { distribData.push(allocData); allocData = []; - changeNonAccreditedLimit(); + await saveInBlockchain(); + return; }); - - stream.pipe(csvStream); } -// MAIN FUNCTION COMMUNICATING TO BLOCKCHAIN -async function changeNonAccreditedLimit() { - // Let's check if token has already been deployed, if it has, skip to STO - let tokenDeployedAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); - if (tokenDeployedAddress != "0x0000000000000000000000000000000000000000") { - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, tokenDeployedAddress); - let result = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); - if (result.length > 0) { - let usdTieredSTOABI = abis.usdTieredSTO(); - usdTieredSTO = new web3.eth.Contract(usdTieredSTOABI, result[0]); - console.log(` --------------------------------------------------------------- ------ Sending non accredited limit changes to blockchain ----- --------------------------------------------------------------- - `); - //this for loop will do the batches, so it should run 75, 75, 50 with 200 +async function saveInBlockchain() { + let gtmModules; + try { + gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); + } catch (e) { + console.log("Please attach USDTieredSTO module before launch this action.", e) + process.exit(0) + } + + if (!gtmModules.length) { + console.log("Please attach USDTieredSTO module before launch this action.") + process.exit(0) + } + + let usdTieredSTO = new web3.eth.Contract(abis.usdTieredSTO(), gtmModules[0]); + + console.log(` + -------------------------------------------------------------- + ----- Sending non accredited limit changes to blockchain ----- + -------------------------------------------------------------- + `); + + for (let i = 0; i < distribData.length; i++) { + try { + + // Splitting the user arrays to be organized by input for (let i = 0; i < distribData.length; i++) { try { - let investorArray = []; - let limitArray = []; + let investorArray = [], limitArray = []; - //splitting the user arrays to be organized by input for (let j = 0; j < distribData[i].length; j++) { investorArray.push(distribData[i][j][0]); limitArray.push(web3.utils.toWei(distribData[i][j][1].toString())); } - + let changeNonAccreditedLimitAction = usdTieredSTO.methods.changeNonAccreditedLimit(investorArray, limitArray); - let r = await common.sendTransaction(changeNonAccreditedLimitAction); + let tx = await common.sendTransaction(changeNonAccreditedLimitAction); console.log(`Batch ${i} - Attempting to change non accredited limits to accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Change accredited transaction was successful.", r.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(r.gasUsed * defaultGasPrice).toString()), "Ether"); + console.log("Change accredited transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString()), "Ether"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); + } catch (err) { console.log("ERROR:", err); } } - } else { - console.log(chalk.red(`There is no STO module attached to the ${tokenSymbol.toUpperCase()} Token. No further actions can be taken.`)); - } + + } catch (err) { + console.log("ERROR", err) + process.exit(0) + } + } + + return; +} + +function nonAccredited_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let isNumber = !isNaN(csv_line[1]); + + if (isAddress && isNumber) { + + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), csv_line[1])] + } else { - console.log(chalk.red(`Token symbol provided is not a registered Security Token.`)); + + return [false, new Array(csv_line[0], csv_line[1])] + } } + +module.exports = { + executeApp: async (tokenSymbol, batchSize) => { + return startScript(tokenSymbol, batchSize); + } +} \ No newline at end of file diff --git a/CLI/commands/scripts/script.sh b/CLI/commands/scripts/script.sh deleted file mode 100755 index 2ee363a8f..000000000 --- a/CLI/commands/scripts/script.sh +++ /dev/null @@ -1,19 +0,0 @@ -#! /bin/bash - -if [ $1 = "Whitelist" ]; -then -echo "Running the $1 script"; -node $PWD/CLI/commands/whitelist.js $2 $3 $4 -elif [ $1 = "Multimint" ]; -then -echo "Running the $1 script"; -node $PWD/CLI/commands/multi_mint.js $2 $3 $4 -elif [ $1 = "Accredit" ]; -then -echo "Running the $1 script"; -node $PWD/CLI/commands/accredit.js $2 $3 $4 -elif [ $1 = "NonAccreditedLimit" ]; -then -echo "Running the $1 script"; -node $PWD/CLI/commands/changeNonAccreditedLimit.js $2 $3 $4 -fi diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 6d496cd00..25831ab9d 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -1,6 +1,5 @@ #!/usr/bin/env node -const shell = require('shelljs'); var faucet = require('./commands/faucet'); var investor_portal = require('./commands/investor_portal'); var module_manager = require('./commands/module_manager'); @@ -9,6 +8,7 @@ var transfer = require('./commands/transfer'); var whitelist = require('./commands/whitelist'); var multimint = require('./commands/multi_mint'); var accredit = require('./commands/accredit'); +var changeNonAccreditedLimit = require('./commands/changeNonAccreditedLimit'); var transfer_ownership = require('./commands/transfer_ownership'); var dividends_manager = require('./commands/dividends_manager'); var transfer_manager = require('./commands/transfer_manager'); @@ -149,7 +149,7 @@ program .description('Runs changeNonAccreditedLimit') .action(async function(tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - shell.exec(`${__dirname}/commands/scripts/script.sh NonAccreditedLimit ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; + await changeNonAccreditedLimit.executeApp(tokenSymbol, batchSize); }); program diff --git a/package.json b/package.json index b350b4ac6..5f8594e10 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,6 @@ "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", - "shelljs": "^0.8.2", "solc": "^0.4.24", "truffle-contract": "^3.0.4", "truffle-hdwallet-provider-privkey": "^0.1.0", From 1fadb74e91a68644d451b9edf326932b2d21e9ac Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 14 Nov 2018 13:51:56 +0200 Subject: [PATCH 091/582] added nextDate to schedule --- contracts/wallet/VestingEscrowWallet.sol | 51 +++++++++++++++++------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 2e8ce15ab..448c0ebe2 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -15,11 +15,13 @@ contract VestingEscrowWallet is Ownable { uint256 vestingDuration; uint256 vestingFrequency; uint256 startDate; + uint256 nextDate; } struct VestingData { - VestingSchedule[] schedules; uint256 index; + VestingSchedule[] schedules; + uint256 availableTokens; } IERC20 public token; @@ -64,6 +66,7 @@ contract VestingEscrowWallet is Ownable { schedule.vestingDuration = _vestingDuration; schedule.vestingFrequency = _vestingFrequency; schedule.startDate = _startDate; + schedule.nextDate = _startDate + _vestingFrequency; //add beneficiary to the schedule list only if adding first schedule if (schedules[_beneficiary].schedules.length == 0) { schedules[_beneficiary].index = beneficiaries.length; @@ -77,10 +80,10 @@ contract VestingEscrowWallet is Ownable { function revokeVestingSchedule(address _beneficiary, uint256 index) external onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); require(index < schedules[_beneficiary].schedules.length, "Schedule not found"); - VestingSchedule[] storage vestingSchedule = schedules[_beneficiary].schedules; - vestingSchedule[index] = vestingSchedule[vestingSchedule.length - 1]; - vestingSchedule.length--; - if (vestingSchedule.length == 0) { + VestingSchedule[] storage schedule = schedules[_beneficiary].schedules; + schedule[index] = schedule[schedule.length - 1]; + schedule.length--; + if (schedule.length == 0) { _revokeVestingSchedules(_beneficiary); } /*solium-disable-next-line security/no-block-members*/ @@ -89,6 +92,7 @@ contract VestingEscrowWallet is Ownable { function revokeVestingSchedules(address _beneficiary) external onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); + delete schedules[_beneficiary].schedules; _revokeVestingSchedules(_beneficiary); /*solium-disable-next-line security/no-block-members*/ emit RevokeVestingSchedules(_beneficiary, now); @@ -97,11 +101,12 @@ contract VestingEscrowWallet is Ownable { function getVestingSchedule(address _beneficiary, uint256 index) external onlyOwner returns(uint256, uint256, uint256, uint256) { require(_beneficiary != address(0), "Invalid beneficiary address"); require(index < schedules[_beneficiary].schedules.length, "Schedule not found"); + VestingSchedule schedule = schedules[_beneficiary].schedules[index]; return ( - schedules[_beneficiary].schedules[index].numberOfTokens, - schedules[_beneficiary].schedules[index].vestingDuration, - schedules[_beneficiary].schedules[index].vestingFrequency, - schedules[_beneficiary].schedules[index].startDate + schedule.numberOfTokens, + schedule.vestingDuration, + schedule.vestingFrequency, + schedule.startDate ); } @@ -125,15 +130,31 @@ contract VestingEscrowWallet is Ownable { } + function _update(address _beneficiary) internal { + VestingData data = schedules[_beneficiary]; + for (uint256 i = 0; i < data.schedules.length; i++) { + VestingSchedule schedule = data.schedules[i]; + if (schedule.nextDate <= now) { + schedule.nextDate = schedule.nextDate.add(schedule.vestingFrequency); + + } + } + } function _revokeVestingSchedules(address _beneficiary) private { - uint256 index = schedules[_beneficiary].index; - beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; - beneficiaries.length--; - if (index != beneficiaries.length) { - schedules[beneficiaries[index]].index = index; + if (_canBeRemoved(_beneficiary)) { + uint256 index = schedules[_beneficiary].index; + beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; + beneficiaries.length--; + if (index != beneficiaries.length) { + schedules[beneficiaries[index]].index = index; + } + delete schedules[_beneficiary]; } - delete schedules[_beneficiary]; + } + + function _canBeRemoved(address _beneficiary) private returns(bool) { + return (schedules[_beneficiary].availableTokens == 0); } } From d7896ddbb1eda4ed34df2ced4d4af6f0aa46c074 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 14 Nov 2018 16:43:14 +0200 Subject: [PATCH 092/582] added _update, State, lockedTokens --- contracts/wallet/VestingEscrowWallet.sol | 92 ++++++++++++++++-------- 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 448c0ebe2..a222210c0 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -1,35 +1,43 @@ pragma solidity ^0.4.24; -import "../../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "../../node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +//TODO ? import "../interfaces/IERC20.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; /** * @title Wallet for core vesting escrow functionality */ contract VestingEscrowWallet is Ownable { using SafeMath for uint256; + using SafeERC20 for ERC20Basic; struct VestingSchedule { uint256 numberOfTokens; + uint256 lockedTokens; uint256 vestingDuration; uint256 vestingFrequency; uint256 startDate; uint256 nextDate; + State state; } struct VestingData { uint256 index; VestingSchedule[] schedules; uint256 availableTokens; + uint256 claimedTokens; } + enum State {STARTED, COMPLETED} + IERC20 public token; address public treasury; uint256 public unassignedTokens; - mapping (address => VestingData) public schedules; + mapping (address => VestingData) public vestingData; address[] public beneficiaries; event AddVestingSchedule( @@ -59,31 +67,39 @@ contract VestingEscrowWallet is Ownable { onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); - //TODO validation + require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); + require(_vestingDuration % _vestingFrequency == 0, "Duration should be divided entirely by frequency"); + uint256 periodCount = _vestingDuration.div(_vestingFrequency); + require(_numberOfTokens % periodCount == 0, "Number of tokens should be divided entirely by period count"); + require(_numberOfTokens <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); VestingSchedule memory schedule; + unassignedTokens = unassignedTokens.sub(_numberOfTokens); schedule.numberOfTokens = _numberOfTokens; + schedule.lockedTokens = _numberOfTokens; schedule.vestingDuration = _vestingDuration; schedule.vestingFrequency = _vestingFrequency; schedule.startDate = _startDate; - schedule.nextDate = _startDate + _vestingFrequency; + schedule.nextDate = _startDate.add(schedule.vestingFrequency); + schedule.state = State.STARTED; //add beneficiary to the schedule list only if adding first schedule - if (schedules[_beneficiary].schedules.length == 0) { - schedules[_beneficiary].index = beneficiaries.length; + if (vestingData[_beneficiary].schedules.length == 0) { + vestingData[_beneficiary].index = beneficiaries.length; beneficiaries.push(_beneficiary); } - schedules[_beneficiary].schedules.push(schedule); + vestingData[_beneficiary].schedules.push(schedule); /*solium-disable-next-line security/no-block-members*/ emit AddVestingSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); } function revokeVestingSchedule(address _beneficiary, uint256 index) external onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); - require(index < schedules[_beneficiary].schedules.length, "Schedule not found"); - VestingSchedule[] storage schedule = schedules[_beneficiary].schedules; - schedule[index] = schedule[schedule.length - 1]; - schedule.length--; - if (schedule.length == 0) { + require(index < vestingData[_beneficiary].schedules.length, "Schedule not found"); + VestingSchedule[] storage schedules = vestingData[_beneficiary].schedules; + unassignedTokens = unassignedTokens.add(schedules[index].lockedTokens); + schedules[index] = schedules[schedules.length - 1]; + schedules.length--; + if (schedules.length == 0) { _revokeVestingSchedules(_beneficiary); } /*solium-disable-next-line security/no-block-members*/ @@ -92,32 +108,39 @@ contract VestingEscrowWallet is Ownable { function revokeVestingSchedules(address _beneficiary) external onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); - delete schedules[_beneficiary].schedules; + VestingData data = vestingData[_beneficiary]; + for (uint256 i = 0; i < data.schedules.length; i++) { + unassignedTokens = unassignedTokens.add(data.schedules[i].lockedTokens); + } + delete vestingData[_beneficiary].schedules; _revokeVestingSchedules(_beneficiary); /*solium-disable-next-line security/no-block-members*/ emit RevokeVestingSchedules(_beneficiary, now); } - function getVestingSchedule(address _beneficiary, uint256 index) external onlyOwner returns(uint256, uint256, uint256, uint256) { + function getVestingSchedule(address _beneficiary, uint256 _index) external onlyOwner returns(uint256, uint256, uint256, uint256, uint256, uint256, State) { require(_beneficiary != address(0), "Invalid beneficiary address"); - require(index < schedules[_beneficiary].schedules.length, "Schedule not found"); - VestingSchedule schedule = schedules[_beneficiary].schedules[index]; + require(_index < vestingData[_beneficiary].schedules.length, "Schedule not found"); + VestingSchedule schedule = vestingData[_beneficiary].schedules[_index]; return ( schedule.numberOfTokens, + schedule.lockedTokens, schedule.vestingDuration, schedule.vestingFrequency, - schedule.startDate + schedule.startDate, + schedule.nextDate, + schedule.state ); } - function getVestingScheduleCount(address _beneficiary, uint256 index) external onlyOwner returns(uint256) { + function getVestingScheduleCount(address _beneficiary) external onlyOwner returns(uint256) { require(_beneficiary != address(0), "Invalid beneficiary address"); - return schedules[_beneficiary].schedules.length; + return vestingData[_beneficiary].schedules.length; } function editVestingSchedule( address _beneficiary, - uint256 index, + uint256 _index, uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, @@ -130,31 +153,42 @@ contract VestingEscrowWallet is Ownable { } + + function _update(address _beneficiary) internal { - VestingData data = schedules[_beneficiary]; + VestingData data = vestingData[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { VestingSchedule schedule = data.schedules[i]; - if (schedule.nextDate <= now) { - schedule.nextDate = schedule.nextDate.add(schedule.vestingFrequency); - + /*solium-disable-next-line security/no-block-members*/ + if (schedule.state == State.STARTED && schedule.nextDate <= now) { + uint256 periodCount = schedule.vestingDuration.div(schedule.vestingFrequency); + uint256 numberOfTokens = schedule.numberOfTokens.div(periodCount); + data.availableTokens = data.availableTokens.add(numberOfTokens); + schedule.lockedTokens = schedule.lockedTokens.sub(numberOfTokens); + + if (schedule.nextDate == schedule.startDate.add(schedule.vestingDuration)) { + schedule.state = State.COMPLETED; + } else { + schedule.nextDate = schedule.nextDate.add(schedule.vestingFrequency); + } } } } function _revokeVestingSchedules(address _beneficiary) private { if (_canBeRemoved(_beneficiary)) { - uint256 index = schedules[_beneficiary].index; + uint256 index = vestingData[_beneficiary].index; beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; beneficiaries.length--; if (index != beneficiaries.length) { - schedules[beneficiaries[index]].index = index; + vestingData[beneficiaries[index]].index = index; } - delete schedules[_beneficiary]; + delete vestingData[_beneficiary]; } } function _canBeRemoved(address _beneficiary) private returns(bool) { - return (schedules[_beneficiary].availableTokens == 0); + return (vestingData[_beneficiary].availableTokens == 0); } } From dd6c292be2b53333055dfd9ba834a8266b3922f8 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Wed, 14 Nov 2018 12:00:03 -0300 Subject: [PATCH 093/582] sto_manager command --- CLI/commands/sto_manager.js | 927 ++++++++++++++++++++++++++++++++++++ CLI/polymath-cli.js | 10 + 2 files changed, 937 insertions(+) create mode 100644 CLI/commands/sto_manager.js diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js new file mode 100644 index 000000000..871e6d37b --- /dev/null +++ b/CLI/commands/sto_manager.js @@ -0,0 +1,927 @@ +var readlineSync = require('readline-sync'); +var BigNumber = require('bignumber.js'); +var chalk = require('chalk'); +const shell = require('shelljs'); +var contracts = require('./helpers/contract_addresses'); +var abis = require('./helpers/contract_abis'); +var common = require('./common/common_functions'); +var gbl = require('./common/global'); + +/////////////////// +// Crowdsale params +let tokenSymbol; + +//////////////////////// +// Artifacts +let securityTokenRegistry; +let polyToken; +let usdToken; +let securityToken; + +async function executeApp() { + common.logAsciiBull(); + console.log("********************************************"); + console.log("Welcome to the Command-Line ST-20 Generator."); + console.log("********************************************"); + console.log("The following script will create a new ST-20 according to the parameters you enter."); + console.log("Issuer Account: " + Issuer.address + "\n"); + + await setup(); + + securityToken = await selectToken(); + while (true) { + await start_explorer(); + } +}; + +async function setup(){ + try { + let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); + let securityTokenRegistryABI = abis.securityTokenRegistry(); + securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); + securityTokenRegistry.setProvider(web3.currentProvider); + + let polytokenAddress = await contracts.polyToken(); + let polytokenABI = abis.polyToken(); + polyToken = new web3.eth.Contract(polytokenABI, polytokenAddress); + polyToken.setProvider(web3.currentProvider); + + //TODO: Use proper DAI token here + let usdTokenAddress = await contracts.usdToken(); + usdToken = new web3.eth.Contract(polytokenABI, usdTokenAddress); + usdToken.setProvider(web3.currentProvider); + } catch (err) { + console.log(err) + console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); + process.exit(0); + } +} + +async function selectToken() { + let stAddress; + let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); + if (userTokens.length == 0) { + console.log(chalk.red(`You have not issued any Security Token yet!`)); + process.exit(0); + } else if (userTokens.length == 1) { + let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(userTokens[0]).call(); + console.log(chalk.yellow(`You have only one token. ${tokenData[0]} will be selected automatically.`)); + stAddress = userTokens[0]; + } else { + let options = await Promise.all(userTokens.map(async function (t) { + let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); + return `${tokenData[0]} + Deployed at ${t}`; + })); + + let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); + if (index == -1) { + process.exit(0); + } else { + stAddress = userTokens[index]; + } + } + + let securityTokenABI = abis.securityToken(); + let securityToken = new web3.eth.Contract(securityTokenABI, stAddress); + + return securityToken; +} + +async function start_explorer() { + console.log(); + console.log(chalk.blue('STO Manager - Main Menu')); + + // Show non-archived attached STO modules + console.log(); + let stoModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.STO); + let nonArchivedModules = stoModules.filter(m => !m.archived); + if (nonArchivedModules.length > 0) { + console.log(`STO modules attached:`); + nonArchivedModules.map(m => console.log(`- ${m.name} at ${m.address}`)) + } else { + console.log(`There are no STO modules attached`); + } + + let options = []; + if (nonArchivedModules.length > 0) { + options.push('Show existing STO information', 'Modify existing STO'); + } + options.push('Add new STO module'); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Exit'}); + let optionSelected = index != -1 ? options[index] : 'Exit'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Show existing STO information': + let stoToShow = selectExistingSTO(nonArchivedModules, true); + await showSTO(stoToShow.name, stoToShow.module); + break; + case 'Modify existing STO': + let stoToModify = selectExistingSTO(nonArchivedModules); + await modifySTO(stoToModify.name, stoToModify.module); + break; + case 'Add new STO module': + await addSTOModule(); + break; + case 'Exit': + process.exit(0); + } +} + +function selectExistingSTO(stoModules, showPaused) { + let filteredModules = stoModules; + if (!showPaused) { + filteredModules = stoModules.filter(m => !m.paused); + } + let options = filteredModules.map(m => `${m.name} at ${m.address}`); + let index = readlineSync.keyInSelect(options, 'Select a module: ', {cancel: false}); + console.log('Selected:', options[index], '\n'); + let selectedName = filteredModules[index].name; + let stoABI; + switch (selectedName) { + case 'CappedSTO': + stoABI = abis.cappedSTO(); + break; + case 'USDTieredSTO': + stoABI = abis.usdTieredSTO(); + break; + } + + let stoModule = new web3.eth.Contract(stoABI, filteredModules[index].address); + return {name: selectedName, module: stoModule}; +} + +async function showSTO(selectedSTO, currentSTO) { + switch (selectedSTO) { + case 'CappedSTO': + await cappedSTO_status(currentSTO); + break; + case 'USDTieredSTO': + await usdTieredSTO_status(currentSTO); + break; + } +} + +async function modifySTO(selectedSTO, currentSTO) { + switch (selectedSTO) { + case 'CappedSTO': + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************`)); + break; + case 'USDTieredSTO': + await usdTieredSTO_configure(currentSTO); + break; + } +} + +async function addSTOModule() { + console.log(chalk.blue('Launch STO - Configuration')); + + let options = ['CappedSTO', 'USDTieredSTO']; + let index = readlineSync.keyInSelect(options, 'What type of STO do you want?', { cancel: 'Return' }); + let optionSelected = index != -1 ? options[index] : 'Return'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'CappedSTO': + let cappedSTO = await cappedSTO_launch(); + await cappedSTO_status(cappedSTO); + break; + case 'USDTieredSTO': + let usdTieredSTO = await usdTieredSTO_launch(); + await usdTieredSTO_status(usdTieredSTO); + break; + } +} + +//////////////// +// Capped STO // +//////////////// +async function cappedSTO_launch() { + console.log(chalk.blue('Launch STO - Capped STO in No. of Tokens')); + + let cappedSTOFactoryABI = abis.cappedSTOFactory(); + let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.STO, "CappedSTO"); + let cappedSTOFactory = new web3.eth.Contract(cappedSTOFactoryABI, cappedSTOFactoryAddress); + cappedSTOFactory.setProvider(web3.currentProvider); + let stoFee = await cappedSTOFactory.methods.getSetupCost().call(); + + let contractBalance = await polyToken.methods.balanceOf(securityToken._address).call(); + if (parseInt(contractBalance) < parseInt(stoFee)) { + let transferAmount = parseInt(stoFee) - parseInt(contractBalance); + let ownerBalance = await polyToken.methods.balanceOf(Issuer.address).call(); + if (parseInt(ownerBalance) < transferAmount) { + console.log(chalk.red(`\n**************************************************************************************************************************************************`)); + console.log(chalk.red(`Not enough balance to pay the CappedSTO fee, Requires ${(new BigNumber(transferAmount).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY but have ${(new BigNumber(ownerBalance).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY. Access POLY faucet to get the POLY to complete this txn`)); + console.log(chalk.red(`**************************************************************************************************************************************************\n`)); + return; + } else { + let transferAction = polyToken.methods.transfer(securityToken._address, new BigNumber(transferAmount)); + let receipt = await common.sendTransaction(transferAction, {factor: 2}); + let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); + console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) + } + } + + let cap = readlineSync.question('How many tokens do you plan to sell on the STO? (500.000): '); + if (cap == "") cap = '500000'; + + let oneMinuteFromNow = BigNumber((Math.floor(Date.now() / 1000) + 60)); + let startTime = readlineSync.question('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): '); + if (startTime == "") startTime = oneMinuteFromNow; + + let oneMonthFromNow = BigNumber((Math.floor(Date.now()/1000)+ (30 * 24 * 60 * 60))); + let endTime = readlineSync.question('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): '); + if (endTime == "") endTime = oneMonthFromNow; + + let wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): '); + if (wallet == "") wallet = Issuer.address; + + let raiseType = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise or leave empty for Ether raise (E): '); + if (raiseType.toUpperCase() == 'P' ) { + raiseType = [1]; + } else { + raiseType = [0]; + } + + let rate = readlineSync.question(`Enter the rate (1 ${(raiseType == 1 ? 'POLY' : 'ETH')} = X ${tokenSymbol}) for the STO (1000): `); + if (rate == "") rate = 1000; + + let bytesSTO = web3.eth.abi.encodeFunctionCall( { + name: 'configure', + type: 'function', + inputs: [ + { + type: 'uint256', + name: '_startTime' + },{ + type: 'uint256', + name: '_endTime' + },{ + type: 'uint256', + name: '_cap' + },{ + type: 'uint256', + name: '_rate' + },{ + type: 'uint8[]', + name: '_fundRaiseTypes' + },{ + type: 'address', + name: '_fundsReceiver' + } + ] + }, [startTime, endTime, web3.utils.toWei(cap), rate, raiseType, wallet]); + + let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); + let receipt = await common.sendTransaction(addModuleAction); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); + console.log(`STO deployed at address: ${event._module}`); + + let cappedSTOABI = abis.cappedSTO(); + let cappedSTO = new web3.eth.Contract(cappedSTOABI, event._module); + cappedSTO.setProvider(web3.currentProvider); + + return cappedSTO; +} + +async function cappedSTO_status(currentSTO) { + let displayStartTime = await currentSTO.methods.startTime().call(); + let displayEndTime = await currentSTO.methods.endTime().call(); + let displayRate = await currentSTO.methods.rate().call(); + let displayCap = await currentSTO.methods.cap().call(); + let displayWallet = await currentSTO.methods.wallet().call(); + let displayRaiseType; + let displayFundsRaised; + let displayWalletBalance; + let raiseType = await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.ETH).call(); + if (raiseType) { + displayRaiseType = 'ETH'; + displayFundsRaised = await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES.ETH).call(); + displayWalletBalance = web3.utils.fromWei(await web3.eth.getBalance(displayWallet)); + } else { + displayRaiseType = 'POLY'; + displayFundsRaised = await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES.POLY).call(); + displayWalletBalance = web3.utils.fromWei(await getBalance(displayWallet, 'POLY')); + } + let displayTokensSold = await currentSTO.methods.totalTokensSold().call(); + let displayInvestorCount = await currentSTO.methods.investorCount().call(); + let displayTokenSymbol = await securityToken.methods.symbol().call(); + + let formattedCap = BigNumber(web3.utils.fromWei(displayCap)); + let formattedSold = BigNumber(web3.utils.fromWei(displayTokensSold)); + + let now = Math.floor(Date.now()/1000); + let timeTitle; + let timeRemaining; + + if (now < displayStartTime) { + timeTitle = "STO starts in: "; + timeRemaining = displayStartTime - now; + } else { + timeTitle = "Time remaining:"; + timeRemaining = displayEndTime - now; + } + + timeRemaining = common.convertToDaysRemaining(timeRemaining); + + console.log(` + *************** STO Information *************** + - Address: ${currentSTO.options.address} + - Raise Cap: ${web3.utils.fromWei(displayCap)} ${displayTokenSymbol.toUpperCase()} + - Start Time: ${new Date(displayStartTime * 1000)} + - End Time: ${new Date(displayEndTime * 1000)} + - Raise Type: ${displayRaiseType} + - Rate: 1 ${displayRaiseType} = ${displayRate} ${displayTokenSymbol.toUpperCase()} + - Wallet: ${displayWallet} + - Wallet Balance: ${displayWalletBalance} ${displayRaiseType} + ----------------------------------------------- + - ${timeTitle} ${timeRemaining} + - Funds raised: ${web3.utils.fromWei(displayFundsRaised)} ${displayRaiseType} + - Tokens sold: ${web3.utils.fromWei(displayTokensSold)} ${displayTokenSymbol.toUpperCase()} + - Tokens remaining: ${formattedCap.minus(formattedSold).toNumber()} ${displayTokenSymbol.toUpperCase()} + - Investor count: ${displayInvestorCount} + `); + + console.log(chalk.green(`\n${(web3.utils.fromWei(await getBalance(Issuer.address, 'POLY')))} POLY balance remaining at issuer address ${Issuer.address}`)); +} + +//////////////////// +// USD Tiered STO // +//////////////////// +function fundingConfigUSDTieredSTO() { + let funding = {}; + + let selectedFunding = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise,' + chalk.green(` D `) + 'for DAI raise,' + chalk.green(` E `) + 'for Ether raise or any combination of them (i.e.'+ chalk.green(` PED `) + 'for all): ').toUpperCase(); + + funding.raiseType = []; + if (selectedFunding.includes('E')) { + funding.raiseType.push(gbl.constants.FUND_RAISE_TYPES.ETH); + } + if (selectedFunding.includes('P')) { + funding.raiseType.push(gbl.constants.FUND_RAISE_TYPES.POLY); + } + if (selectedFunding.includes('D')) { + funding.raiseType.push(gbl.constants.FUND_RAISE_TYPES.DAI); + } + if (funding.raiseType.length == 0) { + funding.raiseType = [gbl.constants.FUND_RAISE_TYPES.ETH, gbl.constants.FUND_RAISE_TYPES.POLY, gbl.constants.FUND_RAISE_TYPES.DAI]; + } + + return funding; +} + +function addressesConfigUSDTieredSTO(usdTokenRaise) { + let addresses = {}; + + addresses.wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: Issuer.address + }); + if (addresses.wallet == "") addresses.wallet = Issuer.address; + + addresses.reserveWallet = readlineSync.question('Enter the address that will receive remaining tokens in the case the cap is not met (' + Issuer.address + '): ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: Issuer.address + }); + if (addresses.reserveWallet == "") addresses.reserveWallet = Issuer.address; + + if (usdTokenRaise) { + addresses.usdToken = readlineSync.question('Enter the address of the USD Token or stable coin (' + usdToken.options.address + '): ', { + limit: function(input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: usdToken.options.address + }); + if (addresses.usdToken == "") addresses.usdToken = usdToken.options.address; + } else { + addresses.usdToken = '0x0000000000000000000000000000000000000000'; + } + + return addresses; +} + +function tiersConfigUSDTieredSTO(polyRaise) { + let tiers = {}; + + let defaultTiers = 3; + tiers.tiers = readlineSync.questionInt(`Enter the number of tiers for the STO? (${defaultTiers}): `, { + limit: function(input) { + return input > 0; + }, + limitMessage: 'Must be greater than zero', + defaultInput: defaultTiers + }); + + let defaultTokensPerTier = [190000000, 100000000, 200000000]; + let defaultRatePerTier = ['0.05', '0.10', '0.15']; + let defaultTokensPerTierDiscountPoly = [90000000, 50000000, 100000000]; + let defaultRatePerTierDiscountPoly = ['0.025', '0.05', '0.075']; + tiers.tokensPerTier = []; + tiers.ratePerTier = []; + tiers.tokensPerTierDiscountPoly = []; + tiers.ratePerTierDiscountPoly = []; + for (let i = 0; i < tiers.tiers; i++) { + tiers.tokensPerTier[i] = web3.utils.toWei(readlineSync.question(`How many tokens do you plan to sell on tier No. ${i+1}? (${defaultTokensPerTier[i]}): `, { + limit: function(input) { + return parseFloat(input) > 0; + }, + limitMessage: 'Must be greater than zero', + defaultInput: defaultTokensPerTier[i] + })); + + tiers.ratePerTier[i] = web3.utils.toWei(readlineSync.question(`What is the USD per token rate for tier No. ${i+1}? (${defaultRatePerTier[i]}): `, { + limit: function(input) { + return parseFloat(input) > 0; + }, + limitMessage: 'Must be greater than zero', + defaultInput: defaultRatePerTier[i] + })); + + if (polyRaise && readlineSync.keyInYNStrict(`Do you plan to have a discounted rate for POLY investments for tier No. ${i+1}? `)) { + tiers.tokensPerTierDiscountPoly[i] = web3.utils.toWei(readlineSync.question(`How many of those tokens do you plan to sell at discounted rate on tier No. ${i+1}? (${defaultTokensPerTierDiscountPoly[i]}): `, { + limit: function(input) { + return new BigNumber(web3.utils.toWei(input)).lte(tiers.tokensPerTier[i]) + }, + limitMessage: 'Must be less than the No. of tokens of the tier', + defaultInput: defaultTokensPerTierDiscountPoly[i] + })); + + tiers.ratePerTierDiscountPoly[i] = web3.utils.toWei(readlineSync.question(`What is the discounted rate for tier No. ${i+1}? (${defaultRatePerTierDiscountPoly[i]}): `, { + limit: function(input) { + return new BigNumber(web3.utils.toWei(input)).lte(tiers.ratePerTier[i]) + }, + limitMessage: 'Must be less than the rate of the tier', + defaultInput: defaultRatePerTierDiscountPoly[i] + })); + } else { + tiers.tokensPerTierDiscountPoly[i] = 0; + tiers.ratePerTierDiscountPoly[i] = 0; + } + } + + return tiers; +} + +function timesConfigUSDTieredSTO() { + let times = {}; + + let oneMinuteFromNow = Math.floor(Date.now() / 1000) + 60; + times.startTime = readlineSync.questionInt('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): ', { + limit: function(input) { + return input > Math.floor(Date.now() / 1000); + }, + limitMessage: "Must be a future time", + defaultInput: oneMinuteFromNow + }); + if (times.startTime == "") times.startTime = oneMinuteFromNow; + + let oneMonthFromNow = Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60); + times.endTime = readlineSync.questionInt('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): ', { + limit: function(input) { + return input > times.startTime; + }, + limitMessage: "Must be greater than Start Time", + defaultInput: oneMonthFromNow + }); + if (times.endTime == "") times.endTime = oneMonthFromNow; + + return times; +} + +function limitsConfigUSDTieredSTO() { + let limits = {}; + + let defaultMinimumInvestment = 5; + limits.minimumInvestmentUSD = web3.utils.toWei(readlineSync.question(`What is the minimum investment in USD? (${defaultMinimumInvestment}): `, { + limit: function(input) { + return parseInt(input) > 0; + }, + limitMessage: "Must be greater than zero", + defaultInput: defaultMinimumInvestment + })); + + let nonAccreditedLimit = 2500; + limits.nonAccreditedLimitUSD = web3.utils.toWei(readlineSync.question(`What is the default limit for non accredited investors in USD? (${nonAccreditedLimit}): `, { + limit: function(input) { + return new BigNumber(web3.utils.toWei(input)).gte(limits.minimumInvestmentUSD); + }, + limitMessage: "Must be greater than minimum investment", + defaultInput: nonAccreditedLimit + })); + + return limits; +} + +async function usdTieredSTO_launch() { + console.log(chalk.blue('Launch STO - USD pegged tiered STO')); + + let usdTieredSTOFactoryABI = abis.usdTieredSTOFactory(); + let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.STO, 'USDTieredSTO'); + let usdTieredSTOFactory = new web3.eth.Contract(usdTieredSTOFactoryABI, usdTieredSTOFactoryAddress); + usdTieredSTOFactory.setProvider(web3.currentProvider); + let stoFee = await usdTieredSTOFactory.methods.getSetupCost().call(); + + let contractBalance = await polyToken.methods.balanceOf(securityToken._address).call(); + if (new web3.utils.BN(contractBalance).lt(new web3.utils.BN(stoFee))) { + let transferAmount = (new web3.utils.BN(stoFee)).sub(new web3.utils.BN(contractBalance)); + let ownerBalance = new web3.utils.BN(await polyToken.methods.balanceOf(Issuer.address).call()); + if (ownerBalance.lt(transferAmount)) { + console.log(chalk.red(`\n**************************************************************************************************************************************************`)); + console.log(chalk.red(`Not enough balance to pay the USDTieredSTO fee, Requires ${web3.utils.fromWei(transferAmount)} POLY but have ${web3.utils.fromWei(ownerBalance)} POLY. Access POLY faucet to get the POLY to complete this txn`)); + console.log(chalk.red(`**************************************************************************************************************************************************\n`)); + return; + } else { + let transferAction = polyToken.methods.transfer(securityToken._address, transferAmount); + let receipt = await common.sendTransaction(transferAction, {factor: 2}); + let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); + console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) + } + } + + let funding = fundingConfigUSDTieredSTO(); + let addresses = addressesConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.DAI)); + let tiers = tiersConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.POLY)); + let limits = limitsConfigUSDTieredSTO(); + let times = timesConfigUSDTieredSTO(); + let bytesSTO = web3.eth.abi.encodeFunctionCall( { + name: 'configure', + type: 'function', + inputs: [ + { + type: 'uint256', + name: '_startTime' + },{ + type: 'uint256', + name: '_endTime' + },{ + type: 'uint256[]', + name: '_ratePerTier' + },{ + type: 'uint256[]', + name: '_ratePerTierDiscountPoly' + },{ + type: 'uint256[]', + name: '_tokensPerTier' + },{ + type: 'uint256[]', + name: '_tokensPerTierDiscountPoly' + },{ + type: 'uint256', + name: '_nonAccreditedLimitUSD' + },{ + type: 'uint256', + name: '_minimumInvestmentUSD' + },{ + type: 'uint8[]', + name: '_fundRaiseTypes' + },{ + type: 'address', + name: '_wallet' + },{ + type: 'address', + name: '_reserveWallet' + },{ + type: 'address', + name: '_usdToken' + } + ] + }, [times.startTime, + times.endTime, + tiers.ratePerTier, + tiers.ratePerTierDiscountPoly, + tiers.tokensPerTier, + tiers.tokensPerTierDiscountPoly, + limits.nonAccreditedLimitUSD, + limits.minimumInvestmentUSD, + funding.raiseType, + addresses.wallet, + addresses.reserveWallet, + addresses.usdToken + ]); + + let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); + let receipt = await common.sendTransaction(addModuleAction); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); + console.log(`STO deployed at address: ${event._module}`); + + let usdTieredSTOABI = abis.usdTieredSTO(); + let usdTieredSTO = new web3.eth.Contract(usdTieredSTOABI, event._module); + usdTieredSTO.setProvider(web3.currentProvider); + + return usdTieredSTO; +} + +async function usdTieredSTO_status(currentSTO) { + let displayStartTime = await currentSTO.methods.startTime().call(); + let displayEndTime = await currentSTO.methods.endTime().call(); + let displayCurrentTier = parseInt(await currentSTO.methods.currentTier().call()) + 1; + let displayNonAccreditedLimitUSD = web3.utils.fromWei(await currentSTO.methods.nonAccreditedLimitUSD().call()); + let displayMinimumInvestmentUSD = web3.utils.fromWei(await currentSTO.methods.minimumInvestmentUSD().call()); + let displayWallet = await currentSTO.methods.wallet().call(); + let displayReserveWallet = await currentSTO.methods.reserveWallet().call(); + let displayTokensSold = web3.utils.fromWei(await currentSTO.methods.getTokensSold().call()); + let displayInvestorCount = await currentSTO.methods.investorCount().call(); + let displayIsFinalized = await currentSTO.methods.isFinalized().call() ? "YES" : "NO"; + let displayTokenSymbol = await securityToken.methods.symbol().call(); + + let tiersLength = await currentSTO.methods.getNumberOfTiers().call();; + + let raiseTypes = []; + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { + raiseTypes.push(fundType); + } + } + + let displayTiers = ""; + let displayMintedPerTier = ""; + for (let t = 0; t < tiersLength; t++) { + let ratePerTier = await currentSTO.methods.ratePerTier(t).call(); + let tokensPerTierTotal = await currentSTO.methods.tokensPerTierTotal(t).call(); + let mintedPerTierTotal = await currentSTO.methods.mintedPerTierTotal(t).call(); + + let displayMintedPerTierPerType = ""; + let displayDiscountTokens = ""; + for (const type of raiseTypes) { + let displayDiscountMinted = ""; + if (type == 'POLY') { + let tokensPerTierDiscountPoly = await currentSTO.methods.tokensPerTierDiscountPoly(t).call(); + if (tokensPerTierDiscountPoly > 0) { + let ratePerTierDiscountPoly = await currentSTO.methods.ratePerTierDiscountPoly(t).call(); + let mintedPerTierDiscountPoly = await currentSTO.methods.mintedPerTierDiscountPoly(t).call(); + displayDiscountTokens = ` + Tokens at discounted rate: ${web3.utils.fromWei(tokensPerTierDiscountPoly)} ${displayTokenSymbol} + Discounted rate: ${web3.utils.fromWei(ratePerTierDiscountPoly, 'ether')} USD per Token`; + + displayDiscountMinted = `(${web3.utils.fromWei(mintedPerTierDiscountPoly)} ${displayTokenSymbol} at discounted rate)`; + } + } + + let mintedPerTier = await currentSTO.methods.mintedPerTier(gbl.constants.FUND_RAISE_TYPES[type], t).call(); + displayMintedPerTierPerType += ` + Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + } + + displayTiers += ` + - Tier ${t+1}: + Tokens: ${web3.utils.fromWei(tokensPerTierTotal)} ${displayTokenSymbol} + Rate: ${web3.utils.fromWei(ratePerTier)} USD per Token` + + displayDiscountTokens; + + displayMintedPerTier += ` + - Tokens minted in Tier ${t+1}: ${web3.utils.fromWei(mintedPerTierTotal)} ${displayTokenSymbol}` + + displayMintedPerTierPerType; + } + + let displayFundsRaisedUSD = web3.utils.fromWei(await currentSTO.methods.fundsRaisedUSD().call()); + + let displayWalletBalancePerType = ''; + let displayReserveWalletBalancePerType = ''; + let displayFundsRaisedPerType = ''; + let displayTokensSoldPerType = ''; + for (const type of raiseTypes) { + let balance = await getBalance(displayWallet, type); + let walletBalance = web3.utils.fromWei(balance); + let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); + displayWalletBalancePerType += ` + Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; + + balance = await getBalance(displayReserveWallet, type); + let reserveWalletBalance = web3.utils.fromWei(balance); + let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); + displayReserveWalletBalancePerType += ` + Balance ${type}:\t\t ${reserveWalletBalance} ${type} (${reserveWalletBalanceUSD} USD)`; + + let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); + displayFundsRaisedPerType += ` + ${type}:\t\t\t ${fundsRaised} ${type}`; + + //Only show sold for if more than one raise type are allowed + if (raiseTypes.length > 1) { + let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(gbl.constants.FUND_RAISE_TYPES[type]).call()); + displayTokensSoldPerType += ` + Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; + } + } + + let displayRaiseType = raiseTypes.join(' - '); + + let now = Math.floor(Date.now()/1000); + let timeTitle; + let timeRemaining; + if (now < displayStartTime) { + timeTitle = "STO starts in: "; + timeRemaining = displayStartTime - now; + } else { + timeTitle = "Time remaining:"; + timeRemaining = displayEndTime - now; + } + + timeRemaining = common.convertToDaysRemaining(timeRemaining); + + console.log(` + *********************** STO Information *********************** + - Address: ${currentSTO.options.address} + - Start Time: ${new Date(displayStartTime * 1000)} + - End Time: ${new Date(displayEndTime * 1000)} + - Raise Type: ${displayRaiseType} + - Tiers: ${tiersLength}` + + displayTiers + ` + - Minimum Investment: ${displayMinimumInvestmentUSD} USD + - Non Accredited Limit: ${displayNonAccreditedLimitUSD} USD + - Wallet: ${displayWallet}` + + displayWalletBalancePerType + ` + - Reserve Wallet: ${displayReserveWallet}` + + displayReserveWalletBalancePerType + ` + + --------------------------------------------------------------- + - ${timeTitle} ${timeRemaining} + - Is Finalized: ${displayIsFinalized} + - Tokens Sold: ${displayTokensSold} ${displayTokenSymbol}` + + displayTokensSoldPerType + ` + - Current Tier: ${displayCurrentTier}` + + displayMintedPerTier + ` + - Investor count: ${displayInvestorCount} + - Funds Raised` + + displayFundsRaisedPerType + ` + USD: ${displayFundsRaisedUSD} USD + `); + + console.log(chalk.green(`\n${(web3.utils.fromWei(await getBalance(Issuer.address, 'POLY')))} POLY balance remaining at issuer address ${Issuer.address}`)); +} + +async function usdTieredSTO_configure(currentSTO) { + console.log(chalk.blue('STO Configuration - USD Tiered STO')); + + let isFinalized = await currentSTO.methods.isFinalized().call(); + if (isFinalized) { + console.log(chalk.red(`STO is finalized`)); + } else { + let options = []; + options.push('Finalize STO', + 'Change accredited account', 'Change accredited in batch', + 'Change non accredited limit for an account', 'Change non accredited limits in batch'); + + // If STO is not started, you can modify configuration + let now = Math.floor(Date.now() / 1000); + let startTime = await currentSTO.methods.startTime().call.call(); + if (now < startTime) { + options.push('Modify times configuration', 'Modify tiers configuration', 'Modify addresses configuration', + 'Modify limits configuration', 'Modify funding configuration'); + } + + let index = readlineSync.keyInSelect(options, 'What do you want to do?'); + switch (index) { + case 0: + let reserveWallet = await currentSTO.methods.reserveWallet().call(); + let isVerified = await securityToken.methods.verifyTransfer('0x0000000000000000000000000000000000000000', reserveWallet, 0, web3.utils.fromAscii("")).call(); + if (isVerified) { + if (readlineSync.keyInYNStrict()) { + let finalizeAction = currentSTO.methods.finalize(); + await common.sendTransaction(finalizeAction); + } + } else { + console.log(chalk.red(`Reserve wallet (${reserveWallet}) is not able to receive remaining tokens. Check if this address is whitelisted.`)); + } + break; + case 1: + let investor = readlineSync.question('Enter the address to change accreditation: '); + let isAccredited = readlineSync.keyInYNStrict(`Is ${investor} accredited?`); + let investors = [investor]; + let accredited = [isAccredited]; + let changeAccreditedAction = currentSTO.methods.changeAccredited(investors, accredited); + // 2 GAS? + await common.sendTransaction(changeAccreditedAction); + break; + case 2: + shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${remoteNetwork}`); + break; + case 3: + let account = readlineSync.question('Enter the address to change non accredited limit: '); + let limit = readlineSync.question(`Enter the limit in USD: `); + let accounts = [account]; + let limits = [web3.utils.toWei(limit)]; + let changeNonAccreditedLimitAction = currentSTO.methods.changeNonAccreditedLimit(accounts, limits); + // 2 GAS? + await common.sendTransaction(changeNonAccreditedLimitAction); + break; + case 4: + shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${remoteNetwork}`); + break; + case 5: + await modfifyTimes(currentSTO); + await usdTieredSTO_status(currentSTO); + break; + case 6: + await modfifyTiers(currentSTO); + await usdTieredSTO_status(currentSTO); + break; + case 7: + await modfifyAddresses(currentSTO); + await usdTieredSTO_status(currentSTO); + break; + case 8: + await modfifyLimits(currentSTO); + await usdTieredSTO_status(currentSTO); + break; + case 9: + await modfifyFunding(currentSTO); + await usdTieredSTO_status(currentSTO); + break; + } + } +} + +async function modfifyTimes(currentSTO) { + let times = timesConfigUSDTieredSTO(); + let modifyTimesAction = currentSTO.methods.modifyTimes(times.startTime, times.endTime); + await common.sendTransaction(modifyTimesAction); +} + +async function modfifyLimits(currentSTO) { + let limits = limitsConfigUSDTieredSTO(); + let modifyLimitsAction = currentSTO.methods.modifyLimits(limits.nonAccreditedLimitUSD, limits.minimumInvestmentUSD); + await common.sendTransaction(modifyLimitsAction); +} + +async function modfifyFunding(currentSTO) { + let funding = fundingConfigUSDTieredSTO(); + let modifyFundingAction = currentSTO.methods.modifyFunding(funding.raiseType); + await common.sendTransaction(modifyFundingAction); +} + +async function modfifyAddresses(currentSTO) { + let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.DAI).call()); + let modifyAddressesAction = currentSTO.methods.modifyAddresses(addresses.wallet, addresses.reserveWallet, addresses.usdToken); + await common.sendTransaction(modifyAddressesAction); +} + +async function modfifyTiers(currentSTO) { + let tiers = tiersConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.POLY).call()); + let modifyTiersAction = currentSTO.methods.modifyTiers( + tiers.ratePerTier, + tiers.ratePerTierDiscountPoly, + tiers.tokensPerTier, + tiers.tokensPerTierDiscountPoly, + ); + await common.sendTransaction(modifyTiersAction); +} + +////////////////////// +// HELPER FUNCTIONS // +////////////////////// +async function getBalance(from, type) { + switch (type) { + case 'ETH': + return await web3.eth.getBalance(from); + case 'POLY': + return await polyToken.methods.balanceOf(from).call(); + case 'DAI': + return await usdToken.methods.balanceOf(from).call(); + } +} + +async function getAllModulesByType(type) { + function ModuleInfo(_moduleType, _name, _address, _factoryAddress, _archived, _paused) { + this.name = _name; + this.type = _moduleType; + this.address = _address; + this.factoryAddress = _factoryAddress; + this.archived = _archived; + this.paused = _paused; + } + + let modules = []; + + let allModules = await securityToken.methods.getModulesByType(type).call(); + + for (let i = 0; i < allModules.length; i++) { + let details = await securityToken.methods.getModule(allModules[i]).call(); + let nameTemp = web3.utils.hexToUtf8(details[0]); + let pausedTemp = null; + if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER) { + let abiTemp = JSON.parse(require('fs').readFileSync(`./build/contracts/${nameTemp}.json`).toString()).abi; + let contractTemp = new web3.eth.Contract(abiTemp, details[1]); + pausedTemp = await contractTemp.methods.paused().call(); + } + modules.push(new ModuleInfo(type, nameTemp, details[1], details[2], details[3], pausedTemp)); + } + + return modules; +} + +module.exports = { + executeApp: async function() { + return executeApp(); + } +} \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index c21c9abad..f90ac529a 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -5,6 +5,7 @@ var faucet = require('./commands/faucet'); var investor_portal = require('./commands/investor_portal'); var token_manager = require('./commands/token_manager'); var st20generator = require('./commands/ST20Generator'); +var sto_manager = require('./commands/sto_manager'); var transfer = require('./commands/transfer'); var transfer_ownership = require('./commands/transfer_ownership'); var dividends_manager = require('./commands/dividends_manager'); @@ -36,6 +37,15 @@ program await st20generator.executeApp(cmd.ticker, cmd.transferOwnership, cmd.tokenName, cmd.details, cmd.divisible); }); +program + .command('sto_manager') + .alias('sto') + .description('Wizard-like script that will guide technical users in the creation of an STO') + .action(async function() { + await gbl.initialize(program.remoteNode); + await sto_manager.executeApp(); + }); + program .command('faucet [beneficiary] [amount]') .alias('f') From abe233d8fa69980c3770c150e971ce944f5d444a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 14 Nov 2018 21:37:31 +0530 Subject: [PATCH 094/582] Support for indivisible tokens --- contracts/modules/STO/CappedSTO.sol | 36 +++++++++++++++++++---------- test/b_capped_sto.js | 11 ++++----- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 60373ae37..24a3e7c23 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -64,6 +64,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { public onlyFactory { + require(endTime == 0, "Already configured"); require(_rate > 0, "Rate of token should be greater than 0"); require(_fundsReceiver != address(0), "Zero address is not permitted"); /*solium-disable-next-line security/no-block-members*/ @@ -108,9 +109,10 @@ contract CappedSTO is ISTO, ReentrancyGuard { require(fundRaiseTypes[uint8(FundRaiseType.ETH)], "Mode of investment is not ETH"); uint256 weiAmount = msg.value; - _processTx(_beneficiary, weiAmount); + uint256 refund = _processTx(_beneficiary, weiAmount); + weiAmount = weiAmount.sub(refund); - _forwardFunds(); + _forwardFunds(refund); _postValidatePurchase(_beneficiary, weiAmount); } @@ -121,9 +123,9 @@ contract CappedSTO is ISTO, ReentrancyGuard { function buyTokensWithPoly(uint256 _investedPOLY) public nonReentrant{ require(!paused, "Should not be paused"); require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "Mode of investment is not POLY"); - _processTx(msg.sender, _investedPOLY); - _forwardPoly(msg.sender, wallet, _investedPOLY); - _postValidatePurchase(msg.sender, _investedPOLY); + uint256 refund = _processTx(msg.sender, _investedPOLY); + _forwardPoly(msg.sender, wallet, _investedPOLY.sub(refund)); + _postValidatePurchase(msg.sender, _investedPOLY.sub(refund)); } /** @@ -180,11 +182,13 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @param _beneficiary Address performing the token purchase * @param _investedAmount Value in wei involved in the purchase */ - function _processTx(address _beneficiary, uint256 _investedAmount) internal { + function _processTx(address _beneficiary, uint256 _investedAmount) internal returns(uint256 refund) { _preValidatePurchase(_beneficiary, _investedAmount); // calculate token amount to be created - uint256 tokens = _getTokenAmount(_investedAmount); + uint256 tokens; + (tokens, refund) = _getTokenAmount(_investedAmount); + _investedAmount = _investedAmount.sub(refund); // update state if (fundRaiseTypes[uint8(FundRaiseType.POLY)]) { @@ -209,7 +213,9 @@ contract CappedSTO is ISTO, ReentrancyGuard { function _preValidatePurchase(address _beneficiary, uint256 _investedAmount) internal view { require(_beneficiary != address(0), "Beneficiary address should not be 0x"); require(_investedAmount != 0, "Amount invested should not be equal to 0"); - require(totalTokensSold.add(_getTokenAmount(_investedAmount)) <= cap, "Investment more than cap is not allowed"); + uint256 tokens; + (tokens, ) = _getTokenAmount(_investedAmount); + require(totalTokensSold.add(tokens) <= cap, "Investment more than cap is not allowed"); /*solium-disable-next-line security/no-block-members*/ require(now >= startTime && now <= endTime, "Offering is closed/Not yet started"); } @@ -258,16 +264,22 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @notice Overrides to extend the way in which ether is converted to tokens. * @param _investedAmount Value in wei to be converted into tokens * @return Number of tokens that can be purchased with the specified _investedAmount + * @return Remaining amount that should be refunded to the investor */ - function _getTokenAmount(uint256 _investedAmount) internal view returns (uint256) { - return _investedAmount.mul(rate); + function _getTokenAmount(uint256 _investedAmount) internal view returns (uint256 _tokens, uint256 _refund) { + _tokens = _investedAmount.mul(rate); + uint256 granularity = ISecurityToken(securityToken).granularity(); + _tokens = _tokens.div(granularity); + _tokens = _tokens.mul(granularity); + _refund = _investedAmount.sub(_tokens.div(rate)); } /** * @notice Determines how ETH is stored/forwarded on purchases. */ - function _forwardFunds() internal { - wallet.transfer(msg.value); + function _forwardFunds(uint256 _refund) internal { + wallet.transfer(msg.value.sub(_refund)); + msg.sender.transfer(_refund); } /** diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index d89fe6eba..cd2d05b2f 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -427,14 +427,13 @@ contract("CappedSTO", accounts => { assert.isFalse(await I_CappedSTO_Array_ETH[0].paused.call()); }); - it("Should buy the tokens -- Failed due to wrong granularity", async () => { - await catchRevert( + it("Should buy the granular unit tokens and refund pending amount", async () => { + web3.eth.sendTransaction({ from: account_investor1, to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei("0.1111", "ether") - }) - ); + value: web3.utils.toWei("1.1", "ether") + }); }); it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async () => { @@ -456,7 +455,7 @@ contract("CappedSTO", accounts => { from: account_investor2, to: I_CappedSTO_Array_ETH[0].address, gas: 2100000, - value: web3.utils.toWei("9", "ether") + value: web3.utils.toWei("8", "ether") }); assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 10); From ebda32a9840d1353ca8f765bc6837a7374bcf4fa Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 14 Nov 2018 21:42:33 +0530 Subject: [PATCH 095/582] bug fix --- contracts/modules/STO/USDTieredSTO.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 44569d469..d5b7fde2c 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -252,6 +252,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _startTime, uint256 _endTime ) external onlyOwner { + /*solium-disable-next-line security/no-block-members*/ + require(now < startTime, "STO already started"); _modifyTimes(_startTime, _endTime); } From 21bd05a14777f0200a51ab4411ae6a7b241b6699 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 14 Nov 2018 22:29:30 +0530 Subject: [PATCH 096/582] test suite addition --- .../LockupVolumeRestrictionTM.sol | 35 +- ...kup_volume_restriction_transfer_manager.js | 899 +++++++++++------- 2 files changed, 557 insertions(+), 377 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index 514f9f18f..5c7183ee2 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -65,7 +65,6 @@ contract LockupVolumeRestrictionTM is ITransferManager { /** @notice Used to verify the transfer transaction and prevent locked up tokens from being transferred * @param _from Address of the sender * @param _amount The amount of tokens to transfer - * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable */ function verifyTransfer(address _from, address /* _to*/, uint256 _amount, bytes /* _data */, bool /*_isTransfer*/) public returns(Result) { // only attempt to verify the transfer if the token is unpaused, this isn't a mint txn, and there exists a lockup for this user @@ -136,7 +135,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { "Input array length mismatch" ); - for (uint i = 0; i < _userAddresses.length; i++) { + for (uint256 i = 0; i < _userAddresses.length; i++) { addLockUp(_userAddresses[i], _lockupAmounts[i], _startTimes[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i]); } @@ -172,7 +171,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { */ function removeLockUpMulti(address[] _userAddresses, uint256[] _lockupIndexes) external withPerm(ADMIN) { require(_userAddresses.length == _lockupIndexes.length, "Array length mismatch"); - for (uint i = 0; i < _userAddresses.length; i++) { + for (uint256 i = 0; i < _userAddresses.length; i++) { removeLockUp(_userAddresses[i], _lockupIndexes[i]); } } @@ -274,7 +273,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { * @notice Get the length of the lockups array for a specific user address * @param _userAddress Address of the user whose tokens should be locked up */ - function getLockUpsLength(address _userAddress) public view returns (uint) { + function getLockUpsLength(address _userAddress) public view returns (uint256) { return lockUps[_userAddress].length; } @@ -283,7 +282,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { * @param _userAddress Address of the user whose tokens should be locked up * @param _lockUpIndex The index of the LockUp to edit for the given userAddress */ - function getLockUp( address _userAddress, uint _lockUpIndex) public view returns ( + function getLockUp(address _userAddress, uint256 _lockUpIndex) public view returns ( uint256 lockupAmount, uint256 startTime, uint256 lockUpPeriodSeconds, @@ -327,15 +326,22 @@ contract LockupVolumeRestrictionTM is ITransferManager { * @notice Provide the unlock amount for the given lockup for a particular user */ function _getUnlockedAmountForLockup(LockUp[] userLockup, uint256 _lockupIndex) internal view returns (uint256) { - // Calculate the no. of periods for a lockup - uint256 noOfPeriods = (userLockup[_lockupIndex].lockUpPeriodSeconds).div(userLockup[_lockupIndex].releaseFrequencySeconds); - // Calculate the transaction time lies in which period - uint256 elapsedPeriod = (now.sub(userLockup[_lockupIndex].startTime)).div(userLockup[_lockupIndex].releaseFrequencySeconds); - // Calculate the allowed unlocked amount per period - uint256 amountPerPeriod = (userLockup[_lockupIndex].lockupAmount).div(noOfPeriods); - // Find out the unlocked amount for a given lockup - uint256 unLockedAmount = elapsedPeriod.mul(amountPerPeriod); - return unLockedAmount; + /*solium-disable-next-line security/no-block-members*/ + if (userLockup[_lockupIndex].startTime > now) { + return 0; + } else { + // Calculate the no. of periods for a lockup + uint256 noOfPeriods = (userLockup[_lockupIndex].lockUpPeriodSeconds).div(userLockup[_lockupIndex].releaseFrequencySeconds); + // Calculate the transaction time lies in which period + /*solium-disable-next-line security/no-block-members*/ + uint256 elapsedPeriod = (now.sub(userLockup[_lockupIndex].startTime)).div(userLockup[_lockupIndex].releaseFrequencySeconds); + // Calculate the allowed unlocked amount per period + uint256 amountPerPeriod = (userLockup[_lockupIndex].lockupAmount).div(noOfPeriods); + // Find out the unlocked amount for a given lockup + uint256 unLockedAmount = elapsedPeriod.mul(amountPerPeriod); + return unLockedAmount; + } + } /** @@ -357,6 +363,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { require(_userAddress != address(0), "Invalid address"); require(_lockUpPeriodSeconds != 0, "lockUpPeriodSeconds cannot be zero"); require(_releaseFrequencySeconds != 0, "releaseFrequencySeconds cannot be zero"); + require(_lockupAmount != 0, "lockupAmount cannot be zero"); // check that the total amount to be released isn't too granular require( diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index fe06f3f5c..2e0db1844 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -7,7 +7,7 @@ import { catchRevert } from "./helpers/exceptions"; const SecurityToken = artifacts.require('./SecurityToken.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); +const LockUpVolumeRestrictionTM = artifacts.require('./LockupVolumeRestrictionTM'); const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); const Web3 = require('web3'); @@ -33,13 +33,13 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { let message = "Transaction Should Fail!"; // Contract Instance Declaration - let P_VolumeRestrictionTransferManagerFactory; + let P_LockUpVolumeRestrictionTMFactory; let I_SecurityTokenRegistryProxy; - let P_VolumeRestrictionTransferManager; + let P_LockUpVolumeRestrictionTM; let I_GeneralTransferManagerFactory; - let I_VolumeRestrictionTransferManagerFactory; + let I_LockUpVolumeRestrictionTMFactory; let I_GeneralPermissionManager; - let I_VolumeRestrictionTransferManager; + let I_LockUpVolumeRestrictionTM; let I_GeneralTransferManager; let I_ModuleRegistryProxy; let I_ModuleRegistry; @@ -51,6 +51,9 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_SecurityToken_div; + let I_GeneralTransferManager_div; + let I_LockUpVolumeRestrictionTM_div; // SecurityToken Details const name = "Team"; @@ -59,11 +62,16 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { const decimals = 18; const contact = "team@polymath.network"; + const name2 = "Core"; + const symbol2 = "Core"; + // Module key const delegateManagerKey = 1; const transferManagerKey = 2; const stoKey = 3; + let temp; + // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -94,10 +102,10 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { I_STRProxied ] = instances; - // STEP 4(c): Deploy the VolumeRestrictionTransferManager - [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); - // STEP 4(d): Deploy the VolumeRestrictionTransferManager - [P_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + // STEP 4(c): Deploy the LockUpVolumeRestrictionTMFactory + [I_LockUpVolumeRestrictionTMFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 4(d): Deploy the LockUpVolumeRestrictionTMFactory + [P_LockUpVolumeRestrictionTMFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); // Printing all the contract addresses console.log(` @@ -113,7 +121,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} LockupVolumeRestrictionTransferManagerFactory: - ${I_VolumeRestrictionTransferManagerFactory.address} + ${I_LockUpVolumeRestrictionTMFactory.address} ----------------------------------------------------------------------------- `); }); @@ -153,11 +161,46 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); + + it("Should register another ticker before the generation of new security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol2, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol2.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails, true, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol2.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken_div = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken_div.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken_div.getModulesByType(2))[0]; + I_GeneralTransferManager_div = GeneralTransferManager.at(moduleData); + }); + + }); describe("Buy tokens using on-chain whitelist and test locking them up and attempting to transfer", async() => { - it("Should Buy the tokens", async() => { + it("Should Buy the tokens from non-divisible", async() => { // Add the Investor in to the whitelist let tx = await I_GeneralTransferManager.modifyWhitelist( @@ -184,7 +227,34 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should Buy some more tokens", async() => { + it("Should Buy the tokens from the divisible token", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager_div.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken_div.mint(account_investor1, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken_div.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should Buy some more tokens from non-divisible tokens", async() => { // Add the Investor in to the whitelist let tx = await I_GeneralTransferManager.modifyWhitelist( @@ -208,38 +278,50 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should unsuccessfully attach the VolumeRestrictionTransferManager factory with the security token -- failed because Token is not paid", async () => { + it("Should unsuccessfully attach the LockUpVolumeRestrictionTM factory with the security token -- failed because Token is not paid", async () => { await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); await catchRevert( - I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) + I_SecurityToken.addModule(P_LockUpVolumeRestrictionTMFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) ) }); - it("Should successfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { + it("Should successfully attach the LockUpVolumeRestrictionTM factory with the security token", async () => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManagerFactory doesn't get deployed"); + const tx = await I_SecurityToken.addModule(P_LockUpVolumeRestrictionTMFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), "LockupVolumeRestrictionTM", - "VolumeRestrictionTransferManagerFactory module was not added" + "LockUpVolumeRestrictionTM module was not added" ); - P_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[3].args._module); + P_LockUpVolumeRestrictionTM = LockUpVolumeRestrictionTM.at(tx.logs[3].args._module); await revertToSnapshot(snapId); }); - it("Should successfully attach the VolumeRestrictionTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_VolumeRestrictionTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManager doesn't get deployed"); + it("Should successfully attach the LockUpVolumeRestrictionTMFactory with the non-divisible security token", async () => { + const tx = await I_SecurityToken.addModule(I_LockUpVolumeRestrictionTMFactory.address, 0, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "LockupVolumeRestrictionTM", + "LockUpVolumeRestrictionTM module was not added" + ); + I_LockUpVolumeRestrictionTM = LockUpVolumeRestrictionTM.at(tx.logs[2].args._module); + }); + + it("Should successfully attach the LockUpVolumeRestrictionTMFactory with the divisible security token", async () => { + const tx = await I_SecurityToken_div.addModule(I_LockUpVolumeRestrictionTMFactory.address, 0, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), "LockupVolumeRestrictionTM", - "VolumeRestrictionTransferManager module was not added" + "LockUpVolumeRestrictionTM module was not added" ); - I_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[2].args._module); + I_LockUpVolumeRestrictionTM_div = LockUpVolumeRestrictionTM.at(tx.logs[2].args._module); }); it("Add a new token holder", async() => { @@ -267,12 +349,11 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); it("Should pause the tranfers at transferManager level", async() => { - let tx = await I_VolumeRestrictionTransferManager.pause({from: token_owner}); + let tx = await I_LockUpVolumeRestrictionTM.pause({from: token_owner}); }); it("Should still be able to transfer between existing token holders up to limit", async() => { - // Add the Investor in to the whitelist - // Mint some tokens + // Transfer Some tokens between the investor await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); assert.equal( @@ -282,14 +363,23 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); it("Should unpause the tranfers at transferManager level", async() => { - await I_VolumeRestrictionTransferManager.unpause({from: token_owner}); + await I_LockUpVolumeRestrictionTM.unpause({from: token_owner}); }); - it("Should prevent the creation of a lockup with bad parameters where the totalAmount is zero", async() => { + it("Should prevent the creation of a lockup with bad parameters where the lockupAmount is zero", async() => { // create a lockup - // this will generate an exception because the totalAmount is zero + // this will generate an exception because the lockupAmount is zero await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, 0, { from: token_owner }) + I_LockUpVolumeRestrictionTM.addLockUp( + account_investor2, + 0, + latestTime() + + duration.seconds(1), + duration.seconds(400000), + duration.seconds(100000), + { + from: token_owner + } + ) ) }); @@ -297,7 +387,16 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // create a lockup // this will generate an exception because the releaseFrequencySeconds is zero await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 0, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }) + I_LockUpVolumeRestrictionTM.addLockUp( + account_investor2, + web3.utils.toWei('1', 'ether'), + latestTime() + duration.seconds(1), + duration.seconds(400000), + 0, + { + from: token_owner + } + ) ); }); @@ -305,7 +404,16 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // create a lockup // this will generate an exception because the lockUpPeriodSeconds is zero await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 0, 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }) + I_LockUpVolumeRestrictionTM.addLockUp( + account_investor2, + web3.utils.toWei('1', 'ether'), + latestTime() + duration.seconds(1), + 0, + duration.seconds(100000), + { + from: token_owner + } + ) ); }); @@ -314,8 +422,49 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // create a lockup // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, web3.utils.toWei('0.5', 'ether'), { from: token_owner }) + I_LockUpVolumeRestrictionTM.addLockUp( + account_investor2, + web3.utils.toWei('0.5', 'ether'), + latestTime() + + duration.seconds(1), + duration.seconds(400000), + duration.seconds(100000), + { + from: token_owner + } + ) + ); + }); + + it("Should allow the creation of a lockup where the lockup amount is divisible" , async() => { + // create a lockup + let tx = await I_LockUpVolumeRestrictionTM_div.addLockUp( + account_investor1, + web3.utils.toWei('0.5', 'ether'), + latestTime() + duration.seconds(1), + duration.seconds(400000), + duration.seconds(100000), + { + from: token_owner + } ); + assert.equal(tx.logs[0].args.userAddress, account_investor1); + assert.equal((tx.logs[0].args.lockupAmount).toNumber(), web3.utils.toWei('0.5', 'ether')); + }); + + it("Should allow the creation of a lockup where the lockup amount is prime no", async() => { + // create a lockup + let tx = await I_LockUpVolumeRestrictionTM_div.addLockUp( + account_investor1, + web3.utils.toWei('64951', 'ether'), + latestTime() + duration.seconds(1), + duration.seconds(400000), + duration.seconds(100000), + { + from: token_owner + } + ); + assert.equal(tx.logs[0].args.userAddress, account_investor1); + assert.equal((tx.logs[0].args.lockupAmount).toNumber(), web3.utils.toWei('64951', 'ether')); }); it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is not evenly divisible by releaseFrequencySeconds", async() => { @@ -328,17 +477,33 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // over 17 seconds total, with 4 periods. // this will generate an exception because 17 is not evenly divisble by 4. await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 17, 4, 0, balance, { from: token_owner }) + I_LockUpVolumeRestrictionTM.addLockUp( + account_investor2, + web3.utils.toWei('4', 'ether'), + latestTime(), + 17, + 4, + { + from: token_owner + } + ) ); }); it("Should prevent the creation of a lockup with bad parameters where the total amount being locked up isn't evenly divisible by the number of total periods", async() => { // create a lockup for a balance of 1 eth - // over 16e18 seconds total, with 4e18 periods of 4 seconds each. - // this will generate an exception because 16e18 / 4e18 = 4e18 but the token granularity is 1e18 and 1e18 % 4e18 != 0 await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, web3.utils.toWei('16', 'ether'), 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }) + I_LockUpVolumeRestrictionTM.addLockUp( + account_investor2, + web3.utils.toWei('1', 'ether'), + latestTime(), + duration.seconds(400000), + duration.seconds(100000), + { + from: token_owner + } + ) ); }); @@ -351,7 +516,16 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // over 16 seconds total, with 4 periods of 4 seconds each. // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }) + I_LockUpVolumeRestrictionTM.addLockUp( + account_investor2, + balance, + latestTime() + duration.seconds(1), + 16, + 4, + { + from: token_owner + } + ) ); }); @@ -362,445 +536,444 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { console.log("balance", balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); // create a lockup for their entire balance // over 12 seconds total, with 3 periods of 4 seconds each. - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from: token_owner }); - - // read only - check if transfer will pass. it should return INVALID - let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('1', 'ether'), 0, false) - // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 - assert.equal(result.toString(), '0') - + await I_LockUpVolumeRestrictionTM.addLockUp( + account_investor2, + balance, + latestTime() + duration.seconds(1), + 60, + 20, + { + from: token_owner + } + ); + await increaseTime(2); + let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + console.log("Amount get unlocked:", (tx[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) ); }); - it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { - - // wait 4 seconds - await increaseTime(duration.seconds(4)); - - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); - }); - it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { - + // wait 20 seconds + await increaseTime(duration.seconds(20)); + let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + console.log("Amount get unlocked:", (tx[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }) ); }); - it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { - - // wait 4 more seconds - await increaseTime(4000); - - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); + it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { + let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + console.log("Amount get unlocked:", (tx[4].toNumber())); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); }); - it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async() => { - - let balance = await I_SecurityToken.balanceOf(account_investor2) - - // wait 4 more seconds - await increaseTime(4000); - - await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); + it("Should again transfer of tokens in a lockup if a period has passed", async() => { + let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + console.log("Amount get unlocked:", (tx[4].toNumber())); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); }); - it("Should prevent the transfer of tokens in an edited lockup", async() => { + it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { + // wait 20 more seconds + 1 to get rid of same block time + await increaseTime(duration.seconds(21)); + let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + console.log("Amount get unlocked:", (tx[4].toNumber())); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); + }); - // balance here should be 12000000000000000000 (12e18 or 12 eth) - let balance = await I_SecurityToken.balanceOf(account_investor1) + it("Buy more tokens from secondary market to investor2", async() => { + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('5', 'ether'), { from: token_owner }); - // create a lockup for their entire balance - // over 16 seconds total, with 4 periods of 4 seconds each. - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, balance, { from: token_owner }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('10', 'ether') + ); + }) - // let blockNumber = await web3.eth.getBlockNumber(); - // console.log('blockNumber',blockNumber) - let now = (await web3.eth.getBlock('latest')).timestamp + it("Should allow transfer for the tokens that comes from secondary market + unlocked tokens", async() => { - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('6', 'ether') ); + }); - // check and get the lockup - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 1) + it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async() => { - let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 0); - // console.log(lockUp); - // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount - assert.equal(lockUp[0].toString(), '16'); - assert.equal(lockUp[1].toString(), '4'); - assert.equal(lockUp[2].toNumber(), now); - assert.equal(lockUp[3].toString(), balance.toString()); + let balance = await I_SecurityToken.balanceOf(account_investor2) - // edit the lockup - await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 0, 8, 4, 0, balance, { from: token_owner }); + // wait 20 more seconds + 1 to get rid of same block time + await increaseTime(duration.seconds(20)); - // attempt a transfer - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }) + await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('0', 'ether') ); - - // wait 4 seconds - await new Promise(resolve => setTimeout(resolve, 4000)); - - // transfer should succeed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); - }); - it("Should succesfully modify the lockup - fail because array index out of bound", async() => { - // balance here should be 12000000000000000000 (12e18 or 12 eth) - let balance = await I_SecurityToken.balanceOf(account_investor1); + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 8, 8, 4, 0, balance, { from: token_owner }) + I_LockUpVolumeRestrictionTM.addLockUpMulti( + [account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45], + [20, 15], + { + from: token_owner + } + ) ); }) - it("Should succesfully get the lockup - fail because array index out of bound", async() => { + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 9) + I_LockUpVolumeRestrictionTM.addLockUpMulti( + [account_investor3, account_investor3], + [], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45], + [20, 15], + { + from: token_owner + } + ) ); }) - it("Should be possible to remove a lockup -- couldn't transfer because of lock up", async() => { - - let acct1Balance = await I_SecurityToken.balanceOf(account_investor1) - - await catchRevert( - I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }) - ); - - // check and get the lockup - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 1) - - // remove the lockup - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor1, 0, { from: token_owner }); - - lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 0) - - let acct2BalanceBefore = await I_SecurityToken.balanceOf(account_investor2) - await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); - let acct2BalanceAfter = await I_SecurityToken.balanceOf(account_investor2) - - assert.equal(acct2BalanceAfter.sub(acct2BalanceBefore).toString(), acct1Balance.toString()) - }); - - it("Should try to remove the lockup --failed because of index is out of bounds", async() => { + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 7, { from: token_owner }) + I_LockUpVolumeRestrictionTM.addLockUpMulti( + [account_investor3, account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45, 50], + [20, 15], + { + from: token_owner + } + ) ); }) - it("Should be possible to create multiple lockups at once", async() => { - - let balancesBefore = {} - - // should be 12000000000000000000 - balancesBefore[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - - - // should be 10000000000000000000 - balancesBefore[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - - - let lockUpCountsBefore = {} - - // get lockups for acct 2 - lockUpCountsBefore[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCountsBefore[account_investor2], 1) // there's one old, expired lockup on acct already - - // get lockups for acct 3 - lockUpCountsBefore[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); - assert.equal(lockUpCountsBefore[account_investor3], 0) - - // create lockups for their entire balances - await I_VolumeRestrictionTransferManager.addLockUpMulti( - [account_investor2, account_investor3], - [24, 8], - [4, 4], - [0, 0], - [balancesBefore[account_investor2], balancesBefore[account_investor3]], - { from: token_owner } + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { + await catchRevert( + I_LockUpVolumeRestrictionTM.addLockUpMulti( + [account_investor3, account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45, 50], + [20, 15, 10], + { + from: token_owner + } + ) ); + }) - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }) + it("Should add the multiple lockup to a address", async() => { + await I_LockUpVolumeRestrictionTM.addLockUpMulti( + [account_investor3, account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45], + [20, 15], + { + from: token_owner + } ); + await increaseTime(1); + let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor3, 0); + let tx2 = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor3, 1); + console.log("Total Amount get unlocked:", (tx[4].toNumber()) + (tx2[4].toNumber())); await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor3 }) ); - let balancesAfter = {} - balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - assert.equal(balancesBefore[account_investor2].toString(), balancesAfter[account_investor2].toString()) - - balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - assert.equal(balancesBefore[account_investor3].toString(), balancesAfter[account_investor3].toString()) - - let lockUpCountsAfter = {} - - // get lockups for acct 2 - lockUpCountsAfter[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCountsAfter[account_investor2], 2); - - // get lockups for acct 3 - lockUpCountsAfter[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); - assert.equal(lockUpCountsAfter[account_investor3], 1); - - // wait 4 seconds - await increaseTime(4000); - - // try transfers again - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); - - - balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - assert.equal(balancesBefore[account_investor2].sub(web3.utils.toWei('2', 'ether')).toString(), balancesAfter[account_investor2].toString()) + }); - balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - assert.equal(balancesBefore[account_investor3].sub(web3.utils.toWei('5', 'ether')).toString(), balancesAfter[account_investor3].toString()) + it("Should transfer the tokens after period get passed", async() => { + // increase 20 sec that makes 1 period passed + // 2 from a period and 1 is already unlocked + await increaseTime(21); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) + }) + it("Should transfer the tokens after passing another period of the lockup", async() => { + // increase the 15 sec that makes first period of another lockup get passed + // allow 1 token to transfer + await increaseTime(15); + // first fail because 3 tokens are not in unlocked state + await catchRevert( + I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) + ) + // second txn will pass because 1 token is in unlocked state + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1'), { from: account_investor3 }) }); - it("Should revert if the parameters are bad when creating multiple lockups", async() => { + it("Should transfer the tokens from both the lockup simultaneously", async() => { + // Increase the 20 sec (+ 1 to mitigate the block time) that unlocked another 2 tokens from the lockup 1 and simultaneously unlocked 1 + // more token from the lockup 2 + await increaseTime(21); - await catchRevert( - // pass in the wrong number of params. txn should revert - I_VolumeRestrictionTransferManager.addLockUpMulti( - [account_investor2, account_investor3], - [16, 8], - [2], // this array should have 2 elements but it has 1, which should cause a revert - [0, 0], - [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], - { from: token_owner } - ) + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('3', 'ether') ); }); - it("Should be possible to create a lockup with a specific start time in the future", async() => { - - // remove all lockups for account 2 - let lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpsLength, 2); - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); - lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpsLength, 0); - - let now = latestTime(); - - // balance here should be 10000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor2) - - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 100, 10, now + duration.seconds(4), balance, { from: token_owner }); - - // wait 4 seconds for the lockup to begin - await increaseTime(duration.seconds(4)); - - // try another transfer. it should also fail because the lockup has just begun + it("Should remove multiple lockup --failed because of bad owner", async() => { await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); - + I_LockUpVolumeRestrictionTM.removeLockUpMulti( + [account_investor3, account_investor3], + [0,1], + { + from: account_polymath + } + ) + ); }); - it("Should be possible to edit a lockup with a specific start time in the future", async() => { - - // edit the lockup - let now = latestTime(); - - // should be 10000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor2) - - // check and get the lockup - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCount, 1) - - let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - - // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount - assert.equal(lockUp[0].toString(), '100'); - assert.equal(lockUp[1].toString(), '10'); - assert.isAtMost(lockUp[2].toNumber(), now); - assert.equal(lockUp[3].toString(), balance.toString()); - - // edit the lockup - await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor2, 0, 8, 4, now + duration.seconds(4), balance, { from: token_owner }); - - // check and get the lockup again - lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCount, 1) - - lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - - // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount - assert.equal(lockUp[0].toString(), '8'); - assert.equal(lockUp[1].toString(), '4'); - assert.isAtMost(lockUp[2].toNumber(), now + 4); - assert.equal(lockUp[3].toString(), balance.toString()); - - // try a transfer. it should fail because again, the lockup hasn't started yet. + it("Should remove the multiple lockup -- failed because of invalid index", async() => { await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); + I_LockUpVolumeRestrictionTM.removeLockUpMulti( + [account_investor3, account_investor3], + [0,3], + { + from: account_polymath + } + ) + ); + }) - // wait 4 seconds for the lockup to begin - await increaseTime(duration.seconds(4)); + it("Should remove the multiple lockup", async() => { + await I_LockUpVolumeRestrictionTM.removeLockUpMulti( + [account_investor3, account_investor3], + [1,0], + { + from: token_owner + } + ) + // do the free transaction now + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) + }); - // try another transfer. it should fail because the lockup has just begun + it("Should fail to modify the lockup -- because of bad owner", async() => { + await I_SecurityToken.mint(account_investor3, web3.utils.toWei("9"), {from: token_owner}); + + let tx = await I_LockUpVolumeRestrictionTM.addLockUp( + account_investor3, + web3.utils.toWei("9"), + latestTime() + duration.minutes(5), + 60, + 20, + { + from: token_owner + } + ); + temp = (tx.logs[0].args.lockupIndex).toNumber(); await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); - - // wait 4 seconds for the lockup's first period to elapse - await increaseTime(duration.seconds(4)); - - // try another transfer. it should pass - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); - + // edit the lockup + I_LockUpVolumeRestrictionTM.modifyLockUp( + account_investor3, + web3.utils.toWei("9"), + latestTime() + duration.seconds(1), + 60, + 20, + (tx.logs[0].args.lockupIndex).toNumber(), + { + from: account_polymath + } + ) + ) + }) - // try another transfer without waiting for another period to pass. it should fail + it("Modify the lockup when startTime is in past -- failed because startTime is in the past", async() => { await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }) - ); - - // wait 4 seconds for the lockup's first period to elapse - await increaseTime(duration.seconds(4)); - - let lockUpBeforeVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - // check if transfer will pass in read-only operation - let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('5', 'ether'), 0, false) - // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 - assert.equal(result.toString(), '2') - let lockUpAfterVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - - assert.equal(lockUpBeforeVerify[4].toString(), lockUpAfterVerify[4].toString()) - - // try another transfer. it should pass - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); - - // wait 4 seconds for the lockup's first period to elapse. but, we are all out of periods. - await increaseTime(duration.seconds(4)); + // edit the lockup + I_LockUpVolumeRestrictionTM.modifyLockUp( + account_investor3, + web3.utils.toWei("9"), + latestTime() - duration.seconds(50), + 60, + 20, + temp, + { + from: token_owner + } + ) + ) + }) - // try one final transfer. this should fail because the user has already withdrawn their entire balance + it("Modify the lockup when startTime is in past -- failed because of invalid index", async() => { await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) + // edit the lockup + I_LockUpVolumeRestrictionTM.modifyLockUp( + account_investor3, + web3.utils.toWei("9"), + latestTime() + duration.seconds(50), + 60, + 20, + 6, + { + from: token_owner + } + ) + ) + }) + + it("should successfully modify the lockup", async() => { + // edit the lockup + await I_LockUpVolumeRestrictionTM.modifyLockUp( + account_investor3, + web3.utils.toWei("9"), + latestTime() + duration.seconds(50), + 60, + 20, + temp, + { + from: token_owner + } ); - }); + }) - it("Should be possible to stack lockups", async() => { - // should be 17000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor1) + it("Should prevent the transfer of tokens in an edited lockup", async() => { - // check and make sure that acct1 has no lockups so far - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount.toString(), 0) + // balance here should be 12000000000000000000 (12e18 or 12 eth) + let balance = await I_SecurityToken.balanceOf(account_investor1) - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 12, 4, 0, web3.utils.toWei('6', 'ether'), { from: token_owner }); + console.log("balance", balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); - // try to transfer 11 tokens that aren't locked up yet be locked up. should succeed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('11', 'ether'), { from: account_investor1 }); + // create a lockup for their entire balance + // over 16 seconds total, with 4 periods of 4 seconds each. + await I_LockUpVolumeRestrictionTM.addLockUp( + account_investor1, + balance, + latestTime() + duration.minutes(5), + 60, + 20, + { + from: token_owner + } + ); - // try a transfer. it should fail because it's locked up from the first lockups await catchRevert( I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) ); - // wait 4 seconds for the lockup's first period to elapse. - await increaseTime(duration.seconds(4)); - - // should succeed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); - // send 8 back to investor1 so that we can lock them up - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('8', 'ether'), { from: account_investor2 }); - - // let's add another lockup to stack them - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, web3.utils.toWei('8', 'ether'), { from: token_owner }); + // check and get the lockup + let lockUpCount = await I_LockUpVolumeRestrictionTM.getLockUpsLength(account_investor1); + assert.equal(lockUpCount, 1) - // try a transfer. it should fail because it's locked up from both lockups - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) + let lockUp = await I_LockUpVolumeRestrictionTM.getLockUp(account_investor1, 0); + // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount + assert.equal( + lockUp[0].dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber(), + balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber() ); + assert.equal(lockUp[2].toNumber(), 60); + assert.equal(lockUp[3].toNumber(), 20); + assert.equal(lockUp[4].toNumber(), 0); - // wait 4 seconds for the 1st lockup's second period to elapse, and the 2nd lockup's first period to elapse - await increaseTime(duration.seconds(4)); - - // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); + // edit the lockup + temp = latestTime() + duration.seconds(1); + await I_LockUpVolumeRestrictionTM.modifyLockUp( + account_investor1, + balance, + temp, + 60, + 20, + 0, + { + from: token_owner + } + ); - // try aother transfer. it should fail because it's locked up from both lockups again + // attempt a transfer await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }) ); - // wait 4 seconds for the 1st lockup's final period to elapse, and the 2nd lockup's second period to elapse - await increaseTime(duration.seconds(4)); - // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); + // wait 20 seconds + await increaseTime(21); - // wait 8 seconds for 2nd lockup's third and fourth periods to elapse - await increaseTime(duration.seconds(8)); - // should now be able to transfer 4, because there are 2 allowed per period in the 2nd lockup, and 2 periods have elapsed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - - // send the 3 back from acct2 that we sent over in the beginning of this test - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); + // transfer should succeed + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); - // try another transfer. it should pass because both lockups have been entirely used - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); + }); - balance = await I_SecurityToken.balanceOf(account_investor1) - assert.equal(balance.toString(), web3.utils.toWei('2', 'ether')) + it("Modify the lockup during the lockup periods --fail because already tokens get unlocked", async() => { + let balance = await I_SecurityToken.balanceOf(account_investor1) + let lockUp = await I_LockUpVolumeRestrictionTM.getLockUp(account_investor1, 0); + console.log(lockUp[4].dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); + // edit the lockup + await catchRevert( + I_LockUpVolumeRestrictionTM.modifyLockUp( + account_investor1, + balance, + temp, + 90, + 30, + 0, + { + from: token_owner + } + ) + ); }); + it("Should succesfully get the lockup - fail because array index out of bound", async() => { + await catchRevert( + I_LockUpVolumeRestrictionTM.getLockUp(account_investor1, 9) + ); + }) it("Should get configuration function signature", async() => { - let sig = await I_VolumeRestrictionTransferManager.getInitFunction.call(); + let sig = await I_LockUpVolumeRestrictionTM.getInitFunction.call(); assert.equal(web3.utils.hexToNumber(sig), 0); }); it("Should get the permission", async() => { - let perm = await I_VolumeRestrictionTransferManager.getPermissions.call(); + let perm = await I_LockUpVolumeRestrictionTM.getPermissions.call(); assert.equal(perm.length, 1); - // console.log(web3.utils.toAscii(perm[0]).replace(/\u0000/g, '')) assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "ADMIN") }); }); - describe("VolumeRestriction Transfer Manager Factory test cases", async() => { + describe("LockUpVolumeRestrictionTM Transfer Manager Factory test cases", async() => { it("Should get the exact details of the factory", async() => { - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getSetupCost.call(),0); - assert.equal((await I_VolumeRestrictionTransferManagerFactory.getTypes.call())[0],2); - assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTransferManagerFactory.getName.call()) + assert.equal(await I_LockUpVolumeRestrictionTMFactory.getSetupCost.call(),0); + assert.equal((await I_LockUpVolumeRestrictionTMFactory.getTypes.call())[0],2); + assert.equal(web3.utils.toAscii(await I_LockUpVolumeRestrictionTMFactory.getName.call()) .replace(/\u0000/g, ''), "LockupVolumeRestrictionTM", "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.description.call(), + assert.equal(await I_LockUpVolumeRestrictionTMFactory.description.call(), "Manage transfers using lock ups over time", "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.title.call(), + assert.equal(await I_LockUpVolumeRestrictionTMFactory.title.call(), "Lockup Volume Restriction Transfer Manager", "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getInstructions.call(), + assert.equal(await I_LockUpVolumeRestrictionTMFactory.getInstructions.call(), "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.version.call(), "1.0.0"); + assert.equal(await I_LockUpVolumeRestrictionTMFactory.version.call(), "1.0.0"); }); it("Should get the tags of the factory", async() => { - let tags = await I_VolumeRestrictionTransferManagerFactory.getTags.call(); + let tags = await I_LockUpVolumeRestrictionTMFactory.getTags.call(); assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Volume"); }); }); From 2b717850bd9bdb01db0aaffa69465d33a5b57427 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 14 Nov 2018 20:56:24 +0200 Subject: [PATCH 097/582] added deposit/withdrawal functions --- contracts/wallet/VestingEscrowWallet.sol | 49 ++++++++++++++++++++---- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index a222210c0..4fed0fc4d 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -2,8 +2,7 @@ pragma solidity ^0.4.24; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -//TODO ? -import "../interfaces/IERC20.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; /** @@ -11,7 +10,7 @@ import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; */ contract VestingEscrowWallet is Ownable { using SafeMath for uint256; - using SafeERC20 for ERC20Basic; + using SafeERC20 for ERC20; struct VestingSchedule { uint256 numberOfTokens; @@ -32,7 +31,7 @@ contract VestingEscrowWallet is Ownable { enum State {STARTED, COMPLETED} - IERC20 public token; + ERC20 public token; address public treasury; uint256 public unassignedTokens; @@ -51,11 +50,35 @@ contract VestingEscrowWallet is Ownable { event RevokeVestingSchedules(address _beneficiary, uint256 _timestamp); event RevokeVestingSchedule(address _beneficiary, uint256 index, uint256 _timestamp); + //TODO add events + constructor(address _tokenAddress, address _treasury) public { - token = IERC20(_tokenAddress); + token = ERC20(_tokenAddress); treasury = _treasury; } + function depositTokens(uint256 _numberOfTokens) external onlyOwner { + require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); + token.safeTransferFrom(treasury, this, _numberOfTokens); + unassignedTokens = unassignedTokens.add(_numberOfTokens); + } + + function sendToTreasury() external onlyOwner { + uint256 amount = unassignedTokens; + unassignedTokens = 0; + token.safeTransfer(treasury, amount); + } + + function sendAvailableTokens(address _beneficiary) external onlyOwner { + _update(_beneficiary); + _sendTokens(_beneficiary); + } + + function withdrawAvailableTokens() external { + _update(msg.sender); + _sendTokens(msg.sender); + } + function addVestingSchedule( address _beneficiary, uint256 _numberOfTokens, @@ -153,7 +176,14 @@ contract VestingEscrowWallet is Ownable { } - + function _sendTokens(address _beneficiary) private { + VestingData data = vestingData[_beneficiary]; + uint256 amount = data.availableTokens; + require(amount > 0, "Beneficiary doesn't have available tokens"); + data.availableTokens = 0; + data.claimedTokens = data.claimedTokens.add(amount); + token.safeTransfer(_beneficiary, amount); + } function _update(address _beneficiary) internal { VestingData data = vestingData[_beneficiary]; @@ -165,7 +195,6 @@ contract VestingEscrowWallet is Ownable { uint256 numberOfTokens = schedule.numberOfTokens.div(periodCount); data.availableTokens = data.availableTokens.add(numberOfTokens); schedule.lockedTokens = schedule.lockedTokens.sub(numberOfTokens); - if (schedule.nextDate == schedule.startDate.add(schedule.vestingDuration)) { schedule.state = State.COMPLETED; } else { @@ -175,6 +204,12 @@ contract VestingEscrowWallet is Ownable { } } + function _updateAll() internal { + for (uint256 i = 0; i < beneficiaries.length; i++) { + _update(beneficiaries[i]); + } + } + function _revokeVestingSchedules(address _beneficiary) private { if (_canBeRemoved(_beneficiary)) { uint256 index = vestingData[_beneficiary].index; From 1e6e7ca02c50331b005f7330d0629344281176bb Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 14 Nov 2018 23:08:35 +0200 Subject: [PATCH 098/582] added batch operations, events --- contracts/wallet/VestingEscrowWallet.sol | 114 +++++++++++++++++++---- 1 file changed, 94 insertions(+), 20 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 4fed0fc4d..1d9451613 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -47,10 +47,20 @@ contract VestingEscrowWallet is Ownable { uint256 _startDate, uint256 _timestamp ); + event EditVestingSchedule( + address _beneficiary, + uint256 _index, + uint256 _numberOfTokens, + uint256 _vestingDuration, + uint256 _vestingFrequency, + uint256 _startDate, + uint256 _timestamp + ); event RevokeVestingSchedules(address _beneficiary, uint256 _timestamp); - event RevokeVestingSchedule(address _beneficiary, uint256 index, uint256 _timestamp); - - //TODO add events + event RevokeVestingSchedule(address _beneficiary, uint256 _index, uint256 _timestamp); + event DepositTokens(uint256 _numberOfTokens, uint256 _timestamp); + event SendToTreasury(uint256 _numberOfTokens, uint256 _timestamp); + event SendTokens(address _beneficiary, uint256 _numberOfTokens, uint256 _timestamp); constructor(address _tokenAddress, address _treasury) public { token = ERC20(_tokenAddress); @@ -61,15 +71,19 @@ contract VestingEscrowWallet is Ownable { require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); token.safeTransferFrom(treasury, this, _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); + /*solium-disable-next-line security/no-block-members*/ + emit DepositTokens(_numberOfTokens, now); } function sendToTreasury() external onlyOwner { uint256 amount = unassignedTokens; unassignedTokens = 0; token.safeTransfer(treasury, amount); + /*solium-disable-next-line security/no-block-members*/ + emit SendToTreasury(amount, now); } - function sendAvailableTokens(address _beneficiary) external onlyOwner { + function sendAvailableTokens(address _beneficiary) public onlyOwner { _update(_beneficiary); _sendTokens(_beneficiary); } @@ -86,14 +100,10 @@ contract VestingEscrowWallet is Ownable { uint256 _vestingFrequency, uint256 _startDate ) - external + public onlyOwner { - require(_beneficiary != address(0), "Invalid beneficiary address"); - require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); - require(_vestingDuration % _vestingFrequency == 0, "Duration should be divided entirely by frequency"); - uint256 periodCount = _vestingDuration.div(_vestingFrequency); - require(_numberOfTokens % periodCount == 0, "Number of tokens should be divided entirely by period count"); + _validateSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate); require(_numberOfTokens <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); VestingSchedule memory schedule; @@ -115,21 +125,43 @@ contract VestingEscrowWallet is Ownable { emit AddVestingSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); } - function revokeVestingSchedule(address _beneficiary, uint256 index) external onlyOwner { + function editVestingSchedule( + address _beneficiary, + uint256 _index, + uint256 _numberOfTokens, + uint256 _vestingDuration, + uint256 _vestingFrequency, + uint256 _startDate + ) + external + onlyOwner + { + _validateSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate); + require(_index < vestingData[_beneficiary].schedules.length, "Schedule not found"); +// require(_numberOfTokens <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); + + VestingSchedule storage schedule = vestingData[_beneficiary].schedules[_index]; + + //TODO implement + + emit EditVestingSchedule(_beneficiary, _index, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); + } + + function revokeVestingSchedule(address _beneficiary, uint256 _index) external onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); - require(index < vestingData[_beneficiary].schedules.length, "Schedule not found"); + require(_index < vestingData[_beneficiary].schedules.length, "Schedule not found"); VestingSchedule[] storage schedules = vestingData[_beneficiary].schedules; - unassignedTokens = unassignedTokens.add(schedules[index].lockedTokens); - schedules[index] = schedules[schedules.length - 1]; + unassignedTokens = unassignedTokens.add(schedules[_index].lockedTokens); + schedules[_index] = schedules[schedules.length - 1]; schedules.length--; if (schedules.length == 0) { _revokeVestingSchedules(_beneficiary); } /*solium-disable-next-line security/no-block-members*/ - emit RevokeVestingSchedule(_beneficiary, index, now); + emit RevokeVestingSchedule(_beneficiary, _index, now); } - function revokeVestingSchedules(address _beneficiary) external onlyOwner { + function revokeVestingSchedules(address _beneficiary) public onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); VestingData data = vestingData[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { @@ -161,8 +193,35 @@ contract VestingEscrowWallet is Ownable { return vestingData[_beneficiary].schedules.length; } - function editVestingSchedule( - address _beneficiary, + function batchSendAvailableTokens(address[] _beneficiaries) external onlyOwner { + for (uint256 i = 0; i < _beneficiaries.length; i++) { + sendAvailableTokens(_beneficiaries[i]); + } + } + + function batchAddVestingSchedule( + address[] _beneficiaries, + uint256 _numberOfTokens, + uint256 _vestingDuration, + uint256 _vestingFrequency, + uint256 _startDate + ) + external + onlyOwner + { + for (uint256 i = 0; i < _beneficiaries.length; i++) { + addVestingSchedule(_beneficiaries[i], _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate); + } + } + + function batchRevokeVestingSchedules(address[] _beneficiaries) external onlyOwner { + for (uint256 i = 0; i < _beneficiaries.length; i++) { + revokeVestingSchedules(_beneficiaries[i]); + } + } + + function batchEditVestingSchedule( + address[] _beneficiaries, uint256 _index, uint256 _numberOfTokens, uint256 _vestingDuration, @@ -175,6 +234,19 @@ contract VestingEscrowWallet is Ownable { //TODO implement } + function _validateSchedule( + address _beneficiary, + uint256 _numberOfTokens, + uint256 _vestingDuration, + uint256 _vestingFrequency, + uint256 _startDate) + { + require(_beneficiary != address(0), "Invalid beneficiary address"); + require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); + require(_vestingDuration % _vestingFrequency == 0, "Duration should be divided entirely by frequency"); + uint256 periodCount = _vestingDuration.div(_vestingFrequency); + require(_numberOfTokens % periodCount == 0, "Number of tokens should be divided entirely by period count"); + } function _sendTokens(address _beneficiary) private { VestingData data = vestingData[_beneficiary]; @@ -183,9 +255,11 @@ contract VestingEscrowWallet is Ownable { data.availableTokens = 0; data.claimedTokens = data.claimedTokens.add(amount); token.safeTransfer(_beneficiary, amount); + /*solium-disable-next-line security/no-block-members*/ + emit SendTokens(_beneficiary, amount, now); } - function _update(address _beneficiary) internal { + function _update(address _beneficiary) private { VestingData data = vestingData[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { VestingSchedule schedule = data.schedules[i]; @@ -204,7 +278,7 @@ contract VestingEscrowWallet is Ownable { } } - function _updateAll() internal { + function _updateAll() private { for (uint256 i = 0; i < beneficiaries.length; i++) { _update(beneficiaries[i]); } From fa7c049a923bda18c23473070d4dd6a375f8bb93 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 14 Nov 2018 23:50:31 +0200 Subject: [PATCH 099/582] added template --- contracts/wallet/VestingEscrowWallet.sol | 68 ++++++++++++++++-------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 1d9451613..a81c7b04c 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -8,6 +8,7 @@ import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; /** * @title Wallet for core vesting escrow functionality */ +//TODO remove vesting from methods, events, variables contract VestingEscrowWallet is Ownable { using SafeMath for uint256; using SafeERC20 for ERC20; @@ -29,16 +30,23 @@ contract VestingEscrowWallet is Ownable { uint256 claimedTokens; } + struct VestingTemplate { + uint256 numberOfTokens; + uint256 vestingDuration; + uint256 vestingFrequency; + } + enum State {STARTED, COMPLETED} ERC20 public token; address public treasury; - uint256 public unassignedTokens; mapping (address => VestingData) public vestingData; address[] public beneficiaries; + VestingTemplate[] public templates; + event AddVestingSchedule( address _beneficiary, uint256 _numberOfTokens, @@ -61,6 +69,8 @@ contract VestingEscrowWallet is Ownable { event DepositTokens(uint256 _numberOfTokens, uint256 _timestamp); event SendToTreasury(uint256 _numberOfTokens, uint256 _timestamp); event SendTokens(address _beneficiary, uint256 _numberOfTokens, uint256 _timestamp); + event AddVestingTemplate(uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, uint256 _timestamp); + event RemoveVestingTemplate(uint256 _index, uint256 _timestamp); constructor(address _tokenAddress, address _treasury) public { token = ERC20(_tokenAddress); @@ -93,6 +103,25 @@ contract VestingEscrowWallet is Ownable { _sendTokens(msg.sender); } + function addVestingTemplate(uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency) external onlyOwner { + _validateTemplate(_numberOfTokens, _vestingDuration, _vestingFrequency); + VestingTemplate memory template; + template.numberOfTokens = _numberOfTokens; + template.vestingDuration = _vestingDuration; + template.vestingFrequency = _vestingFrequency; + templates.push(template); + /*solium-disable-next-line security/no-block-members*/ + emit AddVestingTemplate(_numberOfTokens, _vestingDuration, _vestingFrequency, now); + } + + function removeVestingTemplate(uint256 _index) external onlyOwner { + require(_index < templates.length, "Template not found"); + templates[_index] = templates[templates.length - 1]; + templates.length--; + /*solium-disable-next-line security/no-block-members*/ + emit RemoveVestingTemplate(_index, now); + } + function addVestingSchedule( address _beneficiary, uint256 _numberOfTokens, @@ -125,6 +154,12 @@ contract VestingEscrowWallet is Ownable { emit AddVestingSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); } + function addVestingScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startDate) public onlyOwner { + require(_index < templates.length, "Template not found"); + VestingTemplate template = templates[_index]; + addVestingSchedule(_beneficiary, template.numberOfTokens, template.vestingDuration, template.vestingFrequency, _startDate); + } + function editVestingSchedule( address _beneficiary, uint256 _index, @@ -214,34 +249,25 @@ contract VestingEscrowWallet is Ownable { } } + function batchAddVestingScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startDate) public onlyOwner { + for (uint256 i = 0; i < _beneficiaries.length; i++) { + addVestingScheduleFromTemplate(_beneficiaries[i], _index, _startDate); + } + } + function batchRevokeVestingSchedules(address[] _beneficiaries) external onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { revokeVestingSchedules(_beneficiaries[i]); } } - function batchEditVestingSchedule( - address[] _beneficiaries, - uint256 _index, - uint256 _numberOfTokens, - uint256 _vestingDuration, - uint256 _vestingFrequency, - uint256 _startDate - ) - external - onlyOwner - { - //TODO implement + function _validateSchedule(address _beneficiary, uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, uint256 _startDate) { + require(_beneficiary != address(0), "Invalid beneficiary address"); + _validateTemplate(_numberOfTokens, _vestingDuration, _vestingFrequency); + require(_startDate < now, "Start date shouldn't be in the past"); } - function _validateSchedule( - address _beneficiary, - uint256 _numberOfTokens, - uint256 _vestingDuration, - uint256 _vestingFrequency, - uint256 _startDate) - { - require(_beneficiary != address(0), "Invalid beneficiary address"); + function _validateTemplate(uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency) { require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); require(_vestingDuration % _vestingFrequency == 0, "Duration should be divided entirely by frequency"); uint256 periodCount = _vestingDuration.div(_vestingFrequency); From a1dccb8d04c6e093366e703fb8cd69533b521a49 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 15 Nov 2018 11:58:56 +0530 Subject: [PATCH 100/582] test cases for divible token capped STO --- test/b_capped_sto.js | 55 +++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index cd2d05b2f..8cc0beacf 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -338,16 +338,6 @@ contract("CappedSTO", accounts => { ); }); - it("Should buy the tokens -- Failed due to wrong granularity", async () => { - await catchRevert( - web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei("0.1111", "ether") - }) - ); - }); - it("Should Buy the tokens", async () => { blockNo = latestBlock(); fromTime = latestTime(); @@ -428,15 +418,7 @@ contract("CappedSTO", accounts => { }); it("Should buy the granular unit tokens and refund pending amount", async () => { - - web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei("1.1", "ether") - }); - }); - - it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async () => { + await I_SecurityToken_ETH.changeGranularity(10 ** 21, {from: token_owner}); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, fromTime, @@ -447,8 +429,19 @@ contract("CappedSTO", accounts => { from: account_issuer } ); - assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); + const initBalance = BigNumber(await web3.eth.getBalance(account_investor2)); + tx = await I_CappedSTO_Array_ETH[0].buyTokens(account_investor2, {from: account_investor2, value: web3.utils.toWei("1.5", "ether"), gasPrice: 1}); + const finalBalance = BigNumber(await web3.eth.getBalance(account_investor2)); + assert.equal(finalBalance.add(BigNumber(tx.receipt.gasUsed)).add(web3.utils.toWei("1", "ether")).toNumber(), initBalance.toNumber()); + await I_SecurityToken_ETH.changeGranularity(1, {from: token_owner}); + assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 2); + + assert.equal((await I_SecurityToken_ETH.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1000); + }); + + it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async () => { + // Fallback transaction await web3.eth.sendTransaction({ @@ -792,8 +785,8 @@ contract("CappedSTO", accounts => { await I_CappedSTO_Array_POLY[0].unpause({ from: account_issuer }); }); - - it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async () => { + it("Should buy the granular unit tokens and charge only required POLY", async () => { + await I_SecurityToken_POLY.changeGranularity(10 ** 22, {from: token_owner}); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, P_fromTime, @@ -805,15 +798,25 @@ contract("CappedSTO", accounts => { gas: 500000 } ); - + console.log((await I_SecurityToken_POLY.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber()); assert.equal(tx.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); - await I_PolyToken.getTokens(10000 * Math.pow(10, 18), account_investor2); - await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, 9000 * Math.pow(10, 18), { from: account_investor2 }); + const initRaised = (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).dividedBy(new BigNumber(10).pow(18)).toNumber(); + tx = await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(3000 * Math.pow(10, 18), { from: account_investor2 }); + await I_SecurityToken_POLY.changeGranularity(1, {from: token_owner}); + assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).dividedBy(new BigNumber(10).pow(18)).toNumber(), initRaised + 2000); //2000 this call, 1000 earlier + assert.equal((await I_PolyToken.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 8000); + assert.equal( + (await I_SecurityToken_POLY.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), + 10000 + ); + }); + + it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async () => { // buyTokensWithPoly transaction - await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(9000 * Math.pow(10, 18), { from: account_investor2 }); + await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(7000 * Math.pow(10, 18), { from: account_investor2 }); assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 10000); From 7cb5b540b8bb832d06de375350add834a60ca67a Mon Sep 17 00:00:00 2001 From: Polymath Date: Thu, 15 Nov 2018 05:42:20 -0300 Subject: [PATCH 101/582] CSV sync & ST20generator fix --- CLI/commands/ST20Generator.js | 14 ++--- CLI/commands/accredit.js | 49 ++++++++--------- CLI/commands/changeNonAccreditedLimit.js | 49 ++++++++--------- CLI/commands/common/common_functions.js | 3 +- CLI/commands/common/csv_sync.js | 39 ++++++++++++++ CLI/commands/multi_mint.js | 68 ++++++++++-------------- CLI/commands/whitelist.js | 52 +++++++++--------- package.json | 1 - 8 files changed, 145 insertions(+), 130 deletions(-) create mode 100644 CLI/commands/common/csv_sync.js diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index a7dabe7d7..457788e49 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -2,11 +2,14 @@ var readlineSync = require('readline-sync'); var BigNumber = require('bignumber.js'); var moment = require('moment'); var chalk = require('chalk'); -const shell = require('shelljs'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); var common = require('./common/common_functions'); var gbl = require('./common/global'); +var whitelist = require('./whitelist'); +var multi_mint = require('./multi_mint'); +var accredit = require('./accredit'); +var changeNonAccreditedLimit = require('./changeNonAccreditedLimit'); let securityTokenRegistryAddress; @@ -241,12 +244,11 @@ async function step_Wallet_Issuance(){ } async function multi_mint_tokens() { - //await whitelist.startWhitelisting(tokenSymbol); - shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${remoteNetwork}`); + await whitelist.executeApp(tokenSymbol, 75); console.log(chalk.green(`\nCongrats! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); - shell.exec(`${__dirname}/scripts//script.sh Multimint ${tokenSymbol} 75 ${remoteNetwork}`); + await multi_mint.executeApp(tokenSymbol, 75); console.log(chalk.green(`\nHurray!! Tokens get successfully Minted and transferred to token holders`)); } @@ -1003,7 +1005,7 @@ async function usdTieredSTO_configure() { await common.sendTransaction(changeAccreditedAction); break; case 2: - shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${remoteNetwork}`); + await accredit.executeApp(tokenSymbol, 75); break; case 3: let account = readlineSync.question('Enter the address to change non accredited limit: '); @@ -1015,7 +1017,7 @@ async function usdTieredSTO_configure() { await common.sendTransaction(changeNonAccreditedLimitAction); break; case 4: - shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${remoteNetwork}`); + await changeNonAccreditedLimit.executeApp(tokenSymbol, 75); break; case 5: await modfifyTimes(); diff --git a/CLI/commands/accredit.js b/CLI/commands/accredit.js index 079e1040c..dd2c5d3af 100644 --- a/CLI/commands/accredit.js +++ b/CLI/commands/accredit.js @@ -1,6 +1,5 @@ var common = require('./common/common_functions'); -var fs = require('fs'); -var csv = require('fast-csv'); +var csv = require('./common/csv_sync'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); var BigNumber = require('bignumber.js'); @@ -18,7 +17,7 @@ async function startScript(tokenSymbol, batchSize) { BATCH_SIZE = batchSize; } - common.logAsciiBull(); + //common.logAsciiBull(); let STAddress = await checkST(tokenSymbol); securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); @@ -51,34 +50,30 @@ async function STConnect() { } async function readCsv() { - var CSV_STRING = fs.readFileSync("./CLI/data/accredited_data.csv").toString(); + var CSV_STRING = csv('./CLI/data/accredited_data.csv'); let i = 0; - csv.fromString(CSV_STRING) - .on("data", (data) => { - let data_processed = accredit_processing(data); - fullFileData.push(data_processed[1]); - - if (data_processed[0]) { - allocData.push(data_processed[1]); - i++; - if (i >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - i = 0; - } - } else { - badData.push(data_processed[1]); + CSV_STRING.forEach(line => { + let data_processed = accredit_processing(line); + fullFileData.push(data_processed[1]); + + if (data_processed[0]) { + allocData.push(data_processed[1]); + i++; + if (i >= BATCH_SIZE) { + distribData.push(allocData); + allocData = []; + i = 0; } + } else { + badData.push(data_processed[1]); + } + }); - }) - .on("end", async () => { - distribData.push(allocData); - allocData = []; + distribData.push(allocData); + allocData = []; - await saveInBlockchain(); - return; - }); + await saveInBlockchain(); } async function saveInBlockchain() { @@ -116,7 +111,7 @@ async function saveInBlockchain() { isAccreditedArray.push(distribData[i][j][1]) } - let changeAccreditedAction = usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); + let changeAccreditedAction = await usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); let tx = await common.sendTransaction(changeAccreditedAction); console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); diff --git a/CLI/commands/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js index da3589f3d..35ae68b57 100644 --- a/CLI/commands/changeNonAccreditedLimit.js +++ b/CLI/commands/changeNonAccreditedLimit.js @@ -1,6 +1,5 @@ var common = require('./common/common_functions'); -var fs = require('fs'); -var csv = require('fast-csv'); +var csv = require('./common/csv_sync'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); var BigNumber = require('bignumber.js'); @@ -18,7 +17,7 @@ async function startScript(tokenSymbol, batchSize) { BATCH_SIZE = batchSize; } - common.logAsciiBull(); + //common.logAsciiBull(); let STAddress = await checkST(tokenSymbol); securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); @@ -51,34 +50,30 @@ async function STConnect() { } async function readCsv() { - var CSV_STRING = fs.readFileSync("./CLI/data/nonAccreditedLimits_data.csv").toString(); + var CSV_STRING = csv('./CLI/data/nonAccreditedLimits_data.csv'); let i = 0; - csv.fromString(CSV_STRING) - .on("data", (data) => { - let data_processed = nonAccredited_processing(data); - fullFileData.push(data_processed[1]); - - if (data_processed[0]) { - allocData.push(data_processed[1]); - i++; - if (i >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - i = 0; - } - } else { - badData.push(data_processed[1]); + CSV_STRING.forEach(line => { + let data_processed = nonAccredited_processing(line); + fullFileData.push(data_processed[1]); + + if (data_processed[0]) { + allocData.push(data_processed[1]); + i++; + if (i >= BATCH_SIZE) { + distribData.push(allocData); + allocData = []; + i = 0; } + } else { + badData.push(data_processed[1]); + } + }); - }) - .on("end", async () => { - distribData.push(allocData); - allocData = []; + distribData.push(allocData); + allocData = []; - await saveInBlockchain(); - return; - }); + await saveInBlockchain(); } async function saveInBlockchain() { @@ -116,7 +111,7 @@ async function saveInBlockchain() { limitArray.push(web3.utils.toWei(distribData[i][j][1].toString())); } - let changeNonAccreditedLimitAction = usdTieredSTO.methods.changeNonAccreditedLimit(investorArray, limitArray); + let changeNonAccreditedLimitAction = await usdTieredSTO.methods.changeNonAccreditedLimit(investorArray, limitArray); let tx = await common.sendTransaction(changeNonAccreditedLimitAction); console.log(`Batch ${i} - Attempting to change non accredited limits to accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index 123e158cb..700d6b4eb 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -50,7 +50,7 @@ async function checkPermissions(action) { //NOTE this is a condition to verify if the transaction comes from a module or not. if (contractRegistry.methods.hasOwnProperty('factory')) { let moduleAddress = await contractRegistry.methods.factory().call(); - let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress) + let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress); let parentModule = await moduleRegistry.methods.getName().call(); let result = await checkPermission(web3.utils.hexToUtf8(parentModule), action._method.name, contractRegistry); if (!result) { @@ -58,6 +58,7 @@ async function checkPermissions(action) { process.exit(0); } } + return } module.exports = { diff --git a/CLI/commands/common/csv_sync.js b/CLI/commands/common/csv_sync.js new file mode 100644 index 000000000..6955a2445 --- /dev/null +++ b/CLI/commands/common/csv_sync.js @@ -0,0 +1,39 @@ +var fs = require('fs'); + +function load(filename, options) { + var content = fs.readFileSync(filename, 'utf-8'); + var lines = content.split('\n'); + var splitToColumns = options && check.fn(options.getColumns) ? options.getColumns : getColumns; + var results = []; + + lines.forEach(function (line, index) { + if (!line) { + return; + } + + var obj = []; + var values = stripQuotes(splitToColumns(line, index)); + + values.forEach(function (value) { + obj.push(value) + }); + + results.push(obj); + }); + + return results; +} + +function getColumns(line) { + var columns = line.split(','); + return columns; +} + +function stripQuotes(words) { + return words.map(function (word) { + word = word.trim(); + return word.replace(/"/g, ''); + }); +} + +module.exports = load; diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index 723c2a34c..b1f041115 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -1,6 +1,5 @@ var common = require('./common/common_functions'); -var fs = require('fs'); -var csv = require('fast-csv'); +var csv = require('./common/csv_sync'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); var BigNumber = require('bignumber.js'); @@ -19,7 +18,7 @@ async function startScript(tokenSymbol, batchSize) { BATCH_SIZE = batchSize; } - common.logAsciiBull(); + //common.logAsciiBull(); let STAddress = await checkST(tokenSymbol); securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); @@ -52,50 +51,39 @@ async function STConnect() { } async function readCsv() { - var CSV_STRING = fs.readFileSync("./CLI/data/multi_mint_data.csv").toString(); + var CSV_STRING = csv('./CLI/data/multi_mint_data.csv'); let i = 0; - csv.fromString(CSV_STRING) - .on("data", (data) => { - let data_processed = multimint_processing(data); - fullFileData.push(data_processed[1]); - - if (data_processed[0]) { - allocData.push(data_processed[1]); - i++; - if (i >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - i = 0; - } - } else { - badData.push(data_processed[1]); + CSV_STRING.forEach(line => { + let data_processed = multimint_processing(line); + fullFileData.push(data_processed[1]); + + if (data_processed[0]) { + allocData.push(data_processed[1]); + i++; + if (i >= BATCH_SIZE) { + distribData.push(allocData); + allocData = []; + i = 0; } + } else { + badData.push(data_processed[1]); + } + }); - }) - .on("end", async () => { - distribData.push(allocData); - allocData = []; + distribData.push(allocData); + allocData = []; - await saveInBlockchain(); - await finalResults(); - return; - }); + await saveInBlockchain(); + await finalResults(); } async function saveInBlockchain() { - let gtmModules; - - try { - gtmModules = await securityToken.methods.getModulesByType(3).call(); - } catch (e) { - console.log("Minting of tokens is only allowed before the STO get attached", e) - process.exit(0) - } - - if (!gtmModules.length) { - console.log("Minting of tokens is only allowed before the STO get attached") - process.exit(0) + let gtmModules = await securityToken.methods.getModulesByType(3).call(); + + if (gtmModules.length > 0) { + console.log("Minting of tokens is only allowed before the STO get attached"); + process.exit(0); } console.log(` @@ -128,7 +116,7 @@ async function saveInBlockchain() { } } - let mintMultiAction = securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); + let mintMultiAction = await securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); let tx = await common.sendTransaction(mintMultiAction); console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); diff --git a/CLI/commands/whitelist.js b/CLI/commands/whitelist.js index d176903ee..2cd108030 100644 --- a/CLI/commands/whitelist.js +++ b/CLI/commands/whitelist.js @@ -1,6 +1,5 @@ var common = require('./common/common_functions'); -var fs = require('fs'); -var csv = require('fast-csv'); +var csv = require('./common/csv_sync'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); var BigNumber = require('bignumber.js'); @@ -18,7 +17,7 @@ async function startScript(tokenSymbol, batchSize) { BATCH_SIZE = batchSize; } - common.logAsciiBull(); + //common.logAsciiBull(); let STAddress = await checkST(tokenSymbol); securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); @@ -51,35 +50,32 @@ async function STConnect() { } async function readCsv() { - var CSV_STRING = fs.readFileSync("./CLI/data/whitelist_data.csv").toString(); + var CSV_STRING = csv('./CLI/data/whitelist_data.csv'); let i = 0; - csv.fromString(CSV_STRING) - .on("data", (data) => { - let data_processed = whitelist_processing(data); - fullFileData.push(data_processed[1]); - - if (data_processed[0]) { - allocData.push(data_processed[1]); - i++; - if (i >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - i = 0; - } - } else { - badData.push(data_processed[1]); + CSV_STRING.forEach(line => { + let data_processed = whitelist_processing(line); + fullFileData.push(data_processed[1]); + + if (data_processed[0]) { + allocData.push(data_processed[1]); + i++; + if (i >= BATCH_SIZE) { + distribData.push(allocData); + allocData = []; + i = 0; } + } else { + badData.push(data_processed[1]); + } + }); + + distribData.push(allocData); + allocData = []; - }) - .on("end", async () => { - distribData.push(allocData); - allocData = []; + await saveInBlockchain(); + await finalResults(); - await saveInBlockchain(); - await finalResults(); - return; - }); } async function saveInBlockchain() { @@ -112,7 +108,7 @@ async function saveInBlockchain() { canBuyFromSTOArray.push(distribData[i][j][4]) } - let modifyWhitelistMultiAction = generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); + let modifyWhitelistMultiAction = await generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); let tx = await common.sendTransaction(modifyWhitelistMultiAction); console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); diff --git a/package.json b/package.json index 5f8594e10..ef2d76c38 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,6 @@ "eslint-plugin-standard": "^3.0.1", "ethereum-bridge": "^0.6.1", "ethereumjs-abi": "^0.6.5", - "fast-csv": "^2.4.1", "ganache-cli": "^6.1.8", "prettier": "^1.14.3", "sol-merger": "^0.1.2", From a13bdacb6721b87c2906ec0835e69e2839a5cf25 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 15 Nov 2018 11:04:06 +0200 Subject: [PATCH 102/582] renamed startDate, nextDate to startTime, nextTime --- contracts/wallet/VestingEscrowWallet.sol | 51 ++++++++++++------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index a81c7b04c..db1184ca4 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -8,6 +8,7 @@ import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; /** * @title Wallet for core vesting escrow functionality */ +//TODO add docs for public, external methods //TODO remove vesting from methods, events, variables contract VestingEscrowWallet is Ownable { using SafeMath for uint256; @@ -18,8 +19,8 @@ contract VestingEscrowWallet is Ownable { uint256 lockedTokens; uint256 vestingDuration; uint256 vestingFrequency; - uint256 startDate; - uint256 nextDate; + uint256 startTime; + uint256 nextTime; State state; } @@ -52,7 +53,7 @@ contract VestingEscrowWallet is Ownable { uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, - uint256 _startDate, + uint256 _startTime, uint256 _timestamp ); event EditVestingSchedule( @@ -61,7 +62,7 @@ contract VestingEscrowWallet is Ownable { uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, - uint256 _startDate, + uint256 _startTime, uint256 _timestamp ); event RevokeVestingSchedules(address _beneficiary, uint256 _timestamp); @@ -127,12 +128,12 @@ contract VestingEscrowWallet is Ownable { uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, - uint256 _startDate + uint256 _startTime ) public onlyOwner { - _validateSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate); + _validateSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime); require(_numberOfTokens <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); VestingSchedule memory schedule; @@ -141,8 +142,8 @@ contract VestingEscrowWallet is Ownable { schedule.lockedTokens = _numberOfTokens; schedule.vestingDuration = _vestingDuration; schedule.vestingFrequency = _vestingFrequency; - schedule.startDate = _startDate; - schedule.nextDate = _startDate.add(schedule.vestingFrequency); + schedule.startTime = _startTime; + schedule.nextTime = _startTime.add(schedule.vestingFrequency); schedule.state = State.STARTED; //add beneficiary to the schedule list only if adding first schedule if (vestingData[_beneficiary].schedules.length == 0) { @@ -151,13 +152,13 @@ contract VestingEscrowWallet is Ownable { } vestingData[_beneficiary].schedules.push(schedule); /*solium-disable-next-line security/no-block-members*/ - emit AddVestingSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); + emit AddVestingSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime, now); } - function addVestingScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startDate) public onlyOwner { + function addVestingScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) public onlyOwner { require(_index < templates.length, "Template not found"); VestingTemplate template = templates[_index]; - addVestingSchedule(_beneficiary, template.numberOfTokens, template.vestingDuration, template.vestingFrequency, _startDate); + addVestingSchedule(_beneficiary, template.numberOfTokens, template.vestingDuration, template.vestingFrequency, _startTime); } function editVestingSchedule( @@ -166,12 +167,12 @@ contract VestingEscrowWallet is Ownable { uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, - uint256 _startDate + uint256 _startTime ) external onlyOwner { - _validateSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate); + _validateSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime); require(_index < vestingData[_beneficiary].schedules.length, "Schedule not found"); // require(_numberOfTokens <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); @@ -179,7 +180,7 @@ contract VestingEscrowWallet is Ownable { //TODO implement - emit EditVestingSchedule(_beneficiary, _index, _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate, now); + emit EditVestingSchedule(_beneficiary, _index, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime, now); } function revokeVestingSchedule(address _beneficiary, uint256 _index) external onlyOwner { @@ -217,8 +218,8 @@ contract VestingEscrowWallet is Ownable { schedule.lockedTokens, schedule.vestingDuration, schedule.vestingFrequency, - schedule.startDate, - schedule.nextDate, + schedule.startTime, + schedule.nextTime, schedule.state ); } @@ -239,19 +240,19 @@ contract VestingEscrowWallet is Ownable { uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, - uint256 _startDate + uint256 _startTime ) external onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { - addVestingSchedule(_beneficiaries[i], _numberOfTokens, _vestingDuration, _vestingFrequency, _startDate); + addVestingSchedule(_beneficiaries[i], _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime); } } - function batchAddVestingScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startDate) public onlyOwner { + function batchAddVestingScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startTime) public onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { - addVestingScheduleFromTemplate(_beneficiaries[i], _index, _startDate); + addVestingScheduleFromTemplate(_beneficiaries[i], _index, _startTime); } } @@ -261,10 +262,10 @@ contract VestingEscrowWallet is Ownable { } } - function _validateSchedule(address _beneficiary, uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, uint256 _startDate) { + function _validateSchedule(address _beneficiary, uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, uint256 _startTime) { require(_beneficiary != address(0), "Invalid beneficiary address"); _validateTemplate(_numberOfTokens, _vestingDuration, _vestingFrequency); - require(_startDate < now, "Start date shouldn't be in the past"); + require(_startTime < now, "Start date shouldn't be in the past"); } function _validateTemplate(uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency) { @@ -290,15 +291,15 @@ contract VestingEscrowWallet is Ownable { for (uint256 i = 0; i < data.schedules.length; i++) { VestingSchedule schedule = data.schedules[i]; /*solium-disable-next-line security/no-block-members*/ - if (schedule.state == State.STARTED && schedule.nextDate <= now) { + if (schedule.state == State.STARTED && schedule.nextTime <= now) { uint256 periodCount = schedule.vestingDuration.div(schedule.vestingFrequency); uint256 numberOfTokens = schedule.numberOfTokens.div(periodCount); data.availableTokens = data.availableTokens.add(numberOfTokens); schedule.lockedTokens = schedule.lockedTokens.sub(numberOfTokens); - if (schedule.nextDate == schedule.startDate.add(schedule.vestingDuration)) { + if (schedule.nextTime == schedule.startTime.add(schedule.vestingDuration)) { schedule.state = State.COMPLETED; } else { - schedule.nextDate = schedule.nextDate.add(schedule.vestingFrequency); + schedule.nextTime = schedule.nextTime.add(schedule.vestingFrequency); } } } From ae3c85bdc862bbf5430ad21191835252e8cc6cbc Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 15 Nov 2018 12:00:51 +0200 Subject: [PATCH 103/582] added edit and batchEdit --- contracts/wallet/VestingEscrowWallet.sol | 45 +++++++++++++++++++----- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index db1184ca4..08ee8775c 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -37,7 +37,7 @@ contract VestingEscrowWallet is Ownable { uint256 vestingFrequency; } - enum State {STARTED, COMPLETED} + enum State {CREATED, STARTED, COMPLETED} ERC20 public token; address public treasury; @@ -144,7 +144,7 @@ contract VestingEscrowWallet is Ownable { schedule.vestingFrequency = _vestingFrequency; schedule.startTime = _startTime; schedule.nextTime = _startTime.add(schedule.vestingFrequency); - schedule.state = State.STARTED; + schedule.state = State.CREATED; //add beneficiary to the schedule list only if adding first schedule if (vestingData[_beneficiary].schedules.length == 0) { vestingData[_beneficiary].index = beneficiaries.length; @@ -169,17 +169,26 @@ contract VestingEscrowWallet is Ownable { uint256 _vestingFrequency, uint256 _startTime ) - external + public onlyOwner { _validateSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime); require(_index < vestingData[_beneficiary].schedules.length, "Schedule not found"); -// require(_numberOfTokens <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); - VestingSchedule storage schedule = vestingData[_beneficiary].schedules[_index]; - - //TODO implement - + /*solium-disable-next-line security/no-block-members*/ + require(schedule.startTime < now, "It's not possible to edit the started schedule"); + if (_numberOfTokens <= schedule.lockedTokens) { + unassignedTokens = unassignedTokens.add(schedule.lockedTokens - _numberOfTokens); + } else { + require((_numberOfTokens - schedule.lockedTokens) <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); + unassignedTokens = unassignedTokens.sub(_numberOfTokens - schedule.lockedTokens); + } + schedule.numberOfTokens = _numberOfTokens; + schedule.lockedTokens = _numberOfTokens; + schedule.vestingDuration = _vestingDuration; + schedule.vestingFrequency = _vestingFrequency; + schedule.startTime = _startTime; + schedule.nextTime = _startTime.add(schedule.vestingFrequency); emit EditVestingSchedule(_beneficiary, _index, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime, now); } @@ -262,6 +271,23 @@ contract VestingEscrowWallet is Ownable { } } + function batchEditVestingSchedule( + address[] _beneficiaries, + uint256[] _indexes, + uint256 _numberOfTokens, + uint256 _vestingDuration, + uint256 _vestingFrequency, + uint256 _startTime + ) + external + onlyOwner + { + require(_beneficiaries.length == _indexes.length, "Beneficiaries array and indexes array should have the same length"); + for (uint256 i = 0; i < _beneficiaries.length; i++) { + editVestingSchedule(_beneficiaries[i], _indexes[i], _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime); + } + } + function _validateSchedule(address _beneficiary, uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, uint256 _startTime) { require(_beneficiary != address(0), "Invalid beneficiary address"); _validateTemplate(_numberOfTokens, _vestingDuration, _vestingFrequency); @@ -291,7 +317,7 @@ contract VestingEscrowWallet is Ownable { for (uint256 i = 0; i < data.schedules.length; i++) { VestingSchedule schedule = data.schedules[i]; /*solium-disable-next-line security/no-block-members*/ - if (schedule.state == State.STARTED && schedule.nextTime <= now) { + if (schedule.state != State.COMPLETED && schedule.nextTime <= now) { uint256 periodCount = schedule.vestingDuration.div(schedule.vestingFrequency); uint256 numberOfTokens = schedule.numberOfTokens.div(periodCount); data.availableTokens = data.availableTokens.add(numberOfTokens); @@ -299,6 +325,7 @@ contract VestingEscrowWallet is Ownable { if (schedule.nextTime == schedule.startTime.add(schedule.vestingDuration)) { schedule.state = State.COMPLETED; } else { + schedule.state = State.STARTED; schedule.nextTime = schedule.nextTime.add(schedule.vestingFrequency); } } From 21377cdd8da1952a11606e69600ff279a307548b Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 15 Nov 2018 13:07:00 +0200 Subject: [PATCH 104/582] removed redundant "vesting" from names --- contracts/wallet/VestingEscrowWallet.sol | 201 +++++++++++------------ test/z_vesting_escrow_wallet.js | 23 +-- 2 files changed, 108 insertions(+), 116 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 08ee8775c..2d8ca803f 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -9,32 +9,31 @@ import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; * @title Wallet for core vesting escrow functionality */ //TODO add docs for public, external methods -//TODO remove vesting from methods, events, variables contract VestingEscrowWallet is Ownable { using SafeMath for uint256; using SafeERC20 for ERC20; - struct VestingSchedule { + struct Schedule { uint256 numberOfTokens; uint256 lockedTokens; - uint256 vestingDuration; - uint256 vestingFrequency; + uint256 duration; + uint256 frequency; uint256 startTime; uint256 nextTime; State state; } - struct VestingData { + struct Data { uint256 index; - VestingSchedule[] schedules; + Schedule[] schedules; uint256 availableTokens; uint256 claimedTokens; } - struct VestingTemplate { + struct Template { uint256 numberOfTokens; - uint256 vestingDuration; - uint256 vestingFrequency; + uint256 duration; + uint256 frequency; } enum State {CREATED, STARTED, COMPLETED} @@ -43,35 +42,35 @@ contract VestingEscrowWallet is Ownable { address public treasury; uint256 public unassignedTokens; - mapping (address => VestingData) public vestingData; + mapping (address => Data) public dataMap; address[] public beneficiaries; - VestingTemplate[] public templates; + Template[] public templates; - event AddVestingSchedule( + event AddSchedule( address _beneficiary, uint256 _numberOfTokens, - uint256 _vestingDuration, - uint256 _vestingFrequency, + uint256 _duration, + uint256 _frequency, uint256 _startTime, uint256 _timestamp ); - event EditVestingSchedule( + event EditSchedule( address _beneficiary, uint256 _index, uint256 _numberOfTokens, - uint256 _vestingDuration, - uint256 _vestingFrequency, + uint256 _duration, + uint256 _frequency, uint256 _startTime, uint256 _timestamp ); - event RevokeVestingSchedules(address _beneficiary, uint256 _timestamp); - event RevokeVestingSchedule(address _beneficiary, uint256 _index, uint256 _timestamp); + event RevokeSchedules(address _beneficiary, uint256 _timestamp); + event RevokeSchedule(address _beneficiary, uint256 _index, uint256 _timestamp); event DepositTokens(uint256 _numberOfTokens, uint256 _timestamp); event SendToTreasury(uint256 _numberOfTokens, uint256 _timestamp); event SendTokens(address _beneficiary, uint256 _numberOfTokens, uint256 _timestamp); - event AddVestingTemplate(uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, uint256 _timestamp); - event RemoveVestingTemplate(uint256 _index, uint256 _timestamp); + event AddTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, uint256 _timestamp); + event RemoveTemplate(uint256 _index, uint256 _timestamp); constructor(address _tokenAddress, address _treasury) public { token = ERC20(_tokenAddress); @@ -104,77 +103,77 @@ contract VestingEscrowWallet is Ownable { _sendTokens(msg.sender); } - function addVestingTemplate(uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency) external onlyOwner { - _validateTemplate(_numberOfTokens, _vestingDuration, _vestingFrequency); - VestingTemplate memory template; + function addTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) external onlyOwner { + _validateTemplate(_numberOfTokens, _duration, _frequency); + Template memory template; template.numberOfTokens = _numberOfTokens; - template.vestingDuration = _vestingDuration; - template.vestingFrequency = _vestingFrequency; + template.duration = _duration; + template.frequency = _frequency; templates.push(template); /*solium-disable-next-line security/no-block-members*/ - emit AddVestingTemplate(_numberOfTokens, _vestingDuration, _vestingFrequency, now); + emit AddTemplate(_numberOfTokens, _duration, _frequency, now); } - function removeVestingTemplate(uint256 _index) external onlyOwner { + function removeTemplate(uint256 _index) external onlyOwner { require(_index < templates.length, "Template not found"); templates[_index] = templates[templates.length - 1]; templates.length--; /*solium-disable-next-line security/no-block-members*/ - emit RemoveVestingTemplate(_index, now); + emit RemoveTemplate(_index, now); } - function addVestingSchedule( + function addSchedule( address _beneficiary, uint256 _numberOfTokens, - uint256 _vestingDuration, - uint256 _vestingFrequency, + uint256 _duration, + uint256 _frequency, uint256 _startTime ) public onlyOwner { - _validateSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime); + _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); require(_numberOfTokens <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); - VestingSchedule memory schedule; + Schedule memory schedule; unassignedTokens = unassignedTokens.sub(_numberOfTokens); schedule.numberOfTokens = _numberOfTokens; schedule.lockedTokens = _numberOfTokens; - schedule.vestingDuration = _vestingDuration; - schedule.vestingFrequency = _vestingFrequency; + schedule.duration = _duration; + schedule.frequency = _frequency; schedule.startTime = _startTime; - schedule.nextTime = _startTime.add(schedule.vestingFrequency); + schedule.nextTime = _startTime.add(schedule.frequency); schedule.state = State.CREATED; //add beneficiary to the schedule list only if adding first schedule - if (vestingData[_beneficiary].schedules.length == 0) { - vestingData[_beneficiary].index = beneficiaries.length; + if (dataMap[_beneficiary].schedules.length == 0) { + dataMap[_beneficiary].index = beneficiaries.length; beneficiaries.push(_beneficiary); } - vestingData[_beneficiary].schedules.push(schedule); + dataMap[_beneficiary].schedules.push(schedule); /*solium-disable-next-line security/no-block-members*/ - emit AddVestingSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime, now); + emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime, now); } - function addVestingScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) public onlyOwner { + function addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) public onlyOwner { require(_index < templates.length, "Template not found"); - VestingTemplate template = templates[_index]; - addVestingSchedule(_beneficiary, template.numberOfTokens, template.vestingDuration, template.vestingFrequency, _startTime); + Template storage template = templates[_index]; + addSchedule(_beneficiary, template.numberOfTokens, template.duration, template.frequency, _startTime); } - function editVestingSchedule( + function editSchedule( address _beneficiary, uint256 _index, uint256 _numberOfTokens, - uint256 _vestingDuration, - uint256 _vestingFrequency, + uint256 _duration, + uint256 _frequency, uint256 _startTime ) public onlyOwner { - _validateSchedule(_beneficiary, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime); - require(_index < vestingData[_beneficiary].schedules.length, "Schedule not found"); - VestingSchedule storage schedule = vestingData[_beneficiary].schedules[_index]; + _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); + require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); + Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; /*solium-disable-next-line security/no-block-members*/ require(schedule.startTime < now, "It's not possible to edit the started schedule"); if (_numberOfTokens <= schedule.lockedTokens) { @@ -185,57 +184,57 @@ contract VestingEscrowWallet is Ownable { } schedule.numberOfTokens = _numberOfTokens; schedule.lockedTokens = _numberOfTokens; - schedule.vestingDuration = _vestingDuration; - schedule.vestingFrequency = _vestingFrequency; + schedule.duration = _duration; + schedule.frequency = _frequency; schedule.startTime = _startTime; - schedule.nextTime = _startTime.add(schedule.vestingFrequency); - emit EditVestingSchedule(_beneficiary, _index, _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime, now); + schedule.nextTime = _startTime.add(schedule.frequency); + emit EditSchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime, now); } - function revokeVestingSchedule(address _beneficiary, uint256 _index) external onlyOwner { + function revokeSchedule(address _beneficiary, uint256 _index) external onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); - require(_index < vestingData[_beneficiary].schedules.length, "Schedule not found"); - VestingSchedule[] storage schedules = vestingData[_beneficiary].schedules; + require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); + Schedule[] storage schedules = dataMap[_beneficiary].schedules; unassignedTokens = unassignedTokens.add(schedules[_index].lockedTokens); schedules[_index] = schedules[schedules.length - 1]; schedules.length--; if (schedules.length == 0) { - _revokeVestingSchedules(_beneficiary); + _revokeSchedules(_beneficiary); } /*solium-disable-next-line security/no-block-members*/ - emit RevokeVestingSchedule(_beneficiary, _index, now); + emit RevokeSchedule(_beneficiary, _index, now); } - function revokeVestingSchedules(address _beneficiary) public onlyOwner { + function revokeSchedules(address _beneficiary) public onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); - VestingData data = vestingData[_beneficiary]; + Data storage data = dataMap[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { unassignedTokens = unassignedTokens.add(data.schedules[i].lockedTokens); } - delete vestingData[_beneficiary].schedules; - _revokeVestingSchedules(_beneficiary); + delete dataMap[_beneficiary].schedules; + _revokeSchedules(_beneficiary); /*solium-disable-next-line security/no-block-members*/ - emit RevokeVestingSchedules(_beneficiary, now); + emit RevokeSchedules(_beneficiary, now); } - function getVestingSchedule(address _beneficiary, uint256 _index) external onlyOwner returns(uint256, uint256, uint256, uint256, uint256, uint256, State) { + function getSchedule(address _beneficiary, uint256 _index) external view onlyOwner returns(uint256, uint256, uint256, uint256, uint256, uint256, State) { require(_beneficiary != address(0), "Invalid beneficiary address"); - require(_index < vestingData[_beneficiary].schedules.length, "Schedule not found"); - VestingSchedule schedule = vestingData[_beneficiary].schedules[_index]; + require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); + Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; return ( schedule.numberOfTokens, schedule.lockedTokens, - schedule.vestingDuration, - schedule.vestingFrequency, + schedule.duration, + schedule.frequency, schedule.startTime, schedule.nextTime, schedule.state ); } - function getVestingScheduleCount(address _beneficiary) external onlyOwner returns(uint256) { + function getScheduleCount(address _beneficiary) external view onlyOwner returns(uint256) { require(_beneficiary != address(0), "Invalid beneficiary address"); - return vestingData[_beneficiary].schedules.length; + return dataMap[_beneficiary].schedules.length; } function batchSendAvailableTokens(address[] _beneficiaries) external onlyOwner { @@ -244,39 +243,39 @@ contract VestingEscrowWallet is Ownable { } } - function batchAddVestingSchedule( + function batchAddSchedule( address[] _beneficiaries, uint256 _numberOfTokens, - uint256 _vestingDuration, - uint256 _vestingFrequency, + uint256 _duration, + uint256 _frequency, uint256 _startTime ) external onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { - addVestingSchedule(_beneficiaries[i], _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime); + addSchedule(_beneficiaries[i], _numberOfTokens, _duration, _frequency, _startTime); } } - function batchAddVestingScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startTime) public onlyOwner { + function batchAddScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startTime) public onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { - addVestingScheduleFromTemplate(_beneficiaries[i], _index, _startTime); + addScheduleFromTemplate(_beneficiaries[i], _index, _startTime); } } - function batchRevokeVestingSchedules(address[] _beneficiaries) external onlyOwner { + function batchRevokeSchedules(address[] _beneficiaries) external onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { - revokeVestingSchedules(_beneficiaries[i]); + revokeSchedules(_beneficiaries[i]); } } - function batchEditVestingSchedule( + function batchEditSchedule( address[] _beneficiaries, uint256[] _indexes, uint256 _numberOfTokens, - uint256 _vestingDuration, - uint256 _vestingFrequency, + uint256 _duration, + uint256 _frequency, uint256 _startTime ) external @@ -284,25 +283,25 @@ contract VestingEscrowWallet is Ownable { { require(_beneficiaries.length == _indexes.length, "Beneficiaries array and indexes array should have the same length"); for (uint256 i = 0; i < _beneficiaries.length; i++) { - editVestingSchedule(_beneficiaries[i], _indexes[i], _numberOfTokens, _vestingDuration, _vestingFrequency, _startTime); + editSchedule(_beneficiaries[i], _indexes[i], _numberOfTokens, _duration, _frequency, _startTime); } } - function _validateSchedule(address _beneficiary, uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency, uint256 _startTime) { + function _validateSchedule(address _beneficiary, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, uint256 _startTime) private view { require(_beneficiary != address(0), "Invalid beneficiary address"); - _validateTemplate(_numberOfTokens, _vestingDuration, _vestingFrequency); - require(_startTime < now, "Start date shouldn't be in the past"); + _validateTemplate(_numberOfTokens, _duration, _frequency); + require(_startTime > now, "Start date shouldn't be in the past"); } - function _validateTemplate(uint256 _numberOfTokens, uint256 _vestingDuration, uint256 _vestingFrequency) { + function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) private pure { require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); - require(_vestingDuration % _vestingFrequency == 0, "Duration should be divided entirely by frequency"); - uint256 periodCount = _vestingDuration.div(_vestingFrequency); + require(_duration % _frequency == 0, "Duration should be divided entirely by frequency"); + uint256 periodCount = _duration.div(_frequency); require(_numberOfTokens % periodCount == 0, "Number of tokens should be divided entirely by period count"); } function _sendTokens(address _beneficiary) private { - VestingData data = vestingData[_beneficiary]; + Data storage data = dataMap[_beneficiary]; uint256 amount = data.availableTokens; require(amount > 0, "Beneficiary doesn't have available tokens"); data.availableTokens = 0; @@ -313,20 +312,20 @@ contract VestingEscrowWallet is Ownable { } function _update(address _beneficiary) private { - VestingData data = vestingData[_beneficiary]; + Data storage data = dataMap[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { - VestingSchedule schedule = data.schedules[i]; + Schedule storage schedule = data.schedules[i]; /*solium-disable-next-line security/no-block-members*/ if (schedule.state != State.COMPLETED && schedule.nextTime <= now) { - uint256 periodCount = schedule.vestingDuration.div(schedule.vestingFrequency); + uint256 periodCount = schedule.duration.div(schedule.frequency); uint256 numberOfTokens = schedule.numberOfTokens.div(periodCount); data.availableTokens = data.availableTokens.add(numberOfTokens); schedule.lockedTokens = schedule.lockedTokens.sub(numberOfTokens); - if (schedule.nextTime == schedule.startTime.add(schedule.vestingDuration)) { + if (schedule.nextTime == schedule.startTime.add(schedule.duration)) { schedule.state = State.COMPLETED; } else { schedule.state = State.STARTED; - schedule.nextTime = schedule.nextTime.add(schedule.vestingFrequency); + schedule.nextTime = schedule.nextTime.add(schedule.frequency); } } } @@ -338,20 +337,20 @@ contract VestingEscrowWallet is Ownable { } } - function _revokeVestingSchedules(address _beneficiary) private { + function _revokeSchedules(address _beneficiary) private { if (_canBeRemoved(_beneficiary)) { - uint256 index = vestingData[_beneficiary].index; + uint256 index = dataMap[_beneficiary].index; beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; beneficiaries.length--; if (index != beneficiaries.length) { - vestingData[beneficiaries[index]].index = index; + dataMap[beneficiaries[index]].index = index; } - delete vestingData[_beneficiary]; + delete dataMap[_beneficiary]; } } - function _canBeRemoved(address _beneficiary) private returns(bool) { - return (vestingData[_beneficiary].availableTokens == 0); + function _canBeRemoved(address _beneficiary) private view returns(bool) { + return (dataMap[_beneficiary].availableTokens == 0); } } diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 4b4b8adbb..9b4f0cd45 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -1,6 +1,6 @@ import {deployPolyRegistryAndPolyToken, deployVestingEscrowWallet} from "./helpers/createInstances"; import latestTime from "./helpers/latestTime"; -import {duration} from "./helpers/utils"; +import {duration as durationUtil} from "./helpers/utils"; const VestingEscrowWallet = artifacts.require('./VestingEscrowWallet.sol'); @@ -57,24 +57,17 @@ contract('VestingEscrowWallet', accounts => { it("Should add Vesting Schedule to the beneficiary address", async () => { let numberOfTokens = 100000; - let vestingDuration = duration.years(4); - let vestingFrequency = duration.years(1); - let startDate = latestTime(); - const tx = await I_VestingEscrowWallet.addVestingSchedule( - account_beneficiary1, - numberOfTokens, - vestingDuration, - vestingFrequency, - startDate, - {from: account_polymath} - ); + let duration = durationUtil.years(4); + let frequency = durationUtil.years(1); + let startTime = latestTime() + durationUtil.days(1); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: account_polymath}); let log = tx.logs[0]; assert.equal(log.args._beneficiary, account_beneficiary1); assert.equal(log.args._numberOfTokens, numberOfTokens); - assert.equal(log.args._vestingDuration, vestingDuration); - assert.equal(log.args._vestingFrequency, vestingFrequency); - assert.equal(log.args._startDate, startDate); + assert.equal(log.args._duration, duration); + assert.equal(log.args._frequency, frequency); + assert.equal(log.args._startTime, startTime); }); From d600f9752b828dd8f10a28c3fdcffd62278a4a4b Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 15 Nov 2018 17:22:27 +0200 Subject: [PATCH 105/582] updated test addVestingSchedule --- test/helpers/createInstances.js | 4 ++-- test/z_vesting_escrow_wallet.js | 24 ++++++++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 319c61f51..966602ba2 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -424,8 +424,8 @@ export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, return new Array(I_MockWrongTypeBurnFactory); } -export async function deployVestingEscrowWallet(accountPolymath, polyToken, treasury) { - I_VestingEscrowWallet = await VestingEscrowWallet.new(polyToken, treasury, { from: accountPolymath }); +export async function deployVestingEscrowWallet(accountOwner, polyToken, treasury) { + I_VestingEscrowWallet = await VestingEscrowWallet.new(polyToken, treasury, { from: accountOwner }); assert.notEqual( I_VestingEscrowWallet.address.valueOf(), "0x0000000000000000000000000000000000000000", diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 9b4f0cd45..c37a9eb29 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -12,8 +12,8 @@ contract('VestingEscrowWallet', accounts => { // Accounts Variable declaration let account_polymath; - let account_issuer; - let token_owner; + let wallet_owner; + let account_treasury; let account_beneficiary1; let account_beneficiary2; let account_beneficiary3; @@ -28,19 +28,18 @@ contract('VestingEscrowWallet', accounts => { before(async () => { // Accounts setup account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; + wallet_owner = accounts[1]; + account_treasury = accounts[2]; account_beneficiary1 = accounts[7]; account_beneficiary2 = accounts[8]; account_beneficiary3 = accounts[9]; // Step 1: Deploy the PolyToken - [I_PolymathRegistry, I_PolyToken] = await deployPolyRegistryAndPolyToken(account_polymath, token_owner); + [I_PolymathRegistry, I_PolyToken] = await deployPolyRegistryAndPolyToken(account_polymath, account_treasury); // STEP 2: Deploy the VestingEscrowWallet - [I_VestingEscrowWallet] = await deployVestingEscrowWallet(account_polymath, I_PolyToken.address, token_owner); + [I_VestingEscrowWallet] = await deployVestingEscrowWallet(wallet_owner, I_PolyToken.address, account_treasury); // Printing all the contract addresses console.log(` @@ -60,7 +59,9 @@ contract('VestingEscrowWallet', accounts => { let duration = durationUtil.years(4); let frequency = durationUtil.years(1); let startTime = latestTime() + durationUtil.days(1); - const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: account_polymath}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); let log = tx.logs[0]; assert.equal(log.args._beneficiary, account_beneficiary1); @@ -68,6 +69,13 @@ contract('VestingEscrowWallet', accounts => { assert.equal(log.args._duration, duration); assert.equal(log.args._frequency, frequency); assert.equal(log.args._startTime, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1, {from: wallet_owner}); + assert.equal(scheduleCount, 1); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0, {from: wallet_owner}); + console.log("=========================================="); + console.log(schedule); }); From be15824823701d8a4626c47ff4f91098df8d16d6 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Thu, 15 Nov 2018 16:12:10 +0000 Subject: [PATCH 106/582] Add getTokensSoldByTier --- contracts/modules/STO/USDTieredSTO.sol | 35 ++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index d5b7fde2c..e5e7bb3aa 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -22,7 +22,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 rate; // How many token units a buyer gets per USD in this tier (multiplied by 10**18) when investing in POLY up to tokensDiscountPoly - uint256 rateDiscountPoly; + uint256 rateDiscountPoly; // How many tokens are available in this tier (relative to totalSupply) uint256 tokenTotal; @@ -202,7 +202,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } /** - * @dev Modifies fund raise types + * @dev Modifies fund raise types * @param _fundRaiseTypes Array of fund raise types to allow */ function modifyFunding(FundRaiseType[] _fundRaiseTypes) external onlyOwner { @@ -291,7 +291,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { require(_tokensPerTierTotal.length > 0, "No tiers provided"); require(_ratePerTier.length == _tokensPerTierTotal.length && _ratePerTierDiscountPoly.length == _tokensPerTierTotal.length && - _tokensPerTierDiscountPoly.length == _tokensPerTierTotal.length, + _tokensPerTierDiscountPoly.length == _tokensPerTierTotal.length, "Tier data length mismatch" ); delete tiers; @@ -408,7 +408,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { buyWithETHRateLimited(msg.sender, 0); } - // Buy functions without rate restriction + // Buy functions without rate restriction function buyWithETH(address _beneficiary) external payable { buyWithETHRateLimited(_beneficiary, 0); } @@ -448,7 +448,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @param _minTokens Minumum number of tokens to buy or else revert */ function buyWithPOLYRateLimited(address _beneficiary, uint256 _investedPOLY, uint256 _minTokens) public validPOLY { - _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, _minTokens); + _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, _minTokens); } /** @@ -529,7 +529,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { if (!gotoNextTier) break; } - + } // Modify storage @@ -544,7 +544,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { spentValue = 0; } else { //_rate is actually OriginalUSD. Reusing variable to prevent stackoverflow - spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, _rate), _investmentValue); + spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, _rate), _investmentValue); } // Return calculated amounts @@ -556,7 +556,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _tier, uint256 _investedUSD, FundRaiseType _fundRaiseType - ) + ) internal returns(uint256 spentUSD, bool gotoNextTier) { @@ -712,7 +712,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } /** - * @notice Return the total no. of tokens sold for ETH + * @notice Return the total no. of tokens sold for the given fund raise type + * param _fundRaiseType The fund raising currency (e.g. ETH, POLY, DAI) to calculate sold tokens for * @return uint256 Total number of tokens sold for ETH */ function getTokensSoldFor(FundRaiseType _fundRaiseType) public view returns (uint256) { @@ -723,6 +724,20 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { return tokensSold; } + /** + * @notice Return the total no. of tokens sold in a given tier + * param _tier The tier to calculate sold tokens for + * @return uint256 Total number of tokens sold in the tier + */ + function getTokensSoldByTier(uint256 _tier) public view returns (uint256) { + require(_tier < tiers.length, "Incorrect tier"); + uint256 tokensSold; + tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.ETH)]); + tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.POLY)]); + tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.DAI)]); + return tokensSold; + } + /** * @notice Return the total no. of tiers * @return uint256 Total number of tiers @@ -748,7 +763,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @return Array Rate at which tokens are sold at different tiers * @return Amount of funds raised * @return Number of individual investors this STO have. - * @return Amount of tokens sold. + * @return Amount of tokens sold. * @return Array of bools to show if funding is allowed in ETH, POLY, DAI respectively */ function getSTODetails() public view returns(uint256, uint256, uint256, uint256[], uint256[], uint256, uint256, uint256, bool[]) { From bafb54029ebd4dc3b454b097a1101ff748d93923 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 15 Nov 2018 19:58:07 +0200 Subject: [PATCH 107/582] tests for adding and revoking schedules --- test/z_vesting_escrow_wallet.js | 125 +++++++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 12 deletions(-) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index c37a9eb29..231441a80 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -10,6 +10,10 @@ const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); contract('VestingEscrowWallet', accounts => { + const CREATED = 0; + const STARTED = 1; + const COMPLETED = 2; + // Accounts Variable declaration let account_polymath; let wallet_owner; @@ -52,9 +56,30 @@ contract('VestingEscrowWallet', accounts => { `); }); - describe("Adding Vesting Schedule", async () => { - - it("Should add Vesting Schedule to the beneficiary address", async () => { + describe("Adding and Revoking Vesting Schedule", async () => { + + let schedules = [ + { + numberOfTokens: 100000, + duration: durationUtil.years(4), + frequency: durationUtil.years(1), + startTime: latestTime() + durationUtil.days(1) + }, + { + numberOfTokens: 30000, + duration: durationUtil.weeks(6), + frequency: durationUtil.weeks(1), + startTime: latestTime() + durationUtil.days(2) + }, + { + numberOfTokens: 2000, + duration: durationUtil.days(10), + frequency: durationUtil.days(2), + startTime: latestTime() + durationUtil.days(3) + } + ]; + + it("Should add Vesting Schedule to the first beneficiary address", async () => { let numberOfTokens = 100000; let duration = durationUtil.years(4); let frequency = durationUtil.years(1); @@ -64,21 +89,97 @@ contract('VestingEscrowWallet', accounts => { const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); let log = tx.logs[0]; - assert.equal(log.args._beneficiary, account_beneficiary1); - assert.equal(log.args._numberOfTokens, numberOfTokens); - assert.equal(log.args._duration, duration); - assert.equal(log.args._frequency, frequency); - assert.equal(log.args._startTime, startTime); + checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1, {from: wallet_owner}); - assert.equal(scheduleCount, 1); + assert.equal(scheduleCount.toNumber(), 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0, {from: wallet_owner}); - console.log("=========================================="); - console.log(schedule); + checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + }); + + it("Should revoke Vesting Schedule from the first beneficiary address", async () => { + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); + + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); + assert.equal(tx.logs[0].args._index, 0); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1, {from: wallet_owner}); + assert.equal(scheduleCount.toNumber(), 0); + }); + + it("Should add 3 Vesting Schedules to the second beneficiary address", async () => { + let totalNumberOfTokens = getTotalNumberOfTokens(schedules); + await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); + for (let i = 0; i < schedules.length; i++) { + let numberOfTokens = schedules[i].numberOfTokens; + let duration = schedules[i].duration; + let frequency = schedules[i].frequency; + let startTime = schedules[i].startTime; + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary2, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + + let log = tx.logs[0]; + checkScheduleLog(log, account_beneficiary2, numberOfTokens, duration, frequency, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2, {from: wallet_owner}); + assert.equal(scheduleCount.toNumber(), i + 1); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, i, {from: wallet_owner}); + checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + } + }); + + it("Should revoke Vesting Schedule from the second beneficiary address", async () => { + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, 1, {from: wallet_owner}); + + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); + assert.equal(tx.logs[0].args._index, 1); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2, {from: wallet_owner}); + assert.equal(scheduleCount.toNumber(), 2); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, 1, {from: wallet_owner}); + checkSchedule(schedule, schedules[2].numberOfTokens, schedules[2].numberOfTokens, schedules[2].duration, schedules[2].frequency, + schedules[2].startTime, schedules[2].startTime + schedules[2].frequency, CREATED); + }); + + it("Should revoke 2 Vesting Schedules from the second beneficiary address", async () => { + const tx = await I_VestingEscrowWallet.revokeSchedules(account_beneficiary2, {from: wallet_owner}); + + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2, {from: wallet_owner}); + assert.equal(scheduleCount.toNumber(), 0); }); }); -}); \ No newline at end of file +}); + +function checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime) { + assert.equal(log.args._beneficiary, beneficiary); + assert.equal(log.args._numberOfTokens, numberOfTokens); + assert.equal(log.args._duration, duration); + assert.equal(log.args._frequency, frequency); + assert.equal(log.args._startTime, startTime); +} + +function checkSchedule(schedule, numberOfTokens, lockedTokens, duration, frequency, startTime, nextTime, state) { + assert.equal(schedule[0].toNumber(), numberOfTokens); + assert.equal(schedule[1].toNumber(), lockedTokens); + assert.equal(schedule[2].toNumber(), duration); + assert.equal(schedule[3].toNumber(), frequency); + assert.equal(schedule[4].toNumber(), startTime); + assert.equal(schedule[5].toNumber(), nextTime); + assert.equal(schedule[6].toNumber(), state); +} + +function getTotalNumberOfTokens(schedules) { + let numberOfTokens = 0; + for (let i = 0; i < schedules.length; i++) { + numberOfTokens += schedules[i].numberOfTokens; + } + return numberOfTokens; +} From ecc03aad940aee0cc416e56960f8eb1159b4f4ca Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 15 Nov 2018 21:56:31 +0200 Subject: [PATCH 108/582] tests for templates --- contracts/wallet/VestingEscrowWallet.sol | 17 +++- test/z_vesting_escrow_wallet.js | 124 ++++++++++++++++++----- 2 files changed, 114 insertions(+), 27 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 2d8ca803f..14fd8e272 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -122,6 +122,10 @@ contract VestingEscrowWallet is Ownable { emit RemoveTemplate(_index, now); } + function getTemplateCount() external onlyOwner returns(uint256) { + return templates.length; + } + function addSchedule( address _beneficiary, uint256 _numberOfTokens, @@ -175,7 +179,7 @@ contract VestingEscrowWallet is Ownable { require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; /*solium-disable-next-line security/no-block-members*/ - require(schedule.startTime < now, "It's not possible to edit the started schedule"); + require(now < schedule.startTime, "It's not possible to edit the started schedule"); if (_numberOfTokens <= schedule.lockedTokens) { unassignedTokens = unassignedTokens.add(schedule.lockedTokens - _numberOfTokens); } else { @@ -217,7 +221,7 @@ contract VestingEscrowWallet is Ownable { emit RevokeSchedules(_beneficiary, now); } - function getSchedule(address _beneficiary, uint256 _index) external view onlyOwner returns(uint256, uint256, uint256, uint256, uint256, uint256, State) { + function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256, uint256, uint256, State) { require(_beneficiary != address(0), "Invalid beneficiary address"); require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; @@ -232,11 +236,16 @@ contract VestingEscrowWallet is Ownable { ); } - function getScheduleCount(address _beneficiary) external view onlyOwner returns(uint256) { + function getScheduleCount(address _beneficiary) external view returns(uint256) { require(_beneficiary != address(0), "Invalid beneficiary address"); return dataMap[_beneficiary].schedules.length; } + function getAvailableTokens(address _beneficiary) external view returns(uint256) { + require(_beneficiary != address(0), "Invalid beneficiary address"); + return dataMap[_beneficiary].availableTokens; + } + function batchSendAvailableTokens(address[] _beneficiaries) external onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { sendAvailableTokens(_beneficiaries[i]); @@ -290,7 +299,7 @@ contract VestingEscrowWallet is Ownable { function _validateSchedule(address _beneficiary, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, uint256 _startTime) private view { require(_beneficiary != address(0), "Invalid beneficiary address"); _validateTemplate(_numberOfTokens, _duration, _frequency); - require(_startTime > now, "Start date shouldn't be in the past"); + require(now < _startTime, "Start date shouldn't be in the past"); } function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) private pure { diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 231441a80..281b9b9b2 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -1,6 +1,7 @@ import {deployPolyRegistryAndPolyToken, deployVestingEscrowWallet} from "./helpers/createInstances"; import latestTime from "./helpers/latestTime"; import {duration as durationUtil} from "./helpers/utils"; +import {catchRevert} from "./helpers/exceptions"; const VestingEscrowWallet = artifacts.require('./VestingEscrowWallet.sol'); @@ -56,7 +57,7 @@ contract('VestingEscrowWallet', accounts => { `); }); - describe("Adding and Revoking Vesting Schedule", async () => { + describe("Adding, Editing and Revoking Vesting Schedule", async () => { let schedules = [ { @@ -80,10 +81,10 @@ contract('VestingEscrowWallet', accounts => { ]; it("Should add Vesting Schedule to the first beneficiary address", async () => { - let numberOfTokens = 100000; - let duration = durationUtil.years(4); - let frequency = durationUtil.years(1); - let startTime = latestTime() + durationUtil.days(1); + let numberOfTokens = schedules[0].numberOfTokens; + let duration = schedules[0].duration; + let frequency = schedules[0].frequency; + let startTime = schedules[0].startTime; await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); @@ -91,21 +92,51 @@ contract('VestingEscrowWallet', accounts => { let log = tx.logs[0]; checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); - let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1, {from: wallet_owner}); - assert.equal(scheduleCount.toNumber(), 1); + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); + assert.equal(scheduleCount, 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0, {from: wallet_owner}); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); }); + it("Should edit Vesting Schedule to the first beneficiary address", async () => { + let numberOfTokens = schedules[1].numberOfTokens; + let duration = schedules[1].duration; + let frequency = schedules[1].frequency; + let startTime = schedules[1].startTime; + const tx = await I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + + let log = tx.logs[0]; + checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); + assert.equal(scheduleCount, 1); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); + checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + assert.equal(unassignedTokens, schedules[0].numberOfTokens - schedules[1].numberOfTokens); + }); + + it("Should fail edit Vesting Schedule to the first beneficiary address", async () => { + let numberOfTokens = schedules[0].numberOfTokens + schedules[1].numberOfTokens; + let duration = schedules[0].duration; + let frequency = schedules[0].frequency; + let startTime = schedules[0].startTime; + await catchRevert( + I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + ); + }); + it("Should revoke Vesting Schedule from the first beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); assert.equal(tx.logs[0].args._index, 0); - let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1, {from: wallet_owner}); - assert.equal(scheduleCount.toNumber(), 0); + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); + assert.equal(scheduleCount, 0); }); it("Should add 3 Vesting Schedules to the second beneficiary address", async () => { @@ -122,10 +153,10 @@ contract('VestingEscrowWallet', accounts => { let log = tx.logs[0]; checkScheduleLog(log, account_beneficiary2, numberOfTokens, duration, frequency, startTime); - let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2, {from: wallet_owner}); - assert.equal(scheduleCount.toNumber(), i + 1); + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); + assert.equal(scheduleCount, i + 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, i, {from: wallet_owner}); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, i); checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); } }); @@ -136,10 +167,10 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); assert.equal(tx.logs[0].args._index, 1); - let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2, {from: wallet_owner}); - assert.equal(scheduleCount.toNumber(), 2); + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); + assert.equal(scheduleCount, 2); - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, 1, {from: wallet_owner}); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, 1); checkSchedule(schedule, schedules[2].numberOfTokens, schedules[2].numberOfTokens, schedules[2].duration, schedules[2].frequency, schedules[2].startTime, schedules[2].startTime + schedules[2].frequency, CREATED); }); @@ -149,10 +180,57 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); - let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2, {from: wallet_owner}); - assert.equal(scheduleCount.toNumber(), 0); + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); + assert.equal(scheduleCount, 0); + }); + + it("Should add 3 Templates", async () => { + for (let i = 0; i < schedules.length; i++) { + let numberOfTokens = schedules[i].numberOfTokens; + let duration = schedules[i].duration; + let frequency = schedules[i].frequency; + const tx = await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_owner}); + + assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + assert.equal(tx.logs[0].args._duration.toNumber(), duration); + assert.equal(tx.logs[0].args._frequency.toNumber(), frequency); + } + }); + + it("Should remove first Template", async () => { + const tx = await I_VestingEscrowWallet.removeTemplate(1, {from: wallet_owner}); + + assert.equal(tx.logs[0].args._index, 1); + }); + + it("Should add Vesting Schedule from Template", async () => { + let numberOfTokens = schedules[2].numberOfTokens; + let duration = schedules[2].duration; + let frequency = schedules[2].frequency; + let startTime = schedules[2].startTime; + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_owner}); + + let log = tx.logs[0]; + checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); + assert.equal(scheduleCount, 1); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); + checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + + await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); }); + it("Should remove 2 Templates", async () => { + await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_owner}); + await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_owner}); + + let templateCount = await I_VestingEscrowWallet.getTemplateCount.call({from: wallet_owner}); + assert.equal(templateCount, 0); + }); }); @@ -160,10 +238,10 @@ contract('VestingEscrowWallet', accounts => { function checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime) { assert.equal(log.args._beneficiary, beneficiary); - assert.equal(log.args._numberOfTokens, numberOfTokens); - assert.equal(log.args._duration, duration); - assert.equal(log.args._frequency, frequency); - assert.equal(log.args._startTime, startTime); + assert.equal(log.args._numberOfTokens.toNumber(), numberOfTokens); + assert.equal(log.args._duration.toNumber(), duration); + assert.equal(log.args._frequency.toNumber(), frequency); + assert.equal(log.args._startTime.toNumber(), startTime); } function checkSchedule(schedule, numberOfTokens, lockedTokens, duration, frequency, startTime, nextTime, state) { @@ -173,7 +251,7 @@ function checkSchedule(schedule, numberOfTokens, lockedTokens, duration, frequen assert.equal(schedule[3].toNumber(), frequency); assert.equal(schedule[4].toNumber(), startTime); assert.equal(schedule[5].toNumber(), nextTime); - assert.equal(schedule[6].toNumber(), state); + assert.equal(schedule[6], state); } function getTotalNumberOfTokens(schedules) { From 12864712d7c0dd78456cc5f70ae51b41b975cf21 Mon Sep 17 00:00:00 2001 From: Polymath Date: Thu, 15 Nov 2018 17:09:22 -0300 Subject: [PATCH 109/582] Improvements over mint tokens (parseFloat for divisible tokens) --- CLI/commands/multi_mint.js | 16 +++++++++++----- CLI/data/multi_mint_data.csv | 6 +++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index b1f041115..684be6bac 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -12,6 +12,7 @@ let BATCH_SIZE = 75; let securityToken; let affiliatesFailedArray = new Array(); let affiliatesKYCInvalidArray = new Array(); +let tokenDivisible; async function startScript(tokenSymbol, batchSize) { if (batchSize) { @@ -22,6 +23,7 @@ async function startScript(tokenSymbol, batchSize) { let STAddress = await checkST(tokenSymbol); securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); + tokenDivisible = await securityToken.methods.granularity().call() == 1; await readCsv(); }; @@ -80,7 +82,7 @@ async function readCsv() { async function saveInBlockchain() { let gtmModules = await securityToken.methods.getModulesByType(3).call(); - + if (gtmModules.length > 0) { console.log("Minting of tokens is only allowed before the STO get attached"); process.exit(0); @@ -235,11 +237,15 @@ function multimint_processing(csv_line) { } function isValidToken(token) { - var tokenAmount = parseInt(token); - if ((tokenAmount % 1 == 0)) { - return tokenAmount; + var tokenAmount = parseFloat(token); + if (tokenDivisible) { + return tokenAmount + } else { + if ((tokenAmount % 1 == 0)) { + return tokenAmount; + } + return false } - return false; } module.exports = { diff --git a/CLI/data/multi_mint_data.csv b/CLI/data/multi_mint_data.csv index 0b157b164..8b27f06b0 100644 --- a/CLI/data/multi_mint_data.csv +++ b/CLI/data/multi_mint_data.csv @@ -1,8 +1,8 @@ -0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,1000 +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,123.4 0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,1000 -0xac297053173b02b02a737d47f7b4a718e5b170ef,1000 +0xac297053173b02b02a737d47f7b4a718e5b170ef,234.5 0x49fc0b78238dab644698a90fa351b4c749e123d2,1000 -0x10223927009b8add0960359dd90d1449415b7ca9,1000 +0x10223927009b8add0960359dd90d1449415b7ca9,345.6 0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,1000 0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,1000 0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,1000 From 29ed76d79a5f6a09ab99e484de53c77eb39cf113 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 16 Nov 2018 11:55:30 +0530 Subject: [PATCH 110/582] intialise --- .../libraries/BokkyPooBahsDateTimeLibrary.sol | 339 ++++++++++++++++++ .../TransferManager/VolumeRestrictionTM.sol | 7 + .../VolumeRestrictionTMFactory.sol | 68 ++++ 3 files changed, 414 insertions(+) create mode 100644 contracts/libraries/BokkyPooBahsDateTimeLibrary.sol create mode 100644 contracts/modules/TransferManager/VolumeRestrictionTM.sol create mode 100644 contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol diff --git a/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol b/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol new file mode 100644 index 000000000..2823f9993 --- /dev/null +++ b/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol @@ -0,0 +1,339 @@ +pragma solidity ^0.4.24; + +// ---------------------------------------------------------------------------- +// BokkyPooBah's DateTime Library v1.00 +// +// A gas-efficient Solidity date and time library +// +// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary +// +// Tested date range 1970/01/01 to 2345/12/31 +// +// Conventions: +// Unit | Range | Notes +// :-------- |:-------------:|:----- +// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC +// year | 1970 ... 2345 | +// month | 1 ... 12 | +// day | 1 ... 31 | +// hour | 0 ... 23 | +// minute | 0 ... 59 | +// second | 0 ... 59 | +// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday +// +// +// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018. +// +// GNU Lesser General Public License 3.0 +// https://www.gnu.org/licenses/lgpl-3.0.en.html +// ---------------------------------------------------------------------------- + +library BokkyPooBahsDateTimeLibrary { + + uint constant SECONDS_PER_DAY = 24 * 60 * 60; + uint constant SECONDS_PER_HOUR = 60 * 60; + uint constant SECONDS_PER_MINUTE = 60; + int constant OFFSET19700101 = 2440588; + + uint constant DOW_MON = 1; + uint constant DOW_TUE = 2; + uint constant DOW_WED = 3; + uint constant DOW_THU = 4; + uint constant DOW_FRI = 5; + uint constant DOW_SAT = 6; + uint constant DOW_SUN = 7; + + // ------------------------------------------------------------------------ + // Calculate the number of days from 1970/01/01 to year/month/day using + // the date conversion algorithm from + // http://aa.usno.navy.mil/faq/docs/JD_Formula.php + // and subtracting the offset 2440588 so that 1970/01/01 is day 0 + // + // days = day + // - 32075 + // + 1461 * (year + 4800 + (month - 14) / 12) / 4 + // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12 + // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4 + // - offset + // ------------------------------------------------------------------------ + function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) { + require(year >= 1970); + int _year = int(year); + int _month = int(month); + int _day = int(day); + + int __days = _day + - 32075 + + 1461 * (_year + 4800 + (_month - 14) / 12) / 4 + + 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12 + - 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4 + - OFFSET19700101; + + _days = uint(__days); + } + + // ------------------------------------------------------------------------ + // Calculate year/month/day from the number of days since 1970/01/01 using + // the date conversion algorithm from + // http://aa.usno.navy.mil/faq/docs/JD_Formula.php + // and adding the offset 2440588 so that 1970/01/01 is day 0 + // + // int L = days + 68569 + offset + // int N = 4 * L / 146097 + // L = L - (146097 * N + 3) / 4 + // year = 4000 * (L + 1) / 1461001 + // L = L - 1461 * year / 4 + 31 + // month = 80 * L / 2447 + // dd = L - 2447 * month / 80 + // L = month / 11 + // month = month + 2 - 12 * L + // year = 100 * (N - 49) + year + L + // ------------------------------------------------------------------------ + function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) { + int __days = int(_days); + + int L = __days + 68569 + OFFSET19700101; + int N = 4 * L / 146097; + L = L - (146097 * N + 3) / 4; + int _year = 4000 * (L + 1) / 1461001; + L = L - 1461 * _year / 4 + 31; + int _month = 80 * L / 2447; + int _day = L - 2447 * _month / 80; + L = _month / 11; + _month = _month + 2 - 12 * L; + _year = 100 * (N - 49) + _year + L; + + year = uint(_year); + month = uint(_month); + day = uint(_day); + } + + function timestampFromDate(uint year, uint month, uint day) internal pure returns (uint timestamp) { + timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY; + } + function timestampFromDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (uint timestamp) { + timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second; + } + function timestampToDate(uint timestamp) internal pure returns (uint year, uint month, uint day) { + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + } + function timestampToDateTime(uint timestamp) internal pure returns (uint year, uint month, uint day, uint hour, uint minute, uint second) { + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + uint secs = timestamp % SECONDS_PER_DAY; + hour = secs / SECONDS_PER_HOUR; + secs = secs % SECONDS_PER_HOUR; + minute = secs / SECONDS_PER_MINUTE; + second = secs % SECONDS_PER_MINUTE; + } + + function isValidDate(uint year, uint month, uint day) internal pure returns (bool valid) { + if (year >= 1970 && month > 0 && month <= 12) { + uint daysInMonth = _getDaysInMonth(year, month); + if (day > 0 && day <= daysInMonth) { + valid = true; + } + } + } + function isValidDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (bool valid) { + if (isValidDate(year, month, day)) { + if (hour < 24 && minute < 60 && second < 60) { + valid = true; + } + } + } + function isLeapYear(uint timestamp) internal pure returns (bool leapYear) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + leapYear = _isLeapYear(year); + } + function _isLeapYear(uint year) internal pure returns (bool leapYear) { + leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); + } + function isWeekDay(uint timestamp) internal pure returns (bool weekDay) { + weekDay = getDayOfWeek(timestamp) <= DOW_FRI; + } + function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) { + weekEnd = getDayOfWeek(timestamp) >= DOW_SAT; + } + function getDaysInMonth(uint timestamp) internal pure returns (uint daysInMonth) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + daysInMonth = _getDaysInMonth(year, month); + } + function _getDaysInMonth(uint year, uint month) internal pure returns (uint daysInMonth) { + if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { + daysInMonth = 31; + } else if (month != 2) { + daysInMonth = 30; + } else { + daysInMonth = _isLeapYear(year) ? 29 : 28; + } + } + // 1 = Monday, 7 = Sunday + function getDayOfWeek(uint timestamp) internal pure returns (uint dayOfWeek) { + uint _days = timestamp / SECONDS_PER_DAY; + dayOfWeek = (_days + 3) % 7 + 1; + } + + function getYear(uint timestamp) internal pure returns (uint year) { + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + } + function getMonth(uint timestamp) internal pure returns (uint month) { + uint year; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + } + function getDay(uint timestamp) internal pure returns (uint day) { + uint year; + uint month; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + } + function getHour(uint timestamp) internal pure returns (uint hour) { + uint secs = timestamp % SECONDS_PER_DAY; + hour = secs / SECONDS_PER_HOUR; + } + function getMinute(uint timestamp) internal pure returns (uint minute) { + uint secs = timestamp % SECONDS_PER_HOUR; + minute = secs / SECONDS_PER_MINUTE; + } + function getSecond(uint timestamp) internal pure returns (uint second) { + second = timestamp % SECONDS_PER_MINUTE; + } + + function addYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + year += _years; + uint daysInMonth = _getDaysInMonth(year, month); + if (day > daysInMonth) { + day = daysInMonth; + } + newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; + require(newTimestamp >= timestamp); + } + function addMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + month += _months; + year += (month - 1) / 12; + month = (month - 1) % 12 + 1; + uint daysInMonth = _getDaysInMonth(year, month); + if (day > daysInMonth) { + day = daysInMonth; + } + newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; + require(newTimestamp >= timestamp); + } + function addDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp + _days * SECONDS_PER_DAY; + require(newTimestamp >= timestamp); + } + function addHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp + _hours * SECONDS_PER_HOUR; + require(newTimestamp >= timestamp); + } + function addMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE; + require(newTimestamp >= timestamp); + } + function addSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp + _seconds; + require(newTimestamp >= timestamp); + } + + function subYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + year -= _years; + uint daysInMonth = _getDaysInMonth(year, month); + if (day > daysInMonth) { + day = daysInMonth; + } + newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; + require(newTimestamp <= timestamp); + } + function subMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + uint yearMonth = year * 12 + (month - 1) - _months; + year = yearMonth / 12; + month = yearMonth % 12 + 1; + uint daysInMonth = _getDaysInMonth(year, month); + if (day > daysInMonth) { + day = daysInMonth; + } + newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; + require(newTimestamp <= timestamp); + } + function subDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp - _days * SECONDS_PER_DAY; + require(newTimestamp <= timestamp); + } + function subHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp - _hours * SECONDS_PER_HOUR; + require(newTimestamp <= timestamp); + } + function subMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE; + require(newTimestamp <= timestamp); + } + function subSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp - _seconds; + require(newTimestamp <= timestamp); + } + + function diffYears(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _years) { + require(fromTimestamp <= toTimestamp); + uint fromYear; + uint fromMonth; + uint fromDay; + uint toYear; + uint toMonth; + uint toDay; + (fromYear, fromMonth, fromDay) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); + (toYear, toMonth, toDay) = _daysToDate(toTimestamp / SECONDS_PER_DAY); + _years = toYear - fromYear; + } + function diffMonths(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _months) { + require(fromTimestamp <= toTimestamp); + uint fromYear; + uint fromMonth; + uint fromDay; + uint toYear; + uint toMonth; + uint toDay; + (fromYear, fromMonth, fromDay) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); + (toYear, toMonth, toDay) = _daysToDate(toTimestamp / SECONDS_PER_DAY); + _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth; + } + function diffDays(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _days) { + require(fromTimestamp <= toTimestamp); + _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY; + } + function diffHours(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _hours) { + require(fromTimestamp <= toTimestamp); + _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR; + } + function diffMinutes(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _minutes) { + require(fromTimestamp <= toTimestamp); + _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE; + } + function diffSeconds(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _seconds) { + require(fromTimestamp <= toTimestamp); + _seconds = toTimestamp - fromTimestamp; + } +} \ No newline at end of file diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol new file mode 100644 index 000000000..c1c088d29 --- /dev/null +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.4.24; + +import "./ITransferManager.sol"; + +contract VolumeRestrictionTM is ITransferManager { + +} diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol new file mode 100644 index 000000000..b1b799c26 --- /dev/null +++ b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol @@ -0,0 +1,68 @@ +pragma solidity ^0.4.24; + +import "./VolumeRestrictionTM.sol"; +import "../ModuleFactory.sol"; + +/** + * @title Factory for deploying VolumeRestrictionTM module + */ +contract VolumeRestrictionTMFactory is ModuleFactory { + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "VolumeRestrictionTM"; + title = "Volume Restriction Transfer Manager"; + description = "Manage transfers based on the volume of tokens that transact"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + } + + + /** + * @notice Used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes /* _data */) external returns(address) { + if (setupCost > 0) + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Sufficent Allowance is not provided"); + address VolumeRestrictionTransferManager = new VolumeRestrictionTM(msg.sender, address(polyToken)); + /*solium-disable-next-line security/no-block-members*/ + emit GenerateModuleFromFactory(address(VolumeRestrictionTransferManager), getName(), address(this), msg.sender, setupCost, now); + return address(VolumeRestrictionTransferManager); + } + + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 2; + return res; + } + + /** + * @notice Returns the instructions associated with the module + */ + function getInstructions() external view returns(string) { + /*solium-disable-next-line max-len*/ + return ""; /// TODO - need to add the Instruction for module + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() public view returns(bytes32[]) { + bytes32[] memory availableTags = new bytes32[](2); + availableTags[0] = "Maximum Volume"; + availableTags[1] = "Transfer Restriction"; + availableTags[2] = "Daily Restriction"; + return availableTags; + } + +} \ No newline at end of file From b847f54cb7aab35860723407a41fecbc75641a5a Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 16 Nov 2018 12:30:39 +0530 Subject: [PATCH 111/582] minor fixes --- .../LockupVolumeRestrictionTM.sol | 177 ++++++++++++------ 1 file changed, 117 insertions(+), 60 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index 5c7183ee2..c9cdb3d8a 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -93,20 +93,13 @@ contract LockupVolumeRestrictionTM is ITransferManager { public withPerm(ADMIN) { - /*solium-disable-next-line security/no-block-members*/ - require(_startTime >= now, "start time is in past"); - _checkLockUpParams(_userAddress, _lockupAmount, _lockUpPeriodSeconds, _releaseFrequencySeconds); - - lockUps[_userAddress].push(LockUp(_lockupAmount, _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds)); - - emit AddNewLockUp( + _addLockUp( _userAddress, _lockupAmount, _startTime, _lockUpPeriodSeconds, - _releaseFrequencySeconds, - lockUps[_userAddress].length -1 - ); + _releaseFrequencySeconds + ); } /** @@ -136,7 +129,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { ); for (uint256 i = 0; i < _userAddresses.length; i++) { - addLockUp(_userAddresses[i], _lockupAmounts[i], _startTimes[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i]); + _addLockUp(_userAddresses[i], _lockupAmounts[i], _startTimes[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i]); } } @@ -147,21 +140,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { * @param _lockupIndex Index of the lockup need to be removed. */ function removeLockUp(address _userAddress, uint256 _lockupIndex) public withPerm(ADMIN) { - require(lockUps[_userAddress].length > _lockupIndex, "Invalid index"); - LockUp[] storage userLockup = lockUps[_userAddress]; - - emit RemoveLockUp( - _userAddress, - _lockupIndex - ); - - if (_lockupIndex != userLockup.length - 1) { - // move the last element in the array into the index that is desired to be removed. - userLockup[_lockupIndex] = userLockup[userLockup.length - 1]; - /*solium-disable-next-line security/no-block-members*/ - emit ChangeLockupIndex(_userAddress, userLockup.length - 1, _lockupIndex, now); - } - userLockup.length--; + _removeLockUp(_userAddress, _lockupIndex); } /** @@ -172,7 +151,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { function removeLockUpMulti(address[] _userAddresses, uint256[] _lockupIndexes) external withPerm(ADMIN) { require(_userAddresses.length == _lockupIndexes.length, "Array length mismatch"); for (uint256 i = 0; i < _userAddresses.length; i++) { - removeLockUp(_userAddresses[i], _lockupIndexes[i]); + _removeLockUp(_userAddresses[i], _lockupIndexes[i]); } } @@ -196,33 +175,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { public withPerm(ADMIN) { - require(lockUps[_userAddress].length > _lockupIndex, "Invalid index"); - - // Get the lockup from the master list and edit it - LockUp[] storage userLockup = lockUps[_userAddress]; - // If _startTime is equal to the previous startTime then it only allow to modify - // when there is no tokens gets unlocked from the lockup - if (_startTime == userLockup[_lockupIndex].startTime) { - require(_getUnlockedAmountForLockup(userLockup, _lockupIndex) == uint256(0)); - } else { - /*solium-disable-next-line security/no-block-members*/ - require(_startTime >= now, "start time is in past"); - } - _checkLockUpParams( - _userAddress, - _lockupAmount, - _lockUpPeriodSeconds, - _releaseFrequencySeconds - ); - - userLockup[_lockupIndex] = LockUp( - _lockupAmount, - _startTime, - _lockUpPeriodSeconds, - _releaseFrequencySeconds - ); - - emit ModifyLockUp( + _modifyLockUp( _userAddress, _lockupAmount, _startTime, @@ -258,7 +211,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { "Input array length mismatch" ); for (uint256 i = 0; i < _userAddresses.length; i++) { - modifyLockUp( + _modifyLockUp( _userAddresses[i], _lockupAmounts[i], _startTimes[i], @@ -301,11 +254,12 @@ contract LockupVolumeRestrictionTM is ITransferManager { } /** - * @notice Checks whether the transfer is allowed - * @param _userAddress Address of the user whose lock ups should be checked - * @param _amount Amount of tokens that need to transact + * @notice Use to get the total locked tokens for a given user + * @param _userAddress Address of the user + * @return uint256 Total locked tokens amount */ - function _checkIfValidTransfer(address _userAddress, uint256 _amount) internal view returns (Result) { + function getLockedTokenToUser(address _userAddress) public view returns(uint256) { + require(_userAddress != address(0), "Invalid address"); LockUp[] memory userLockup = lockUps[_userAddress]; uint256 totalRemainingLockedAmount = 0; for (uint256 i = 0; i < userLockup.length; i++) { @@ -314,10 +268,109 @@ contract LockupVolumeRestrictionTM is ITransferManager { // aggregating all the remaining locked amount for all the lockups for a given address totalRemainingLockedAmount = totalRemainingLockedAmount.add(remainingLockedAmount); } + return totalRemainingLockedAmount; + } + + function _modifyLockUp( + address _userAddress, + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + uint256 _lockupIndex + ) + internal + { + require(lockUps[_userAddress].length > _lockupIndex, "Invalid index"); + + // Get the lockup from the master list and edit it + LockUp[] storage userLockup = lockUps[_userAddress]; + // If _startTime is equal to the previous startTime then it only allow to modify + // when there is no tokens gets unlocked from the lockup + if (_startTime == userLockup[_lockupIndex].startTime) { + require(_getUnlockedAmountForLockup(userLockup, _lockupIndex) == uint256(0)); + } else { + /*solium-disable-next-line security/no-block-members*/ + require(_startTime >= now, "start time is in past"); + } + _checkLockUpParams( + _userAddress, + _lockupAmount, + _lockUpPeriodSeconds, + _releaseFrequencySeconds + ); + + userLockup[_lockupIndex] = LockUp( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds + ); + + emit ModifyLockUp( + _userAddress, + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupIndex + ); + } + + function _removeLockUp(address _userAddress, uint256 _lockupIndex) internal { + require(lockUps[_userAddress].length > _lockupIndex, "Invalid index"); + LockUp[] storage userLockup = lockUps[_userAddress]; + + emit RemoveLockUp( + _userAddress, + _lockupIndex + ); + + if (_lockupIndex != userLockup.length - 1) { + // move the last element in the array into the index that is desired to be removed. + userLockup[_lockupIndex] = userLockup[userLockup.length - 1]; + /*solium-disable-next-line security/no-block-members*/ + emit ChangeLockupIndex(_userAddress, userLockup.length - 1, _lockupIndex, now); + } + userLockup.length--; + } + + function _addLockUp( + address _userAddress, + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds + ) + internal + { + /*solium-disable-next-line security/no-block-members*/ + require(_startTime >= now, "start time is in past"); + _checkLockUpParams(_userAddress, _lockupAmount, _lockUpPeriodSeconds, _releaseFrequencySeconds); + + lockUps[_userAddress].push(LockUp(_lockupAmount, _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds)); + + emit AddNewLockUp( + _userAddress, + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + lockUps[_userAddress].length -1 + ); + } + + /** + * @notice Checks whether the transfer is allowed + * @param _userAddress Address of the user whose lock ups should be checked + * @param _amount Amount of tokens that need to transact + */ + function _checkIfValidTransfer(address _userAddress, uint256 _amount) internal view returns (Result) { + uint256 totalRemainingLockedAmount = getLockedTokenToUser(_userAddress); // Present balance of the user uint256 currentBalance = ISecurityToken(securityToken).balanceOf(_userAddress); if ((currentBalance.sub(_amount)) >= totalRemainingLockedAmount) { - return Result.VALID; + return Result.NA; } return Result.INVALID; } @@ -380,6 +433,10 @@ contract LockupVolumeRestrictionTM is ITransferManager { // make sure the amount to be released per period is not too granular for the token uint256 totalPeriods = _lockUpPeriodSeconds.div(_releaseFrequencySeconds); uint256 amountPerPeriod = _lockupAmount.div(totalPeriods); + require( + amountPerPeriod.mul(totalPeriods) == _lockupAmount, + "lockup amount should be completely divisible by the amount per period" + ); require( amountPerPeriod % ISecurityToken(securityToken).granularity() == 0, "The amount to be released per period is more granular than allowed by the token" From 8a91610be7b69ae3d0865c57aec5e42994f23445 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Fri, 16 Nov 2018 09:42:44 +0000 Subject: [PATCH 112/582] Update changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9ffcb644..e5293b1fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. * Added `getSTODetails` to USDTSTO. * Added an Array of Tiers that will hold data about every tier in USDTSTO. * Added `buyWithETHRateLimited`, `buyWithPOLYRateLimited` and `buyWithUSDRateLimited` to USDTSTO. +* Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier. ##Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. @@ -63,7 +64,7 @@ All notable changes to this project will be documented in this file. ====== -# v1.4.1 +# v1.4.1 [__1.4.1__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-08-18__ @@ -87,7 +88,7 @@ All notable changes to this project will be documented in this file. * Fix #238: make beneficial investments optionally supported (default to not allowed) -# v1.4.0 +# v1.4.0 [__1.4.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-08-18__ From 53fcaac757b44ab19207bd773a1ef3f5a69b007d Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Fri, 16 Nov 2018 09:43:05 +0000 Subject: [PATCH 113/582] Typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5293b1fc..a99b5f767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file. * Added `getSTODetails` to USDTSTO. * Added an Array of Tiers that will hold data about every tier in USDTSTO. * Added `buyWithETHRateLimited`, `buyWithPOLYRateLimited` and `buyWithUSDRateLimited` to USDTSTO. -* Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier. +* Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. ##Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. From 8adb72d6890dfe3f8f57b9b2f30021c29a6095a4 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 16 Nov 2018 18:29:52 +0530 Subject: [PATCH 114/582] function declaration --- .../TransferManager/VolumeRestrictionTM.sol | 136 ++++++++++++++++++ .../VolumeRestrictionTMFactory.sol | 2 +- .../TransferManager/VolumeRestrictionTM.sol | 7 - 3 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol rename contracts/modules/{ => Experimental}/TransferManager/VolumeRestrictionTMFactory.sol (98%) delete mode 100644 contracts/modules/TransferManager/VolumeRestrictionTM.sol diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol new file mode 100644 index 000000000..a4096b0a0 --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -0,0 +1,136 @@ +pragma solidity ^0.4.24; + +import "../../TransferManager/ITransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../../../libraries/BokkyPooBahsDateTimeLibrary.sol"; + +contract VolumeRestrictionTM is ITransferManager { + + using SafeMath for uint256; + + enum RestrictionType { Global, Individual } + enum TokenType { Fixed, Variable} + + struct VolumeRestriction { + uint256 allowedTokens; + uint256 startTime; + uint256 rollingPeriodInDays; + uint256 endTime; + } + + VolumeRestriction fixedGlobalRestriction; + VolumeRestriction variableGlobalRestriction; + + mapping(address => VolumeRestriction[]) internal fixedIndividualRestriction; + mapping(address => VolumeRestriciton[]) internal variableIndividualRestriction; + mapping(address => mapping(uint256 => )) + + mapping(address => bool) public exemptList; + + event ExemptWalletListChanged(address _wallet, bool _change); + + function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { + + } + + function addFixedIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime + ) + public + withPerm(ADMIN) + { + + } + + function addVariableIndividualRestriction( + address _holder, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime + ) + public + withPerm(ADMIN) + { + + } + + function addFixedGlobalRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime + ) + public + withPerm(ADMIN) + { + + } + + function addVariableGlobalRestriciton( + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime + ) + public + withPerm(ADMIN) + { + + } + + function modifyFixedIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime + ) + public + withPerm(ADMIN) + { + + } + + function modifyVariableIndividualRestriction( + address _holder, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime + ) + public + withPerm(ADMIN) + { + + } + + function modifyFixedGlobalRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime + ) + public + withPerm(ADMIN) + { + + } + + function modifyVariableGlobalRestriciton( + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime + ) + public + withPerm(ADMIN) + { + + } + +} diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol similarity index 98% rename from contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol rename to contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol index b1b799c26..0c1821b17 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "./VolumeRestrictionTM.sol"; -import "../ModuleFactory.sol"; +import "../../ModuleFactory.sol"; /** * @title Factory for deploying VolumeRestrictionTM module diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol deleted file mode 100644 index c1c088d29..000000000 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.4.24; - -import "./ITransferManager.sol"; - -contract VolumeRestrictionTM is ITransferManager { - -} From d28ef32a531b38f23417e59e249558d8a9a8fdb9 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 16 Nov 2018 18:33:09 +0530 Subject: [PATCH 115/582] change to external --- .../TransferManager/LockupVolumeRestrictionTM.sol | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index c9cdb3d8a..9753486ec 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -90,7 +90,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { uint256 _lockUpPeriodSeconds, uint256 _releaseFrequencySeconds ) - public + external withPerm(ADMIN) { _addLockUp( @@ -139,7 +139,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { * @param _userAddress Address of the user whose tokens are locked up * @param _lockupIndex Index of the lockup need to be removed. */ - function removeLockUp(address _userAddress, uint256 _lockupIndex) public withPerm(ADMIN) { + function removeLockUp(address _userAddress, uint256 _lockupIndex) external withPerm(ADMIN) { _removeLockUp(_userAddress, _lockupIndex); } @@ -172,7 +172,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { uint256 _releaseFrequencySeconds, uint256 _lockupIndex ) - public + external withPerm(ADMIN) { _modifyLockUp( @@ -201,7 +201,10 @@ contract LockupVolumeRestrictionTM is ITransferManager { uint256[] _lockUpPeriodsSeconds, uint256[] _releaseFrequenciesSeconds, uint256[] _lockupIndexes - ) public withPerm(ADMIN) { + ) + external + withPerm(ADMIN) + { require( _userAddresses.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ _userAddresses.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ From 59c422650c1765f8472a1a5047a1481bb7128c57 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 16 Nov 2018 15:28:46 +0200 Subject: [PATCH 116/582] tests for depositing and withdrawing tokens --- contracts/wallet/VestingEscrowWallet.sol | 2 +- test/z_vesting_escrow_wallet.js | 50 +++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 14fd8e272..a88aa9dab 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -122,7 +122,7 @@ contract VestingEscrowWallet is Ownable { emit RemoveTemplate(_index, now); } - function getTemplateCount() external onlyOwner returns(uint256) { + function getTemplateCount() external view onlyOwner returns(uint256) { return templates.length; } diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 281b9b9b2..1f94b63c4 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -57,6 +57,54 @@ contract('VestingEscrowWallet', accounts => { `); }); + describe("Depositing and withdrawing tokens", async () => { + + it("Should deposit tokens for new Vesting Schedules", async () => { + let numberOfTokens = 25000; + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); + const tx = await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); + + assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); + + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + assert.equal(unassignedTokens, numberOfTokens); + + let balance = await I_PolyToken.balanceOf.call(I_VestingEscrowWallet.address); + assert.equal(balance.toNumber(), numberOfTokens); + }); + + it("Should withdraw tokens to a treasury", async () => { + let numberOfTokens = 25000; + const tx = await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + + assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); + + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + assert.equal(unassignedTokens, 0); + + let balance = await I_PolyToken.balanceOf.call(I_VestingEscrowWallet.address); + assert.equal(balance.toNumber(), 0); + }); + + it("Should send tokens to the third beneficiary address", async () => { + let numberOfTokens = 75000; + let duration = durationUtil.seconds(3); + let frequency = durationUtil.seconds(1); + let startTime = latestTime() + durationUtil.seconds(10); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + + const tx = await I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: wallet_owner}); + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens / 3); + + let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toNumber(), numberOfTokens / 3); + }); + + }); + describe("Adding, Editing and Revoking Vesting Schedule", async () => { let schedules = [ @@ -116,7 +164,7 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); - assert.equal(unassignedTokens, schedules[0].numberOfTokens - schedules[1].numberOfTokens); + assert.equal(unassignedTokens.toNumber(), schedules[0].numberOfTokens - schedules[1].numberOfTokens); }); it("Should fail edit Vesting Schedule to the first beneficiary address", async () => { From d4d35e5def725926bf5667980b4c053bcbcdd2ed Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 16 Nov 2018 19:32:33 +0530 Subject: [PATCH 117/582] stack too deep erro fix --- .../Experimental/TransferManager/LockupVolumeRestrictionTM.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index 9753486ec..887f78d3a 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -202,7 +202,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { uint256[] _releaseFrequenciesSeconds, uint256[] _lockupIndexes ) - external + public withPerm(ADMIN) { require( From fb9b15ee5046d13dee9e8f677c5a2ad7af6a1668 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 16 Nov 2018 19:38:53 +0200 Subject: [PATCH 118/582] fixed depositing/withdrawing tests --- contracts/wallet/VestingEscrowWallet.sol | 10 +++- test/z_vesting_escrow_wallet.js | 62 +++++++++++++++++++----- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index a88aa9dab..0603fa600 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -94,12 +94,10 @@ contract VestingEscrowWallet is Ownable { } function sendAvailableTokens(address _beneficiary) public onlyOwner { - _update(_beneficiary); _sendTokens(_beneficiary); } function withdrawAvailableTokens() external { - _update(msg.sender); _sendTokens(msg.sender); } @@ -320,6 +318,10 @@ contract VestingEscrowWallet is Ownable { emit SendTokens(_beneficiary, amount, now); } + function update(address _beneficiary) external onlyOwner { + _update(_beneficiary); + } + function _update(address _beneficiary) private { Data storage data = dataMap[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { @@ -340,6 +342,10 @@ contract VestingEscrowWallet is Ownable { } } + function updateAll() external onlyOwner { + _updateAll(); + } + function _updateAll() private { for (uint256 i = 0; i < beneficiaries.length; i++) { _update(beneficiaries[i]); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 1f94b63c4..741d06a92 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -2,6 +2,7 @@ import {deployPolyRegistryAndPolyToken, deployVestingEscrowWallet} from "./helpe import latestTime from "./helpers/latestTime"; import {duration as durationUtil} from "./helpers/utils"; import {catchRevert} from "./helpers/exceptions"; +import {increaseTime} from "./helpers/time"; const VestingEscrowWallet = artifacts.require('./VestingEscrowWallet.sol'); @@ -9,6 +10,9 @@ const Web3 = require('web3'); const BigNumber = require('bignumber.js'); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));// Hardcoded development port +//TODO check withdraw with 3 schedules and few passed steps for beneficiary +//TODO tests for batch operations +//TODO negative cases contract('VestingEscrowWallet', accounts => { const CREATED = 0; @@ -86,14 +90,17 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), 0); }); - it("Should send tokens to the third beneficiary address", async () => { + it("Should send available tokens to the beneficiary address", async () => { let numberOfTokens = 75000; - let duration = durationUtil.seconds(3); - let frequency = durationUtil.seconds(1); - let startTime = latestTime() + durationUtil.seconds(10); + let duration = durationUtil.seconds(30); + let frequency = durationUtil.seconds(10); + let timeShift = durationUtil.seconds(100); + let startTime = latestTime() + timeShift; await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + await increaseTime(timeShift + frequency); + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); const tx = await I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: wallet_owner}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); @@ -101,6 +108,37 @@ contract('VestingEscrowWallet', accounts => { let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens / 3); + + await I_PolyToken.transfer(account_treasury, balance, {from: account_beneficiary3}); + await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_owner}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + }); + + it("Should withdraw available tokens to the beneficiary address", async () => { + let numberOfTokens = 33000; + let duration = durationUtil.seconds(30); + let frequency = durationUtil.seconds(10); + let timeShift = durationUtil.seconds(100); + let startTime = latestTime() + timeShift; + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + await increaseTime(timeShift + frequency * 3); + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + + const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + + let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toNumber(), numberOfTokens); + + await I_PolyToken.transfer(account_treasury, balance, {from: account_beneficiary3}); + await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_owner}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); }); }); @@ -128,7 +166,7 @@ contract('VestingEscrowWallet', accounts => { } ]; - it("Should add Vesting Schedule to the first beneficiary address", async () => { + it("Should add Vesting Schedule to the beneficiary address", async () => { let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; @@ -147,7 +185,7 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); }); - it("Should edit Vesting Schedule to the first beneficiary address", async () => { + it("Should edit Vesting Schedule to the beneficiary address", async () => { let numberOfTokens = schedules[1].numberOfTokens; let duration = schedules[1].duration; let frequency = schedules[1].frequency; @@ -167,7 +205,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(unassignedTokens.toNumber(), schedules[0].numberOfTokens - schedules[1].numberOfTokens); }); - it("Should fail edit Vesting Schedule to the first beneficiary address", async () => { + it("Should fail edit Vesting Schedule to the beneficiary address", async () => { let numberOfTokens = schedules[0].numberOfTokens + schedules[1].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; @@ -177,7 +215,7 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should revoke Vesting Schedule from the first beneficiary address", async () => { + it("Should revoke Vesting Schedule from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); @@ -187,7 +225,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 0); }); - it("Should add 3 Vesting Schedules to the second beneficiary address", async () => { + it("Should add 3 Vesting Schedules to the beneficiary address", async () => { let totalNumberOfTokens = getTotalNumberOfTokens(schedules); await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); @@ -209,7 +247,7 @@ contract('VestingEscrowWallet', accounts => { } }); - it("Should revoke Vesting Schedule from the second beneficiary address", async () => { + it("Should revoke Vesting Schedule from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, 1, {from: wallet_owner}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); @@ -223,7 +261,7 @@ contract('VestingEscrowWallet', accounts => { schedules[2].startTime, schedules[2].startTime + schedules[2].frequency, CREATED); }); - it("Should revoke 2 Vesting Schedules from the second beneficiary address", async () => { + it("Should revoke 2 Vesting Schedules from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedules(account_beneficiary2, {from: wallet_owner}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); @@ -245,7 +283,7 @@ contract('VestingEscrowWallet', accounts => { } }); - it("Should remove first Template", async () => { + it("Should remove template", async () => { const tx = await I_VestingEscrowWallet.removeTemplate(1, {from: wallet_owner}); assert.equal(tx.logs[0].args._index, 1); From e3b9bb3871191c31c98da2b4d336d9defb690ee5 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 19 Nov 2018 10:42:58 +0200 Subject: [PATCH 119/582] docs for public, external functions --- contracts/wallet/VestingEscrowWallet.sol | 115 ++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/wallet/VestingEscrowWallet.sol index 0603fa600..8c5d025e2 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/wallet/VestingEscrowWallet.sol @@ -8,7 +8,6 @@ import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; /** * @title Wallet for core vesting escrow functionality */ -//TODO add docs for public, external methods contract VestingEscrowWallet is Ownable { using SafeMath for uint256; using SafeERC20 for ERC20; @@ -77,6 +76,9 @@ contract VestingEscrowWallet is Ownable { treasury = _treasury; } + /** + * @notice Used to deposit tokens from treasury + */ function depositTokens(uint256 _numberOfTokens) external onlyOwner { require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); token.safeTransferFrom(treasury, this, _numberOfTokens); @@ -85,6 +87,9 @@ contract VestingEscrowWallet is Ownable { emit DepositTokens(_numberOfTokens, now); } + /** + * @notice Sends unassigned tokens to treasury + */ function sendToTreasury() external onlyOwner { uint256 amount = unassignedTokens; unassignedTokens = 0; @@ -93,14 +98,27 @@ contract VestingEscrowWallet is Ownable { emit SendToTreasury(amount, now); } + /** + * @notice Sends available tokens to beneficiary + * @param _beneficiary beneficiary's address + */ function sendAvailableTokens(address _beneficiary) public onlyOwner { _sendTokens(_beneficiary); } + /** + * @notice Used to withdraw available tokens by beneficiary + */ function withdrawAvailableTokens() external { _sendTokens(msg.sender); } + /** + * @notice Add template + * @param _numberOfTokens number of tokens + * @param _duration vesting duration + * @param _frequency vesting frequency + */ function addTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) external onlyOwner { _validateTemplate(_numberOfTokens, _duration, _frequency); Template memory template; @@ -112,6 +130,10 @@ contract VestingEscrowWallet is Ownable { emit AddTemplate(_numberOfTokens, _duration, _frequency, now); } + /** + * @notice Removes template + * @param _index index of the template + */ function removeTemplate(uint256 _index) external onlyOwner { require(_index < templates.length, "Template not found"); templates[_index] = templates[templates.length - 1]; @@ -120,10 +142,22 @@ contract VestingEscrowWallet is Ownable { emit RemoveTemplate(_index, now); } + /** + * @notice Returns count of templates + * @return count of templates + */ function getTemplateCount() external view onlyOwner returns(uint256) { return templates.length; } + /** + * @notice Adds vesting schedules for each of beneficiary + * @param _beneficiary beneficiary's addresses + * @param _numberOfTokens number of tokens + * @param _duration vesting duration + * @param _frequency vesting frequency + * @param _startTime vesting start time + */ function addSchedule( address _beneficiary, uint256 _numberOfTokens, @@ -156,12 +190,27 @@ contract VestingEscrowWallet is Ownable { emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime, now); } + /** + * @notice Adds vesting schedules from template for each of beneficiary + * @param _beneficiary beneficiary's addresses + * @param _index index of the template + * @param _startTime vesting start time + */ function addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) public onlyOwner { require(_index < templates.length, "Template not found"); Template storage template = templates[_index]; addSchedule(_beneficiary, template.numberOfTokens, template.duration, template.frequency, _startTime); } + /** + * @notice Edits vesting schedules for each of beneficiary + * @param _beneficiary beneficiary's addresses + * @param _index index of schedule + * @param _numberOfTokens number of tokens + * @param _duration vesting duration + * @param _frequency vesting frequency + * @param _startTime vesting start time + */ function editSchedule( address _beneficiary, uint256 _index, @@ -193,6 +242,11 @@ contract VestingEscrowWallet is Ownable { emit EditSchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime, now); } + /** + * @notice Revokes beneficiary's schedule + * @param _beneficiary beneficiary's address + * @param _index index of the schedule + */ function revokeSchedule(address _beneficiary, uint256 _index) external onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); @@ -207,6 +261,11 @@ contract VestingEscrowWallet is Ownable { emit RevokeSchedule(_beneficiary, _index, now); } + + /** + * @notice Revokes all beneficiary's schedules + * @param _beneficiary beneficiary's address + */ function revokeSchedules(address _beneficiary) public onlyOwner { require(_beneficiary != address(0), "Invalid beneficiary address"); Data storage data = dataMap[_beneficiary]; @@ -219,6 +278,12 @@ contract VestingEscrowWallet is Ownable { emit RevokeSchedules(_beneficiary, now); } + /** + * @notice Returns beneficiary's schedule + * @param _beneficiary beneficiary's address + * @param _index index of the schedule + * @return beneficiary's schedule + */ function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256, uint256, uint256, State) { require(_beneficiary != address(0), "Invalid beneficiary address"); require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); @@ -234,22 +299,44 @@ contract VestingEscrowWallet is Ownable { ); } + /** + * @notice Returns count of beneficiary's schedules + * @param _beneficiary beneficiary's address + * @return count of beneficiary's schedules + */ function getScheduleCount(address _beneficiary) external view returns(uint256) { require(_beneficiary != address(0), "Invalid beneficiary address"); return dataMap[_beneficiary].schedules.length; } + /** + * @notice Returns available tokens for beneficiary + * @param _beneficiary beneficiary's address + * @return available tokens for beneficiary + */ function getAvailableTokens(address _beneficiary) external view returns(uint256) { require(_beneficiary != address(0), "Invalid beneficiary address"); return dataMap[_beneficiary].availableTokens; } + /** + * @notice Used to bulk send available tokens for each of beneficiaries + * @param _beneficiaries array of beneficiary's addresses + */ function batchSendAvailableTokens(address[] _beneficiaries) external onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { sendAvailableTokens(_beneficiaries[i]); } } + /** + * @notice Used to bulk add vesting schedules for each of beneficiaries + * @param _beneficiaries array of beneficiary's addresses + * @param _numberOfTokens number of tokens + * @param _duration vesting duration + * @param _frequency vesting frequency + * @param _startTime vesting start time + */ function batchAddSchedule( address[] _beneficiaries, uint256 _numberOfTokens, @@ -265,18 +352,37 @@ contract VestingEscrowWallet is Ownable { } } + /** + * @notice Used to bulk add vesting schedules from template for each of beneficiaries + * @param _beneficiaries array of beneficiary's addresses + * @param _index index of the template + * @param _startTime vesting start time + */ function batchAddScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startTime) public onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { addScheduleFromTemplate(_beneficiaries[i], _index, _startTime); } } + /** + * @notice Used to bulk revoke vesting schedules for each of beneficiaries + * @param _beneficiaries array of beneficiary's addresses + */ function batchRevokeSchedules(address[] _beneficiaries) external onlyOwner { for (uint256 i = 0; i < _beneficiaries.length; i++) { revokeSchedules(_beneficiaries[i]); } } + /** + * @notice Used to bulk edit vesting schedules for each of beneficiaries + * @param _beneficiaries array of beneficiary's addresses + * @param _indexes array of beneficiary's indexes of schedule + * @param _numberOfTokens number of tokens + * @param _duration vesting duration + * @param _frequency vesting frequency + * @param _startTime vesting start time + */ function batchEditSchedule( address[] _beneficiaries, uint256[] _indexes, @@ -318,6 +424,10 @@ contract VestingEscrowWallet is Ownable { emit SendTokens(_beneficiary, amount, now); } + /** + * @notice manually triggers update outside for beneficiary's schedule (can be used to reduce user gas costs) + * @param _beneficiary beneficiary's address of the schedule + */ function update(address _beneficiary) external onlyOwner { _update(_beneficiary); } @@ -342,6 +452,9 @@ contract VestingEscrowWallet is Ownable { } } + /** + * @notice manually triggers update outside for all schedules (can be used to reduce user gas costs) + */ function updateAll() external onlyOwner { _updateAll(); } From af8297bd700cd65f178b22e692fdc16f99e894e9 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 19 Nov 2018 11:42:40 +0200 Subject: [PATCH 120/582] check withdraw with 3 schedules --- test/z_vesting_escrow_wallet.js | 55 ++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 741d06a92..ea0c88b45 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -10,7 +10,6 @@ const Web3 = require('web3'); const BigNumber = require('bignumber.js'); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));// Hardcoded development port -//TODO check withdraw with 3 schedules and few passed steps for beneficiary //TODO tests for batch operations //TODO negative cases contract('VestingEscrowWallet', accounts => { @@ -124,11 +123,57 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); await increaseTime(timeShift + frequency * 3); - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + for (let i = 0; i < 4; i++) { + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + } + + const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toNumber(), numberOfTokens); + + await I_PolyToken.transfer(account_treasury, balance, {from: account_beneficiary3}); + await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_owner}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + }); + + it("Should withdraw available tokens by 3 schedules to the beneficiary address", async () => { + let schedules = [ + { + numberOfTokens: 100000, + duration: durationUtil.seconds(4), + frequency: durationUtil.seconds(1) + }, + { + numberOfTokens: 30000, + duration: durationUtil.seconds(6), + frequency: durationUtil.seconds(1) + }, + { + numberOfTokens: 2000, + duration: durationUtil.seconds(10), + frequency: durationUtil.seconds(1) + } + ]; + + let totalNumberOfTokens = getTotalNumberOfTokens(schedules); + await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); + for (let i = 0; i < schedules.length; i++) { + let numberOfTokens = schedules[i].numberOfTokens; + let duration = schedules[i].duration; + let frequency = schedules[i].frequency; + let startTime = latestTime() + durationUtil.seconds(100); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + } + await increaseTime(durationUtil.minutes(5)); + let stepCount = 4; + for (let i = 0; i < stepCount; i++) { + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + } + let numberOfTokens = 100000 + (30000 / 6 * stepCount) + (2000 / 10 * stepCount); const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); From e9b0566697963fcd17b5f92ab79473906f67c40e Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 19 Nov 2018 14:49:06 +0200 Subject: [PATCH 121/582] Tests for batch operations --- test/z_vesting_escrow_wallet.js | 146 ++++++++++++++++++++++++++++++-- 1 file changed, 141 insertions(+), 5 deletions(-) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index ea0c88b45..64eae8ce2 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -25,6 +25,9 @@ contract('VestingEscrowWallet', accounts => { let account_beneficiary1; let account_beneficiary2; let account_beneficiary3; + let account_beneficiary4; + + let beneficiaries; let message = "Transaction Should Fail!"; @@ -39,9 +42,16 @@ contract('VestingEscrowWallet', accounts => { wallet_owner = accounts[1]; account_treasury = accounts[2]; - account_beneficiary1 = accounts[7]; - account_beneficiary2 = accounts[8]; - account_beneficiary3 = accounts[9]; + account_beneficiary1 = accounts[6]; + account_beneficiary2 = accounts[7]; + account_beneficiary3 = accounts[8]; + account_beneficiary4 = accounts[9]; + + beneficiaries = [ + account_beneficiary1, + account_beneficiary2, + account_beneficiary3 + ]; // Step 1: Deploy the PolyToken [I_PolymathRegistry, I_PolyToken] = await deployPolyRegistryAndPolyToken(account_polymath, account_treasury); @@ -230,7 +240,7 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); }); - it("Should edit Vesting Schedule to the beneficiary address", async () => { + it("Should edit Vesting Schedule for the beneficiary's address", async () => { let numberOfTokens = schedules[1].numberOfTokens; let duration = schedules[1].duration; let frequency = schedules[1].frequency; @@ -262,6 +272,7 @@ contract('VestingEscrowWallet', accounts => { it("Should revoke Vesting Schedule from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); assert.equal(tx.logs[0].args._index, 0); @@ -294,6 +305,7 @@ contract('VestingEscrowWallet', accounts => { it("Should revoke Vesting Schedule from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, 1, {from: wallet_owner}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); assert.equal(tx.logs[0].args._index, 1); @@ -308,6 +320,7 @@ contract('VestingEscrowWallet', accounts => { it("Should revoke 2 Vesting Schedules from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedules(account_beneficiary2, {from: wallet_owner}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); @@ -334,7 +347,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._index, 1); }); - it("Should add Vesting Schedule from Template", async () => { + it("Should add Vesting Schedule from template", async () => { let numberOfTokens = schedules[2].numberOfTokens; let duration = schedules[2].duration; let frequency = schedules[2].frequency; @@ -353,6 +366,7 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); }); it("Should remove 2 Templates", async () => { @@ -365,6 +379,128 @@ contract('VestingEscrowWallet', accounts => { }); + describe("Tests for batch operations", async () => { + + it("Should add schedules for 3 beneficiaries", async () => { + let numberOfTokens = 30000; + let duration = durationUtil.weeks(4); + let frequency = durationUtil.weeks(1); + let startTime = latestTime() + durationUtil.seconds(100); + + let totalNumberOfTokens = numberOfTokens * 3; + await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); + + let tx = await I_VestingEscrowWallet.batchAddSchedule(beneficiaries, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + + for (let i = 0; i < beneficiaries.length; i++) { + let log = tx.logs[i]; + let beneficiary = beneficiaries[i]; + checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); + assert.equal(scheduleCount, 1); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); + checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + } + }); + + it("Should edit Vesting Schedule for 3 beneficiary's addresses", async () => { + let numberOfTokens = 25000; + let duration = durationUtil.seconds(50); + let frequency = durationUtil.seconds(10); + let timeShift = durationUtil.seconds(100); + let startTime = latestTime() + timeShift; + + let indexes = [0, 0, 0]; + const tx = await I_VestingEscrowWallet.batchEditSchedule(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + await increaseTime(timeShift + frequency); + + for (let i = 0; i < beneficiaries.length; i++) { + let log = tx.logs[i]; + let beneficiary = beneficiaries[i]; + checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); + assert.equal(scheduleCount, 1); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); + checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + } + + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + assert.equal(unassignedTokens.toNumber(), 5000 * beneficiaries.length); + }); + + it("Should send available tokens to the beneficiaries addresses", async () => { + for (let i = 0; i < beneficiaries.length; i++) { + let beneficiary = beneficiaries[i]; + await I_VestingEscrowWallet.update(beneficiary, {from: wallet_owner}); + } + + const tx = await I_VestingEscrowWallet.batchSendAvailableTokens(beneficiaries, {from: wallet_owner}); + + for (let i = 0; i < beneficiaries.length; i++) { + let log = tx.logs[i]; + let beneficiary = beneficiaries[i]; + assert.equal(log.args._beneficiary, beneficiary); + assert.equal(log.args._numberOfTokens.toNumber(), 5000); + + let balance = await I_PolyToken.balanceOf.call(beneficiary); + assert.equal(balance.toNumber(), 5000); + + await I_PolyToken.transfer(account_treasury, balance, {from: beneficiary}); + await I_VestingEscrowWallet.revokeSchedules(beneficiary, {from: wallet_owner}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + } + }); + + it("Should add schedules from template for 3 beneficiaries", async () => { + let numberOfTokens = 18000; + let duration = durationUtil.weeks(3); + let frequency = durationUtil.weeks(1); + let startTime = latestTime() + durationUtil.seconds(100); + + let totalNumberOfTokens = numberOfTokens * 3; + await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); + await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_owner}); + + let tx = await I_VestingEscrowWallet.batchAddScheduleFromTemplate(beneficiaries, 0, startTime, {from: wallet_owner}); + await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_owner}); + + for (let i = 0; i < beneficiaries.length; i++) { + let log = tx.logs[i]; + let beneficiary = beneficiaries[i]; + checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); + assert.equal(scheduleCount, 1); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); + checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + } + + }); + + it("Should revoke Vesting Schedule from the 3 beneficiary's addresses", async () => { + const tx = await I_VestingEscrowWallet.batchRevokeSchedules(beneficiaries, {from: wallet_owner}); + + for (let i = 0; i < beneficiaries.length; i++) { + let log = tx.logs[i]; + let beneficiary = beneficiaries[i]; + assert.equal(log.args._beneficiary, beneficiary); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); + assert.equal(scheduleCount, 0); + } + + await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + }); + + }); + }); function checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime) { From 4974b1362204e73088828fe4f864940a3625eee6 Mon Sep 17 00:00:00 2001 From: Polymath Date: Mon, 19 Nov 2018 11:40:14 -0300 Subject: [PATCH 122/582] Final CSV refactor --- CLI/commands/accredit.js | 90 +++------------ CLI/commands/changeNonAccreditedLimit.js | 90 +++------------ CLI/commands/common/csv_shared.js | 82 ++++++++++++++ CLI/commands/multi_mint.js | 114 +++++-------------- CLI/commands/whitelist.js | 138 +++++++---------------- 5 files changed, 179 insertions(+), 335 deletions(-) create mode 100644 CLI/commands/common/csv_shared.js diff --git a/CLI/commands/accredit.js b/CLI/commands/accredit.js index dd2c5d3af..cc550af2e 100644 --- a/CLI/commands/accredit.js +++ b/CLI/commands/accredit.js @@ -1,81 +1,37 @@ var common = require('./common/common_functions'); -var csv = require('./common/csv_sync'); -var contracts = require('./helpers/contract_addresses'); +var csv_shared = require('./common/csv_shared'); var abis = require('./helpers/contract_abis'); var BigNumber = require('bignumber.js'); let distribData = new Array(); -let allocData = new Array(); let fullFileData = new Array(); let badData = new Array(); -let BATCH_SIZE = 70; let securityToken; async function startScript(tokenSymbol, batchSize) { - if (batchSize) { - BATCH_SIZE = batchSize; - } - - //common.logAsciiBull(); + securityToken = await csv_shared.start(tokenSymbol, batchSize); - let STAddress = await checkST(tokenSymbol); - securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); + let result_processing = await csv_shared.read('./CLI/data/accredited_data.csv', accredit_processing); + distribData = result_processing.distribData; + fullFileData = result_processing.fullFileData; + badData = result_processing.badData; - await readCsv(); + await saveInBlockchain(); }; -async function checkST(tokenSymbol) { - let securityTokenRegistry = await STConnect(); - - return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { - if (result != "0x0000000000000000000000000000000000000000") { - return result - } else { - console.log("Token doesn't exist") - process.exit(0) - } - }); -} +function accredit_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let isAccredited = (typeof JSON.parse(csv_line[1].toLowerCase())) == "boolean" ? JSON.parse(csv_line[1].toLowerCase()) : "not-valid"; -async function STConnect() { - try { - let STRegistryAddress = await contracts.securityTokenRegistry(); - let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); - return STRegistry; - } catch (err) { - console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); - process.exit(0); + if (isAddress && + (isAccredited != "not-valid")) { + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), isAccredited)] + } else { + return [false, new Array(csv_line[0], isAccredited)] } } -async function readCsv() { - var CSV_STRING = csv('./CLI/data/accredited_data.csv'); - let i = 0; - - CSV_STRING.forEach(line => { - let data_processed = accredit_processing(line); - fullFileData.push(data_processed[1]); - - if (data_processed[0]) { - allocData.push(data_processed[1]); - i++; - if (i >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - i = 0; - } - } else { - badData.push(data_processed[1]); - } - }); - - distribData.push(allocData); - allocData = []; - - await saveInBlockchain(); -} - async function saveInBlockchain() { let gtmModules; try { @@ -131,22 +87,6 @@ async function saveInBlockchain() { return; } -function accredit_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let isAccredited = (typeof JSON.parse(csv_line[1].toLowerCase())) == "boolean" ? JSON.parse(csv_line[1].toLowerCase()) : "not-valid"; - - if (isAddress && - (isAccredited != "not-valid")) { - - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), isAccredited)] - - } else { - - return [false, new Array(csv_line[0], isAccredited)] - - } -} - module.exports = { executeApp: async (tokenSymbol, batchSize) => { return startScript(tokenSymbol, batchSize); diff --git a/CLI/commands/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js index 35ae68b57..029f2fc70 100644 --- a/CLI/commands/changeNonAccreditedLimit.js +++ b/CLI/commands/changeNonAccreditedLimit.js @@ -1,79 +1,34 @@ var common = require('./common/common_functions'); -var csv = require('./common/csv_sync'); -var contracts = require('./helpers/contract_addresses'); +var csv_shared = require('./common/csv_shared'); var abis = require('./helpers/contract_abis'); var BigNumber = require('bignumber.js'); let distribData = new Array(); -let allocData = new Array(); let fullFileData = new Array(); let badData = new Array(); -let BATCH_SIZE = 70; let securityToken; async function startScript(tokenSymbol, batchSize) { - if (batchSize) { - BATCH_SIZE = batchSize; - } - - //common.logAsciiBull(); + securityToken = await csv_shared.start(tokenSymbol, batchSize); - let STAddress = await checkST(tokenSymbol); - securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); + let result_processing = await csv_shared.read('./CLI/data/nonAccreditedLimits_data.csv', nonAccredited_processing); + distribData = result_processing.distribData; + fullFileData = result_processing.fullFileData; + badData = result_processing.badData; - await readCsv(); -}; - -async function checkST(tokenSymbol) { - let securityTokenRegistry = await STConnect(); - - return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { - if (result != "0x0000000000000000000000000000000000000000") { - return result - } else { - console.log("Token doesn't exist") - process.exit(0) - } - }); -} - -async function STConnect() { - try { - let STRegistryAddress = await contracts.securityTokenRegistry(); - let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); - return STRegistry; - } catch (err) { - console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); - process.exit(0); - } + await saveInBlockchain(); } -async function readCsv() { - var CSV_STRING = csv('./CLI/data/nonAccreditedLimits_data.csv'); - let i = 0; - - CSV_STRING.forEach(line => { - let data_processed = nonAccredited_processing(line); - fullFileData.push(data_processed[1]); - - if (data_processed[0]) { - allocData.push(data_processed[1]); - i++; - if (i >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - i = 0; - } - } else { - badData.push(data_processed[1]); - } - }); - - distribData.push(allocData); - allocData = []; +function nonAccredited_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let isNumber = !isNaN(csv_line[1]); - await saveInBlockchain(); + if (isAddress && isNumber) { + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), csv_line[1])] + } else { + return [false, new Array(csv_line[0], csv_line[1])] + } } async function saveInBlockchain() { @@ -132,21 +87,6 @@ async function saveInBlockchain() { return; } -function nonAccredited_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let isNumber = !isNaN(csv_line[1]); - - if (isAddress && isNumber) { - - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), csv_line[1])] - - } else { - - return [false, new Array(csv_line[0], csv_line[1])] - - } -} - module.exports = { executeApp: async (tokenSymbol, batchSize) => { return startScript(tokenSymbol, batchSize); diff --git a/CLI/commands/common/csv_shared.js b/CLI/commands/common/csv_shared.js new file mode 100644 index 000000000..471db13d1 --- /dev/null +++ b/CLI/commands/common/csv_shared.js @@ -0,0 +1,82 @@ +var contracts = require('../helpers/contract_addresses'); +var abis = require('../helpers/contract_abis'); +var csv = require('./csv_sync'); + +let BATCH_SIZE = 70; + +async function startScript(tokenSymbol, batchSize) { + if (batchSize) { + BATCH_SIZE = batchSize; + } + let STAddress = await checkST(tokenSymbol); + return new web3.eth.Contract(abis.securityToken(), STAddress); +}; + +async function checkST(tokenSymbol) { + let securityTokenRegistry = await STConnect(); + + return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { + if (result != "0x0000000000000000000000000000000000000000") { + return result + } else { + console.log("Token doesn't exist") + process.exit(0) + } + }); +} + +async function STConnect() { + try { + let STRegistryAddress = await contracts.securityTokenRegistry(); + let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); + return STRegistry; + } catch (err) { + console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); + process.exit(0); + } +} + +async function readScript(file, processing) { + let allocData = new Array(); + let distribData = new Array(); + let fullFileData = new Array(); + let badData = new Array(); + let i = 0; + + var CSV_STRING = csv(file); + + CSV_STRING.forEach(line => { + let data_processed = processing(line); + fullFileData.push(data_processed[1]); + + if (data_processed[0]) { + allocData.push(data_processed[1]); + i++; + if (i >= BATCH_SIZE) { + distribData.push(allocData); + allocData = []; + i = 0; + } + } else { + badData.push(data_processed[1]); + } + }); + + distribData.push(allocData); + allocData = []; + + return { + distribData: distribData, + fullFileData: fullFileData, + badData: badData + } +} + +module.exports = { + start: async (tokenSymbol, batchSize) => { + return await startScript(tokenSymbol, batchSize); + }, + read: async (file, processing) => { + return await readScript(file, processing); + } +} \ No newline at end of file diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js index 684be6bac..3147b2754 100644 --- a/CLI/commands/multi_mint.js +++ b/CLI/commands/multi_mint.js @@ -1,83 +1,53 @@ var common = require('./common/common_functions'); -var csv = require('./common/csv_sync'); -var contracts = require('./helpers/contract_addresses'); +var csv_shared = require('./common/csv_shared'); var abis = require('./helpers/contract_abis'); var BigNumber = require('bignumber.js'); let distribData = new Array(); -let allocData = new Array(); let fullFileData = new Array(); let badData = new Array(); -let BATCH_SIZE = 75; -let securityToken; let affiliatesFailedArray = new Array(); let affiliatesKYCInvalidArray = new Array(); + +let securityToken; let tokenDivisible; async function startScript(tokenSymbol, batchSize) { - if (batchSize) { - BATCH_SIZE = batchSize; - } + securityToken = await csv_shared.start(tokenSymbol, batchSize); - //common.logAsciiBull(); + let result_processing = await csv_shared.read('./CLI/data/multi_mint_data.csv', multimint_processing); + distribData = result_processing.distribData; + fullFileData = result_processing.fullFileData; + badData = result_processing.badData; - let STAddress = await checkST(tokenSymbol); - securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); tokenDivisible = await securityToken.methods.granularity().call() == 1; - await readCsv(); -}; - -async function checkST(tokenSymbol) { - let securityTokenRegistry = await STConnect(); - - return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { - if (result != "0x0000000000000000000000000000000000000000") { - return result - } else { - console.log("Token doesn't exist") - process.exit(0) - } - }); + await saveInBlockchain(); + await finalResults(); } -async function STConnect() { - try { - let STRegistryAddress = await contracts.securityTokenRegistry(); - let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); - return STRegistry; - } catch (err) { - console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); - process.exit(0); +function multimint_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let validToken = isValidToken(csv_line[1]); + + if (isAddress && + validToken) { + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), validToken)] + } else { + return [false, new Array(csv_line[0], csv_line[1])] } } -async function readCsv() { - var CSV_STRING = csv('./CLI/data/multi_mint_data.csv'); - let i = 0; - - CSV_STRING.forEach(line => { - let data_processed = multimint_processing(line); - fullFileData.push(data_processed[1]); - - if (data_processed[0]) { - allocData.push(data_processed[1]); - i++; - if (i >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - i = 0; - } - } else { - badData.push(data_processed[1]); +function isValidToken(token) { + var tokenAmount = parseFloat(token); + if (tokenDivisible) { + return tokenAmount + } else { + if ((tokenAmount % 1 == 0)) { + return tokenAmount; } - }); - - distribData.push(allocData); - allocData = []; - - await saveInBlockchain(); - await finalResults(); + return false + } } async function saveInBlockchain() { @@ -220,34 +190,6 @@ async function finalResults() { } -function multimint_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let validToken = isValidToken(csv_line[1]); - - if (isAddress && - validToken) { - - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), validToken)] - - } else { - - return [false, new Array(csv_line[0], csv_line[1])] - - } -} - -function isValidToken(token) { - var tokenAmount = parseFloat(token); - if (tokenDivisible) { - return tokenAmount - } else { - if ((tokenAmount % 1 == 0)) { - return tokenAmount; - } - return false - } -} - module.exports = { executeApp: async (tokenSymbol, batchSize) => { return startScript(tokenSymbol, batchSize); diff --git a/CLI/commands/whitelist.js b/CLI/commands/whitelist.js index 2cd108030..7a5767611 100644 --- a/CLI/commands/whitelist.js +++ b/CLI/commands/whitelist.js @@ -1,81 +1,62 @@ var common = require('./common/common_functions'); -var csv = require('./common/csv_sync'); -var contracts = require('./helpers/contract_addresses'); +var csv_shared = require('./common/csv_shared'); var abis = require('./helpers/contract_abis'); var BigNumber = require('bignumber.js'); let distribData = new Array(); -let allocData = new Array(); let fullFileData = new Array(); let badData = new Array(); -let BATCH_SIZE = 70; + let securityToken; let generalTransferManager; async function startScript(tokenSymbol, batchSize) { - if (batchSize) { - BATCH_SIZE = batchSize; - } + securityToken = await csv_shared.start(tokenSymbol, batchSize); - //common.logAsciiBull(); + let result_processing = await csv_shared.read('./CLI/data/whitelist_data.csv', whitelist_processing); + distribData = result_processing.distribData; + fullFileData = result_processing.fullFileData; + badData = result_processing.badData; - let STAddress = await checkST(tokenSymbol); - securityToken = new web3.eth.Contract(abis.securityToken(), STAddress); - - await readCsv(); + await saveInBlockchain(); + await finalResults(); }; -async function checkST(tokenSymbol) { - let securityTokenRegistry = await STConnect(); - - return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { - if (result != "0x0000000000000000000000000000000000000000") { - return result - } else { - console.log("Token doesn't exist") - process.exit(0) - } - }); -} +function whitelist_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let sellValid = isValidDate(csv_line[1]) + let buyValid = isValidDate(csv_line[2]) + let kycExpiryDate = isValidDate(csv_line[3]) + let canBuyFromSTO = (typeof JSON.parse(csv_line[4].toLowerCase())) == "boolean" ? JSON.parse(csv_line[4].toLowerCase()) : "not-valid"; -async function STConnect() { - try { - let STRegistryAddress = await contracts.securityTokenRegistry(); - let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); - return STRegistry; - } catch (err) { - console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); - process.exit(0); + if (isAddress && + sellValid && + buyValid && + kycExpiryDate && + (canBuyFromSTO != "not-valid")) { + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] + } else { + return [false, new Array(csv_line[0], sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] } } -async function readCsv() { - var CSV_STRING = csv('./CLI/data/whitelist_data.csv'); - let i = 0; - - CSV_STRING.forEach(line => { - let data_processed = whitelist_processing(line); - fullFileData.push(data_processed[1]); - - if (data_processed[0]) { - allocData.push(data_processed[1]); - i++; - if (i >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - i = 0; - } - } else { - badData.push(data_processed[1]); - } - }); - - distribData.push(allocData); - allocData = []; - - await saveInBlockchain(); - await finalResults(); +function isValidDate(date) { + var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(date); + if (matches == null) return false; + var d = matches[2]; + var m = matches[1] - 1; + var y = matches[3]; + var composedDate = new Date(y, m, d); + var timestampDate = composedDate.getTime() + // For some reason these timestamps are being recorded +4 hours UTC + if (composedDate.getDate() == d && + composedDate.getMonth() == m && + composedDate.getFullYear() == y) { + return timestampDate / 1000 + } else { + return false + } } async function saveInBlockchain() { @@ -194,47 +175,6 @@ async function finalResults() { } -function whitelist_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let sellValid = isValidDate(csv_line[1]) - let buyValid = isValidDate(csv_line[2]) - let kycExpiryDate = isValidDate(csv_line[3]) - let canBuyFromSTO = (typeof JSON.parse(csv_line[4].toLowerCase())) == "boolean" ? JSON.parse(csv_line[4].toLowerCase()) : "not-valid"; - - if (isAddress && - sellValid && - buyValid && - kycExpiryDate && - (canBuyFromSTO != "not-valid")) { - - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] - - } else { - - return [false, new Array(csv_line[0], sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] - - } -} - -function isValidDate(date) { - var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(date); - if (matches == null) return false; - var d = matches[2]; - var m = matches[1] - 1; - var y = matches[3]; - var composedDate = new Date(y, m, d); - var timestampDate = composedDate.getTime() - - // For some reason these timestamps are being recorded +4 hours UTC - if (composedDate.getDate() == d && - composedDate.getMonth() == m && - composedDate.getFullYear() == y) { - return timestampDate / 1000 - } else { - return false - } -} - module.exports = { executeApp: async (tokenSymbol, batchSize) => { return startScript(tokenSymbol, batchSize); From 3b6fd8911f1c031f6e958864e46c425f9f0d1ac8 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 19 Nov 2018 16:56:14 +0200 Subject: [PATCH 123/582] tests for negative cases --- test/z_vesting_escrow_wallet.js | 149 +++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 1 deletion(-) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 64eae8ce2..b7eef2742 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -10,7 +10,6 @@ const Web3 = require('web3'); const BigNumber = require('bignumber.js'); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));// Hardcoded development port -//TODO tests for batch operations //TODO negative cases contract('VestingEscrowWallet', accounts => { @@ -72,6 +71,12 @@ contract('VestingEscrowWallet', accounts => { describe("Depositing and withdrawing tokens", async () => { + it("Should fail to deposit zero amount of tokens", async () => { + await catchRevert( + I_VestingEscrowWallet.depositTokens(0, {from: wallet_owner}) + ); + }); + it("Should deposit tokens for new Vesting Schedules", async () => { let numberOfTokens = 25000; await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); @@ -99,6 +104,12 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), 0); }); + it("Should fail to send available tokens -- fail because beneficiary doesn't have available tokens", async () => { + catchRevert( + I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: wallet_owner}) + ); + }); + it("Should send available tokens to the beneficiary address", async () => { let numberOfTokens = 75000; let duration = durationUtil.seconds(30); @@ -119,6 +130,18 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), numberOfTokens / 3); await I_PolyToken.transfer(account_treasury, balance, {from: account_beneficiary3}); + }); + + it("Should fail to edit Vesting Schedule -- fail because schedule already started", async () => { + let numberOfTokens = 75000; + let duration = durationUtil.seconds(30); + let frequency = durationUtil.seconds(10); + let timeShift = durationUtil.seconds(100); + let startTime = latestTime() + timeShift; + await catchRevert( + I_VestingEscrowWallet.editSchedule(account_beneficiary3, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + ); + await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_owner}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); }); @@ -221,6 +244,66 @@ contract('VestingEscrowWallet', accounts => { } ]; + it("Should fail to add Vesting Schedule to the beneficiary address -- fail because not enough unassigned tokens", async () => { + await catchRevert( + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) + ); + }); + + it("Should fail to add Vesting Schedule to the beneficiary address -- fail because address in invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.addSchedule(0, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) + ); + }); + + it("Should fail to add Vesting Schedule to the beneficiary address -- fail because start date in the past", async () => { + await catchRevert( + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() - durationUtil.days(1), {from: wallet_owner}) + ); + }); + + it("Should fail to add Vesting Schedule to the beneficiary address -- fail because number of tokens is 0", async () => { + await catchRevert( + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 0, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) + ); + }); + + it("Should fail to add Vesting Schedule to the beneficiary address -- fail because duration can't be divided entirely by frequency", async () => { + await catchRevert( + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 3, latestTime() + durationUtil.days(1), {from: wallet_owner}) + ); + }); + + it("Should fail to add Vesting Schedule to the beneficiary address -- fail because number of tokens can't be divided entirely by period count", async () => { + await catchRevert( + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 5, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) + ); + }); + + it("Should fail to get Vesting Schedule -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.getSchedule(0, 0) + ); + }); + + it("Should fail to get Vesting Schedule -- fail because schedule not found", async () => { + await catchRevert( + I_VestingEscrowWallet.getSchedule(account_beneficiary1, 0) + ); + }); + + it("Should fail to get count of Vesting Schedule -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.getScheduleCount(0) + ); + }); + + it("Should fail to get available tokens -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.getAvailableTokens(0) + ); + }); + it("Should add Vesting Schedule to the beneficiary address", async () => { let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; @@ -240,6 +323,26 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); }); + it("Should fail to edit Vesting Schedule -- fail because schedule not found", async () => { + let numberOfTokens = schedules[0].numberOfTokens; + let duration = schedules[0].duration; + let frequency = schedules[0].frequency; + let startTime = schedules[0].startTime; + await catchRevert( + I_VestingEscrowWallet.editSchedule(account_beneficiary1, 1, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + ); + }); + + it("Should fail to edit Vesting Schedule -- fail because not enough unassigned tokens", async () => { + let numberOfTokens = schedules[0].numberOfTokens * 2; + let duration = schedules[0].duration; + let frequency = schedules[0].frequency; + let startTime = schedules[0].startTime; + await catchRevert( + I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + ); + }); + it("Should edit Vesting Schedule for the beneficiary's address", async () => { let numberOfTokens = schedules[1].numberOfTokens; let duration = schedules[1].duration; @@ -270,6 +373,18 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should fail to revoke Vesting Schedule -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeSchedule(0, 0, {from: wallet_owner}) + ); + }); + + it("Should fail to revoke Vesting Schedule -- fail because schedule not found", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_owner}) + ); + }); + it("Should revoke Vesting Schedule from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); @@ -281,6 +396,12 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 0); }); + it("Should fail to revoke Vesting Schedules -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeSchedules(0, {from: wallet_owner}) + ); + }); + it("Should add 3 Vesting Schedules to the beneficiary address", async () => { let totalNumberOfTokens = getTotalNumberOfTokens(schedules); await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); @@ -347,6 +468,13 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._index, 1); }); + it("Should fail to add Vesting Schedule from template -- fail because template not found", async () => { + let startTime = schedules[2].startTime; + await catchRevert( + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_owner}) + ); + }); + it("Should add Vesting Schedule from template", async () => { let numberOfTokens = schedules[2].numberOfTokens; let duration = schedules[2].duration; @@ -369,6 +497,12 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); }); + it("Should fail to remove template", async () => { + await catchRevert( + I_VestingEscrowWallet.removeTemplate(2, {from: wallet_owner}) + ); + }); + it("Should remove 2 Templates", async () => { await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_owner}); await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_owner}); @@ -406,6 +540,19 @@ contract('VestingEscrowWallet', accounts => { } }); + it("Should edit Vesting Schedule for 3 beneficiary's addresses", async () => { + let numberOfTokens = 25000; + let duration = durationUtil.seconds(50); + let frequency = durationUtil.seconds(10); + let timeShift = durationUtil.seconds(100); + let startTime = latestTime() + timeShift; + + let indexes = [0, 0, 0, 0]; + await catchRevert( + I_VestingEscrowWallet.batchEditSchedule(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + ); + }); + it("Should edit Vesting Schedule for 3 beneficiary's addresses", async () => { let numberOfTokens = 25000; let duration = durationUtil.seconds(50); From 99750f6f9f131d1b4ee4be0ca5061cb343a8ea2a Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 20 Nov 2018 00:19:21 +0200 Subject: [PATCH 124/582] disabled tests: depositing and withdrawing tokens --- test/z_vesting_escrow_wallet.js | 92 +++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index b7eef2742..a5351321d 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -10,7 +10,6 @@ const Web3 = require('web3'); const BigNumber = require('bignumber.js'); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));// Hardcoded development port -//TODO negative cases contract('VestingEscrowWallet', accounts => { const CREATED = 0; @@ -68,7 +67,7 @@ contract('VestingEscrowWallet', accounts => { ----------------------------------------------------------------------------- `); }); - +/* describe("Depositing and withdrawing tokens", async () => { it("Should fail to deposit zero amount of tokens", async () => { @@ -77,7 +76,7 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should deposit tokens for new Vesting Schedules", async () => { + it("Should deposit tokens for new vesting schedules", async () => { let numberOfTokens = 25000; await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); const tx = await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); @@ -132,7 +131,7 @@ contract('VestingEscrowWallet', accounts => { await I_PolyToken.transfer(account_treasury, balance, {from: account_beneficiary3}); }); - it("Should fail to edit Vesting Schedule -- fail because schedule already started", async () => { + it("Should fail to edit vesting schedule -- fail because schedule already started", async () => { let numberOfTokens = 75000; let duration = durationUtil.seconds(30); let frequency = durationUtil.seconds(10); @@ -220,8 +219,8 @@ contract('VestingEscrowWallet', accounts => { }); }); - - describe("Adding, Editing and Revoking Vesting Schedule", async () => { +*/ + describe("Adding, editing and revoking vesting schedule", async () => { let schedules = [ { @@ -244,55 +243,55 @@ contract('VestingEscrowWallet', accounts => { } ]; - it("Should fail to add Vesting Schedule to the beneficiary address -- fail because not enough unassigned tokens", async () => { + it("Should fail to add vesting schedule to the beneficiary address -- fail because not enough unassigned tokens", async () => { await catchRevert( I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) ); }); - it("Should fail to add Vesting Schedule to the beneficiary address -- fail because address in invalid", async () => { + it("Should fail to add vesting schedule to the beneficiary address -- fail because address in invalid", async () => { await catchRevert( I_VestingEscrowWallet.addSchedule(0, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) ); }); - it("Should fail to add Vesting Schedule to the beneficiary address -- fail because start date in the past", async () => { + it("Should fail to add vesting schedule to the beneficiary address -- fail because start date in the past", async () => { await catchRevert( I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() - durationUtil.days(1), {from: wallet_owner}) ); }); - it("Should fail to add Vesting Schedule to the beneficiary address -- fail because number of tokens is 0", async () => { + it("Should fail to add vesting schedule to the beneficiary address -- fail because number of tokens is 0", async () => { await catchRevert( I_VestingEscrowWallet.addSchedule(account_beneficiary1, 0, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) ); }); - it("Should fail to add Vesting Schedule to the beneficiary address -- fail because duration can't be divided entirely by frequency", async () => { + it("Should fail to add vesting schedule to the beneficiary address -- fail because duration can't be divided entirely by frequency", async () => { await catchRevert( I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 3, latestTime() + durationUtil.days(1), {from: wallet_owner}) ); }); - it("Should fail to add Vesting Schedule to the beneficiary address -- fail because number of tokens can't be divided entirely by period count", async () => { + it("Should fail to add vesting schedule to the beneficiary address -- fail because number of tokens can't be divided entirely by period count", async () => { await catchRevert( I_VestingEscrowWallet.addSchedule(account_beneficiary1, 5, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) ); }); - it("Should fail to get Vesting Schedule -- fail because address is invalid", async () => { + it("Should fail to get vesting schedule -- fail because address is invalid", async () => { await catchRevert( I_VestingEscrowWallet.getSchedule(0, 0) ); }); - it("Should fail to get Vesting Schedule -- fail because schedule not found", async () => { + it("Should fail to get vesting schedule -- fail because schedule not found", async () => { await catchRevert( I_VestingEscrowWallet.getSchedule(account_beneficiary1, 0) ); }); - it("Should fail to get count of Vesting Schedule -- fail because address is invalid", async () => { + it("Should fail to get count of vesting schedule -- fail because address is invalid", async () => { await catchRevert( I_VestingEscrowWallet.getScheduleCount(0) ); @@ -304,12 +303,12 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should add Vesting Schedule to the beneficiary address", async () => { + it("Should add vesting schedule to the beneficiary address", async () => { let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: account_treasury}); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); @@ -323,7 +322,7 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); }); - it("Should fail to edit Vesting Schedule -- fail because schedule not found", async () => { + it("Should fail to edit vesting schedule -- fail because schedule not found", async () => { let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; @@ -333,7 +332,7 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should fail to edit Vesting Schedule -- fail because not enough unassigned tokens", async () => { + it("Should fail to edit vesting schedule -- fail because not enough unassigned tokens", async () => { let numberOfTokens = schedules[0].numberOfTokens * 2; let duration = schedules[0].duration; let frequency = schedules[0].frequency; @@ -343,7 +342,7 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should edit Vesting Schedule for the beneficiary's address", async () => { + it("Should edit vesting schedule for the beneficiary's address", async () => { let numberOfTokens = schedules[1].numberOfTokens; let duration = schedules[1].duration; let frequency = schedules[1].frequency; @@ -363,7 +362,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(unassignedTokens.toNumber(), schedules[0].numberOfTokens - schedules[1].numberOfTokens); }); - it("Should fail edit Vesting Schedule to the beneficiary address", async () => { + it("Should fail edit vesting schedule to the beneficiary address", async () => { let numberOfTokens = schedules[0].numberOfTokens + schedules[1].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; @@ -373,19 +372,19 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should fail to revoke Vesting Schedule -- fail because address is invalid", async () => { + it("Should fail to revoke vesting schedule -- fail because address is invalid", async () => { await catchRevert( I_VestingEscrowWallet.revokeSchedule(0, 0, {from: wallet_owner}) ); }); - it("Should fail to revoke Vesting Schedule -- fail because schedule not found", async () => { + it("Should fail to revoke vesting schedule -- fail because schedule not found", async () => { await catchRevert( I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_owner}) ); }); - it("Should revoke Vesting Schedule from the beneficiary address", async () => { + it("Should revoke vesting schedule from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); @@ -396,13 +395,13 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 0); }); - it("Should fail to revoke Vesting Schedules -- fail because address is invalid", async () => { + it("Should fail to revoke vesting schedules -- fail because address is invalid", async () => { await catchRevert( I_VestingEscrowWallet.revokeSchedules(0, {from: wallet_owner}) ); }); - it("Should add 3 Vesting Schedules to the beneficiary address", async () => { + it("Should add 3 vesting schedules to the beneficiary address", async () => { let totalNumberOfTokens = getTotalNumberOfTokens(schedules); await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); @@ -424,7 +423,7 @@ contract('VestingEscrowWallet', accounts => { } }); - it("Should revoke Vesting Schedule from the beneficiary address", async () => { + it("Should revoke vesting schedule from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, 1, {from: wallet_owner}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); @@ -436,10 +435,10 @@ contract('VestingEscrowWallet', accounts => { let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, 1); checkSchedule(schedule, schedules[2].numberOfTokens, schedules[2].numberOfTokens, schedules[2].duration, schedules[2].frequency, - schedules[2].startTime, schedules[2].startTime + schedules[2].frequency, CREATED); + schedules[2].startTime, schedules[2].startTime + schedules[2].frequency, CREATED); }); - it("Should revoke 2 Vesting Schedules from the beneficiary address", async () => { + it("Should revoke 2 vesting schedules from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedules(account_beneficiary2, {from: wallet_owner}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); @@ -449,6 +448,31 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 0); }); + }); + + describe("Adding, using and removing templates", async () => { + + let schedules = [ + { + numberOfTokens: 100000, + duration: durationUtil.years(4), + frequency: durationUtil.years(1), + startTime: latestTime() + durationUtil.days(1) + }, + { + numberOfTokens: 30000, + duration: durationUtil.weeks(6), + frequency: durationUtil.weeks(1), + startTime: latestTime() + durationUtil.days(2) + }, + { + numberOfTokens: 2000, + duration: durationUtil.days(10), + frequency: durationUtil.days(2), + startTime: latestTime() + durationUtil.days(3) + } + ]; + it("Should add 3 Templates", async () => { for (let i = 0; i < schedules.length; i++) { let numberOfTokens = schedules[i].numberOfTokens; @@ -468,14 +492,14 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._index, 1); }); - it("Should fail to add Vesting Schedule from template -- fail because template not found", async () => { + it("Should fail to add vesting schedule from template -- fail because template not found", async () => { let startTime = schedules[2].startTime; await catchRevert( I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_owner}) ); }); - it("Should add Vesting Schedule from template", async () => { + it("Should add vesting schedule from template", async () => { let numberOfTokens = schedules[2].numberOfTokens; let duration = schedules[2].duration; let frequency = schedules[2].frequency; @@ -540,7 +564,7 @@ contract('VestingEscrowWallet', accounts => { } }); - it("Should edit Vesting Schedule for 3 beneficiary's addresses", async () => { + it("Should edit vesting schedule for 3 beneficiary's addresses", async () => { let numberOfTokens = 25000; let duration = durationUtil.seconds(50); let frequency = durationUtil.seconds(10); @@ -553,7 +577,7 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should edit Vesting Schedule for 3 beneficiary's addresses", async () => { + it("Should edit vesting schedule for 3 beneficiary's addresses", async () => { let numberOfTokens = 25000; let duration = durationUtil.seconds(50); let frequency = durationUtil.seconds(10); @@ -631,7 +655,7 @@ contract('VestingEscrowWallet', accounts => { }); - it("Should revoke Vesting Schedule from the 3 beneficiary's addresses", async () => { + it("Should revoke vesting schedule from the 3 beneficiary's addresses", async () => { const tx = await I_VestingEscrowWallet.batchRevokeSchedules(beneficiaries, {from: wallet_owner}); for (let i = 0; i < beneficiaries.length; i++) { From 313c7d0b55494796563c409df52cc2daf4d413e1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 20 Nov 2018 08:50:17 +0200 Subject: [PATCH 125/582] fixed "Error: Exceeds block gas limit" --- test/z_vesting_escrow_wallet.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index a5351321d..32fbfb058 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -67,7 +67,7 @@ contract('VestingEscrowWallet', accounts => { ----------------------------------------------------------------------------- `); }); -/* + describe("Depositing and withdrawing tokens", async () => { it("Should fail to deposit zero amount of tokens", async () => { @@ -173,11 +173,6 @@ contract('VestingEscrowWallet', accounts => { it("Should withdraw available tokens by 3 schedules to the beneficiary address", async () => { let schedules = [ - { - numberOfTokens: 100000, - duration: durationUtil.seconds(4), - frequency: durationUtil.seconds(1) - }, { numberOfTokens: 30000, duration: durationUtil.seconds(6), @@ -205,7 +200,7 @@ contract('VestingEscrowWallet', accounts => { for (let i = 0; i < stepCount; i++) { await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); } - let numberOfTokens = 100000 + (30000 / 6 * stepCount) + (2000 / 10 * stepCount); + let numberOfTokens = (30000 / 6 * stepCount) + (2000 / 10 * stepCount); const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); @@ -219,7 +214,7 @@ contract('VestingEscrowWallet', accounts => { }); }); -*/ + describe("Adding, editing and revoking vesting schedule", async () => { let schedules = [ From 055d2acdade9c3fbc6c452ad33b9d5e1378cc973 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 20 Nov 2018 16:03:17 +0530 Subject: [PATCH 126/582] initial draft of VRTM --- .../TransferManager/VolumeRestrictionTM.sol | 546 ++++++++++++++++-- .../VolumeRestrictionTMFactory.sol | 2 +- 2 files changed, 498 insertions(+), 50 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index a4096b0a0..6fafbf62c 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -8,129 +8,577 @@ contract VolumeRestrictionTM is ITransferManager { using SafeMath for uint256; - enum RestrictionType { Global, Individual } - enum TokenType { Fixed, Variable} + // permission definition + bytes32 public constant ADMIN = "ADMIN"; + + enum RestrictionType { Fixed, Variable } struct VolumeRestriction { uint256 allowedTokens; + uint256 allowedPercentageOfTokens; uint256 startTime; uint256 rollingPeriodInDays; uint256 endTime; + RestrictionType typeOfRestriction; + } + + struct BucketDetails { + uint256[] timestamps; + uint256 sumOfLastPeriod; + uint256 daysCovered; + uint256 latestTimestampIndex; } - VolumeRestriction fixedGlobalRestriction; - VolumeRestriction variableGlobalRestriction; + uint256 globalSumOfLastPeriod; - mapping(address => VolumeRestriction[]) internal fixedIndividualRestriction; - mapping(address => VolumeRestriciton[]) internal variableIndividualRestriction; - mapping(address => mapping(uint256 => )) + VolumeRestriction globalRestriction; + mapping(address => VolumeRestriction) internal individualRestriction; + // Storing _from => day's timestamp => total amount transact in a day + mapping(address => mapping(uint256 => uint256)) internal bucket; + // Storing the information that used to validate the transaction + mapping(address => BucketDetails) internal bucketToUser; + // List of wallets that are exempted from all the restrictions applied by the this contract mapping(address => bool) public exemptList; + mapping(address => BucketDetails) internal globalBucketToUser; - event ExemptWalletListChanged(address _wallet, bool _change); + event ChangedExemptWalletList(address indexed _wallet, bool _change); + + event AddNewIndividualRestriction( + address indexed _holder, + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); - function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { + event ModifyIndividualRestriction( + address indexed _holder, + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); - } + event AddNewGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); - function addFixedIndividualRestriction( - address _holder, + event ModifyGlobalRestriction( uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, - uint256 _endTime - ) - public - withPerm(ADMIN) + uint256 _endTime, + uint256 _typeOfRestriction + ); + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) { } - function addVariableIndividualRestriction( - address _holder, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime + /** + * @notice Used to verify the transfer/transferFrom transaction and prevent tranaction + * whose volume of tokens will voilate the maximum volume transfer restriction + * @param _from Address of the sender + * @param _to Address of the reciever + * @param _amount The amount of tokens to transfer + * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable + */ + function verifyTransfer(address _from, address _to, uint256 _amount, bytes /*_data*/, bool _isTransfer) public returns (Result) { + if (!paused && _from != address(0) && !exemptList[_from]) { + require(msg.sender == securityToken || !_isTransfer); + return _checkRestriction(_from, _amount, _isTransfer); + } else { + return Result.NA; + } + } + + function _checkRestriction(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { + BucketDetails memory _bucketDetails = bucketToUser[_from]; + if (_bucketDetails.timestamps[0] == 0) { + return _individualBucketCheck(individualRestriction[_from].startTime, now, _from,individualRestriction[_from], _amount); + } else { + return _individualBucketCheck(_bucketDetails.timestamps[_bucketDetails.latestTimestampIndex], now, _from, individualRestriction[_from], _amount); + } + } else if (now <= globalRestriction.endTime && now >= globalRestriction.startTime) { + // TODO: Add the global bucket check + // Algorithm should be loop to all(who doesn't have the individual restriction) the individualBucketCheck + // and get the amount that was transacted till now. + // Calculate the sum of that amount + new txn amount and compare with allowed percentage or fixed amount + // amount of tokens + _globalBucketCheck(); + } else { + return Result.NA; + } + } + + function _globalBucketCheck() internal { + // TODO: Definition pending + } + + function _individualBucketCheck( + uint256 _fromTimestamp, + uint256 _toTimestamp, + address _from, + VolumeRestriction storage _restriction, + uint256 _amount ) - public - withPerm(ADMIN) + internal + returns (Result) + { + uint256 _diffDays = BokkyPooBahsDateTimeLibrary.diffDays(_fromTimestamp, _toTimestamp); + uint256 i = 0; + BucketDetails storage _bucketDetails = bucketToUser[_from]; + uint256 counter = _bucketDetails.latestTimestampIndex; + uint256 tempTimeStamp = 0; + for (i = 1; i <= _diffDays; i++) { + // calculating the timestamp that will used as an index of the next bucket + // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... + // where T1,T2,T3 are timestamps having 24 hrs difference + tempTimeStamp = _fromTimestamp.add((i - 1) * 1 days); + // Creating the round array + if (counter > _restriction.rollingPeriodInDays -1) { + counter = 0; + } + // This condition is to check whether the first rolling period is covered or not + // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting + // the earlier value at that index + if (_bucketDetails.daysCovered <= _restriction.rollingPeriodInDays) { + _bucketDetails.daysCovered++; + } else { + // temporarily storing the preious value of timestamp at the "counter" index + uint256 _previousTimestamp = _bucketDetails.timestamps[counter]; + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.sub(bucket[_from][_previousTimestamp]); + } + // Adding the last amount that is transacted on the tempTimeStamp + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); + // Storing the passed timestamp in the array + _bucketDetails.timestamps[counter] = tempTimeStamp; + // Assigning the sum of transacted amount on the passed day + bucket[_from][tempTimeStamp] = 0; + counter ++; + } + bool valid; + if (_restriction.typeOfRestriction == RestrictionType.Variable) { + uint256 _allowedAmount = (_restriction.allowedTokens.mul(ISecurityToken(securityToken).totalSupply()))/ 10 ** 18; + valid = _checkValidAmountToTransact(_bucketDetails.sumOfLastPeriod, _amount, _allowedAmount); + } else { + valid = _checkValidAmountToTransact(_bucketDetails.sumOfLastPeriod, _amount, _restriction.allowedTokens); + } + // Storing the index of the latest timestamp from the array of timestamp that is being processed + _bucketDetails.latestTimestampIndex = counter; + if (!valid) { + return Result.INVALID; + } else { + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod + _amount; + bucket[_from][_bucketDetails.timestamps[counter]] = bucket[_from][_bucketDetails.timestamps[counter]].add(_amount); + return Result.NA; + } + + } + + function _checkValidAmountToTransact( + uint256 _sumOfLastPeriod, + uint256 _amountToTransact, + uint256 _allowedTokens + ) + internal + pure + returns (bool) { + if (_allowedTokens >= _sumOfLastPeriod.add(_amountToTransact)) { + return true; + } else { + return false; + } + } + /** + * @notice Add/Remove wallet address from the exempt list + * @param _wallet Ethereum wallet/contract address that need to be exempted + * @param _change Boolean value used to add (i.e true) or remove (i.e false) from the list + */ + function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { + require(_wallet != address(0), "0x0 address not allowed"); + exemptList[_wallet] = _change; + emit ChangedExemptWalletList(_wallet, _change); } - function addFixedGlobalRestriction( + /** + * @notice Use to add the new individual restriction for a given token holder + * @param _holder Address of the token holder, whom restriction will be implied + * @param _allowedTokens Amount of tokens allowed to be trade for a given address. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function addIndividualRestriction( + address _holder, uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, - uint256 _endTime + uint256 _endTime, + uint256 _restrictionType ) public withPerm(ADMIN) { + _addIndividualRestriction( + _holder, + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + /** + * @notice Use to add the new individual restriction for multiple token holders + * @param _holders Array of address of the token holders, whom restriction will be implied + * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. + * @param _allowedPercentageOfTokens Array of percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTimes Array of unix timestamps at which restrictions get into effect + * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) + * @param _endTimes Array of unix timestamps at which restriction effects will gets end. + * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function addIndividualRestrictionMulti( + address[] _holders, + uint256[] _allowedTokens, + uint256[] _allowedPercentageOfTokens, + uint256[] _startTimes, + uint256[] _rollingPeriodInDays, + uint256[] _endTimes, + uint256[] _restrictionTypes + ) + public + withPerm(ADMIN) + { + _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + require(_holders.length == _allowedTokens.length, "Array length mismatch"); + for (uint256 i = 0; i < _holders.length; i++) { + _addIndividualRestriction( + _holders[i], + _allowedTokens[i], + _allowedPercentageOfTokens[i], + _startTimes[i], + _rollingPeriodInDays[i], + _endTimes[i], + _restrictionTypes[i] + ); + } } - function addVariableGlobalRestriciton( + /** + * @notice Use to add the new global restriction for all token holder + * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function addGlobalRestriction( + uint256 _allowedTokens, uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, - uint256 _endTime - ) + uint256 _endTime, + uint256 _restrictionType + ) public withPerm(ADMIN) - { - + { + require( + globalRestriction.endTime == 0 || globalRestriction.endTime > now, + "Restriction already present" + ); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + globalRestriction = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddNewGlobalRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); } - function modifyFixedIndividualRestriction( + /** + * @notice Use to modify the existing individual restriction for a given token holder + * @param _holder Address of the token holder, whom restriction will be implied + * @param _allowedTokens Amount of tokens allowed to be trade for a given address. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function modifyIndividualRestriction( address _holder, uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, - uint256 _endTime + uint256 _endTime, + uint256 _restrictionType ) public withPerm(ADMIN) { - + _modifyIndividualRestriction( + _holder, + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); } - function modifyVariableIndividualRestriction( - address _holder, + /** + * @notice Use to modify the existing individual restriction for multiple token holders + * @param _holders Array of address of the token holders, whom restriction will be implied + * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. + * @param _allowedPercentageOfTokens Array of percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTimes Array of unix timestamps at which restrictions get into effect + * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) + * @param _endTimes Array of unix timestamps at which restriction effects will gets end. + * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function modifyIndividualRestrictionMulti( + address[] _holders, + uint256[] _allowedTokens, + uint256[] _allowedPercentageOfTokens, + uint256[] _startTimes, + uint256[] _rollingPeriodInDays, + uint256[] _endTimes, + uint256[] _restrictionTypes + ) + public + withPerm(ADMIN) + { + _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + require(_holders.length == _allowedTokens.length, "Array length mismatch"); + for (uint256 i = 0; i < _holders.length; i++) { + _modifyIndividualRestriction( + _holders[i], + _allowedTokens[i], + _allowedPercentageOfTokens[i], + _startTimes[i], + _rollingPeriodInDays[i], + _endTimes[i], + _restrictionTypes[i] + ); + } + } + + /** + * @notice Use to modify the global restriction for all token holder + * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function modifyGlobalRestriction( + uint256 _allowedTokens, uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, - uint256 _endTime - ) + uint256 _endTime, + uint256 _restrictionType + ) public withPerm(ADMIN) - { - + { + require(globalRestriction.startTime > now, "Not allowed to modify"); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + globalRestriction = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyGlobalRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); } - function modifyFixedGlobalRestriction( + function _modifyIndividualRestriction( + address _holder, uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, - uint256 _endTime + uint256 _endTime, + uint256 _restrictionType ) - public - withPerm(ADMIN) - { + internal + { + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + require(individualRestriction[_holder].startTime > now, "Not allowed to modify"); + individualRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + bucketToUser[_holder] = BucketDetails(new uint256[](_rollingPeriodInDays), 0, 0, 0); + emit ModifyIndividualRestriction( + _holder, + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); } - function modifyVariableGlobalRestriciton( + function _addIndividualRestriction( + address _holder, + uint256 _allowedTokens, uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, - uint256 _endTime + uint256 _endTime, + uint256 _restrictionType + ) + internal + { + require( + individualRestriction[_holder].endTime == 0 || individualRestriction[_holder].endTime > now, + "Restriction already present" + ); + require(_holder != address(0) && !exemptList[_holder], "Invalid address"); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + + individualRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + bucketToUser[_holder] = BucketDetails(new uint256[](_rollingPeriodInDays), 0, 0, 0); + emit AddNewIndividualRestriction( + _holder, + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + function _checkInputParams( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodDays, + uint256 _endTime, + uint256 _restrictionType ) - public - withPerm(ADMIN) + internal + pure { + require(_restrictionType == 0 || _restrictionType == 1, "Invalid restriction type"); + if (_restrictionType == uint256(RestrictionType.Fixed)) { + require(_allowedTokens > 0, "Invalid value of allowed tokens"); + } else { + require( + _allowedPercentageOfTokens > 0 && _allowedPercentageOfTokens <= 100 * 10 ** 16, + "Percentage of tokens not within (0,100]" + ); + } + require(_startTime > 0 && _endTime > _startTime); + require(_rollingPeriodDays >= 1); + require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays); + } + + function _checkLengthOfArray( + uint256[] _allowedTokens, + uint256[] _allowedPercentageOfTokens, + uint256[] _startTimes, + uint256[] _rollingPeriodInDays, + uint256[] _endTimes, + uint256[] _restrictionTypes + ) + internal + pure + { + require( + _allowedTokens.length == _allowedPercentageOfTokens.length && + _allowedPercentageOfTokens.length == _startTimes.length && + _startTimes.length == _rollingPeriodInDays.length && + _rollingPeriodInDays.length == _endTimes.length && + _endTimes.length == _restrictionTypes.length, + "Array length mismatch" + ); + } + + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public view returns(bytes4) { + return bytes4(0); + } + /** + * @notice Returns the permissions flag that are associated with Percentage transfer Manager + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; } } diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol index 0c1821b17..5065b42d7 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol @@ -17,7 +17,7 @@ contract VolumeRestrictionTMFactory is ModuleFactory { version = "1.0.0"; name = "VolumeRestrictionTM"; title = "Volume Restriction Transfer Manager"; - description = "Manage transfers based on the volume of tokens that transact"; + description = "Manage transfers based on the volume of tokens that needs to be transact"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } From bfa6a5c5d841d15bfa19a4197299d11f29c7e7da Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 20 Nov 2018 13:05:16 +0200 Subject: [PATCH 127/582] updated VestingEscrowWallet to use it as a module --- contracts/modules/Wallet/IWallet.sol | 19 ++++ .../Wallet}/VestingEscrowWallet.sol | 88 ++++++++++++++----- .../Wallet/VestingEscrowWalletFactory.sol | 72 +++++++++++++++ 3 files changed, 157 insertions(+), 22 deletions(-) create mode 100644 contracts/modules/Wallet/IWallet.sol rename contracts/{wallet => modules/Wallet}/VestingEscrowWallet.sol (88%) create mode 100644 contracts/modules/Wallet/VestingEscrowWalletFactory.sol diff --git a/contracts/modules/Wallet/IWallet.sol b/contracts/modules/Wallet/IWallet.sol new file mode 100644 index 000000000..ea5c918d8 --- /dev/null +++ b/contracts/modules/Wallet/IWallet.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.4.24; + +import "../../Pausable.sol"; +import "../Module.sol"; + +/** + * @title Interface to be implemented by all Wallet modules + * @dev abstract contract + */ +contract IWallet is Module, Pausable { + + function unpause() public onlyOwner { + super._unpause(); + } + + function pause() public onlyOwner { + super._pause(); + } +} diff --git a/contracts/wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol similarity index 88% rename from contracts/wallet/VestingEscrowWallet.sol rename to contracts/modules/Wallet/VestingEscrowWallet.sol index 8c5d025e2..4c1e757f5 100644 --- a/contracts/wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -4,14 +4,17 @@ import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; +import "./IWallet.sol"; /** * @title Wallet for core vesting escrow functionality */ -contract VestingEscrowWallet is Ownable { +contract VestingEscrowWallet is IWallet { using SafeMath for uint256; using SafeERC20 for ERC20; + bytes32 public constant ADMIN = "ADMIN"; + struct Schedule { uint256 numberOfTokens; uint256 lockedTokens; @@ -71,15 +74,38 @@ contract VestingEscrowWallet is Ownable { event AddTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, uint256 _timestamp); event RemoveTemplate(uint256 _index, uint256 _timestamp); - constructor(address _tokenAddress, address _treasury) public { - token = ERC20(_tokenAddress); + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { + token = ERC20(_polyAddress); + } + + /** + * @notice Function used to initialize the different variables + * @param _treasury Address of the treasury + */ + function configure(address _treasury) public onlyFactory { + require(_treasury != address(0), "Invalid address"); treasury = _treasury; } + /** + * @notice This function returns the signature of the configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(keccak256("configure(address)")); + } + /** * @notice Used to deposit tokens from treasury */ - function depositTokens(uint256 _numberOfTokens) external onlyOwner { + function depositTokens(uint256 _numberOfTokens) external withPerm(ADMIN) { require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); token.safeTransferFrom(treasury, this, _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); @@ -90,7 +116,7 @@ contract VestingEscrowWallet is Ownable { /** * @notice Sends unassigned tokens to treasury */ - function sendToTreasury() external onlyOwner { + function sendToTreasury() external withPerm(ADMIN) { uint256 amount = unassignedTokens; unassignedTokens = 0; token.safeTransfer(treasury, amount); @@ -102,7 +128,7 @@ contract VestingEscrowWallet is Ownable { * @notice Sends available tokens to beneficiary * @param _beneficiary beneficiary's address */ - function sendAvailableTokens(address _beneficiary) public onlyOwner { + function sendAvailableTokens(address _beneficiary) public withPerm(ADMIN) { _sendTokens(_beneficiary); } @@ -119,7 +145,7 @@ contract VestingEscrowWallet is Ownable { * @param _duration vesting duration * @param _frequency vesting frequency */ - function addTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) external onlyOwner { + function addTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) external withPerm(ADMIN) { _validateTemplate(_numberOfTokens, _duration, _frequency); Template memory template; template.numberOfTokens = _numberOfTokens; @@ -134,7 +160,7 @@ contract VestingEscrowWallet is Ownable { * @notice Removes template * @param _index index of the template */ - function removeTemplate(uint256 _index) external onlyOwner { + function removeTemplate(uint256 _index) external withPerm(ADMIN) { require(_index < templates.length, "Template not found"); templates[_index] = templates[templates.length - 1]; templates.length--; @@ -146,7 +172,7 @@ contract VestingEscrowWallet is Ownable { * @notice Returns count of templates * @return count of templates */ - function getTemplateCount() external view onlyOwner returns(uint256) { + function getTemplateCount() external view withPerm(ADMIN) returns(uint256) { return templates.length; } @@ -166,7 +192,7 @@ contract VestingEscrowWallet is Ownable { uint256 _startTime ) public - onlyOwner + withPerm(ADMIN) { _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); require(_numberOfTokens <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); @@ -196,7 +222,7 @@ contract VestingEscrowWallet is Ownable { * @param _index index of the template * @param _startTime vesting start time */ - function addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) public onlyOwner { + function addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) public withPerm(ADMIN) { require(_index < templates.length, "Template not found"); Template storage template = templates[_index]; addSchedule(_beneficiary, template.numberOfTokens, template.duration, template.frequency, _startTime); @@ -220,7 +246,7 @@ contract VestingEscrowWallet is Ownable { uint256 _startTime ) public - onlyOwner + withPerm(ADMIN) { _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); @@ -247,7 +273,7 @@ contract VestingEscrowWallet is Ownable { * @param _beneficiary beneficiary's address * @param _index index of the schedule */ - function revokeSchedule(address _beneficiary, uint256 _index) external onlyOwner { + function revokeSchedule(address _beneficiary, uint256 _index) external withPerm(ADMIN) { require(_beneficiary != address(0), "Invalid beneficiary address"); require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); Schedule[] storage schedules = dataMap[_beneficiary].schedules; @@ -266,7 +292,7 @@ contract VestingEscrowWallet is Ownable { * @notice Revokes all beneficiary's schedules * @param _beneficiary beneficiary's address */ - function revokeSchedules(address _beneficiary) public onlyOwner { + function revokeSchedules(address _beneficiary) public withPerm(ADMIN) { require(_beneficiary != address(0), "Invalid beneficiary address"); Data storage data = dataMap[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { @@ -323,7 +349,7 @@ contract VestingEscrowWallet is Ownable { * @notice Used to bulk send available tokens for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses */ - function batchSendAvailableTokens(address[] _beneficiaries) external onlyOwner { + function batchSendAvailableTokens(address[] _beneficiaries) external withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { sendAvailableTokens(_beneficiaries[i]); } @@ -345,7 +371,7 @@ contract VestingEscrowWallet is Ownable { uint256 _startTime ) external - onlyOwner + withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { addSchedule(_beneficiaries[i], _numberOfTokens, _duration, _frequency, _startTime); @@ -358,7 +384,7 @@ contract VestingEscrowWallet is Ownable { * @param _index index of the template * @param _startTime vesting start time */ - function batchAddScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startTime) public onlyOwner { + function batchAddScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startTime) public withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { addScheduleFromTemplate(_beneficiaries[i], _index, _startTime); } @@ -368,7 +394,7 @@ contract VestingEscrowWallet is Ownable { * @notice Used to bulk revoke vesting schedules for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses */ - function batchRevokeSchedules(address[] _beneficiaries) external onlyOwner { + function batchRevokeSchedules(address[] _beneficiaries) external withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { revokeSchedules(_beneficiaries[i]); } @@ -392,7 +418,7 @@ contract VestingEscrowWallet is Ownable { uint256 _startTime ) external - onlyOwner + withPerm(ADMIN) { require(_beneficiaries.length == _indexes.length, "Beneficiaries array and indexes array should have the same length"); for (uint256 i = 0; i < _beneficiaries.length; i++) { @@ -400,7 +426,16 @@ contract VestingEscrowWallet is Ownable { } } - function _validateSchedule(address _beneficiary, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, uint256 _startTime) private view { + function _validateSchedule( + address _beneficiary, + uint256 _numberOfTokens, + uint256 _duration, + uint256 _frequency, + uint256 _startTime + ) + private + view + { require(_beneficiary != address(0), "Invalid beneficiary address"); _validateTemplate(_numberOfTokens, _duration, _frequency); require(now < _startTime, "Start date shouldn't be in the past"); @@ -428,7 +463,7 @@ contract VestingEscrowWallet is Ownable { * @notice manually triggers update outside for beneficiary's schedule (can be used to reduce user gas costs) * @param _beneficiary beneficiary's address of the schedule */ - function update(address _beneficiary) external onlyOwner { + function update(address _beneficiary) external withPerm(ADMIN) { _update(_beneficiary); } @@ -455,7 +490,7 @@ contract VestingEscrowWallet is Ownable { /** * @notice manually triggers update outside for all schedules (can be used to reduce user gas costs) */ - function updateAll() external onlyOwner { + function updateAll() external withPerm(ADMIN) { _updateAll(); } @@ -481,4 +516,13 @@ contract VestingEscrowWallet is Ownable { return (dataMap[_beneficiary].availableTokens == 0); } + /** + * @notice Return the permissions flag that are associated with VestingEscrowWallet + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; + } + } diff --git a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol new file mode 100644 index 000000000..8f187251c --- /dev/null +++ b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol @@ -0,0 +1,72 @@ +pragma solidity ^0.4.24; + +import "./VestingEscrowWallet.sol"; +import "../ModuleFactory.sol"; +import "../../libraries/Util.sol"; + +/** + * @title Factory for deploying VestingEscrowWallet module + */ +contract VestingEscrowWalletFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "VestingEscrowWallet"; + title = "Vesting Escrow Wallet"; + description = "Manage vesting schedules to employees / affiliates"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + } + + /** + * @notice Used to launch the Module with the help of factory + * _data Data used for the intialization of the module factory variables + * @return address Contract address of the Module + */ + function deploy(bytes _data) external returns(address) { + if (setupCost > 0) { + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance provided"); + } + VestingEscrowWallet vestingEscrowWallet = new VestingEscrowWallet(msg.sender, address(polyToken)); + //Checks that _data is valid (not calling anything it shouldn't) + require(Util.getSig(_data) == vestingEscrowWallet.getInitFunction(), "Invalid data"); + /*solium-disable-next-line security/no-low-level-calls*/ + require(address(vestingEscrowWallet).call(_data), "Unsuccessfull call"); + /*solium-disable-next-line security/no-block-members*/ + emit GenerateModuleFromFactory(address(vestingEscrowWallet), getName(), address(this), msg.sender, setupCost, now); + return address(vestingEscrowWallet); + } + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 6; + return res; + } + + /** + * @notice Returns the instructions associated with the module + */ + function getInstructions() external view returns(string) { + /*solium-disable-next-line max-len*/ + return "Issuer can send tokens to and then select the address that would be able to withdraw them according to their specific vesting schedule."; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() external view returns(bytes32[]) { + bytes32[] memory availableTags = new bytes32[](2); + availableTags[0] = "Vested Wallet"; + availableTags[1] = "Escrow"; + return availableTags; + } +} From 6aee7991a782dbd4a0b303e8906e1eca59637e41 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 20 Nov 2018 17:08:12 +0530 Subject: [PATCH 128/582] remove BokkyPooBahsDateTimeLibrary from coverage --- .solcover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.solcover.js b/.solcover.js index 23ac4d3ef..3a6f05092 100644 --- a/.solcover.js +++ b/.solcover.js @@ -4,6 +4,6 @@ module.exports = { copyPackages: ['openzeppelin-solidity'], testCommand: 'node ../node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js` --network coverage', deepSkip: true, - skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'storage', 'modules/Experimental'], + skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'libraries/BokkyPooBahsDateTimeLibrary.sol', 'storage', 'modules/Experimental'], forceParse: ['mocks', 'oracles', 'modules/Experimental'] }; From f805ad6da04e312a31c93755f83997e821c50182 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 20 Nov 2018 17:48:55 +0530 Subject: [PATCH 129/582] test file addition --- test/helpers/createInstances.js | 18 +++- test/z_volume_restriction_tm.js | 163 ++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 test/z_volume_restriction_tm.js diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 2021d350e..2303e7eed 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -30,6 +30,7 @@ const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); +const VolumeRestrictionTMFactory = artifacts.require("./VolumeRestrictionTMFactory.sol"); const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port @@ -48,6 +49,7 @@ let I_PercentageTransferManagerFactory; let I_EtherDividendCheckpointFactory; let I_CountTransferManagerFactory; let I_ERC20DividendCheckpointFactory; +let I_VolumeRestrictionTMFactory; let I_GeneralPermissionManagerFactory; let I_GeneralTransferManagerFactory; let I_GeneralTransferManager; @@ -196,7 +198,7 @@ export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, pol I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), + I_GeneralTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", "GeneralPermissionManagerFactory contract was not deployed" ); @@ -206,6 +208,20 @@ export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, pol return new Array(I_GeneralTransferManagerFactory); } +export async function deployVRTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { + I_VolumeRestrictionTMFactory = await VolumeRestrictionTMFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + + assert.notEqual( + I_VolumeRestrictionTMFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "VolumeRestrictionTMFactory contract was not deployed" + ); + + // (B) : Register the GeneralDelegateManagerFactory + await registerAndVerifyByMR(I_VolumeRestrictionTMFactory.address, accountPolymath, MRProxyInstance); + return new Array(I_VolumeRestrictionTMFactory); +} + export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { I_CountTransferManagerFactory = await CountTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js new file mode 100644 index 000000000..b6748c360 --- /dev/null +++ b/test/z_volume_restriction_tm.js @@ -0,0 +1,163 @@ +import latestTime from './helpers/latestTime'; +import {signData} from './helpers/signData'; +import { pk } from './helpers/testprivateKey'; +import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { catchRevert } from "./helpers/exceptions"; +import { setUpPolymathNetwork, deployVRTMAndVerifyed } from "./helpers/createInstances"; + +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager.sol'); +const VolumeRestrictionTM = artifacts.require('./VolumeRestrictionTM.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('VolumeRestrictionTransferManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let token_owner_pk; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_delegate; + let account_delegate2; + let account_delegate3; + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_VolumeRestrictionTMFactory; + let P_VolumeRestrictionTMFactory; + let I_SecurityTokenRegistryProxy; + let P_VolumeRestrictionTM; + let I_GeneralTransferManagerFactory; + let I_VolumeRestrictionTM; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_DummySTOFactory; + let I_STFactory; + let I_SecurityToken; + let I_MRProxied; + let I_STRProxied; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + const delegateDetails = "Hello I am legit delegate"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + token_owner_pk = pk.account_1; + + account_investor1 = accounts[8]; + account_investor2 = accounts[9]; + account_delegate = accounts[7]; + account_delegate2 = accounts[6]; + account_delegate3 = accounts[5]; + + // Step 1: Deploy the genral PM ecosystem + let instances = await setUpPolymathNetwork(account_polymath, token_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; + + // STEP 5: Deploy the VolumeRestrictionTMFactory + [I_VolumeRestrictionTMFactory] = await deployVRTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 6: Deploy the VolumeRestrictionTMFactory + [P_VolumeRestrictionTMFactory] = await deployVRTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${I_PolymathRegistry.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistryProxy ${I_ModuleRegistryProxy.address} + ModuleRegistry: ${I_ModuleRegistry.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + STFactory: ${I_STFactory.address} + GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + VolumeRestrictionTMFactory: ${I_VolumeRestrictionTMFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async () => { + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from: token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal(web3.utils.toAscii(log.args._name).replace(/\u0000/g, ""), "GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + }); + + describe("Attach the VRTM", async() => { + it("Deploy the VRTM and attach with the ST", async()=> { + + }) + }) +}); \ No newline at end of file From 0e357eba06e6673b76c7297018ee9ce3edc60674 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 20 Nov 2018 14:19:08 +0200 Subject: [PATCH 130/582] updated tests for VestingEscrowWallet --- test/helpers/createInstances.js | 28 +++++++-------- test/z_vesting_escrow_wallet.js | 64 ++++++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 23 deletions(-) diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 966602ba2..d31737346 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -30,7 +30,7 @@ const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); -const VestingEscrowWallet = artifacts.require("./VestingEscrowWallet.sol"); +const VestingEscrowWalletFactory = artifacts.require("./VestingEscrowWalletFactory.sol"); const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port @@ -51,6 +51,7 @@ let I_CountTransferManagerFactory; let I_ERC20DividendCheckpointFactory; let I_GeneralPermissionManagerFactory; let I_GeneralTransferManagerFactory; +let I_VestingEscrowWalletFactory; let I_GeneralTransferManager; let I_ModuleRegistryProxy; let I_PreSaleSTOFactory; @@ -66,7 +67,6 @@ let I_PolymathRegistry; let I_SecurityTokenRegistryProxy; let I_STRProxied; let I_MRProxied; -let I_VestingEscrowWallet; // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -397,6 +397,18 @@ export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstan return new Array(I_TrackedRedemptionFactory); } +export async function deployVestingEscrowWalletAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { + I_VestingEscrowWalletFactory = await VestingEscrowWalletFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + + assert.notEqual( + I_VestingEscrowWalletFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "VestingEscrowWalletFactory contract was not deployed" + ); + + await registerAndVerifyByMR(I_VestingEscrowWalletFactory.address, accountPolymath, MRProxyInstance); + return new Array(I_VestingEscrowWalletFactory); +} export async function deployMockRedemptionAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { I_MockBurnFactory = await MockBurnFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); @@ -424,18 +436,6 @@ export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, return new Array(I_MockWrongTypeBurnFactory); } -export async function deployVestingEscrowWallet(accountOwner, polyToken, treasury) { - I_VestingEscrowWallet = await VestingEscrowWallet.new(polyToken, treasury, { from: accountOwner }); - assert.notEqual( - I_VestingEscrowWallet.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "VestingEscrowWallet contract was not deployed" - ); - - return new Array(I_VestingEscrowWallet); -} - - /// Helper function function mergeReturn(returnData) { let returnArray = new Array(); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 32fbfb058..c3951b874 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -1,4 +1,4 @@ -import {deployPolyRegistryAndPolyToken, deployVestingEscrowWallet} from "./helpers/createInstances"; +import {deployVestingEscrowWalletAndVerifyed, setUpPolymathNetwork} from "./helpers/createInstances"; import latestTime from "./helpers/latestTime"; import {duration as durationUtil} from "./helpers/utils"; import {catchRevert} from "./helpers/exceptions"; @@ -13,8 +13,6 @@ const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); contract('VestingEscrowWallet', accounts => { const CREATED = 0; - const STARTED = 1; - const COMPLETED = 2; // Accounts Variable declaration let account_polymath; @@ -30,10 +28,39 @@ contract('VestingEscrowWallet', accounts => { let message = "Transaction Should Fail!"; // Contract Instance Declaration + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_ScheduledCheckpointFactory; + let I_GeneralPermissionManager; + let I_ScheduledCheckpoint; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_MRProxied; + let I_STFactory; + let I_SecurityToken; let I_VestingEscrowWallet; let I_PolyToken; let I_PolymathRegistry; + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + before(async () => { // Accounts setup account_polymath = accounts[0]; @@ -51,19 +78,38 @@ contract('VestingEscrowWallet', accounts => { account_beneficiary3 ]; - // Step 1: Deploy the PolyToken - [I_PolymathRegistry, I_PolyToken] = await deployPolyRegistryAndPolyToken(account_polymath, account_treasury); + // Step 1: Deploy the genral PM ecosystem + let instances = await setUpPolymathNetwork(account_polymath, wallet_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; // STEP 2: Deploy the VestingEscrowWallet - [I_VestingEscrowWallet] = await deployVestingEscrowWallet(wallet_owner, I_PolyToken.address, account_treasury); + [I_VestingEscrowWalletFactory] = await deployVestingEscrowWalletAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); // Printing all the contract addresses console.log(` --------------------- Polymath Network Smart Contracts: --------------------- PolymathRegistry: ${I_PolymathRegistry.address} - PolyToken: ${I_PolyToken.address} - - VestingEscrowWalle: ${I_VestingEscrowWallet.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistry: ${I_ModuleRegistry.address} + ModuleRegistryProxy: ${I_ModuleRegistryProxy.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + STFactory: ${I_STFactory.address} + GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} ----------------------------------------------------------------------------- `); }); From 99eeaf37068abc0bee375a0ce56995ee25314022 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 20 Nov 2018 15:27:27 +0200 Subject: [PATCH 131/582] changed error messages --- .../modules/Wallet/VestingEscrowWallet.sol | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 4c1e757f5..a1b8ee07b 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -106,7 +106,7 @@ contract VestingEscrowWallet is IWallet { * @notice Used to deposit tokens from treasury */ function depositTokens(uint256 _numberOfTokens) external withPerm(ADMIN) { - require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); + require(_numberOfTokens > 0, "Should be greater than zero"); token.safeTransferFrom(treasury, this, _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); /*solium-disable-next-line security/no-block-members*/ @@ -195,7 +195,7 @@ contract VestingEscrowWallet is IWallet { withPerm(ADMIN) { _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); - require(_numberOfTokens <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); + require(_numberOfTokens <= unassignedTokens, "Not enough tokens"); Schedule memory schedule; unassignedTokens = unassignedTokens.sub(_numberOfTokens); @@ -252,11 +252,11 @@ contract VestingEscrowWallet is IWallet { require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; /*solium-disable-next-line security/no-block-members*/ - require(now < schedule.startTime, "It's not possible to edit the started schedule"); + require(now < schedule.startTime, "Schedule started"); if (_numberOfTokens <= schedule.lockedTokens) { unassignedTokens = unassignedTokens.add(schedule.lockedTokens - _numberOfTokens); } else { - require((_numberOfTokens - schedule.lockedTokens) <= unassignedTokens, "Wallet doesn't contain enough unassigned tokens"); + require((_numberOfTokens - schedule.lockedTokens) <= unassignedTokens, "Not enough tokens"); unassignedTokens = unassignedTokens.sub(_numberOfTokens - schedule.lockedTokens); } schedule.numberOfTokens = _numberOfTokens; @@ -293,7 +293,7 @@ contract VestingEscrowWallet is IWallet { * @param _beneficiary beneficiary's address */ function revokeSchedules(address _beneficiary) public withPerm(ADMIN) { - require(_beneficiary != address(0), "Invalid beneficiary address"); + require(_beneficiary != address(0), "Invalid address"); Data storage data = dataMap[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { unassignedTokens = unassignedTokens.add(data.schedules[i].lockedTokens); @@ -311,7 +311,7 @@ contract VestingEscrowWallet is IWallet { * @return beneficiary's schedule */ function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256, uint256, uint256, State) { - require(_beneficiary != address(0), "Invalid beneficiary address"); + require(_beneficiary != address(0), "Invalid address"); require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; return ( @@ -331,7 +331,7 @@ contract VestingEscrowWallet is IWallet { * @return count of beneficiary's schedules */ function getScheduleCount(address _beneficiary) external view returns(uint256) { - require(_beneficiary != address(0), "Invalid beneficiary address"); + require(_beneficiary != address(0), "Invalid address"); return dataMap[_beneficiary].schedules.length; } @@ -341,7 +341,7 @@ contract VestingEscrowWallet is IWallet { * @return available tokens for beneficiary */ function getAvailableTokens(address _beneficiary) external view returns(uint256) { - require(_beneficiary != address(0), "Invalid beneficiary address"); + require(_beneficiary != address(0), "Invalid address"); return dataMap[_beneficiary].availableTokens; } @@ -420,7 +420,7 @@ contract VestingEscrowWallet is IWallet { external withPerm(ADMIN) { - require(_beneficiaries.length == _indexes.length, "Beneficiaries array and indexes array should have the same length"); + require(_beneficiaries.length == _indexes.length, "Arrays sizes mismatch"); for (uint256 i = 0; i < _beneficiaries.length; i++) { editSchedule(_beneficiaries[i], _indexes[i], _numberOfTokens, _duration, _frequency, _startTime); } @@ -436,22 +436,22 @@ contract VestingEscrowWallet is IWallet { private view { - require(_beneficiary != address(0), "Invalid beneficiary address"); + require(_beneficiary != address(0), "Invalid address"); _validateTemplate(_numberOfTokens, _duration, _frequency); - require(now < _startTime, "Start date shouldn't be in the past"); + require(now < _startTime, "Date in the past"); } function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) private pure { - require(_numberOfTokens > 0, "Number of tokens should be greater than zero"); - require(_duration % _frequency == 0, "Duration should be divided entirely by frequency"); + require(_numberOfTokens > 0, "Zero amount"); + require(_duration % _frequency == 0, "Duration and frequency mismatch"); uint256 periodCount = _duration.div(_frequency); - require(_numberOfTokens % periodCount == 0, "Number of tokens should be divided entirely by period count"); + require(_numberOfTokens % periodCount == 0, "Tokens and periods mismatch"); } function _sendTokens(address _beneficiary) private { Data storage data = dataMap[_beneficiary]; uint256 amount = data.availableTokens; - require(amount > 0, "Beneficiary doesn't have available tokens"); + require(amount > 0, "No tokens"); data.availableTokens = 0; data.claimedTokens = data.claimedTokens.add(amount); token.safeTransfer(_beneficiary, amount); From a6c7b5502aedafd10b5e816ac599afdb4aaada4d Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 20 Nov 2018 17:52:00 +0200 Subject: [PATCH 132/582] Initialization of VestingEscrowWallet module in tests --- .../modules/Wallet/VestingEscrowWallet.sol | 25 +++---- .../Wallet/VestingEscrowWalletFactory.sol | 2 +- test/z_vesting_escrow_wallet.js | 69 +++++++++++++++++-- 3 files changed, 79 insertions(+), 17 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index a1b8ee07b..d20db9c6b 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -487,18 +487,19 @@ contract VestingEscrowWallet is IWallet { } } - /** - * @notice manually triggers update outside for all schedules (can be used to reduce user gas costs) - */ - function updateAll() external withPerm(ADMIN) { - _updateAll(); - } - - function _updateAll() private { - for (uint256 i = 0; i < beneficiaries.length; i++) { - _update(beneficiaries[i]); - } - } + //TODO temporally for decreasing contract size +// /** +// * @notice manually triggers update outside for all schedules (can be used to reduce user gas costs) +// */ +// function updateAll() external withPerm(ADMIN) { +// _updateAll(); +// } +// +// function _updateAll() private { +// for (uint256 i = 0; i < beneficiaries.length; i++) { +// _update(beneficiaries[i]); +// } +// } function _revokeSchedules(address _beneficiary) private { if (_canBeRemoved(_beneficiary)) { diff --git a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol index 8f187251c..88db1919d 100644 --- a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol +++ b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol @@ -29,7 +29,7 @@ contract VestingEscrowWalletFactory is ModuleFactory { * _data Data used for the intialization of the module factory variables * @return address Contract address of the Module */ - function deploy(bytes _data) external returns(address) { + function deploy(bytes _data) external returns(address) { if (setupCost > 0) { require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance provided"); } diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index c3951b874..e228dd3f2 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -1,9 +1,12 @@ import {deployVestingEscrowWalletAndVerifyed, setUpPolymathNetwork} from "./helpers/createInstances"; import latestTime from "./helpers/latestTime"; -import {duration as durationUtil} from "./helpers/utils"; +import {duration as durationUtil, latestBlock, promisifyLogWatch} from "./helpers/utils"; import {catchRevert} from "./helpers/exceptions"; import {increaseTime} from "./helpers/time"; +import {encodeModuleCall} from "./helpers/encodeCall"; +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); const VestingEscrowWallet = artifacts.require('./VestingEscrowWallet.sol'); const Web3 = require('web3'); @@ -17,6 +20,7 @@ contract('VestingEscrowWallet', accounts => { // Accounts Variable declaration let account_polymath; let wallet_owner; + let token_owner; let account_treasury; let account_beneficiary1; let account_beneficiary2; @@ -30,9 +34,9 @@ contract('VestingEscrowWallet', accounts => { // Contract Instance Declaration let I_SecurityTokenRegistryProxy; let I_GeneralTransferManagerFactory; - let I_ScheduledCheckpointFactory; + let I_VestingEscrowWalletFactory; let I_GeneralPermissionManager; - let I_ScheduledCheckpoint; + let I_VestingEscrowWallet; let I_GeneralTransferManager; let I_ModuleRegistryProxy; let I_ModuleRegistry; @@ -42,7 +46,6 @@ contract('VestingEscrowWallet', accounts => { let I_MRProxied; let I_STFactory; let I_SecurityToken; - let I_VestingEscrowWallet; let I_PolyToken; let I_PolymathRegistry; @@ -65,6 +68,7 @@ contract('VestingEscrowWallet', accounts => { // Accounts setup account_polymath = accounts[0]; wallet_owner = accounts[1]; + token_owner = wallet_owner; account_treasury = accounts[2]; account_beneficiary1 = accounts[6]; @@ -114,6 +118,63 @@ contract('VestingEscrowWallet', accounts => { `); }); + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + + }); + + it("Should successfully attach the VestingEscrowWallet with the security token", async () => { + let bytesData = encodeModuleCall( + ["address"], + [account_treasury] + ); + + await I_SecurityToken.changeGranularity(1, {from: token_owner}); + const tx = await I_SecurityToken.addModule(I_VestingEscrowWalletFactory.address, bytesData, 0, 0, { from: token_owner }); + + assert.equal(tx.logs[2].args._types[0].toNumber(), 6, "VestingEscrowWallet doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "VestingEscrowWallet", + "VestingEscrowWallet module was not added" + ); + I_VestingEscrowWallet = VestingEscrowWallet.at(tx.logs[2].args._module); + }); + + }); + describe("Depositing and withdrawing tokens", async () => { it("Should fail to deposit zero amount of tokens", async () => { From afb4baee9b5e1a4f5b8b7902e0e8c3f2f2f55ed4 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 21 Nov 2018 10:46:03 +0530 Subject: [PATCH 133/582] Added helper view functions --- contracts/modules/STO/USDTieredSTO.sol | 164 ++++++++++++++++++++----- 1 file changed, 130 insertions(+), 34 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index e5e7bb3aa..d20b98884 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -491,45 +491,25 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { internal nonReentrant whenNotPaused - returns(uint256, uint256) + returns(uint256 spentUSD, uint256 spentValue) { - if (!allowBeneficialInvestments) { - require(_beneficiary == msg.sender, "Beneficiary != funder"); - } - - require(isOpen(), "STO not open"); - require(_investmentValue > 0, "No funds were sent"); - uint256 investedUSD = DecimalMath.mul(_rate, _investmentValue); - _rate = investedUSD; // Reusing variable to prevent stackoverflow - // Check for minimum investment - require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); + investedUSD = _buyTokensChecks(_beneficiary, _investmentValue, investedUSD); - // Check for non-accredited cap - if (!accredited[_beneficiary]) { - uint256 investorLimitUSD = (nonAccreditedLimitUSDOverride[_beneficiary] == 0) ? nonAccreditedLimitUSD : nonAccreditedLimitUSDOverride[_beneficiary]; - require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Over Non-accredited investor limit"); - if (investedUSD.add(investorInvestedUSD[_beneficiary]) > investorLimitUSD) - investedUSD = investorLimitUSD.sub(investorInvestedUSD[_beneficiary]); - } - uint256 spentUSD; - uint256 spentValue; - // Iterate over each tier and process payment for (uint256 i = currentTier; i < tiers.length; i++) { bool gotoNextTier; + uint256 tempSpentUSD; // Update current tier if needed if (currentTier != i) currentTier = i; // If there are tokens remaining, process investment if (tiers[i].mintedTotal < tiers[i].tokenTotal) { - //spentValue used as temp variable here to prevent stackoverflow - (spentValue, gotoNextTier) = _calculateTier(_beneficiary, i, investedUSD.sub(spentUSD), _fundRaiseType); - spentUSD = spentUSD.add(spentValue); + (tempSpentUSD, gotoNextTier) = _calculateTier(_beneficiary, i, investedUSD.sub(spentUSD), _fundRaiseType); + spentUSD = spentUSD.add(tempSpentUSD); // If all funds have been spent, exit the loop if (!gotoNextTier) break; } - } // Modify storage @@ -540,15 +520,74 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { fundsRaisedUSD = fundsRaisedUSD.add(spentUSD); } - if (spentUSD == 0) { - spentValue = 0; - } else { - //_rate is actually OriginalUSD. Reusing variable to prevent stackoverflow - spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, _rate), _investmentValue); + spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, investedUSD), _investmentValue); + } + + /** + * @notice Getter function for buyer to calculate how many tokens will they get + * @param _beneficiary Address where security tokens are to be sent + * @param _investmentValue Amount of POLY, ETH or DAI invested + * @param _fundRaiseType Fund raise type (POLY, ETH, DAI) + */ + function buyTokensView( + address _beneficiary, + uint256 _investmentValue, + FundRaiseType _fundRaiseType + ) + public + view + returns(uint256 spentUSD, uint256 spentValue, uint256 tokensMinted) + { + require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI, "Invalid raise type"); + uint256 rate = getRate(_fundRaiseType); + uint256 investedUSD = DecimalMath.mul(rate, _investmentValue); + investedUSD = _buyTokensChecks(_beneficiary, _investmentValue, investedUSD); + + // Iterate over each tier and process payment + for (uint256 i = currentTier; i < tiers.length; i++) { + bool gotoNextTier; + uint256 tempSpentUSD; + uint256 tempTokensMinted; + // If there are tokens remaining, process investment + if (tiers[i].mintedTotal < tiers[i].tokenTotal) { + (tempSpentUSD, gotoNextTier, tempTokensMinted) = _calculateTierView(i, investedUSD.sub(spentUSD), _fundRaiseType); + spentUSD = spentUSD.add(tempSpentUSD); + tokensMinted = tokensMinted.add(tempTokensMinted); + // If all funds have been spent, exit the loop + if (!gotoNextTier) + break; + } + } + + spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, investedUSD), _investmentValue); + } + + function _buyTokensChecks( + address _beneficiary, + uint256 _investmentValue, + uint256 investedUSD + ) + internal + view + returns(uint256 netInvestedUSD) + { + if (!allowBeneficialInvestments) { + require(_beneficiary == msg.sender, "Beneficiary != funder"); } - // Return calculated amounts - return (spentUSD, spentValue); + require(isOpen(), "STO not open"); + require(_investmentValue > 0, "No funds were sent"); + + // Check for minimum investment + require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); + netInvestedUSD = investedUSD; + // Check for non-accredited cap + if (!accredited[_beneficiary]) { + uint256 investorLimitUSD = (nonAccreditedLimitUSDOverride[_beneficiary] == 0) ? nonAccreditedLimitUSD : nonAccreditedLimitUSDOverride[_beneficiary]; + require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Over Non-accredited investor limit"); + if (investedUSD.add(investorInvestedUSD[_beneficiary]) > investorLimitUSD) + netInvestedUSD = investorLimitUSD.sub(investorInvestedUSD[_beneficiary]); + } } function _calculateTier( @@ -587,6 +626,37 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } } + function _calculateTierView( + uint256 _tier, + uint256 _investedUSD, + FundRaiseType _fundRaiseType + ) + internal + view + returns(uint256 spentUSD, bool gotoNextTier, uint256 tokensMinted) + { + // First purchase any discounted tokens if POLY investment + uint256 tierSpentUSD; + uint256 tierPurchasedTokens; + Tier storage tierData = tiers[_tier]; + // Check whether there are any remaining discounted tokens + if ((_fundRaiseType == FundRaiseType.POLY) && (tierData.tokensDiscountPoly > tierData.mintedDiscountPoly)) { + uint256 discountRemaining = tierData.tokensDiscountPoly.sub(tierData.mintedDiscountPoly); + uint256 totalRemaining = tierData.tokenTotal.sub(tierData.mintedTotal); + if (totalRemaining < discountRemaining) + (spentUSD, tokensMinted, gotoNextTier) = _purchaseTierAmount(tierData.rateDiscountPoly, totalRemaining, _investedUSD); + else + (spentUSD, tokensMinted, gotoNextTier) = _purchaseTierAmount(tierData.rateDiscountPoly, discountRemaining, _investedUSD); + _investedUSD = _investedUSD.sub(spentUSD); + } + // Now, if there is any remaining USD to be invested, purchase at non-discounted rate + if ((_investedUSD > 0) && (tierData.tokenTotal.sub(tierData.mintedTotal.add(tokensMinted)) > 0)) { + (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTierAmount(tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), _investedUSD); + spentUSD = spentUSD.add(tierSpentUSD); + tokensMinted = tokensMinted.add(tierPurchasedTokens); + } + } + function _purchaseTier( address _beneficiary, uint256 _tierPrice, @@ -596,6 +666,20 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { ) internal returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) + { + (spentUSD, purchasedTokens, gotoNextTier) = _purchaseTierAmount(_tierPrice, _tierRemaining, _investedUSD); + require(ISecurityToken(securityToken).mint(_beneficiary, purchasedTokens), "Error in minting"); + emit TokenPurchase(msg.sender, _beneficiary, purchasedTokens, spentUSD, _tierPrice, _tier); + } + + function _purchaseTierAmount( + uint256 _tierPrice, + uint256 _tierRemaining, + uint256 _investedUSD + ) + internal + view + returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) { uint256 maximumTokens = DecimalMath.div(_investedUSD, _tierPrice); uint256 granularity = ISecurityToken(securityToken).granularity(); @@ -613,8 +697,6 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { spentUSD = DecimalMath.mul(maximumTokens, _tierPrice); purchasedTokens = maximumTokens; } - require(ISecurityToken(securityToken).mint(_beneficiary, purchasedTokens), "Error in minting"); - emit TokenPurchase(msg.sender, _beneficiary, purchasedTokens, spentUSD, _tierPrice, _tier); } ///////////// @@ -724,6 +806,20 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { return tokensSold; } + /** + * @notice Return array of minted tokens in each fund raise type for given tier + * param _tier The tier to return minted tokens for + * @return uint256[] array of minted tokens in each fund raise type + */ + function getTokensMintedByTier(uint256 _tier) public view returns (uint256[]) { + require(_tier < tiers.length, "Invalid tier"); + uint256[] memory tokensMinted = new uint256[](3); + tokensMinted[0] = tiers[_tier].minted[uint8(FundRaiseType.ETH)]; + tokensMinted[1] = tiers[_tier].minted[uint8(FundRaiseType.POLY)]; + tokensMinted[2] = tiers[_tier].minted[uint8(FundRaiseType.DAI)]; + return tokensMinted; + } + /** * @notice Return the total no. of tokens sold in a given tier * param _tier The tier to calculate sold tokens for From 1f992cb9c8b523cdd679578b322e5a88fe467742 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 21 Nov 2018 10:46:37 +0530 Subject: [PATCH 134/582] Updated gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1693ab75c..395634f11 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,7 @@ package-lock.json bridge.log .node-xml* .solcover.js.bk -allFiredEvents \ No newline at end of file +allFiredEvents +extract/ +extract.py +extract.zip \ No newline at end of file From efcde8aefa89961d871d5b6e069139dd5fcaa4e3 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 21 Nov 2018 10:53:18 +0530 Subject: [PATCH 135/582] Bug fix --- contracts/modules/STO/USDTieredSTO.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index d20b98884..9ddeb4c8b 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -493,8 +493,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { whenNotPaused returns(uint256 spentUSD, uint256 spentValue) { - uint256 investedUSD = DecimalMath.mul(_rate, _investmentValue); - investedUSD = _buyTokensChecks(_beneficiary, _investmentValue, investedUSD); + uint256 originalUSD = DecimalMath.mul(_rate, _investmentValue); + uint256 allowedUSD = _buyTokensChecks(_beneficiary, _investmentValue, originalUSD); for (uint256 i = currentTier; i < tiers.length; i++) { bool gotoNextTier; @@ -504,7 +504,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { currentTier = i; // If there are tokens remaining, process investment if (tiers[i].mintedTotal < tiers[i].tokenTotal) { - (tempSpentUSD, gotoNextTier) = _calculateTier(_beneficiary, i, investedUSD.sub(spentUSD), _fundRaiseType); + (tempSpentUSD, gotoNextTier) = _calculateTier(_beneficiary, i, allowedUSD.sub(spentUSD), _fundRaiseType); spentUSD = spentUSD.add(tempSpentUSD); // If all funds have been spent, exit the loop if (!gotoNextTier) @@ -520,7 +520,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { fundsRaisedUSD = fundsRaisedUSD.add(spentUSD); } - spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, investedUSD), _investmentValue); + spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, originalUSD), _investmentValue); } /** @@ -540,8 +540,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { { require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI, "Invalid raise type"); uint256 rate = getRate(_fundRaiseType); - uint256 investedUSD = DecimalMath.mul(rate, _investmentValue); - investedUSD = _buyTokensChecks(_beneficiary, _investmentValue, investedUSD); + uint256 originalUSD = DecimalMath.mul(rate, _investmentValue); + uint256 allowedUSD = _buyTokensChecks(_beneficiary, _investmentValue, originalUSD); // Iterate over each tier and process payment for (uint256 i = currentTier; i < tiers.length; i++) { @@ -550,7 +550,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 tempTokensMinted; // If there are tokens remaining, process investment if (tiers[i].mintedTotal < tiers[i].tokenTotal) { - (tempSpentUSD, gotoNextTier, tempTokensMinted) = _calculateTierView(i, investedUSD.sub(spentUSD), _fundRaiseType); + (tempSpentUSD, gotoNextTier, tempTokensMinted) = _calculateTierView(i, allowedUSD.sub(spentUSD), _fundRaiseType); spentUSD = spentUSD.add(tempSpentUSD); tokensMinted = tokensMinted.add(tempTokensMinted); // If all funds have been spent, exit the loop @@ -559,7 +559,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } } - spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, investedUSD), _investmentValue); + spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, originalUSD), _investmentValue); } function _buyTokensChecks( From b6221ac14ff05460c3eb9d7f3ccfd64a9e9bb64d Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 21 Nov 2018 10:58:44 +0530 Subject: [PATCH 136/582] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a99b5f767..1c2ec5fdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. [__2.1.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-09-18__ ## Added +* Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. * Added `getSTODetails` to USDTSTO. * Added an Array of Tiers that will hold data about every tier in USDTSTO. * Added `buyWithETHRateLimited`, `buyWithPOLYRateLimited` and `buyWithUSDRateLimited` to USDTSTO. From e16a4671380f8fdf9d028eddff1892c6484cbd08 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 21 Nov 2018 11:57:09 +0530 Subject: [PATCH 137/582] Added test cases --- contracts/modules/STO/USDTieredSTO.sol | 8 ++++---- test/p_usd_tiered_sto.js | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 9ddeb4c8b..1c424cba0 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -493,6 +493,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { whenNotPaused returns(uint256 spentUSD, uint256 spentValue) { + if (!allowBeneficialInvestments) { + require(_beneficiary == msg.sender, "Beneficiary != funder"); + } + uint256 originalUSD = DecimalMath.mul(_rate, _investmentValue); uint256 allowedUSD = _buyTokensChecks(_beneficiary, _investmentValue, originalUSD); @@ -571,10 +575,6 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { view returns(uint256 netInvestedUSD) { - if (!allowBeneficialInvestments) { - require(_beneficiary == msg.sender, "Beneficiary != funder"); - } - require(isOpen(), "STO not open"); require(_investmentValue > 0, "No funds were sent"); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 86a2eded4..604eb1aaf 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -3790,6 +3790,8 @@ contract("USDTieredSTO", accounts => { let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + let tokensToMint = (await I_USDTieredSTO_Array[stoId].buyTokensView(ACCREDITED1, investment_POLY,POLY))[2]; + // Buy With POLY let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1, @@ -3818,6 +3820,11 @@ contract("USDTieredSTO", accounts => { .toNumber(), "Token Supply not changed as expected" ); + assert.equal( + tokensToMint.toNumber(), + investment_Tokens.sub(refund_Tokens).toNumber(), + "View function returned incorrect data" + ); assert.equal( final_InvestorTokenBal.toNumber(), init_InvestorTokenBal @@ -4475,6 +4482,18 @@ contract("USDTieredSTO", accounts => { "fundsRaisedUSD not changed as expected" ); }); + + it("should return minted tokens in a tier", async () => { + let totalMinted = (await I_USDTieredSTO_Array[0].getTokensSoldByTier.call(0)).toNumber(); + let individualMinted = await I_USDTieredSTO_Array[0].getTokensMintedByTier.call(0); + assert.equal(totalMinted, individualMinted[0].add(individualMinted[1]).add(individualMinted[2]).toNumber()); + }); + + it("should return correct tokens sold in token details", async () => { + let tokensSold = (await I_USDTieredSTO_Array[0].getTokensSold.call()).toNumber(); + let tokenDetails = await I_USDTieredSTO_Array[0].getSTODetails.call(); + assert.equal(tokensSold, tokenDetails[7].toNumber()); + }); }); describe("convertToUSD", async () => { From d28da6f2ba768390098f678e0a7bb9fc225bcb74 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 21 Nov 2018 10:51:35 +0200 Subject: [PATCH 138/582] fixed tests --- test/z_vesting_escrow_wallet.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index e228dd3f2..776e48bec 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -68,8 +68,8 @@ contract('VestingEscrowWallet', accounts => { // Accounts setup account_polymath = accounts[0]; wallet_owner = accounts[1]; - token_owner = wallet_owner; - account_treasury = accounts[2]; + token_owner = accounts[1]; + account_treasury = accounts[1]; account_beneficiary1 = accounts[6]; account_beneficiary2 = accounts[7]; @@ -83,7 +83,7 @@ contract('VestingEscrowWallet', accounts => { ]; // Step 1: Deploy the genral PM ecosystem - let instances = await setUpPolymathNetwork(account_polymath, wallet_owner); + let instances = await setUpPolymathNetwork(account_polymath, token_owner); [ I_PolymathRegistry, @@ -114,6 +114,8 @@ contract('VestingEscrowWallet', accounts => { STFactory: ${I_STFactory.address} GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + + I_VestingEscrowWalletFactory: ${I_VestingEscrowWalletFactory.address} ----------------------------------------------------------------------------- `); }); From a361ffec7566fcb94cb2bafd974c0767595a0a41 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 21 Nov 2018 11:24:33 +0200 Subject: [PATCH 139/582] use delegate instead of owner in tests --- test/z_vesting_escrow_wallet.js | 210 ++++++++++++++++++-------------- 1 file changed, 121 insertions(+), 89 deletions(-) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 776e48bec..e53d4a40a 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -1,4 +1,4 @@ -import {deployVestingEscrowWalletAndVerifyed, setUpPolymathNetwork} from "./helpers/createInstances"; +import {setUpPolymathNetwork, deployGPMAndVerifyed, deployVestingEscrowWalletAndVerifyed} from "./helpers/createInstances"; import latestTime from "./helpers/latestTime"; import {duration as durationUtil, latestBlock, promisifyLogWatch} from "./helpers/utils"; import {catchRevert} from "./helpers/exceptions"; @@ -7,6 +7,7 @@ import {encodeModuleCall} from "./helpers/encodeCall"; const SecurityToken = artifacts.require('./SecurityToken.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const VestingEscrowWallet = artifacts.require('./VestingEscrowWallet.sol'); const Web3 = require('web3'); @@ -19,9 +20,8 @@ contract('VestingEscrowWallet', accounts => { // Accounts Variable declaration let account_polymath; - let wallet_owner; let token_owner; - let account_treasury; + let wallet_admin; let account_beneficiary1; let account_beneficiary2; let account_beneficiary3; @@ -33,6 +33,7 @@ contract('VestingEscrowWallet', accounts => { // Contract Instance Declaration let I_SecurityTokenRegistryProxy; + let I_GeneralPermissionManagerFactory; let I_GeneralTransferManagerFactory; let I_VestingEscrowWalletFactory; let I_GeneralPermissionManager; @@ -55,6 +56,7 @@ contract('VestingEscrowWallet', accounts => { const tokenDetails = "This is equity type of issuance"; const decimals = 18; const contact = "team@polymath.network"; + const delegateDetails = "Hello I am legit delegate"; // Module key const delegateManagerKey = 1; @@ -67,9 +69,8 @@ contract('VestingEscrowWallet', accounts => { before(async () => { // Accounts setup account_polymath = accounts[0]; - wallet_owner = accounts[1]; token_owner = accounts[1]; - account_treasury = accounts[1]; + wallet_admin = accounts[2]; account_beneficiary1 = accounts[6]; account_beneficiary2 = accounts[7]; @@ -99,7 +100,10 @@ contract('VestingEscrowWallet', accounts => { I_STRProxied ] = instances; - // STEP 2: Deploy the VestingEscrowWallet + // STEP 2: Deploy the GeneralDelegateManagerFactory + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + // STEP 3: Deploy the VestingEscrowWallet [I_VestingEscrowWalletFactory] = await deployVestingEscrowWalletAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); // Printing all the contract addresses @@ -114,6 +118,7 @@ contract('VestingEscrowWallet', accounts => { STFactory: ${I_STFactory.address} GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${I_GeneralPermissionManagerFactory.address} I_VestingEscrowWalletFactory: ${I_VestingEscrowWalletFactory.address} ----------------------------------------------------------------------------- @@ -156,10 +161,21 @@ contract('VestingEscrowWallet', accounts => { }); + it("Should successfully attach the General permission manager factory with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "GeneralPermissionManager", + "GeneralPermissionManagerFactory module was not added" + ); + I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); + }); + it("Should successfully attach the VestingEscrowWallet with the security token", async () => { let bytesData = encodeModuleCall( ["address"], - [account_treasury] + [token_owner] ); await I_SecurityToken.changeGranularity(1, {from: token_owner}); @@ -175,20 +191,36 @@ contract('VestingEscrowWallet', accounts => { I_VestingEscrowWallet = VestingEscrowWallet.at(tx.logs[2].args._module); }); + it("Should successfully add the delegate", async() => { + let tx = await I_GeneralPermissionManager.addDelegate(wallet_admin, delegateDetails, { from: token_owner}); + assert.equal(tx.logs[0].args._delegate, wallet_admin); + }); + + it("Should provide the permission", async() => { + let tx = await I_GeneralPermissionManager.changePermission( + wallet_admin, + I_VestingEscrowWallet.address, + "ADMIN", + true, + {from: token_owner} + ); + assert.equal(tx.logs[0].args._delegate, wallet_admin); + }); + }); describe("Depositing and withdrawing tokens", async () => { it("Should fail to deposit zero amount of tokens", async () => { await catchRevert( - I_VestingEscrowWallet.depositTokens(0, {from: wallet_owner}) + I_VestingEscrowWallet.depositTokens(0, {from: wallet_admin}) ); }); it("Should deposit tokens for new vesting schedules", async () => { let numberOfTokens = 25000; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); - const tx = await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + const tx = await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); @@ -201,7 +233,7 @@ contract('VestingEscrowWallet', accounts => { it("Should withdraw tokens to a treasury", async () => { let numberOfTokens = 25000; - const tx = await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + const tx = await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); @@ -214,7 +246,7 @@ contract('VestingEscrowWallet', accounts => { it("Should fail to send available tokens -- fail because beneficiary doesn't have available tokens", async () => { catchRevert( - I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: wallet_owner}) + I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: wallet_admin}) ); }); @@ -224,20 +256,20 @@ contract('VestingEscrowWallet', accounts => { let frequency = durationUtil.seconds(10); let timeShift = durationUtil.seconds(100); let startTime = latestTime() + timeShift; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); - await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); - await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency); - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_admin}); - const tx = await I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens / 3); let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens / 3); - await I_PolyToken.transfer(account_treasury, balance, {from: account_beneficiary3}); + await I_PolyToken.transfer(token_owner, balance, {from: account_beneficiary3}); }); it("Should fail to edit vesting schedule -- fail because schedule already started", async () => { @@ -247,11 +279,11 @@ contract('VestingEscrowWallet', accounts => { let timeShift = durationUtil.seconds(100); let startTime = latestTime() + timeShift; await catchRevert( - I_VestingEscrowWallet.editSchedule(account_beneficiary3, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + I_VestingEscrowWallet.editSchedule(account_beneficiary3, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) ); - await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_owner}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should withdraw available tokens to the beneficiary address", async () => { @@ -260,12 +292,12 @@ contract('VestingEscrowWallet', accounts => { let frequency = durationUtil.seconds(10); let timeShift = durationUtil.seconds(100); let startTime = latestTime() + timeShift; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); - await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); - await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency * 3); for (let i = 0; i < 4; i++) { - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_admin}); } const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); @@ -275,9 +307,9 @@ contract('VestingEscrowWallet', accounts => { let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens); - await I_PolyToken.transfer(account_treasury, balance, {from: account_beneficiary3}); - await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_owner}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + await I_PolyToken.transfer(token_owner, balance, {from: account_beneficiary3}); + await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should withdraw available tokens by 3 schedules to the beneficiary address", async () => { @@ -295,19 +327,19 @@ contract('VestingEscrowWallet', accounts => { ]; let totalNumberOfTokens = getTotalNumberOfTokens(schedules); - await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); for (let i = 0; i < schedules.length; i++) { let numberOfTokens = schedules[i].numberOfTokens; let duration = schedules[i].duration; let frequency = schedules[i].frequency; let startTime = latestTime() + durationUtil.seconds(100); - await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); } await increaseTime(durationUtil.minutes(5)); let stepCount = 4; for (let i = 0; i < stepCount; i++) { - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_owner}); + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_admin}); } let numberOfTokens = (30000 / 6 * stepCount) + (2000 / 10 * stepCount); const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); @@ -317,9 +349,9 @@ contract('VestingEscrowWallet', accounts => { let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens); - await I_PolyToken.transfer(account_treasury, balance, {from: account_beneficiary3}); - await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_owner}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + await I_PolyToken.transfer(token_owner, balance, {from: account_beneficiary3}); + await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); }); @@ -349,37 +381,37 @@ contract('VestingEscrowWallet', accounts => { it("Should fail to add vesting schedule to the beneficiary address -- fail because not enough unassigned tokens", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to add vesting schedule to the beneficiary address -- fail because address in invalid", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(0, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) + I_VestingEscrowWallet.addSchedule(0, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to add vesting schedule to the beneficiary address -- fail because start date in the past", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() - durationUtil.days(1), {from: wallet_owner}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() - durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to add vesting schedule to the beneficiary address -- fail because number of tokens is 0", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 0, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 0, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to add vesting schedule to the beneficiary address -- fail because duration can't be divided entirely by frequency", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 3, latestTime() + durationUtil.days(1), {from: wallet_owner}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 3, latestTime() + durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to add vesting schedule to the beneficiary address -- fail because number of tokens can't be divided entirely by period count", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 5, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_owner}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 5, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) ); }); @@ -412,9 +444,9 @@ contract('VestingEscrowWallet', accounts => { let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: account_treasury}); - await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); - const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); let log = tx.logs[0]; checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); @@ -432,7 +464,7 @@ contract('VestingEscrowWallet', accounts => { let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; await catchRevert( - I_VestingEscrowWallet.editSchedule(account_beneficiary1, 1, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + I_VestingEscrowWallet.editSchedule(account_beneficiary1, 1, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) ); }); @@ -442,7 +474,7 @@ contract('VestingEscrowWallet', accounts => { let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; await catchRevert( - I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) ); }); @@ -451,7 +483,7 @@ contract('VestingEscrowWallet', accounts => { let duration = schedules[1].duration; let frequency = schedules[1].frequency; let startTime = schedules[1].startTime; - const tx = await I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); let log = tx.logs[0]; checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); @@ -472,25 +504,25 @@ contract('VestingEscrowWallet', accounts => { let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; await catchRevert( - I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) ); }); it("Should fail to revoke vesting schedule -- fail because address is invalid", async () => { await catchRevert( - I_VestingEscrowWallet.revokeSchedule(0, 0, {from: wallet_owner}) + I_VestingEscrowWallet.revokeSchedule(0, 0, {from: wallet_admin}) ); }); it("Should fail to revoke vesting schedule -- fail because schedule not found", async () => { await catchRevert( - I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_owner}) + I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_admin}) ); }); it("Should revoke vesting schedule from the beneficiary address", async () => { - const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); assert.equal(tx.logs[0].args._index, 0); @@ -501,20 +533,20 @@ contract('VestingEscrowWallet', accounts => { it("Should fail to revoke vesting schedules -- fail because address is invalid", async () => { await catchRevert( - I_VestingEscrowWallet.revokeSchedules(0, {from: wallet_owner}) + I_VestingEscrowWallet.revokeSchedules(0, {from: wallet_admin}) ); }); it("Should add 3 vesting schedules to the beneficiary address", async () => { let totalNumberOfTokens = getTotalNumberOfTokens(schedules); - await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); for (let i = 0; i < schedules.length; i++) { let numberOfTokens = schedules[i].numberOfTokens; let duration = schedules[i].duration; let frequency = schedules[i].frequency; let startTime = schedules[i].startTime; - const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary2, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary2, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); let log = tx.logs[0]; checkScheduleLog(log, account_beneficiary2, numberOfTokens, duration, frequency, startTime); @@ -528,8 +560,8 @@ contract('VestingEscrowWallet', accounts => { }); it("Should revoke vesting schedule from the beneficiary address", async () => { - const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, 1, {from: wallet_owner}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, 1, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); assert.equal(tx.logs[0].args._index, 1); @@ -543,8 +575,8 @@ contract('VestingEscrowWallet', accounts => { }); it("Should revoke 2 vesting schedules from the beneficiary address", async () => { - const tx = await I_VestingEscrowWallet.revokeSchedules(account_beneficiary2, {from: wallet_owner}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + const tx = await I_VestingEscrowWallet.revokeSchedules(account_beneficiary2, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); @@ -582,7 +614,7 @@ contract('VestingEscrowWallet', accounts => { let numberOfTokens = schedules[i].numberOfTokens; let duration = schedules[i].duration; let frequency = schedules[i].frequency; - const tx = await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); assert.equal(tx.logs[0].args._duration.toNumber(), duration); @@ -591,7 +623,7 @@ contract('VestingEscrowWallet', accounts => { }); it("Should remove template", async () => { - const tx = await I_VestingEscrowWallet.removeTemplate(1, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.removeTemplate(1, {from: wallet_admin}); assert.equal(tx.logs[0].args._index, 1); }); @@ -599,7 +631,7 @@ contract('VestingEscrowWallet', accounts => { it("Should fail to add vesting schedule from template -- fail because template not found", async () => { let startTime = schedules[2].startTime; await catchRevert( - I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_owner}) + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_admin}) ); }); @@ -608,9 +640,9 @@ contract('VestingEscrowWallet', accounts => { let duration = schedules[2].duration; let frequency = schedules[2].frequency; let startTime = schedules[2].startTime; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: account_treasury }); - await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_owner}); - const tx = await I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_owner}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_admin}); let log = tx.logs[0]; checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); @@ -621,21 +653,21 @@ contract('VestingEscrowWallet', accounts => { let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); - await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_owner}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should fail to remove template", async () => { await catchRevert( - I_VestingEscrowWallet.removeTemplate(2, {from: wallet_owner}) + I_VestingEscrowWallet.removeTemplate(2, {from: wallet_admin}) ); }); it("Should remove 2 Templates", async () => { - await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_owner}); - await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_owner}); + await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_admin}); - let templateCount = await I_VestingEscrowWallet.getTemplateCount.call({from: wallet_owner}); + let templateCount = await I_VestingEscrowWallet.getTemplateCount.call({from: wallet_admin}); assert.equal(templateCount, 0); }); @@ -650,10 +682,10 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + durationUtil.seconds(100); let totalNumberOfTokens = numberOfTokens * 3; - await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); - let tx = await I_VestingEscrowWallet.batchAddSchedule(beneficiaries, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + let tx = await I_VestingEscrowWallet.batchAddSchedule(beneficiaries, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; @@ -677,7 +709,7 @@ contract('VestingEscrowWallet', accounts => { let indexes = [0, 0, 0, 0]; await catchRevert( - I_VestingEscrowWallet.batchEditSchedule(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}) + I_VestingEscrowWallet.batchEditSchedule(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) ); }); @@ -689,7 +721,7 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + timeShift; let indexes = [0, 0, 0]; - const tx = await I_VestingEscrowWallet.batchEditSchedule(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.batchEditSchedule(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency); for (let i = 0; i < beneficiaries.length; i++) { @@ -711,10 +743,10 @@ contract('VestingEscrowWallet', accounts => { it("Should send available tokens to the beneficiaries addresses", async () => { for (let i = 0; i < beneficiaries.length; i++) { let beneficiary = beneficiaries[i]; - await I_VestingEscrowWallet.update(beneficiary, {from: wallet_owner}); + await I_VestingEscrowWallet.update(beneficiary, {from: wallet_admin}); } - const tx = await I_VestingEscrowWallet.batchSendAvailableTokens(beneficiaries, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.batchSendAvailableTokens(beneficiaries, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; @@ -725,9 +757,9 @@ contract('VestingEscrowWallet', accounts => { let balance = await I_PolyToken.balanceOf.call(beneficiary); assert.equal(balance.toNumber(), 5000); - await I_PolyToken.transfer(account_treasury, balance, {from: beneficiary}); - await I_VestingEscrowWallet.revokeSchedules(beneficiary, {from: wallet_owner}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + await I_PolyToken.transfer(token_owner, balance, {from: beneficiary}); + await I_VestingEscrowWallet.revokeSchedules(beneficiary, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); } }); @@ -738,12 +770,12 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + durationUtil.seconds(100); let totalNumberOfTokens = numberOfTokens * 3; - await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: account_treasury}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_owner}); - await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_owner}); + await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); - let tx = await I_VestingEscrowWallet.batchAddScheduleFromTemplate(beneficiaries, 0, startTime, {from: wallet_owner}); - await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_owner}); + let tx = await I_VestingEscrowWallet.batchAddScheduleFromTemplate(beneficiaries, 0, startTime, {from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; @@ -760,7 +792,7 @@ contract('VestingEscrowWallet', accounts => { }); it("Should revoke vesting schedule from the 3 beneficiary's addresses", async () => { - const tx = await I_VestingEscrowWallet.batchRevokeSchedules(beneficiaries, {from: wallet_owner}); + const tx = await I_VestingEscrowWallet.batchRevokeSchedules(beneficiaries, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; @@ -771,7 +803,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 0); } - await I_VestingEscrowWallet.sendToTreasury({from: wallet_owner}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); }); From 45fddfef5c3f0872e677ba7324d066ac3578ef5a Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 21 Nov 2018 12:20:13 +0200 Subject: [PATCH 140/582] optimized VestingEscrowWallet --- .../modules/Wallet/VestingEscrowWallet.sol | 38 +++++++++---------- test/z_vesting_escrow_wallet.js | 7 +--- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index d20db9c6b..082eb3b00 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -274,7 +274,7 @@ contract VestingEscrowWallet is IWallet { * @param _index index of the schedule */ function revokeSchedule(address _beneficiary, uint256 _index) external withPerm(ADMIN) { - require(_beneficiary != address(0), "Invalid beneficiary address"); + require(_beneficiary != address(0), "Invalid address"); require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); Schedule[] storage schedules = dataMap[_beneficiary].schedules; unassignedTokens = unassignedTokens.add(schedules[_index].lockedTokens); @@ -341,7 +341,7 @@ contract VestingEscrowWallet is IWallet { * @return available tokens for beneficiary */ function getAvailableTokens(address _beneficiary) external view returns(uint256) { - require(_beneficiary != address(0), "Invalid address"); + require(_beneficiary != address(0)); return dataMap[_beneficiary].availableTokens; } @@ -451,7 +451,7 @@ contract VestingEscrowWallet is IWallet { function _sendTokens(address _beneficiary) private { Data storage data = dataMap[_beneficiary]; uint256 amount = data.availableTokens; - require(amount > 0, "No tokens"); + require(amount > 0, "No available tokens"); data.availableTokens = 0; data.claimedTokens = data.claimedTokens.add(amount); token.safeTransfer(_beneficiary, amount); @@ -487,22 +487,22 @@ contract VestingEscrowWallet is IWallet { } } - //TODO temporally for decreasing contract size -// /** -// * @notice manually triggers update outside for all schedules (can be used to reduce user gas costs) -// */ -// function updateAll() external withPerm(ADMIN) { -// _updateAll(); -// } -// -// function _updateAll() private { -// for (uint256 i = 0; i < beneficiaries.length; i++) { -// _update(beneficiaries[i]); -// } -// } + /** + * @notice manually triggers update outside for all schedules (can be used to reduce user gas costs) + */ + function updateAll() external withPerm(ADMIN) { + _updateAll(); + } + + function _updateAll() private { + for (uint256 i = 0; i < beneficiaries.length; i++) { + _update(beneficiaries[i]); + } + } function _revokeSchedules(address _beneficiary) private { - if (_canBeRemoved(_beneficiary)) { + //can be removed + if (dataMap[_beneficiary].availableTokens == 0) { uint256 index = dataMap[_beneficiary].index; beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; beneficiaries.length--; @@ -513,10 +513,6 @@ contract VestingEscrowWallet is IWallet { } } - function _canBeRemoved(address _beneficiary) private view returns(bool) { - return (dataMap[_beneficiary].availableTokens == 0); - } - /** * @notice Return the permissions flag that are associated with VestingEscrowWallet */ diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index e53d4a40a..5c92d2fe0 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -741,10 +741,7 @@ contract('VestingEscrowWallet', accounts => { }); it("Should send available tokens to the beneficiaries addresses", async () => { - for (let i = 0; i < beneficiaries.length; i++) { - let beneficiary = beneficiaries[i]; - await I_VestingEscrowWallet.update(beneficiary, {from: wallet_admin}); - } + await I_VestingEscrowWallet.updateAll({from: wallet_admin}); const tx = await I_VestingEscrowWallet.batchSendAvailableTokens(beneficiaries, {from: wallet_admin}); @@ -783,7 +780,7 @@ contract('VestingEscrowWallet', accounts => { checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); - assert.equal(scheduleCount, 1); + assert.equal(scheduleCount.toNumber(), 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); From b26f12a652205bd714f1bd109976b74907dddad6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 21 Nov 2018 13:44:47 +0200 Subject: [PATCH 141/582] added tests for checking permission --- .../modules/Wallet/VestingEscrowWallet.sol | 6 +- test/helpers/exceptions.js | 3 + test/z_vesting_escrow_wallet.js | 118 +++++++++++++++++- 3 files changed, 121 insertions(+), 6 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 082eb3b00..abd5fea9e 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -83,23 +83,23 @@ contract VestingEscrowWallet is IWallet { public Module(_securityToken, _polyAddress) { - token = ERC20(_polyAddress); } /** * @notice Function used to initialize the different variables * @param _treasury Address of the treasury */ - function configure(address _treasury) public onlyFactory { + function configure(address _treasury, address _token) public onlyFactory { require(_treasury != address(0), "Invalid address"); treasury = _treasury; + token = ERC20(_token); } /** * @notice This function returns the signature of the configure function */ function getInitFunction() public pure returns (bytes4) { - return bytes4(keccak256("configure(address)")); + return bytes4(keccak256("configure(address,address)")); } /** diff --git a/test/helpers/exceptions.js b/test/helpers/exceptions.js index 22c05be07..ea0327af8 100644 --- a/test/helpers/exceptions.js +++ b/test/helpers/exceptions.js @@ -25,6 +25,9 @@ module.exports = { catchRevert: async function(promise) { await tryCatch(promise, "revert"); }, + catchPermission: async function(promise) { + await tryCatch(promise, "revert Permission check failed"); + }, catchOutOfGas: async function(promise) { await tryCatch(promise, "out of gas"); }, diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 5c92d2fe0..421a56acc 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -1,7 +1,7 @@ import {setUpPolymathNetwork, deployGPMAndVerifyed, deployVestingEscrowWalletAndVerifyed} from "./helpers/createInstances"; import latestTime from "./helpers/latestTime"; import {duration as durationUtil, latestBlock, promisifyLogWatch} from "./helpers/utils"; -import {catchRevert} from "./helpers/exceptions"; +import {catchRevert, catchPermission} from "./helpers/exceptions"; import {increaseTime} from "./helpers/time"; import {encodeModuleCall} from "./helpers/encodeCall"; @@ -174,8 +174,8 @@ contract('VestingEscrowWallet', accounts => { it("Should successfully attach the VestingEscrowWallet with the security token", async () => { let bytesData = encodeModuleCall( - ["address"], - [token_owner] + ["address", "address"], + [token_owner, I_PolyToken.address] ); await I_SecurityToken.changeGranularity(1, {from: token_owner}); @@ -805,6 +805,118 @@ contract('VestingEscrowWallet', accounts => { }); + describe("Check permissions", async () => { + + it("Should not be able to deposit", async () => { + await catchPermission( + I_VestingEscrowWallet.depositTokens(25000, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to withdraw tokens to a treasury", async () => { + await catchPermission( + I_VestingEscrowWallet.sendToTreasury({from: account_beneficiary1}) + ); + }); + + it("Should not be able to send available tokens", async () => { + await catchPermission( + I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to add template", async () => { + await catchPermission( + I_VestingEscrowWallet.addTemplate(25000, 4, 1, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to remove template", async () => { + await catchPermission( + I_VestingEscrowWallet.removeTemplate(0, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to get template count", async () => { + await catchPermission( + I_VestingEscrowWallet.getTemplateCount({from: account_beneficiary1}) + ); + }); + + it("Should not be able to add schedule", async () => { + await catchPermission( + I_VestingEscrowWallet.addSchedule(account_beneficiary1, 10000, 4, 1, latestTime(), {from: account_beneficiary1}) + ); + }); + + it("Should not be able to add schedule from template", async () => { + await catchPermission( + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 0, latestTime(), {from: account_beneficiary1}) + ); + }); + + it("Should not be able to edit schedule", async () => { + await catchPermission( + I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, 10000, 4, 1, latestTime(), {from: account_beneficiary1}) + ); + }); + + it("Should not be able to revoke schedule", async () => { + await catchPermission( + I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to revoke schedules", async () => { + await catchPermission( + I_VestingEscrowWallet.revokeSchedules(account_beneficiary1, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to send available tokens to the beneficiaries", async () => { + await catchPermission( + I_VestingEscrowWallet.batchSendAvailableTokens([account_beneficiary1], {from: account_beneficiary1}) + ); + }); + + it("Should not be able to add schedules to the beneficiaries", async () => { + await catchPermission( + I_VestingEscrowWallet.batchAddSchedule([account_beneficiary1], 10000, 4, 1, latestTime(), {from: account_beneficiary1}) + ); + }); + + it("Should not be able to add schedules from template to the beneficiaries", async () => { + await catchPermission( + I_VestingEscrowWallet.batchAddScheduleFromTemplate([account_beneficiary1], 0, latestTime(), {from: account_beneficiary1}) + ); + }); + + it("Should not be able to revoke schedules of the beneficiaries", async () => { + await catchPermission( + I_VestingEscrowWallet.batchRevokeSchedules([account_beneficiary1], {from: account_beneficiary1}) + ); + }); + + it("Should not be able to edit schedules for the beneficiaries", async () => { + await catchPermission( + I_VestingEscrowWallet.batchEditSchedule([account_beneficiary1], [0], 10000, 4, 1, latestTime(), {from: account_beneficiary1}) + ); + }); + + it("Should not be able update schedule", async () => { + await catchPermission( + I_VestingEscrowWallet.update(account_beneficiary1, {from: account_beneficiary1}) + ); + }); + + it("Should not be able update all schedules", async () => { + await catchPermission( + I_VestingEscrowWallet.updateAll({from: account_beneficiary1}) + ); + }); + + }); + }); function checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime) { From c3de389f6b3034b7493e7883063e3b741403a8cb Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 21 Nov 2018 17:18:10 +0530 Subject: [PATCH 142/582] allow read using verifyTransfer() --- .../TransferManager/VolumeRestrictionTM.sol | 85 +++++++++++++------ test/z_volume_restriction_tm.js | 79 ++++++++++++++++- 2 files changed, 135 insertions(+), 29 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index 6fafbf62c..138f1a34a 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -33,7 +33,7 @@ contract VolumeRestrictionTM is ITransferManager { VolumeRestriction globalRestriction; - mapping(address => VolumeRestriction) internal individualRestriction; + mapping(address => VolumeRestriction) public individualRestriction; // Storing _from => day's timestamp => total amount transact in a day mapping(address => mapping(uint256 => uint256)) internal bucket; // Storing the information that used to validate the transaction @@ -114,10 +114,27 @@ contract VolumeRestrictionTM is ITransferManager { function _checkRestriction(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { BucketDetails memory _bucketDetails = bucketToUser[_from]; + uint256 _diffDays; if (_bucketDetails.timestamps[0] == 0) { - return _individualBucketCheck(individualRestriction[_from].startTime, now, _from,individualRestriction[_from], _amount); + _diffDays = BokkyPooBahsDateTimeLibrary.diffDays(individualRestriction[_from].startTime, now); + return _individualBucketCheck( + individualRestriction[_from].startTime, + _diffDays, + _from, + individualRestriction[_from], + _amount, + _isTransfer + ); } else { - return _individualBucketCheck(_bucketDetails.timestamps[_bucketDetails.latestTimestampIndex], now, _from, individualRestriction[_from], _amount); + _diffDays = BokkyPooBahsDateTimeLibrary.diffDays(_bucketDetails.timestamps[_bucketDetails.latestTimestampIndex], now); + return _individualBucketCheck( + _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex], + _diffDays, + _from, + individualRestriction[_from], + _amount, + _isTransfer + ); } } else if (now <= globalRestriction.endTime && now >= globalRestriction.startTime) { // TODO: Add the global bucket check @@ -136,28 +153,31 @@ contract VolumeRestrictionTM is ITransferManager { } function _individualBucketCheck( - uint256 _fromTimestamp, - uint256 _toTimestamp, + uint256 _fromTime, + uint256 _diffDays, address _from, - VolumeRestriction storage _restriction, - uint256 _amount + VolumeRestriction _restriction, + uint256 _amount, + bool _isTransfer ) internal returns (Result) { - uint256 _diffDays = BokkyPooBahsDateTimeLibrary.diffDays(_fromTimestamp, _toTimestamp); + BucketDetails memory _bucketDetails = bucketToUser[_from]; + uint256[] memory passedTimestamps = new uint256[](_diffDays); + uint256[] memory counters = new uint256[](_diffDays); + // using the existing memory variable instead of creating new one (avoiding stack too deep error) + // uint256 counter = _bucketDetails.latestTimestampIndex; uint256 i = 0; - BucketDetails storage _bucketDetails = bucketToUser[_from]; - uint256 counter = _bucketDetails.latestTimestampIndex; - uint256 tempTimeStamp = 0; + bool valid; for (i = 1; i <= _diffDays; i++) { // calculating the timestamp that will used as an index of the next bucket // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... // where T1,T2,T3 are timestamps having 24 hrs difference - tempTimeStamp = _fromTimestamp.add((i - 1) * 1 days); + _fromTime = _fromTime.add(1 days); // Creating the round array - if (counter > _restriction.rollingPeriodInDays -1) { - counter = 0; + if (_bucketDetails.latestTimestampIndex > _restriction.rollingPeriodInDays -1) { + _bucketDetails.latestTimestampIndex = 0; } // This condition is to check whether the first rolling period is covered or not // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting @@ -165,33 +185,42 @@ contract VolumeRestrictionTM is ITransferManager { if (_bucketDetails.daysCovered <= _restriction.rollingPeriodInDays) { _bucketDetails.daysCovered++; } else { - // temporarily storing the preious value of timestamp at the "counter" index - uint256 _previousTimestamp = _bucketDetails.timestamps[counter]; + // temporarily storing the previous value of timestamp at the "_bucketDetails.latestTimestampIndex" index + uint256 _previousTimestamp = _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex]; // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.sub(bucket[_from][_previousTimestamp]); } - // Adding the last amount that is transacted on the tempTimeStamp + // Adding the last amount that is transacted on the _fromTime _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); // Storing the passed timestamp in the array - _bucketDetails.timestamps[counter] = tempTimeStamp; - // Assigning the sum of transacted amount on the passed day - bucket[_from][tempTimeStamp] = 0; - counter ++; + _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex] = _fromTime; + // Storing all those timestamps whose total transacted value is 0 + passedTimestamps[i] = _fromTime; + counters[i] = _bucketDetails.latestTimestampIndex; + _bucketDetails.latestTimestampIndex ++; } - bool valid; if (_restriction.typeOfRestriction == RestrictionType.Variable) { uint256 _allowedAmount = (_restriction.allowedTokens.mul(ISecurityToken(securityToken).totalSupply()))/ 10 ** 18; valid = _checkValidAmountToTransact(_bucketDetails.sumOfLastPeriod, _amount, _allowedAmount); } else { valid = _checkValidAmountToTransact(_bucketDetails.sumOfLastPeriod, _amount, _restriction.allowedTokens); } - // Storing the index of the latest timestamp from the array of timestamp that is being processed - _bucketDetails.latestTimestampIndex = counter; if (!valid) { return Result.INVALID; } else { - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod + _amount; - bucket[_from][_bucketDetails.timestamps[counter]] = bucket[_from][_bucketDetails.timestamps[counter]].add(_amount); + if (_isTransfer) { + for (i = 0; i < passedTimestamps.length; i++) { + // Assigning the sum of transacted amount on the passed day + bucket[_from][passedTimestamps[i]] = 0; + // To save gas by not assigning a memory timestamp array to storage timestamp array. + bucketToUser[_from].timestamps[counters[i]] = _bucketDetails.timestamps[counters[i]]; + } + bucketToUser[_from].sumOfLastPeriod = _bucketDetails.sumOfLastPeriod + _amount; + bucketToUser[_from].daysCovered = _bucketDetails.daysCovered; + // Storing the index of the latest timestamp from the array of timestamp that is being processed + bucketToUser[_from].latestTimestampIndex = _bucketDetails.latestTimestampIndex; + bucket[_from][_bucketDetails.timestamps[_bucketDetails.latestTimestampIndex]] = bucket[_from][_bucketDetails.timestamps[_bucketDetails.latestTimestampIndex]].add(_amount); + } return Result.NA; } @@ -540,7 +569,7 @@ contract VolumeRestrictionTM is ITransferManager { ); } require(_startTime > 0 && _endTime > _startTime); - require(_rollingPeriodDays >= 1); + require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365); require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays); } @@ -563,7 +592,7 @@ contract VolumeRestrictionTM is ITransferManager { _endTimes.length == _restrictionTypes.length, "Array length mismatch" ); - } + } /** * @notice This function returns the signature of configure function diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js index b6748c360..14a55cd62 100644 --- a/test/z_volume_restriction_tm.js +++ b/test/z_volume_restriction_tm.js @@ -81,6 +81,7 @@ contract('VolumeRestrictionTransferManager', accounts => { account_investor1 = accounts[8]; account_investor2 = accounts[9]; + account_investor3 = accounts[4]; account_delegate = accounts[7]; account_delegate2 = accounts[6]; account_delegate3 = accounts[5]; @@ -157,7 +158,83 @@ contract('VolumeRestrictionTransferManager', accounts => { describe("Attach the VRTM", async() => { it("Deploy the VRTM and attach with the ST", async()=> { + let tx = await I_SecurityToken.addModule(I_VolumeRestrictionTMFactory.address, 0, 0, 0, {from: token_owner }); + assert.equal(tx.logs[2].args._moduleFactory, I_VolumeRestrictionTMFactory.address); + assert.equal( + web3.utils.toUtf8(tx.logs[2].args._name), + "VolumeRestrictionTM", + "VolumeRestrictionTMFactory doesn not added"); + I_VolumeRestrictionTM = VolumeRestrictionTM.at(tx.logs[2].args._module); + }); + + it("Transfer some tokens to different account", async() => { + // Add tokens in to the whitelist + await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor1, account_investor2, account_investor3], + [latestTime(), latestTime(), latestTime()], + [latestTime(), latestTime(), latestTime()], + [latestTime() + duration.days(30), latestTime() + duration.days(30), latestTime() + duration.days(30)], + [true, true, true], + { + from: token_owner + } + ); + + // Mint some tokens and transferred to whitelisted addresses + await I_SecurityToken.mint(account_investor1, web3.utils.toWei("40", "ether"), {from: token_owner}); + await I_SecurityToken.mint(account_investor2, web3.utils.toWei("30", "ether"), {from: token_owner}); + + // Check the balance of the investors + let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); + let bal2 = await I_SecurityToken.balanceOf.call(account_investor2); + // Verifying the balances + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 40); + assert.equal(web3.utils.fromWei((bal2.toNumber()).toString()), 30); + + }); + + it("Should transfer the tokens freely without any restriction", async() => { + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('5', 'ether'), { from: account_investor1 }); + let bal1 = await I_SecurityToken.balanceOf.call(account_investor3); + // Verifying the balances + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 5); + }); + }) + + describe("Test for the addIndividualRestriction", async() => { + + it("Should add the restriction succesfully", async() => { + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei("5"), + 0, + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ); + + assert.equal(tx.logs[0].args._holder, account_investor1); + assert.equal(tx.logs[0].args._typeOfRestriction, 0); + console.log(await I_VolumeRestrictionTM.individualRestriction.call(account_investor1)); + }); - }) + // it("Should not successfully transact the tokens -- failed because volume is above the limit", async() => { + // await catchRevert( + // I_SecurityToken.transfer(account_investor3, web3.utils.toWei("6"), { from: account_investor1}) + // ); + // }); + + // it("Should successfully transact the tokens after 1 and half days", async() => { + // await increaseTime(duration.days(1.5)); + // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor1}); + // // Check the balance of the investors + // let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); + // // Verifying the balances + // assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 34); + // }); }) }); \ No newline at end of file From 7ab089a07522d62709e68ff4e8a68d1800aa9cda Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 21 Nov 2018 20:24:15 +0530 Subject: [PATCH 143/582] Minor fix --- contracts/modules/STO/USDTieredSTO.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 1c424cba0..464cb7948 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -542,7 +542,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { view returns(uint256 spentUSD, uint256 spentValue, uint256 tokensMinted) { - require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI, "Invalid raise type"); + require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI || _fundRaiseType == FundRaiseType.ETH, "Invalid raise type"); uint256 rate = getRate(_fundRaiseType); uint256 originalUSD = DecimalMath.mul(rate, _investmentValue); uint256 allowedUSD = _buyTokensChecks(_beneficiary, _investmentValue, originalUSD); From e5c9aac805f464365e17f539b0f19c8485b4f584 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Wed, 21 Nov 2018 12:11:35 -0300 Subject: [PATCH 144/582] CLI changes for new USDTieredSTO changes --- CLI/commands/ST20Generator.js | 26 +++++++++++----------- CLI/commands/investor_portal.js | 39 ++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index a7dabe7d7..43ea37306 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -843,28 +843,28 @@ async function usdTieredSTO_status() { let displayTiers = ""; let displayMintedPerTier = ""; for (let t = 0; t < tiersLength; t++) { - let ratePerTier = await currentSTO.methods.ratePerTier(t).call(); - let tokensPerTierTotal = await currentSTO.methods.tokensPerTierTotal(t).call(); - let mintedPerTierTotal = await currentSTO.methods.mintedPerTierTotal(t).call(); - + let tier = await currentSTO.methods.tiers(t).call(); + let ratePerTier = tier.rate; + let tokensPerTierTotal = tier.tokenTotal; + let mintedPerTierTotal = tier.mintedTotal; + let mintedPerTierPerRaiseType = await currentSTO.methods.getTokensMintedByTier(t).call(); + let displayMintedPerTierPerType = ""; let displayDiscountTokens = ""; for (const type of raiseTypes) { let displayDiscountMinted = ""; - if (type == 'POLY') { - let tokensPerTierDiscountPoly = await currentSTO.methods.tokensPerTierDiscountPoly(t).call(); - if (tokensPerTierDiscountPoly > 0) { - let ratePerTierDiscountPoly = await currentSTO.methods.ratePerTierDiscountPoly(t).call(); - let mintedPerTierDiscountPoly = await currentSTO.methods.mintedPerTierDiscountPoly(t).call(); - displayDiscountTokens = ` + let tokensPerTierDiscountPoly = tier.tokensDiscountPoly; + if (tokensPerTierDiscountPoly > 0) { + let ratePerTierDiscountPoly = tier.rateDiscountPoly; + let mintedPerTierDiscountPoly = tier.mintedDiscountPoly; + displayDiscountTokens = ` Tokens at discounted rate: ${web3.utils.fromWei(tokensPerTierDiscountPoly)} ${displayTokenSymbol} Discounted rate: ${web3.utils.fromWei(ratePerTierDiscountPoly, 'ether')} USD per Token`; - displayDiscountMinted = `(${web3.utils.fromWei(mintedPerTierDiscountPoly)} ${displayTokenSymbol} at discounted rate)`; - } + displayDiscountMinted = `(${web3.utils.fromWei(mintedPerTierDiscountPoly)} ${displayTokenSymbol} at discounted rate)`; } - let mintedPerTier = await currentSTO.methods.mintedPerTier(gbl.constants.FUND_RAISE_TYPES[type], t).call(); + let mintedPerTier = mintedPerTierPerRaiseType[gbl.constants.FUND_RAISE_TYPES[type]]; displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; } diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 276f8bda3..46be05a7b 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -290,28 +290,29 @@ async function showUSDTieredSTOInfo() { let displayTiers = ""; let displayMintedPerTier = ""; for (let t = 0; t < tiersLength; t++) { - let ratePerTier = await currentSTO.methods.ratePerTier(t).call(); - let tokensPerTierTotal = await currentSTO.methods.tokensPerTierTotal(t).call(); - let mintedPerTierTotal = await currentSTO.methods.mintedPerTierTotal(t).call(); + let tier = await currentSTO.methods.tiers(t).call(); + let ratePerTier = tier.rate; + let tokensPerTierTotal = tier.tokenTotal; + let mintedPerTierTotal = tier.mintedTotal; + let mintedPerTierPerRaiseType = await currentSTO.methods.getTokensMintedByTier(t).call(); let displayMintedPerTierPerType = ""; let displayDiscountTokens = ""; for (const type of raiseTypes) { let displayDiscountMinted = ""; - if (type == 'POLY') { - let tokensPerTierDiscountPoly = await currentSTO.methods.tokensPerTierDiscountPoly(t).call(); - if (tokensPerTierDiscountPoly > 0) { - let ratePerTierDiscountPoly = await currentSTO.methods.ratePerTierDiscountPoly(t).call(); - let mintedPerTierDiscountPoly = await currentSTO.methods.mintedPerTierDiscountPoly(t).call(); - displayDiscountTokens = ` + let tokensPerTierDiscountPoly = tier.tokensDiscountPoly; + if (tokensPerTierDiscountPoly > 0) { + let ratePerTierDiscountPoly = tier.rateDiscountPoly; + let mintedPerTierDiscountPoly = tier.mintedDiscountPoly; + displayDiscountTokens = ` Tokens at discounted rate: ${web3.utils.fromWei(tokensPerTierDiscountPoly)} ${displayTokenSymbol} Discounted rate: ${web3.utils.fromWei(ratePerTierDiscountPoly, 'ether')} USD per Token`; - displayDiscountMinted = `(${web3.utils.fromWei(mintedPerTierDiscountPoly)} ${displayTokenSymbol} at discounted rate)`; - } + displayDiscountMinted = `(${web3.utils.fromWei(mintedPerTierDiscountPoly)} ${displayTokenSymbol} at discounted rate)`; } + - let mintedPerTier = await currentSTO.methods.mintedPerTier(gbl.constants.FUND_RAISE_TYPES[type], t).call(); + let mintedPerTier = mintedPerTierPerRaiseType[gbl.constants.FUND_RAISE_TYPES[type]]; displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; } @@ -481,6 +482,14 @@ async function investUsdTieredSTO(currency, amount) { let costWei = web3.utils.toWei(cost.toString()); + let tokensToBuy = await currentSTO.methods.buyTokensView(User.address, costWei, gbl.constants.FUND_RAISE_TYPES[raiseType]).call(); + let minTokenToBuy = tokensToBuy.tokensMinted; + console.log(chalk.yellow(`You are going to spent ${web3.utils.fromWei(tokensToBuy.spentValue)} ${raiseType} (${web3.utils.fromWei(tokensToBuy.spentUSD)} USD) to buy ${web3.utils.fromWei(minTokenToBuy)} ${STSymbol} approx.`)); + console.log(chalk.yellow(`Due to ${raiseType} price changes and network delays, it is possible that the final amount of purchased tokens is lower.`)); + if (typeof amount !== 'undefined' || !readlineSync.keyInYNStrict(`Do you want the transaction to fail if this happens?`)) { + minTokenToBuy = 0; + } + if (raiseType == 'POLY') { let userBalance = await polyBalance(User.address); if (parseInt(userBalance) >= parseInt(cost)) { @@ -489,7 +498,7 @@ async function investUsdTieredSTO(currency, amount) { let approveAction = polyToken.methods.approve(STOAddress, costWei); await common.sendTransaction(approveAction, {from: User}); } - let actionBuyWithPoly = currentSTO.methods.buyWithPOLY(User.address, costWei); + let actionBuyWithPoly = currentSTO.methods.buyWithPOLYRateLimited(User.address, costWei, minTokenToBuy); let receipt = await common.sendTransaction(actionBuyWithPoly, {from: User, factor: 2}); logTokensPurchasedUSDTieredSTO(receipt); } else { @@ -505,7 +514,7 @@ async function investUsdTieredSTO(currency, amount) { let approveAction = usdToken.methods.approve(STOAddress, costWei); await common.sendTransaction(approveAction, {from: User}); } - let actionBuyWithUSD = currentSTO.methods.buyWithUSD(User.address, costWei); + let actionBuyWithUSD = currentSTO.methods.buyWithUSDRateLimited(User.address, costWei, minTokenToBuy); let receipt = await common.sendTransaction(actionBuyWithUSD, {from: User, factor: 1.5}); logTokensPurchasedUSDTieredSTO(receipt); } else { @@ -514,7 +523,7 @@ async function investUsdTieredSTO(currency, amount) { process.exit(); } } else { - let actionBuyWithETH = currentSTO.methods.buyWithETH(User.address); + let actionBuyWithETH = currentSTO.methods.buyWithETHRateLimited(User.address, minTokenToBuy); let receipt = await common.sendTransaction(actionBuyWithETH, {from: User, value: costWei}); logTokensPurchasedUSDTieredSTO(receipt); } From 92fb53a16ec44e4970720142bf032b7819f6f1c2 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 21 Nov 2018 22:04:12 +0200 Subject: [PATCH 145/582] added test for factory, applied review comments --- .../modules/Wallet/VestingEscrowWallet.sol | 60 ++++++++----------- test/z_vesting_escrow_wallet.js | 18 ++++-- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index abd5fea9e..6b2aa584f 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -50,29 +50,27 @@ contract VestingEscrowWallet is IWallet { Template[] public templates; event AddSchedule( - address _beneficiary, + address indexed _beneficiary, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, - uint256 _startTime, - uint256 _timestamp + uint256 _startTime ); event EditSchedule( - address _beneficiary, + address indexed _beneficiary, uint256 _index, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, - uint256 _startTime, - uint256 _timestamp + uint256 _startTime ); - event RevokeSchedules(address _beneficiary, uint256 _timestamp); - event RevokeSchedule(address _beneficiary, uint256 _index, uint256 _timestamp); - event DepositTokens(uint256 _numberOfTokens, uint256 _timestamp); - event SendToTreasury(uint256 _numberOfTokens, uint256 _timestamp); - event SendTokens(address _beneficiary, uint256 _numberOfTokens, uint256 _timestamp); - event AddTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, uint256 _timestamp); - event RemoveTemplate(uint256 _index, uint256 _timestamp); + event RevokeSchedules(address indexed _beneficiary); + event RevokeSchedule(address indexed _beneficiary, uint256 _index); + event DepositTokens(uint256 _numberOfTokens); + event SendToTreasury(uint256 _numberOfTokens); + event SendTokens(address indexed _beneficiary, uint256 _numberOfTokens); + event AddTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, uint256 _index); + event RemoveTemplate(uint256 _index); /** * @notice Constructor @@ -109,8 +107,7 @@ contract VestingEscrowWallet is IWallet { require(_numberOfTokens > 0, "Should be greater than zero"); token.safeTransferFrom(treasury, this, _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); - /*solium-disable-next-line security/no-block-members*/ - emit DepositTokens(_numberOfTokens, now); + emit DepositTokens(_numberOfTokens); } /** @@ -120,8 +117,7 @@ contract VestingEscrowWallet is IWallet { uint256 amount = unassignedTokens; unassignedTokens = 0; token.safeTransfer(treasury, amount); - /*solium-disable-next-line security/no-block-members*/ - emit SendToTreasury(amount, now); + emit SendToTreasury(amount); } /** @@ -152,8 +148,7 @@ contract VestingEscrowWallet is IWallet { template.duration = _duration; template.frequency = _frequency; templates.push(template); - /*solium-disable-next-line security/no-block-members*/ - emit AddTemplate(_numberOfTokens, _duration, _frequency, now); + emit AddTemplate(_numberOfTokens, _duration, _frequency, templates.length - 1); } /** @@ -162,17 +157,18 @@ contract VestingEscrowWallet is IWallet { */ function removeTemplate(uint256 _index) external withPerm(ADMIN) { require(_index < templates.length, "Template not found"); - templates[_index] = templates[templates.length - 1]; + if (_index != templates.length - 1) { + templates[_index] = templates[templates.length - 1]; + } templates.length--; - /*solium-disable-next-line security/no-block-members*/ - emit RemoveTemplate(_index, now); + emit RemoveTemplate(_index); } /** * @notice Returns count of templates * @return count of templates */ - function getTemplateCount() external view withPerm(ADMIN) returns(uint256) { + function getTemplateCount() external view returns(uint256) { return templates.length; } @@ -212,8 +208,7 @@ contract VestingEscrowWallet is IWallet { beneficiaries.push(_beneficiary); } dataMap[_beneficiary].schedules.push(schedule); - /*solium-disable-next-line security/no-block-members*/ - emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime, now); + emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); } /** @@ -224,7 +219,7 @@ contract VestingEscrowWallet is IWallet { */ function addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) public withPerm(ADMIN) { require(_index < templates.length, "Template not found"); - Template storage template = templates[_index]; + Template memory template = templates[_index]; addSchedule(_beneficiary, template.numberOfTokens, template.duration, template.frequency, _startTime); } @@ -265,7 +260,7 @@ contract VestingEscrowWallet is IWallet { schedule.frequency = _frequency; schedule.startTime = _startTime; schedule.nextTime = _startTime.add(schedule.frequency); - emit EditSchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime, now); + emit EditSchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); } /** @@ -283,8 +278,7 @@ contract VestingEscrowWallet is IWallet { if (schedules.length == 0) { _revokeSchedules(_beneficiary); } - /*solium-disable-next-line security/no-block-members*/ - emit RevokeSchedule(_beneficiary, _index, now); + emit RevokeSchedule(_beneficiary, _index); } @@ -300,8 +294,7 @@ contract VestingEscrowWallet is IWallet { } delete dataMap[_beneficiary].schedules; _revokeSchedules(_beneficiary); - /*solium-disable-next-line security/no-block-members*/ - emit RevokeSchedules(_beneficiary, now); + emit RevokeSchedules(_beneficiary); } /** @@ -384,7 +377,7 @@ contract VestingEscrowWallet is IWallet { * @param _index index of the template * @param _startTime vesting start time */ - function batchAddScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startTime) public withPerm(ADMIN) { + function batchAddScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startTime) external withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { addScheduleFromTemplate(_beneficiaries[i], _index, _startTime); } @@ -455,8 +448,7 @@ contract VestingEscrowWallet is IWallet { data.availableTokens = 0; data.claimedTokens = data.claimedTokens.add(amount); token.safeTransfer(_beneficiary, amount); - /*solium-disable-next-line security/no-block-members*/ - emit SendTokens(_beneficiary, amount, now); + emit SendTokens(_beneficiary, amount); } /** diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 421a56acc..20cac61b6 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -207,6 +207,18 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._delegate, wallet_admin); }); + it("Should get the permission", async () => { + let perm = await I_VestingEscrowWallet.getPermissions.call(); + assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ""), "ADMIN"); + }); + + it("Should get the tags of the factory", async () => { + let tags = await I_VestingEscrowWalletFactory.getTags.call(); + assert.equal(tags.length, 2); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ""), "Vested Wallet"); + assert.equal(web3.utils.toAscii(tags[1]).replace(/\u0000/g, ""), "Escrow"); + }); + }); describe("Depositing and withdrawing tokens", async () => { @@ -837,12 +849,6 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should not be able to get template count", async () => { - await catchPermission( - I_VestingEscrowWallet.getTemplateCount({from: account_beneficiary1}) - ); - }); - it("Should not be able to add schedule", async () => { await catchPermission( I_VestingEscrowWallet.addSchedule(account_beneficiary1, 10000, 4, 1, latestTime(), {from: account_beneficiary1}) From a4b7e6c309cf98dcf24cf7adbdba5b06c5e62e1a Mon Sep 17 00:00:00 2001 From: FOBCrypto <42175565+FOBCrypto@users.noreply.github.com> Date: Thu, 22 Nov 2018 16:36:05 +0530 Subject: [PATCH 146/582] Typo fix Co-Authored-By: maxsam4 --- CLI/commands/investor_portal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 46be05a7b..1ced21ce0 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -484,7 +484,7 @@ async function investUsdTieredSTO(currency, amount) { let tokensToBuy = await currentSTO.methods.buyTokensView(User.address, costWei, gbl.constants.FUND_RAISE_TYPES[raiseType]).call(); let minTokenToBuy = tokensToBuy.tokensMinted; - console.log(chalk.yellow(`You are going to spent ${web3.utils.fromWei(tokensToBuy.spentValue)} ${raiseType} (${web3.utils.fromWei(tokensToBuy.spentUSD)} USD) to buy ${web3.utils.fromWei(minTokenToBuy)} ${STSymbol} approx.`)); + console.log(chalk.yellow(`You are going to spend ${web3.utils.fromWei(tokensToBuy.spentValue)} ${raiseType} (${web3.utils.fromWei(tokensToBuy.spentUSD)} USD) to buy ${web3.utils.fromWei(minTokenToBuy)} ${STSymbol} approx.`)); console.log(chalk.yellow(`Due to ${raiseType} price changes and network delays, it is possible that the final amount of purchased tokens is lower.`)); if (typeof amount !== 'undefined' || !readlineSync.keyInYNStrict(`Do you want the transaction to fail if this happens?`)) { minTokenToBuy = 0; From 631d2b107eb85fc7535d210ae4809942528a6525 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Thu, 22 Nov 2018 11:38:47 +0000 Subject: [PATCH 147/582] Allow 0x transfers for MATM --- .../modules/ManualApprovalTransferManager.sol | 169 ++++++++++++++++++ test/j_manual_approval_transfer_manager.js | 47 ++--- 2 files changed, 188 insertions(+), 28 deletions(-) create mode 100644 contracts/modules/ManualApprovalTransferManager.sol diff --git a/contracts/modules/ManualApprovalTransferManager.sol b/contracts/modules/ManualApprovalTransferManager.sol new file mode 100644 index 000000000..d95241e9a --- /dev/null +++ b/contracts/modules/ManualApprovalTransferManager.sol @@ -0,0 +1,169 @@ +pragma solidity ^0.4.24; + +import "./ITransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/** + * @title Transfer Manager module for manually approving or blocking transactions between accounts + */ +contract ManualApprovalTransferManager is ITransferManager { + using SafeMath for uint256; + + //Address from which issuances come + address public issuanceAddress = address(0); + + //Address which can sign whitelist changes + address public signingAddress = address(0); + + bytes32 public constant TRANSFER_APPROVAL = "TRANSFER_APPROVAL"; + + //Manual approval is an allowance (that has been approved) with an expiry time + struct ManualApproval { + uint256 allowance; + uint256 expiryTime; + } + + //Manual blocking allows you to specify a list of blocked address pairs with an associated expiry time for the block + struct ManualBlocking { + uint256 expiryTime; + } + + //Store mappings of address => address with ManualApprovals + mapping (address => mapping (address => ManualApproval)) public manualApprovals; + + //Store mappings of address => address with ManualBlockings + mapping (address => mapping (address => ManualBlocking)) public manualBlockings; + + event AddManualApproval( + address indexed _from, + address indexed _to, + uint256 _allowance, + uint256 _expiryTime, + address indexed _addedBy + ); + + event AddManualBlocking( + address indexed _from, + address indexed _to, + uint256 _expiryTime, + address indexed _addedBy + ); + + event RevokeManualApproval( + address indexed _from, + address indexed _to, + address indexed _addedBy + ); + + event RevokeManualBlocking( + address indexed _from, + address indexed _to, + address indexed _addedBy + ); + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { + } + + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(0); + } + + /** @notice Used to verify the transfer transaction and allow a manually approved transqaction to bypass other restrictions + * @param _from Address of the sender + * @param _to Address of the receiver + * @param _amount The amount of tokens to transfer + * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable + */ + function verifyTransfer(address _from, address _to, uint256 _amount, bytes /* _data */, bool _isTransfer) public returns(Result) { + // function must only be called by the associated security token if _isTransfer == true + require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); + // manual blocking takes precidence over manual approval + if (!paused) { + /*solium-disable-next-line security/no-block-members*/ + if (manualBlockings[_from][_to].expiryTime >= now) { + return Result.INVALID; + } + /*solium-disable-next-line security/no-block-members*/ + if ((manualApprovals[_from][_to].expiryTime >= now) && (manualApprovals[_from][_to].allowance >= _amount)) { + if (_isTransfer) { + manualApprovals[_from][_to].allowance = manualApprovals[_from][_to].allowance.sub(_amount); + } + return Result.VALID; + } + } + return Result.NA; + } + + /** + * @notice Adds a pair of addresses to manual approvals + * @param _from is the address from which transfers are approved + * @param _to is the address to which transfers are approved + * @param _allowance is the approved amount of tokens + * @param _expiryTime is the time until which the transfer is allowed + */ + function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { + require(_to != address(0), "Invalid to address"); + /*solium-disable-next-line security/no-block-members*/ + require(_expiryTime > now, "Invalid expiry time"); + require(manualApprovals[_from][_to].allowance == 0, "Approval already exists"); + manualApprovals[_from][_to] = ManualApproval(_allowance, _expiryTime); + emit AddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender); + } + + /** + * @notice Adds a pair of addresses to manual blockings + * @param _from is the address from which transfers are blocked + * @param _to is the address to which transfers are blocked + * @param _expiryTime is the time until which the transfer is blocked + */ + function addManualBlocking(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { + require(_to != address(0), "Invalid to address"); + /*solium-disable-next-line security/no-block-members*/ + require(_expiryTime > now, "Invalid expiry time"); + require(manualBlockings[_from][_to].expiryTime == 0, "Blocking already exists"); + manualBlockings[_from][_to] = ManualBlocking(_expiryTime); + emit AddManualBlocking(_from, _to, _expiryTime, msg.sender); + } + + /** + * @notice Removes a pairs of addresses from manual approvals + * @param _from is the address from which transfers are approved + * @param _to is the address to which transfers are approved + */ + function revokeManualApproval(address _from, address _to) public withPerm(TRANSFER_APPROVAL) { + require(_to != address(0), "Invalid to address"); + delete manualApprovals[_from][_to]; + emit RevokeManualApproval(_from, _to, msg.sender); + } + + /** + * @notice Removes a pairs of addresses from manual approvals + * @param _from is the address from which transfers are approved + * @param _to is the address to which transfers are approved + */ + function revokeManualBlocking(address _from, address _to) public withPerm(TRANSFER_APPROVAL) { + require(_to != address(0), "Invalid to address"); + delete manualBlockings[_from][_to]; + emit RevokeManualBlocking(_from, _to, msg.sender); + } + + /** + * @notice Returns the permissions flag that are associated with ManualApproval transfer manager + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = TRANSFER_APPROVAL; + return allPermissions; + } +} diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 709991b92..0461f287a 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -321,18 +321,6 @@ contract("ManualApprovalTransferManager", accounts => { assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("5", "ether")); }); - it("Should fail to add a manual approval because invalid _from address", async () => { - await catchRevert( - I_ManualApprovalTransferManager.addManualApproval( - "", - account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), - { from: token_owner } - ) - ); - }); - it("Should fail to add a manual approval because invalid _to address", async () => { await catchRevert( I_ManualApprovalTransferManager.addManualApproval( @@ -367,6 +355,16 @@ contract("ManualApprovalTransferManager", accounts => { ); }); + it("Add a manual approval for a 5th investor from issuance", async () => { + await I_ManualApprovalTransferManager.addManualApproval( + "", + account_investor5, + web3.utils.toWei("2", "ether"), + latestTime() + duration.days(1), + { from: token_owner } + ); + }); + it("Should fail to add a manual approval because allowance is laready exists", async () => { await catchRevert( I_ManualApprovalTransferManager.addManualApproval( @@ -379,10 +377,6 @@ contract("ManualApprovalTransferManager", accounts => { ); }); - it("Should fail to revoke manual approval because invalid _from address", async () => { - await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval("", account_investor4, { from: token_owner })); - }); - it("Should fail to revoke manual approval because invalid _to address", async () => { await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, "", { from: token_owner })); }); @@ -409,6 +403,15 @@ contract("ManualApprovalTransferManager", accounts => { assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei("1", "ether")); }); + it("Approval fails with wrong from to address", async () => { + await catchRevert(I_SecurityToken.transfer(account_investor5, web3.utils.toWei("1", "ether"), { from: account_investor1 })); + }); + + it("Use 100% of issuance approval", async () => { + await I_SecurityToken.mint(account_investor5, web3.utils.toWei("2", "ether"), { from: token_owner }); + assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toNumber(), web3.utils.toWei("2", "ether")); + }); + it("Check verifyTransfer without actually transferring", async () => { let verified = await I_SecurityToken.verifyTransfer.call( account_investor1, @@ -439,14 +442,6 @@ contract("ManualApprovalTransferManager", accounts => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); }); - it("Should fail to add a manual block because invalid _from address", async () => { - await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking("", account_investor2, latestTime() + duration.days(1), { - from: token_owner - }) - ); - }); - it("Should fail to add a manual block because invalid _to address", async () => { await catchRevert( I_ManualApprovalTransferManager.addManualBlocking(account_investor1, "", latestTime() + duration.days(1), { @@ -477,10 +472,6 @@ contract("ManualApprovalTransferManager", accounts => { await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 })); }); - it("Should fail to revoke manual block because invalid _from address", async () => { - await catchRevert(I_ManualApprovalTransferManager.revokeManualBlocking("0x0", account_investor2, { from: token_owner })); - }); - it("Should fail to revoke manual block because invalid _to address", async () => { await catchRevert(I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, "0x0", { from: token_owner })); }); From 115c3cb807a4bc87cf8a8905d2ad685b9881e574 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Thu, 22 Nov 2018 11:55:03 +0000 Subject: [PATCH 148/582] Fix typo --- .../modules/ManualApprovalTransferManager.sol | 169 ------------------ .../ManualApprovalTransferManager.sol | 4 - 2 files changed, 173 deletions(-) delete mode 100644 contracts/modules/ManualApprovalTransferManager.sol diff --git a/contracts/modules/ManualApprovalTransferManager.sol b/contracts/modules/ManualApprovalTransferManager.sol deleted file mode 100644 index d95241e9a..000000000 --- a/contracts/modules/ManualApprovalTransferManager.sol +++ /dev/null @@ -1,169 +0,0 @@ -pragma solidity ^0.4.24; - -import "./ITransferManager.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -/** - * @title Transfer Manager module for manually approving or blocking transactions between accounts - */ -contract ManualApprovalTransferManager is ITransferManager { - using SafeMath for uint256; - - //Address from which issuances come - address public issuanceAddress = address(0); - - //Address which can sign whitelist changes - address public signingAddress = address(0); - - bytes32 public constant TRANSFER_APPROVAL = "TRANSFER_APPROVAL"; - - //Manual approval is an allowance (that has been approved) with an expiry time - struct ManualApproval { - uint256 allowance; - uint256 expiryTime; - } - - //Manual blocking allows you to specify a list of blocked address pairs with an associated expiry time for the block - struct ManualBlocking { - uint256 expiryTime; - } - - //Store mappings of address => address with ManualApprovals - mapping (address => mapping (address => ManualApproval)) public manualApprovals; - - //Store mappings of address => address with ManualBlockings - mapping (address => mapping (address => ManualBlocking)) public manualBlockings; - - event AddManualApproval( - address indexed _from, - address indexed _to, - uint256 _allowance, - uint256 _expiryTime, - address indexed _addedBy - ); - - event AddManualBlocking( - address indexed _from, - address indexed _to, - uint256 _expiryTime, - address indexed _addedBy - ); - - event RevokeManualApproval( - address indexed _from, - address indexed _to, - address indexed _addedBy - ); - - event RevokeManualBlocking( - address indexed _from, - address indexed _to, - address indexed _addedBy - ); - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) - public - Module(_securityToken, _polyAddress) - { - } - - /** - * @notice This function returns the signature of configure function - */ - function getInitFunction() public pure returns (bytes4) { - return bytes4(0); - } - - /** @notice Used to verify the transfer transaction and allow a manually approved transqaction to bypass other restrictions - * @param _from Address of the sender - * @param _to Address of the receiver - * @param _amount The amount of tokens to transfer - * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable - */ - function verifyTransfer(address _from, address _to, uint256 _amount, bytes /* _data */, bool _isTransfer) public returns(Result) { - // function must only be called by the associated security token if _isTransfer == true - require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); - // manual blocking takes precidence over manual approval - if (!paused) { - /*solium-disable-next-line security/no-block-members*/ - if (manualBlockings[_from][_to].expiryTime >= now) { - return Result.INVALID; - } - /*solium-disable-next-line security/no-block-members*/ - if ((manualApprovals[_from][_to].expiryTime >= now) && (manualApprovals[_from][_to].allowance >= _amount)) { - if (_isTransfer) { - manualApprovals[_from][_to].allowance = manualApprovals[_from][_to].allowance.sub(_amount); - } - return Result.VALID; - } - } - return Result.NA; - } - - /** - * @notice Adds a pair of addresses to manual approvals - * @param _from is the address from which transfers are approved - * @param _to is the address to which transfers are approved - * @param _allowance is the approved amount of tokens - * @param _expiryTime is the time until which the transfer is allowed - */ - function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { - require(_to != address(0), "Invalid to address"); - /*solium-disable-next-line security/no-block-members*/ - require(_expiryTime > now, "Invalid expiry time"); - require(manualApprovals[_from][_to].allowance == 0, "Approval already exists"); - manualApprovals[_from][_to] = ManualApproval(_allowance, _expiryTime); - emit AddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender); - } - - /** - * @notice Adds a pair of addresses to manual blockings - * @param _from is the address from which transfers are blocked - * @param _to is the address to which transfers are blocked - * @param _expiryTime is the time until which the transfer is blocked - */ - function addManualBlocking(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { - require(_to != address(0), "Invalid to address"); - /*solium-disable-next-line security/no-block-members*/ - require(_expiryTime > now, "Invalid expiry time"); - require(manualBlockings[_from][_to].expiryTime == 0, "Blocking already exists"); - manualBlockings[_from][_to] = ManualBlocking(_expiryTime); - emit AddManualBlocking(_from, _to, _expiryTime, msg.sender); - } - - /** - * @notice Removes a pairs of addresses from manual approvals - * @param _from is the address from which transfers are approved - * @param _to is the address to which transfers are approved - */ - function revokeManualApproval(address _from, address _to) public withPerm(TRANSFER_APPROVAL) { - require(_to != address(0), "Invalid to address"); - delete manualApprovals[_from][_to]; - emit RevokeManualApproval(_from, _to, msg.sender); - } - - /** - * @notice Removes a pairs of addresses from manual approvals - * @param _from is the address from which transfers are approved - * @param _to is the address to which transfers are approved - */ - function revokeManualBlocking(address _from, address _to) public withPerm(TRANSFER_APPROVAL) { - require(_to != address(0), "Invalid to address"); - delete manualBlockings[_from][_to]; - emit RevokeManualBlocking(_from, _to, msg.sender); - } - - /** - * @notice Returns the permissions flag that are associated with ManualApproval transfer manager - */ - function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](1); - allPermissions[0] = TRANSFER_APPROVAL; - return allPermissions; - } -} diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index fd888680a..d95241e9a 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -113,7 +113,6 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _expiryTime is the time until which the transfer is allowed */ function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { - require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); /*solium-disable-next-line security/no-block-members*/ require(_expiryTime > now, "Invalid expiry time"); @@ -129,7 +128,6 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _expiryTime is the time until which the transfer is blocked */ function addManualBlocking(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { - require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); /*solium-disable-next-line security/no-block-members*/ require(_expiryTime > now, "Invalid expiry time"); @@ -144,7 +142,6 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _to is the address to which transfers are approved */ function revokeManualApproval(address _from, address _to) public withPerm(TRANSFER_APPROVAL) { - require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); delete manualApprovals[_from][_to]; emit RevokeManualApproval(_from, _to, msg.sender); @@ -156,7 +153,6 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _to is the address to which transfers are approved */ function revokeManualBlocking(address _from, address _to) public withPerm(TRANSFER_APPROVAL) { - require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); delete manualBlockings[_from][_to]; emit RevokeManualBlocking(_from, _to, msg.sender); From 3dca9fec5afddcb8de17e353ed6cda650ba6bc20 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Thu, 22 Nov 2018 09:36:16 -0300 Subject: [PATCH 149/582] Add support to remote nodes --- CLI/commands/common/global.js | 23 +++++++++++++++++------ CLI/polymath-cli.js | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CLI/commands/common/global.js b/CLI/commands/common/global.js index e1fb648e2..525030aea 100644 --- a/CLI/commands/common/global.js +++ b/CLI/commands/common/global.js @@ -24,18 +24,29 @@ function getGasPrice (networkId) { return gasPrice; } +function providerValidator(url) { + var expression = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g; + var regex = new RegExp(expression); + return url.match(regex); +} + +async function httpProvider(url, file) { + web3 = new Web3(new Web3.providers.HttpProvider(url)); + Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + require('fs').readFileSync(file).toString()); +} + module.exports = { initialize: async function(network) { remoteNetwork = network; if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { if (typeof remoteNetwork !== 'undefined') { - web3 = new Web3(new Web3.providers.HttpProvider(`https://${remoteNetwork}.infura.io/`)); - let privKey = require('fs').readFileSync('./privKey').toString(); - Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKey); + if (!providerValidator(remoteNetwork)) { + console.log("Invalid remote node") + process.exit(0) + } + await httpProvider(remoteNetwork, './privKey'); } else { - web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); - let privKeyLocal = require('fs').readFileSync('./privKeyLocal').toString() - Issuer = await web3.eth.accounts.privateKeyToAccount("0x" + privKeyLocal); + await httpProvider("http://localhost:8545", './privKeyLocal'); } defaultGasPrice = getGasPrice(await web3.eth.net.getId()); } diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 25831ab9d..f2248b25a 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -23,7 +23,7 @@ const fs = require('fs'); program .version('0.0.1') .description('CLI for Polymath-core') - .option('-r, --remote-node ', 'Use Infura to connect to a remote node on selected network'); + .option('-r, --remote-node ', 'Connect to a remote node'); program .command('st20generator') From eddd5a53b732118e366849c317582e08eda1fa27 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 22 Nov 2018 18:59:45 +0530 Subject: [PATCH 150/582] refactoring bucket function --- .../TransferManager/VolumeRestrictionTM.sol | 140 +++++++----- test/z_volume_restriction_tm.js | 204 ++++++++++++++++-- 2 files changed, 269 insertions(+), 75 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index 138f1a34a..e9f2c9d9c 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -98,11 +98,10 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Used to verify the transfer/transferFrom transaction and prevent tranaction * whose volume of tokens will voilate the maximum volume transfer restriction * @param _from Address of the sender - * @param _to Address of the reciever * @param _amount The amount of tokens to transfer * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable */ - function verifyTransfer(address _from, address _to, uint256 _amount, bytes /*_data*/, bool _isTransfer) public returns (Result) { + function verifyTransfer(address _from, address /*_to */, uint256 _amount, bytes /*_data*/, bool _isTransfer) public returns (Result) { if (!paused && _from != address(0) && !exemptList[_from]) { require(msg.sender == securityToken || !_isTransfer); return _checkRestriction(_from, _amount, _isTransfer); @@ -169,73 +168,89 @@ contract VolumeRestrictionTM is ITransferManager { // using the existing memory variable instead of creating new one (avoiding stack too deep error) // uint256 counter = _bucketDetails.latestTimestampIndex; uint256 i = 0; - bool valid; - for (i = 1; i <= _diffDays; i++) { - // calculating the timestamp that will used as an index of the next bucket - // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... - // where T1,T2,T3 are timestamps having 24 hrs difference - _fromTime = _fromTime.add(1 days); - // Creating the round array - if (_bucketDetails.latestTimestampIndex > _restriction.rollingPeriodInDays -1) { - _bucketDetails.latestTimestampIndex = 0; - } - // This condition is to check whether the first rolling period is covered or not - // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting - // the earlier value at that index - if (_bucketDetails.daysCovered <= _restriction.rollingPeriodInDays) { - _bucketDetails.daysCovered++; - } else { - // temporarily storing the previous value of timestamp at the "_bucketDetails.latestTimestampIndex" index - uint256 _previousTimestamp = _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex]; - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.sub(bucket[_from][_previousTimestamp]); + if (_diffDays != 0) { + for (i = 0; i < _diffDays; i++) { + // calculating the timestamp that will used as an index of the next bucket + // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... + // where T1,T2,T3 are timestamps having 24 hrs difference + _fromTime = _fromTime.add(1 days); + // Creating the round array + if (_bucketDetails.latestTimestampIndex == _restriction.rollingPeriodInDays -1) { + _bucketDetails.latestTimestampIndex = 0; + } + // This condition is to check whether the first rolling period is covered or not + // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting + // the earlier value at that index + if (_bucketDetails.daysCovered < _restriction.rollingPeriodInDays -1) { + _bucketDetails.daysCovered++; + } else { + // temporarily storing the previous value of timestamp at the "_bucketDetails.latestTimestampIndex" index + uint256 _previousTimestamp = _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex]; + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.sub(bucket[_from][_previousTimestamp]); + } + // Adding the last amount that is transacted on the _fromTime + //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); + // increasing the value of latest timestamp Index + _bucketDetails.latestTimestampIndex++; + // Storing the passed timestamp in the array + _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex] = _fromTime; + // Storing all those timestamps whose total transacted value is 0 + passedTimestamps[i] = _fromTime; + counters[i] = _bucketDetails.latestTimestampIndex; } - // Adding the last amount that is transacted on the _fromTime - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); - // Storing the passed timestamp in the array - _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex] = _fromTime; - // Storing all those timestamps whose total transacted value is 0 - passedTimestamps[i] = _fromTime; - counters[i] = _bucketDetails.latestTimestampIndex; - _bucketDetails.latestTimestampIndex ++; - } - if (_restriction.typeOfRestriction == RestrictionType.Variable) { - uint256 _allowedAmount = (_restriction.allowedTokens.mul(ISecurityToken(securityToken).totalSupply()))/ 10 ** 18; - valid = _checkValidAmountToTransact(_bucketDetails.sumOfLastPeriod, _amount, _allowedAmount); - } else { - valid = _checkValidAmountToTransact(_bucketDetails.sumOfLastPeriod, _amount, _restriction.allowedTokens); - } - if (!valid) { - return Result.INVALID; - } else { + } + if (_checkValidAmountToTransact(_bucketDetails.sumOfLastPeriod, _amount, _restriction)) { if (_isTransfer) { - for (i = 0; i < passedTimestamps.length; i++) { - // Assigning the sum of transacted amount on the passed day - bucket[_from][passedTimestamps[i]] = 0; - // To save gas by not assigning a memory timestamp array to storage timestamp array. - bucketToUser[_from].timestamps[counters[i]] = _bucketDetails.timestamps[counters[i]]; - } - bucketToUser[_from].sumOfLastPeriod = _bucketDetails.sumOfLastPeriod + _amount; - bucketToUser[_from].daysCovered = _bucketDetails.daysCovered; - // Storing the index of the latest timestamp from the array of timestamp that is being processed - bucketToUser[_from].latestTimestampIndex = _bucketDetails.latestTimestampIndex; - bucket[_from][_bucketDetails.timestamps[_bucketDetails.latestTimestampIndex]] = bucket[_from][_bucketDetails.timestamps[_bucketDetails.latestTimestampIndex]].add(_amount); + _updateStorage(passedTimestamps, counters, _from, _fromTime, _diffDays, _amount, _bucketDetails); } return Result.NA; - } + } + + return Result.INVALID; } + event LogA(uint256 _sum, uint256 _amount, uint256 _allowedAmount); + function _updateStorage(uint256[] passedTimestamps, uint256[] counters, address _from, uint256 _fromTime, uint256 _diffDays, uint256 _amount, BucketDetails _bucketDetails) internal { + if (_diffDays != 0) { + for (uint256 i = 0; i < passedTimestamps.length; i++) { + // Assigning the sum of transacted amount on the passed day + bucket[_from][passedTimestamps[i]] = 0; + // To save gas by not assigning a memory timestamp array to storage timestamp array. + bucketToUser[_from].timestamps[counters[i]] = _bucketDetails.timestamps[counters[i]]; + } + bucketToUser[_from].daysCovered = _bucketDetails.daysCovered; + // Storing the index of the latest timestamp from the array of timestamp that is being processed + bucketToUser[_from].latestTimestampIndex = _bucketDetails.latestTimestampIndex; + } + // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) + if (_bucketDetails.timestamps[0] == 0) { + bucketToUser[_from].timestamps[_bucketDetails.latestTimestampIndex] = _fromTime; + } + bucketToUser[_from].sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(_amount); + // Re-using the local variable to avoid stack too deep error + _fromTime = bucketToUser[_from].timestamps[_bucketDetails.latestTimestampIndex]; + bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); + } function _checkValidAmountToTransact( uint256 _sumOfLastPeriod, uint256 _amountToTransact, - uint256 _allowedTokens + VolumeRestriction _restriction ) internal - pure + view returns (bool) - { - if (_allowedTokens >= _sumOfLastPeriod.add(_amountToTransact)) { + { + uint256 _allowedAmount = 0; + if (_restriction.typeOfRestriction == RestrictionType.Variable) { + _allowedAmount = (_restriction.allowedTokens.mul(ISecurityToken(securityToken).totalSupply()))/ 10 ** 18; + } else { + _allowedAmount = _restriction.allowedTokens; + } + emit LogA(_sumOfLastPeriod, _amountToTransact, _allowedAmount); + // Validation on the amount to transact + if (_allowedAmount >= _sumOfLastPeriod.add(_amountToTransact)) { return true; } else { return false; @@ -594,6 +609,19 @@ contract VolumeRestrictionTM is ITransferManager { ); } + function getBucketDetailsToUser(address _user) external view returns(uint256[], uint256, uint256, uint256) { + return( + bucketToUser[_user].timestamps, + bucketToUser[_user].sumOfLastPeriod, + bucketToUser[_user].daysCovered, + bucketToUser[_user].latestTimestampIndex + ); + } + + function getTotalTradeByuser(address _user, uint256 _at) external view returns(uint256) { + return bucket[_user][_at]; + } + /** * @notice This function returns the signature of configure function */ diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js index 14a55cd62..83f6add28 100644 --- a/test/z_volume_restriction_tm.js +++ b/test/z_volume_restriction_tm.js @@ -136,7 +136,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should generate the new security token with the same symbol as registered above", async () => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, true, { from: token_owner }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); @@ -197,7 +197,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('5', 'ether'), { from: account_investor1 }); let bal1 = await I_SecurityToken.balanceOf.call(account_investor3); // Verifying the balances - assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 5); + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 5); }); }) @@ -206,7 +206,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should add the restriction succesfully", async() => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, - web3.utils.toWei("5"), + web3.utils.toWei("12"), 0, latestTime() + duration.seconds(2), 3, @@ -219,22 +219,188 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor1); assert.equal(tx.logs[0].args._typeOfRestriction, 0); - console.log(await I_VolumeRestrictionTM.individualRestriction.call(account_investor1)); }); - // it("Should not successfully transact the tokens -- failed because volume is above the limit", async() => { - // await catchRevert( - // I_SecurityToken.transfer(account_investor3, web3.utils.toWei("6"), { from: account_investor1}) - // ); - // }); - - // it("Should successfully transact the tokens after 1 and half days", async() => { - // await increaseTime(duration.days(1.5)); - // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor1}); - // // Check the balance of the investors - // let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); - // // Verifying the balances - // assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 34); - // }); - }) + it("Should not successfully transact the tokens -- failed because volume is above the limit", async() => { + await increaseTime(duration.seconds(10)); + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei("13"), { from: account_investor1}) + ); + }); + + it("Should succesfully transact the tokens just after the starttime", async() => { + // Check the transfer will be valid or not by calling the verifyTransfer() directly by using _isTransfer = false + let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor1, account_investor3, web3.utils.toWei('.3'), "0x0", false); + console.log(result); + assert.equal(result.toNumber(), 1); + // Perform the transaction + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('.3'), {from: account_investor1}); + // Check the balance of the investors + let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 34.7); + + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + console.log('\n'); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + `); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Days Covered : ${data[2].toNumber()} + Last Timestamp Index : ${data[3].toNumber()} + `); + }) + + it("Should successfully transact the tokens after 1 and half days", async() => { + await increaseTime(duration.days(1.5)); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor1}); + // Check the balance of the investors + let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 33.7); + + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + `); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Days Covered : ${data[2].toNumber()} + Last Timestamp Index : ${data[3].toNumber()} + `); + }); + + it("Should successfully transact more tokens on the same day (Fuzz test)", async() => { + // Check the balance of the investors + let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + let totalAmountTransacted = 0; + for (let i = 0; i < 10; i++) { + let amount = Math.random(); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); + console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); + totalAmountTransacted += amount; + } + + // Check the balance of the investors + let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); + + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + `); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Days Covered : ${data[2].toNumber()} + Last Timestamp Index : ${data[3].toNumber()} + `); + }); + + it("Should successfully transfer the tokens after half days-- should increase the day covered by 1", async() => { + await increaseTime(duration.days(.5)); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + `); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Days Covered : ${data[2].toNumber()} + Last Timestamp Index : ${data[3].toNumber()} + `); + assert.equal(data[2].toNumber(), 2); + }); + + it("Should successfully transfer the tokens in the last day of rolling period", async() => { + // Check the balance of the investors + let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + let totalAmountTransacted = 0; + for (let i = 0; i < 3; i++) { + let amount = Math.random(); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); + console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); + totalAmountTransacted += amount; + } + // Check the balance of the investors + let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); + + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + `); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Days Covered : ${data[2].toNumber()} + Last Timestamp Index : ${data[3].toNumber()} + `); + }); + + it("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + let minimumAmount = new BigNumber(12).times(new BigNumber(10).pow(18)).minus(data[1]); + let testAmount = minimumAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))) + await catchRevert( + I_SecurityToken.transfer(account_investor3, testAmount, {from: account_investor1}) + ); + }); + + it("Should fail to buy tokens in the new rolling period --failed because amount is more than last two timestamps", async() => { + await increaseTime(duration.days(2)); + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_investor1}) + ); + }); + + it("Should transfer the tokens in a new rolling period", async() => { + let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 0; i < oldData[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${oldData[0][i].toNumber()} + Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])} + `); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((oldData[1].toNumber()).toString())} + Days Covered : ${oldData[2].toNumber()} + Last Timestamp Index : ${oldData[3].toNumber()} + `); + + let tx = await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(".3"), {from: account_investor1}); + console.log('\n'); + console.log(tx.logs); + let newData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 0; i < newData[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${newData[0][i].toNumber()} + Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])} + `); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((newData[1].toNumber()).toString())} + Days Covered : ${newData[2].toNumber()} + Last Timestamp Index : ${newData[3].toNumber()} + `); + assert.notEqual(oldData[0][0].toNumber(), newData[0][0].toNumber()); + assert.notEqual(oldData[0][1].toNumber(), newData[0][1].toNumber()); + }); + }); }); \ No newline at end of file From 3796d24a2fd435e0e75e3ddfd103e92b6266fc0e Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Thu, 22 Nov 2018 11:52:26 -0300 Subject: [PATCH 151/582] sto_manager improvements --- CLI/commands/sto_manager.js | 325 +++++++++++++++++-------------- CLI/data/capped_sto_data.yml | 49 ++--- CLI/data/usd_tiered_sto_data.yml | 76 +++----- CLI/polymath-cli.js | 11 +- 4 files changed, 233 insertions(+), 228 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 871e6d37b..159ace91b 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -19,18 +19,45 @@ let usdToken; let securityToken; async function executeApp() { - common.logAsciiBull(); - console.log("********************************************"); - console.log("Welcome to the Command-Line ST-20 Generator."); - console.log("********************************************"); - console.log("The following script will create a new ST-20 according to the parameters you enter."); - console.log("Issuer Account: " + Issuer.address + "\n"); - - await setup(); + let exit = false; + while (!exit) { + console.log('\n', chalk.blue('STO Manager - Main Menu'), '\n'); + + // Show non-archived attached STO modules + let stoModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.STO); + let nonArchivedModules = stoModules.filter(m => !m.archived); + if (nonArchivedModules.length > 0) { + console.log(`STO modules attached:`); + nonArchivedModules.map(m => console.log(`- ${m.name} at ${m.address}`)) + } else { + console.log(`There are no STO modules attached`); + } - securityToken = await selectToken(); - while (true) { - await start_explorer(); + let options = []; + if (nonArchivedModules.length > 0) { + options.push('Show existing STO information', 'Modify existing STO'); + } + options.push('Add new STO module'); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Exit'}); + let optionSelected = index != -1 ? options[index] : 'Exit'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Show existing STO information': + let stoToShow = selectExistingSTO(nonArchivedModules, true); + await showSTO(stoToShow.name, stoToShow.module); + break; + case 'Modify existing STO': + let stoToModify = selectExistingSTO(nonArchivedModules); + await modifySTO(stoToModify.name, stoToModify.module); + break; + case 'Add new STO module': + await addSTOModule(); + break; + case 'Exit': + exit = true; + break; + } } }; @@ -58,75 +85,33 @@ async function setup(){ } async function selectToken() { - let stAddress; + let result = null; + let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); if (userTokens.length == 0) { console.log(chalk.red(`You have not issued any Security Token yet!`)); - process.exit(0); } else if (userTokens.length == 1) { let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(userTokens[0]).call(); console.log(chalk.yellow(`You have only one token. ${tokenData[0]} will be selected automatically.`)); - stAddress = userTokens[0]; + result = tokenData[0]; } else { - let options = await Promise.all(userTokens.map(async function (t) { + let tokenDataArray = await Promise.all(userTokens.map(async function (t) { let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); - return `${tokenData[0]} - Deployed at ${t}`; + return {tokenData: tokenData, address: t}; })); + let options = tokenDataArray.map(function (t) { + return `${t.tokenData[0]} - Deployed at ${t.address}`; + }); let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); - if (index == -1) { - process.exit(0); + if (index != -1) { + result = tokenDataArray[index][0]; } else { - stAddress = userTokens[index]; + process.exit(); } } - - let securityTokenABI = abis.securityToken(); - let securityToken = new web3.eth.Contract(securityTokenABI, stAddress); - return securityToken; -} - -async function start_explorer() { - console.log(); - console.log(chalk.blue('STO Manager - Main Menu')); - - // Show non-archived attached STO modules - console.log(); - let stoModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.STO); - let nonArchivedModules = stoModules.filter(m => !m.archived); - if (nonArchivedModules.length > 0) { - console.log(`STO modules attached:`); - nonArchivedModules.map(m => console.log(`- ${m.name} at ${m.address}`)) - } else { - console.log(`There are no STO modules attached`); - } - - let options = []; - if (nonArchivedModules.length > 0) { - options.push('Show existing STO information', 'Modify existing STO'); - } - options.push('Add new STO module'); - - let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Exit'}); - let optionSelected = index != -1 ? options[index] : 'Exit'; - console.log('Selected:', optionSelected, '\n'); - switch (optionSelected) { - case 'Show existing STO information': - let stoToShow = selectExistingSTO(nonArchivedModules, true); - await showSTO(stoToShow.name, stoToShow.module); - break; - case 'Modify existing STO': - let stoToModify = selectExistingSTO(nonArchivedModules); - await modifySTO(stoToModify.name, stoToModify.module); - break; - case 'Add new STO module': - await addSTOModule(); - break; - case 'Exit': - process.exit(0); - } + return result; } function selectExistingSTO(stoModules, showPaused) { @@ -177,20 +162,25 @@ async function modifySTO(selectedSTO, currentSTO) { } } -async function addSTOModule() { +async function addSTOModule(stoConfig) { console.log(chalk.blue('Launch STO - Configuration')); - let options = ['CappedSTO', 'USDTieredSTO']; - let index = readlineSync.keyInSelect(options, 'What type of STO do you want?', { cancel: 'Return' }); - let optionSelected = index != -1 ? options[index] : 'Return'; + let optionSelected; + if (typeof stoConfig === 'undefined') { + let options = ['CappedSTO', 'USDTieredSTO']; + let index = readlineSync.keyInSelect(options, 'What type of STO do you want?', { cancel: 'Return' }); + optionSelected = index != -1 ? options[index] : 'Return'; + } else { + optionSelected = stoConfig.type; + } console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'CappedSTO': - let cappedSTO = await cappedSTO_launch(); + let cappedSTO = await cappedSTO_launch(stoConfig); await cappedSTO_status(cappedSTO); break; case 'USDTieredSTO': - let usdTieredSTO = await usdTieredSTO_launch(); + let usdTieredSTO = await usdTieredSTO_launch(stoConfig); await usdTieredSTO_status(usdTieredSTO); break; } @@ -199,7 +189,7 @@ async function addSTOModule() { //////////////// // Capped STO // //////////////// -async function cappedSTO_launch() { +async function cappedSTO_launch(stoConfig) { console.log(chalk.blue('Launch STO - Capped STO in No. of Tokens')); let cappedSTOFactoryABI = abis.cappedSTOFactory(); @@ -225,29 +215,37 @@ async function cappedSTO_launch() { } } - let cap = readlineSync.question('How many tokens do you plan to sell on the STO? (500.000): '); - if (cap == "") cap = '500000'; - let oneMinuteFromNow = BigNumber((Math.floor(Date.now() / 1000) + 60)); - let startTime = readlineSync.question('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): '); - if (startTime == "") startTime = oneMinuteFromNow; - let oneMonthFromNow = BigNumber((Math.floor(Date.now()/1000)+ (30 * 24 * 60 * 60))); - let endTime = readlineSync.question('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): '); - if (endTime == "") endTime = oneMonthFromNow; - let wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): '); - if (wallet == "") wallet = Issuer.address; + let cappedSTOconfig = {}; + let useConfigFile = typeof stoConfig !== 'undefined'; + if (!useConfigFile) { + cappedSTOconfig.cap = readlineSync.question('How many tokens do you plan to sell on the STO? (500.000): '); + if (cappedSTOconfig.cap == "") cappedSTOconfig.cap = 500000; + + cappedSTOconfig.raiseType = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise or leave empty for Ether raise (E): '); + if (cappedSTOconfig.raiseType.toUpperCase() == 'P' ) { + cappedSTOconfig.raiseType = [1]; + } else { + cappedSTOconfig.raiseType = [0]; + } + + cappedSTOconfig.rate = readlineSync.question(`Enter the rate (1 ${(cappedSTOconfig.raiseType == 1 ? 'POLY' : 'ETH')} = X ${tokenSymbol}) for the STO (1000): `); + if (cappedSTOconfig.rate == "") cappedSTOconfig.rate = 1000; - let raiseType = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise or leave empty for Ether raise (E): '); - if (raiseType.toUpperCase() == 'P' ) { - raiseType = [1]; + cappedSTOconfig.wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): '); + if (cappedSTOconfig.wallet == "") cappedSTOconfig.wallet = Issuer.address; + + cappedSTOconfig.startTime = readlineSync.question('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): '); + + cappedSTOconfig.endTime = readlineSync.question('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): '); } else { - raiseType = [0]; + cappedSTOconfig = stoConfig; } - let rate = readlineSync.question(`Enter the rate (1 ${(raiseType == 1 ? 'POLY' : 'ETH')} = X ${tokenSymbol}) for the STO (1000): `); - if (rate == "") rate = 1000; + if (cappedSTOconfig.startTime == "") cappedSTOconfig.startTime = oneMinuteFromNow; + if (cappedSTOconfig.endTime == "") cappedSTOconfig.endTime = oneMonthFromNow; let bytesSTO = web3.eth.abi.encodeFunctionCall( { name: 'configure', @@ -273,7 +271,7 @@ async function cappedSTO_launch() { name: '_fundsReceiver' } ] - }, [startTime, endTime, web3.utils.toWei(cap), rate, raiseType, wallet]); + }, [cappedSTOconfig.startTime, cappedSTOconfig.endTime, web3.utils.toWei(cappedSTOconfig.cap.toString()), cappedSTOconfig.rate, cappedSTOconfig.raiseType, cappedSTOconfig.wallet]); let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); let receipt = await common.sendTransaction(addModuleAction); @@ -431,38 +429,38 @@ function tiersConfigUSDTieredSTO(polyRaise) { tiers.tokensPerTierDiscountPoly = []; tiers.ratePerTierDiscountPoly = []; for (let i = 0; i < tiers.tiers; i++) { - tiers.tokensPerTier[i] = web3.utils.toWei(readlineSync.question(`How many tokens do you plan to sell on tier No. ${i+1}? (${defaultTokensPerTier[i]}): `, { + tiers.tokensPerTier[i] = readlineSync.question(`How many tokens do you plan to sell on tier No. ${i+1}? (${defaultTokensPerTier[i]}): `, { limit: function(input) { return parseFloat(input) > 0; }, limitMessage: 'Must be greater than zero', defaultInput: defaultTokensPerTier[i] - })); + }); - tiers.ratePerTier[i] = web3.utils.toWei(readlineSync.question(`What is the USD per token rate for tier No. ${i+1}? (${defaultRatePerTier[i]}): `, { + tiers.ratePerTier[i] = readlineSync.question(`What is the USD per token rate for tier No. ${i+1}? (${defaultRatePerTier[i]}): `, { limit: function(input) { return parseFloat(input) > 0; }, limitMessage: 'Must be greater than zero', defaultInput: defaultRatePerTier[i] - })); + }); if (polyRaise && readlineSync.keyInYNStrict(`Do you plan to have a discounted rate for POLY investments for tier No. ${i+1}? `)) { - tiers.tokensPerTierDiscountPoly[i] = web3.utils.toWei(readlineSync.question(`How many of those tokens do you plan to sell at discounted rate on tier No. ${i+1}? (${defaultTokensPerTierDiscountPoly[i]}): `, { + tiers.tokensPerTierDiscountPoly[i] = readlineSync.question(`How many of those tokens do you plan to sell at discounted rate on tier No. ${i+1}? (${defaultTokensPerTierDiscountPoly[i]}): `, { limit: function(input) { - return new BigNumber(web3.utils.toWei(input)).lte(tiers.tokensPerTier[i]) + return parseFloat(input) < parseFloat(tiers.tokensPerTier[i]); }, limitMessage: 'Must be less than the No. of tokens of the tier', defaultInput: defaultTokensPerTierDiscountPoly[i] - })); + }); - tiers.ratePerTierDiscountPoly[i] = web3.utils.toWei(readlineSync.question(`What is the discounted rate for tier No. ${i+1}? (${defaultRatePerTierDiscountPoly[i]}): `, { + tiers.ratePerTierDiscountPoly[i] = readlineSync.question(`What is the discounted rate for tier No. ${i+1}? (${defaultRatePerTierDiscountPoly[i]}): `, { limit: function(input) { - return new BigNumber(web3.utils.toWei(input)).lte(tiers.ratePerTier[i]) + return parseFloat(input) < parseFloat(tiers.ratePerTier[i]); }, limitMessage: 'Must be less than the rate of the tier', defaultInput: defaultRatePerTierDiscountPoly[i] - })); + }); } else { tiers.tokensPerTierDiscountPoly[i] = 0; tiers.ratePerTierDiscountPoly[i] = 0; @@ -472,57 +470,65 @@ function tiersConfigUSDTieredSTO(polyRaise) { return tiers; } -function timesConfigUSDTieredSTO() { - let times = {}; - - let oneMinuteFromNow = Math.floor(Date.now() / 1000) + 60; - times.startTime = readlineSync.questionInt('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): ', { - limit: function(input) { - return input > Math.floor(Date.now() / 1000); - }, - limitMessage: "Must be a future time", - defaultInput: oneMinuteFromNow - }); - if (times.startTime == "") times.startTime = oneMinuteFromNow; - - let oneMonthFromNow = Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60); - times.endTime = readlineSync.questionInt('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): ', { - limit: function(input) { - return input > times.startTime; - }, - limitMessage: "Must be greater than Start Time", - defaultInput: oneMonthFromNow - }); - if (times.endTime == "") times.endTime = oneMonthFromNow; - - return times; -} - function limitsConfigUSDTieredSTO() { let limits = {}; let defaultMinimumInvestment = 5; - limits.minimumInvestmentUSD = web3.utils.toWei(readlineSync.question(`What is the minimum investment in USD? (${defaultMinimumInvestment}): `, { + limits.minimumInvestmentUSD = readlineSync.question(`What is the minimum investment in USD? (${defaultMinimumInvestment}): `, { limit: function(input) { return parseInt(input) > 0; }, limitMessage: "Must be greater than zero", defaultInput: defaultMinimumInvestment - })); + }); let nonAccreditedLimit = 2500; - limits.nonAccreditedLimitUSD = web3.utils.toWei(readlineSync.question(`What is the default limit for non accredited investors in USD? (${nonAccreditedLimit}): `, { + limits.nonAccreditedLimitUSD = readlineSync.question(`What is the default limit for non accredited investors in USD? (${nonAccreditedLimit}): `, { limit: function(input) { - return new BigNumber(web3.utils.toWei(input)).gte(limits.minimumInvestmentUSD); + return parseFloat(input) >= parseFloat(limits.minimumInvestmentUSD); }, limitMessage: "Must be greater than minimum investment", defaultInput: nonAccreditedLimit - })); + }); return limits; } -async function usdTieredSTO_launch() { +function timesConfigUSDTieredSTO(stoConfig) { + let times = {}; + + let oneMinuteFromNow = Math.floor(Date.now() / 1000) + 60; + if (typeof stoConfig === 'undefined') { + times.startTime = readlineSync.questionInt('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): ', { + limit: function(input) { + return input > Math.floor(Date.now() / 1000); + }, + limitMessage: "Must be a future time", + defaultInput: oneMinuteFromNow + }); + } else { + times.startTime = stoConfig.times.startTime; + } + if (times.startTime == "") times.startTime = oneMinuteFromNow; + + let oneMonthFromNow = Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60); + if (typeof stoConfig === 'undefined') { + times.endTime = readlineSync.questionInt('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): ', { + limit: function(input) { + return input > times.startTime; + }, + limitMessage: "Must be greater than Start Time", + defaultInput: oneMonthFromNow + }); + } else { + times.endTime = stoConfig.times.startTime; + } + if (times.endTime == "") times.endTime = oneMonthFromNow; + + return times; +} + +async function usdTieredSTO_launch(stoConfig) { console.log(chalk.blue('Launch STO - USD pegged tiered STO')); let usdTieredSTOFactoryABI = abis.usdTieredSTOFactory(); @@ -548,11 +554,12 @@ async function usdTieredSTO_launch() { } } - let funding = fundingConfigUSDTieredSTO(); - let addresses = addressesConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.DAI)); - let tiers = tiersConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.POLY)); - let limits = limitsConfigUSDTieredSTO(); - let times = timesConfigUSDTieredSTO(); + let useConfigFile = typeof stoConfig !== 'undefined'; + let funding = useConfigFile ? stoConfig.funding : fundingConfigUSDTieredSTO(); + let addresses = useConfigFile ? stoConfig.addresses : addressesConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.DAI)); + let tiers = useConfigFile ? stoConfig.tiers : tiersConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.POLY)); + let limits = useConfigFile ? stoConfig.limits : limitsConfigUSDTieredSTO(); + let times = timesConfigUSDTieredSTO(stoConfig); let bytesSTO = web3.eth.abi.encodeFunctionCall( { name: 'configure', type: 'function', @@ -597,12 +604,12 @@ async function usdTieredSTO_launch() { ] }, [times.startTime, times.endTime, - tiers.ratePerTier, - tiers.ratePerTierDiscountPoly, - tiers.tokensPerTier, - tiers.tokensPerTierDiscountPoly, - limits.nonAccreditedLimitUSD, - limits.minimumInvestmentUSD, + tiers.ratePerTier.map(r => web3.utils.toWei(r.toString())), + tiers.ratePerTierDiscountPoly.map(rd => web3.utils.toWei(rd.toString())), + tiers.tokensPerTier.map(t => web3.utils.toWei(t.toString())), + tiers.tokensPerTierDiscountPoly.map(td => web3.utils.toWei(td.toString())), + web3.utils.toWei(limits.nonAccreditedLimitUSD.toString()), + web3.utils.toWei(limits.minimumInvestmentUSD.toString()), funding.raiseType, addresses.wallet, addresses.reserveWallet, @@ -920,8 +927,40 @@ async function getAllModulesByType(type) { return modules; } +async function initialize(_tokenSymbol) { + welcome(); + await setup(); + if (typeof _tokenSymbol === 'undefined') { + tokenSymbol = await selectToken(); + } else { + tokenSymbol = _tokenSymbol; + } + let securityTokenAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); + if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { + console.log(chalk.red(`Selected Security Token ${tokenSymbol} does not exist.`)); + process.exit(0); + } + let securityTokenABI = abis.securityToken(); + securityToken = new web3.eth.Contract(securityTokenABI, securityTokenAddress); + securityToken.setProvider(web3.currentProvider); +} + +function welcome() { + common.logAsciiBull(); + console.log("****************************************"); + console.log("Welcome to the Command-Line STO Manager."); + console.log("****************************************"); + console.log("The following script will allow you to manage STOs modules."); + console.log("Issuer Account: " + Issuer.address + "\n"); +} + module.exports = { - executeApp: async function() { + executeApp: async function(_tokenSymbol) { + await initialize(_tokenSymbol); return executeApp(); + }, + addSTOModule: async function(_tokenSymbol, stoConfig) { + await initialize(_tokenSymbol); + return addSTOModule(stoConfig) } } \ No newline at end of file diff --git a/CLI/data/capped_sto_data.yml b/CLI/data/capped_sto_data.yml index 6be0c0f66..41653c9ff 100644 --- a/CLI/data/capped_sto_data.yml +++ b/CLI/data/capped_sto_data.yml @@ -1,35 +1,14 @@ -securityToken: - # symbol -> security token symbol - symbol: CAP - # name -> security token name - name: CAP Token - # divisible -> true for divisible token, false for non-divisible - divisible: true - -initialMint: - # multimint -> whitelist and mint tokens to a list of affiliates (true) or only to a single wallet (false) - multimint: true - # singleMint -> Only valid if multimint = false - singleMint: - # wallet -> address that will be whitelisted - wallet: '' - # allowedToBuy -> true to allow wallet to buy tokens from the STO - allowedToBuy: true - # tokenAmount -> tokens minted to wallet - tokenAmount: 500000 - -sto: - # type -> 0 for cappedSTO, 1 for USDTieredSTO, 2 for select STO later - type: 0 - # cap -> - cap: 500000 - # startTime -> start time for the STO (Unix Epoch time) - startTime: '' - # endTime -> end time for the STO (Unix Epoch time) - endTime: '' - # wallet -> address that will receive the funds from the STO - wallet: '' - # raiseType -> 0 for ETH, 1 for POLY - raiseType: 0 - # rate -> rate for the STO - rate: 1000 \ No newline at end of file +# type -> 'CappedSTO' for cappedSTO, 'USDTieredSTO' for USDTieredSTO +type: 'CappedSTO' +# cap -> Maximum No. of tokens for sale. +cap: 1000000 +# startTime -> Unix timestamp at which offering get started. '' for CLI default (one minute from now) +startTime: '' +# endTime -> Unix timestamp at which offering get ended. '' for CLI default (one month from now) +endTime: '' +# wallet -> Ethereum account address to hold the funds +wallet: '0x0a519b4b6501f92e8f516230b97aca83257b0c01' +# raiseType -> Type of currency used to collect the funds. [0] for ETH, [1] for POLY +raiseType: [0] +# rate -> Token units a buyer gets per unit of selected raise type. +rate: 1000 \ No newline at end of file diff --git a/CLI/data/usd_tiered_sto_data.yml b/CLI/data/usd_tiered_sto_data.yml index 305167bd7..29655c5bf 100644 --- a/CLI/data/usd_tiered_sto_data.yml +++ b/CLI/data/usd_tiered_sto_data.yml @@ -1,57 +1,37 @@ -securityToken: - # symbol -> security token symbol - symbol: TIE - # name -> security token name - name: TIEred Token - # divisible -> true for divisible token, false for non-divisible - divisible: true +# type -> 'CappedSTO' for cappedSTO, 'USDTieredSTO' for USDTieredSTO +type: 'USDTieredSTO' -initialMint: - # multimint -> whitelist and mint tokens to a list of affiliates (true) or only to a single wallet (false) - multimint: true - # singleMint -> Only valid if multimint = false - singleMint: - # wallet -> address that will be whitelisted - wallet: '' - # allowedToBuy -> true to allow wallet to buy tokens from the STO - allowedToBuy: true - # tokenAmount -> tokens minted to wallet - tokenAmount: 500000 - -sto: - # type -> 0 for cappedSTO, 1 for USDTieredSTO, 2 for select STO later - type: 1 - - # fundings - # fundigType -> P for POLY, E for ETH, B for both - fundingType: B +funding: + # fundigType -> Types of currency used to collect the funds, 0 for ETH, 1 for POLY, 2 for DAI, any combination of them for more than one (i.e. [0, 1, 2] for all of them) + raiseType: [0, 1] - # addresses - # wallet -> address that will receive the funds from the STO - wallet: '' - # reserveWallet -> address that will receive remaining tokens in the case the cap is not met - reserveWallet: '' +addresses: + # wallet -> Ethereum account address to hold the funds. + wallet: '0x0a519b4b6501f92e8f516230b97aca83257b0c01' + # reserveWallet -> Ethereum account address to receive unsold tokens. + reserveWallet: '0x0a519b4b6501f92e8f516230b97aca83257b0c01' + # usdToken -> Contract address of the stable coin. + usdToken: '0x0000000000000000000000000000000000000000' + - # tiers - # numberOfTiers -> total of tiers for the STO - numberOfTiers: 3 - # tokensPerTiers -> total tokens for each tier - tokensPerTiers: !!seq [ 190000000, 100000000, 200000000 ] - # ratePerTiers -> rate for each tier (in USD) - ratePerTiers: !!seq [ 0.05, 0.10, 0.15 ] - # discountedTokensPerTiers -> tokens for discounted rate for POLY investments (relative to tokensPerTier). 0 for no discounted tokens - discountedTokensPerTiers: !!seq [ 0, 0, 100000000 ] - # discountedRatePerTiers -> discounted rate for POLY investments for each tier. 0 for no discounted rate - discountedRatePerTiers: !!seq [ 0, 0, 0.075 ] +tiers: + # tokensPerTiers -> Total tokens for each tier + tokensPerTier: !!seq [ 190000000, 100000000, 200000000 ] + # ratePerTiers -> Rate for each tier (in USD) + ratePerTier: !!seq [ 0.05, 0.10, 0.15 ] + # discountedTokensPerTiers -> Tokens for discounted rate for POLY investments. 0 for no discounted tokens + tokensPerTierDiscountPoly: !!seq [ 0, 0, 100000000 ] + # discountedRatePerTiers -> Discounted rate for POLY investments for each tier. 0 for no discounted rate + ratePerTierDiscountPoly: !!seq [ 0, 0, 0.075 ] - # limits - # minimumInvestmentUSD -> minimum investment (in USD) +limits: + # minimumInvestmentUSD -> Minimun investment in USD. minimumInvestmentUSD: 5 - # nonAccreditedLimitUSD -> limit for non accredited insvestors (in USD) + # nonAccreditedLimitUSD -> Limit in USD for non-accredited investors nonAccreditedLimitUSD: 10000 - #times - # startTime -> start time for the STO (Unix Epoch time) +times: + # startTime -> Unix timestamp at which offering get started. '' for CLI default (one minute from now) startTime: '' - # endTime -> end time for the STO (Unix Epoch time) + # endTime -> Unix timestamp at which offering get ended. '' for CLI default (one month from now) endTime: '' \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index f90ac529a..e28e4c987 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -39,11 +39,18 @@ program program .command('sto_manager') + .option('-t, --securityToken ', 'Selects a ST to manage modules') + .option('-l, --launch ', 'Uses configuration file to configure and launch a STO') .alias('sto') .description('Wizard-like script that will guide technical users in the creation of an STO') - .action(async function() { + .action(async function(cmd) { await gbl.initialize(program.remoteNode); - await sto_manager.executeApp(); + if (cmd.launch) { + let config = yaml.safeLoad(fs.readFileSync(`${__dirname}/${cmd.launch}`, 'utf8')); + await sto_manager.addSTOModule(cmd.securityToken, config) + } else { + await sto_manager.executeApp(cmd.securityToken); + } }); program From e732ed9e5c3ada2f6af6cab69a3bd047cf07828c Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Thu, 22 Nov 2018 12:25:44 -0300 Subject: [PATCH 152/582] Minor improvements --- CLI/commands/sto_manager.js | 80 +++++++++++++++---------------------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 159ace91b..ae3ba6ea7 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -1,5 +1,4 @@ var readlineSync = require('readline-sync'); -var BigNumber = require('bignumber.js'); var chalk = require('chalk'); const shell = require('shelljs'); var contracts = require('./helpers/contract_addresses'); @@ -196,27 +195,27 @@ async function cappedSTO_launch(stoConfig) { let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.STO, "CappedSTO"); let cappedSTOFactory = new web3.eth.Contract(cappedSTOFactoryABI, cappedSTOFactoryAddress); cappedSTOFactory.setProvider(web3.currentProvider); - let stoFee = await cappedSTOFactory.methods.getSetupCost().call(); + let stoFee = new web3.utils.BN(await cappedSTOFactory.methods.getSetupCost().call()); - let contractBalance = await polyToken.methods.balanceOf(securityToken._address).call(); - if (parseInt(contractBalance) < parseInt(stoFee)) { - let transferAmount = parseInt(stoFee) - parseInt(contractBalance); - let ownerBalance = await polyToken.methods.balanceOf(Issuer.address).call(); - if (parseInt(ownerBalance) < transferAmount) { + let contractBalance = new web3.utils.BN(await polyToken.methods.balanceOf(securityToken._address).call()); + if (contractBalance.lt(stoFee)) { + let transferAmount = stoFee.sub(contractBalance); + let ownerBalance = new web3.utils.BN(await polyToken.methods.balanceOf(Issuer.address).call()); + if (ownerBalance.lt(transferAmount)) { console.log(chalk.red(`\n**************************************************************************************************************************************************`)); - console.log(chalk.red(`Not enough balance to pay the CappedSTO fee, Requires ${(new BigNumber(transferAmount).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY but have ${(new BigNumber(ownerBalance).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY. Access POLY faucet to get the POLY to complete this txn`)); + console.log(chalk.red(`Not enough balance to pay the CappedSTO fee, Requires ${web3.utils.fromWei(transferAmount)} POLY but have ${web3.utils.fromWei(ownerBalance)} POLY. Access POLY faucet to get the POLY to complete this txn`)); console.log(chalk.red(`**************************************************************************************************************************************************\n`)); return; } else { - let transferAction = polyToken.methods.transfer(securityToken._address, new BigNumber(transferAmount)); + let transferAction = polyToken.methods.transfer(securityToken._address, transferAmount); let receipt = await common.sendTransaction(transferAction, {factor: 2}); let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) } } - let oneMinuteFromNow = BigNumber((Math.floor(Date.now() / 1000) + 60)); - let oneMonthFromNow = BigNumber((Math.floor(Date.now()/1000)+ (30 * 24 * 60 * 60))); + let oneMinuteFromNow = new web3.utils.BN((Math.floor(Date.now() / 1000) + 60)); + let oneMonthFromNow = new web3.utils.BN((Math.floor(Date.now()/1000)+ (30 * 24 * 60 * 60))); let cappedSTOconfig = {}; let useConfigFile = typeof stoConfig !== 'undefined'; @@ -226,12 +225,12 @@ async function cappedSTO_launch(stoConfig) { cappedSTOconfig.raiseType = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise or leave empty for Ether raise (E): '); if (cappedSTOconfig.raiseType.toUpperCase() == 'P' ) { - cappedSTOconfig.raiseType = [1]; + cappedSTOconfig.raiseType = [gbl.constants.FUND_RAISE_TYPES.POLY]; } else { - cappedSTOconfig.raiseType = [0]; + cappedSTOconfig.raiseType = [gbl.constants.FUND_RAISE_TYPES.ETH]; } - cappedSTOconfig.rate = readlineSync.question(`Enter the rate (1 ${(cappedSTOconfig.raiseType == 1 ? 'POLY' : 'ETH')} = X ${tokenSymbol}) for the STO (1000): `); + cappedSTOconfig.rate = readlineSync.question(`Enter the rate (1 ${cappedSTOconfig.raiseType == gbl.constants.FUND_RAISE_TYPES.POLY ? 'POLY' : 'ETH'} = X ${tokenSymbol}) for the STO (1000): `); if (cappedSTOconfig.rate == "") cappedSTOconfig.rate = 1000; cappedSTOconfig.wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): '); @@ -273,7 +272,7 @@ async function cappedSTO_launch(stoConfig) { ] }, [cappedSTOconfig.startTime, cappedSTOconfig.endTime, web3.utils.toWei(cappedSTOconfig.cap.toString()), cappedSTOconfig.rate, cappedSTOconfig.raiseType, cappedSTOconfig.wallet]); - let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); + let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, stoFee, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); @@ -289,28 +288,15 @@ async function cappedSTO_status(currentSTO) { let displayStartTime = await currentSTO.methods.startTime().call(); let displayEndTime = await currentSTO.methods.endTime().call(); let displayRate = await currentSTO.methods.rate().call(); - let displayCap = await currentSTO.methods.cap().call(); + let displayCap = new web3.utils.BN(await currentSTO.methods.cap().call()); let displayWallet = await currentSTO.methods.wallet().call(); - let displayRaiseType; - let displayFundsRaised; - let displayWalletBalance; - let raiseType = await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.ETH).call(); - if (raiseType) { - displayRaiseType = 'ETH'; - displayFundsRaised = await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES.ETH).call(); - displayWalletBalance = web3.utils.fromWei(await web3.eth.getBalance(displayWallet)); - } else { - displayRaiseType = 'POLY'; - displayFundsRaised = await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES.POLY).call(); - displayWalletBalance = web3.utils.fromWei(await getBalance(displayWallet, 'POLY')); - } - let displayTokensSold = await currentSTO.methods.totalTokensSold().call(); + let displayRaiseType = await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.ETH).call() ? 'ETH' : 'POLY'; + let displayFundsRaised = await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[displayRaiseType]).call(); + let displayWalletBalance = web3.utils.fromWei(await getBalance(displayWallet, gbl.constants.FUND_RAISE_TYPES[displayRaiseType])); + let displayTokensSold = new web3.utils.BN(await currentSTO.methods.totalTokensSold().call()); let displayInvestorCount = await currentSTO.methods.investorCount().call(); let displayTokenSymbol = await securityToken.methods.symbol().call(); - let formattedCap = BigNumber(web3.utils.fromWei(displayCap)); - let formattedSold = BigNumber(web3.utils.fromWei(displayTokensSold)); - let now = Math.floor(Date.now()/1000); let timeTitle; let timeRemaining; @@ -339,11 +325,11 @@ async function cappedSTO_status(currentSTO) { - ${timeTitle} ${timeRemaining} - Funds raised: ${web3.utils.fromWei(displayFundsRaised)} ${displayRaiseType} - Tokens sold: ${web3.utils.fromWei(displayTokensSold)} ${displayTokenSymbol.toUpperCase()} - - Tokens remaining: ${formattedCap.minus(formattedSold).toNumber()} ${displayTokenSymbol.toUpperCase()} + - Tokens remaining: ${web3.utils.fromWei(displayCap.sub(displayTokensSold))} ${displayTokenSymbol.toUpperCase()} - Investor count: ${displayInvestorCount} `); - console.log(chalk.green(`\n${(web3.utils.fromWei(await getBalance(Issuer.address, 'POLY')))} POLY balance remaining at issuer address ${Issuer.address}`)); + console.log(chalk.green(`\n${(web3.utils.fromWei(await getBalance(Issuer.address, gbl.constants.FUND_RAISE_TYPES.POLY)))} POLY balance remaining at issuer address ${Issuer.address}`)); } //////////////////// @@ -476,7 +462,7 @@ function limitsConfigUSDTieredSTO() { let defaultMinimumInvestment = 5; limits.minimumInvestmentUSD = readlineSync.question(`What is the minimum investment in USD? (${defaultMinimumInvestment}): `, { limit: function(input) { - return parseInt(input) > 0; + return parseFloat(input) > 0; }, limitMessage: "Must be greater than zero", defaultInput: defaultMinimumInvestment @@ -535,11 +521,11 @@ async function usdTieredSTO_launch(stoConfig) { let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.STO, 'USDTieredSTO'); let usdTieredSTOFactory = new web3.eth.Contract(usdTieredSTOFactoryABI, usdTieredSTOFactoryAddress); usdTieredSTOFactory.setProvider(web3.currentProvider); - let stoFee = await usdTieredSTOFactory.methods.getSetupCost().call(); + let stoFee = new web3.utils.BN(await usdTieredSTOFactory.methods.getSetupCost().call()); - let contractBalance = await polyToken.methods.balanceOf(securityToken._address).call(); - if (new web3.utils.BN(contractBalance).lt(new web3.utils.BN(stoFee))) { - let transferAmount = (new web3.utils.BN(stoFee)).sub(new web3.utils.BN(contractBalance)); + let contractBalance = new web3.utils.BN(await polyToken.methods.balanceOf(securityToken._address).call()); + if (contractBalance.lt(stoFee)) { + let transferAmount = stoFee.sub(contractBalance); let ownerBalance = new web3.utils.BN(await polyToken.methods.balanceOf(Issuer.address).call()); if (ownerBalance.lt(transferAmount)) { console.log(chalk.red(`\n**************************************************************************************************************************************************`)); @@ -616,7 +602,7 @@ async function usdTieredSTO_launch(stoConfig) { addresses.usdToken ]); - let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); + let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, stoFee, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); @@ -697,13 +683,13 @@ async function usdTieredSTO_status(currentSTO) { let displayFundsRaisedPerType = ''; let displayTokensSoldPerType = ''; for (const type of raiseTypes) { - let balance = await getBalance(displayWallet, type); + let balance = await getBalance(displayWallet, gbl.constants.FUND_RAISE_TYPES[type]); let walletBalance = web3.utils.fromWei(balance); let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); displayWalletBalancePerType += ` Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; - balance = await getBalance(displayReserveWallet, type); + balance = await getBalance(displayReserveWallet, gbl.constants.FUND_RAISE_TYPES[type]); let reserveWalletBalance = web3.utils.fromWei(balance); let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); displayReserveWalletBalancePerType += ` @@ -764,7 +750,7 @@ async function usdTieredSTO_status(currentSTO) { USD: ${displayFundsRaisedUSD} USD `); - console.log(chalk.green(`\n${(web3.utils.fromWei(await getBalance(Issuer.address, 'POLY')))} POLY balance remaining at issuer address ${Issuer.address}`)); + console.log(chalk.green(`\n${(web3.utils.fromWei(await getBalance(Issuer.address, gbl.constants.FUND_RAISE_TYPES.POLY)))} POLY balance remaining at issuer address ${Issuer.address}`)); } async function usdTieredSTO_configure(currentSTO) { @@ -889,11 +875,11 @@ async function modfifyTiers(currentSTO) { ////////////////////// async function getBalance(from, type) { switch (type) { - case 'ETH': + case gbl.constants.FUND_RAISE_TYPES.ETH: return await web3.eth.getBalance(from); - case 'POLY': + case gbl.constants.FUND_RAISE_TYPES.POLY: return await polyToken.methods.balanceOf(from).call(); - case 'DAI': + case gbl.constants.FUND_RAISE_TYPES.DAI: return await usdToken.methods.balanceOf(from).call(); } } From a6cd7049de0e20adcef639bc0487a678bb1b0908 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Thu, 22 Nov 2018 12:33:17 -0300 Subject: [PATCH 153/582] Get configure function from ABI --- CLI/commands/sto_manager.js | 109 +++++++++--------------------------- 1 file changed, 27 insertions(+), 82 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index ae3ba6ea7..076401968 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -246,38 +246,22 @@ async function cappedSTO_launch(stoConfig) { if (cappedSTOconfig.startTime == "") cappedSTOconfig.startTime = oneMinuteFromNow; if (cappedSTOconfig.endTime == "") cappedSTOconfig.endTime = oneMonthFromNow; - let bytesSTO = web3.eth.abi.encodeFunctionCall( { - name: 'configure', - type: 'function', - inputs: [ - { - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'uint256', - name: '_rate' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes' - },{ - type: 'address', - name: '_fundsReceiver' - } - ] - }, [cappedSTOconfig.startTime, cappedSTOconfig.endTime, web3.utils.toWei(cappedSTOconfig.cap.toString()), cappedSTOconfig.rate, cappedSTOconfig.raiseType, cappedSTOconfig.wallet]); + let cappedSTOABI = abis.cappedSTO(); + let configureFunction = cappedSTOABI.find(o => o.name === 'configure' && o.type === 'function'); + let bytesSTO = web3.eth.abi.encodeFunctionCall( configureFunction, + [ cappedSTOconfig.startTime, + cappedSTOconfig.endTime, + web3.utils.toWei(cappedSTOconfig.cap.toString()), + cappedSTOconfig.rate, + cappedSTOconfig.raiseType, + cappedSTOconfig.wallet ] + ); let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, stoFee, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); - let cappedSTOABI = abis.cappedSTO(); let cappedSTO = new web3.eth.Contract(cappedSTOABI, event._module); cappedSTO.setProvider(web3.currentProvider); @@ -546,68 +530,29 @@ async function usdTieredSTO_launch(stoConfig) { let tiers = useConfigFile ? stoConfig.tiers : tiersConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.POLY)); let limits = useConfigFile ? stoConfig.limits : limitsConfigUSDTieredSTO(); let times = timesConfigUSDTieredSTO(stoConfig); - let bytesSTO = web3.eth.abi.encodeFunctionCall( { - name: 'configure', - type: 'function', - inputs: [ - { - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256[]', - name: '_ratePerTier' - },{ - type: 'uint256[]', - name: '_ratePerTierDiscountPoly' - },{ - type: 'uint256[]', - name: '_tokensPerTier' - },{ - type: 'uint256[]', - name: '_tokensPerTierDiscountPoly' - },{ - type: 'uint256', - name: '_nonAccreditedLimitUSD' - },{ - type: 'uint256', - name: '_minimumInvestmentUSD' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes' - },{ - type: 'address', - name: '_wallet' - },{ - type: 'address', - name: '_reserveWallet' - },{ - type: 'address', - name: '_usdToken' - } - ] - }, [times.startTime, - times.endTime, - tiers.ratePerTier.map(r => web3.utils.toWei(r.toString())), - tiers.ratePerTierDiscountPoly.map(rd => web3.utils.toWei(rd.toString())), - tiers.tokensPerTier.map(t => web3.utils.toWei(t.toString())), - tiers.tokensPerTierDiscountPoly.map(td => web3.utils.toWei(td.toString())), - web3.utils.toWei(limits.nonAccreditedLimitUSD.toString()), - web3.utils.toWei(limits.minimumInvestmentUSD.toString()), - funding.raiseType, - addresses.wallet, - addresses.reserveWallet, - addresses.usdToken - ]); + + let usdTieredSTOABI = abis.usdTieredSTO(); + let configureFunction = usdTieredSTOABI.find(o => o.name === 'configure' && o.type === 'function'); + let bytesSTO = web3.eth.abi.encodeFunctionCall( configureFunction, + [ times.startTime, + times.endTime, + tiers.ratePerTier.map(r => web3.utils.toWei(r.toString())), + tiers.ratePerTierDiscountPoly.map(rd => web3.utils.toWei(rd.toString())), + tiers.tokensPerTier.map(t => web3.utils.toWei(t.toString())), + tiers.tokensPerTierDiscountPoly.map(td => web3.utils.toWei(td.toString())), + web3.utils.toWei(limits.nonAccreditedLimitUSD.toString()), + web3.utils.toWei(limits.minimumInvestmentUSD.toString()), + funding.raiseType, + addresses.wallet, + addresses.reserveWallet, + addresses.usdToken ] + ); let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, stoFee, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); - let usdTieredSTOABI = abis.usdTieredSTO(); let usdTieredSTO = new web3.eth.Contract(usdTieredSTOABI, event._module); usdTieredSTO.setProvider(web3.currentProvider); From 3de498b5a172de909d1ce72185e72fe6adba18ab Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 22 Nov 2018 17:47:48 +0200 Subject: [PATCH 154/582] review comments: renaming, redundant operations --- .../modules/Wallet/VestingEscrowWallet.sol | 89 ++++++------- test/z_vesting_escrow_wallet.js | 126 ++++++++++-------- 2 files changed, 117 insertions(+), 98 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 6b2aa584f..7cf9b8aea 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -56,7 +56,7 @@ contract VestingEscrowWallet is IWallet { uint256 _frequency, uint256 _startTime ); - event EditSchedule( + event ModifySchedule( address indexed _beneficiary, uint256 _index, uint256 _numberOfTokens, @@ -104,6 +104,10 @@ contract VestingEscrowWallet is IWallet { * @notice Used to deposit tokens from treasury */ function depositTokens(uint256 _numberOfTokens) external withPerm(ADMIN) { + _depositTokens(_numberOfTokens); + } + + function _depositTokens(uint256 _numberOfTokens) internal { require(_numberOfTokens > 0, "Should be greater than zero"); token.safeTransferFrom(treasury, this, _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); @@ -121,10 +125,10 @@ contract VestingEscrowWallet is IWallet { } /** - * @notice Sends available tokens to beneficiary + * @notice Pushes available tokens to beneficiary * @param _beneficiary beneficiary's address */ - function sendAvailableTokens(address _beneficiary) public withPerm(ADMIN) { + function pushAvailableTokens(address _beneficiary) public withPerm(ADMIN) { _sendTokens(_beneficiary); } @@ -143,11 +147,7 @@ contract VestingEscrowWallet is IWallet { */ function addTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) external withPerm(ADMIN) { _validateTemplate(_numberOfTokens, _duration, _frequency); - Template memory template; - template.numberOfTokens = _numberOfTokens; - template.duration = _duration; - template.frequency = _frequency; - templates.push(template); + templates.push(Template(_numberOfTokens, _duration, _frequency)); emit AddTemplate(_numberOfTokens, _duration, _frequency, templates.length - 1); } @@ -191,23 +191,20 @@ contract VestingEscrowWallet is IWallet { withPerm(ADMIN) { _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); - require(_numberOfTokens <= unassignedTokens, "Not enough tokens"); - - Schedule memory schedule; + if (_numberOfTokens > unassignedTokens) { + _depositTokens(_numberOfTokens.sub(unassignedTokens)); + } unassignedTokens = unassignedTokens.sub(_numberOfTokens); - schedule.numberOfTokens = _numberOfTokens; - schedule.lockedTokens = _numberOfTokens; - schedule.duration = _duration; - schedule.frequency = _frequency; - schedule.startTime = _startTime; - schedule.nextTime = _startTime.add(schedule.frequency); - schedule.state = State.CREATED; //add beneficiary to the schedule list only if adding first schedule if (dataMap[_beneficiary].schedules.length == 0) { dataMap[_beneficiary].index = beneficiaries.length; beneficiaries.push(_beneficiary); } - dataMap[_beneficiary].schedules.push(schedule); + dataMap[_beneficiary].schedules.push( + Schedule( + _numberOfTokens, _numberOfTokens, _duration, _frequency, _startTime, _startTime.add(_frequency), State.CREATED + ) + ); emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); } @@ -217,14 +214,18 @@ contract VestingEscrowWallet is IWallet { * @param _index index of the template * @param _startTime vesting start time */ - function addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) public withPerm(ADMIN) { + function addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) external withPerm(ADMIN) { + _addScheduleFromTemplate(_beneficiary, _index, _startTime); + } + + function _addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) internal { require(_index < templates.length, "Template not found"); Template memory template = templates[_index]; addSchedule(_beneficiary, template.numberOfTokens, template.duration, template.frequency, _startTime); } /** - * @notice Edits vesting schedules for each of beneficiary + * @notice Modifies vesting schedules for each of beneficiary * @param _beneficiary beneficiary's addresses * @param _index index of schedule * @param _numberOfTokens number of tokens @@ -232,7 +233,7 @@ contract VestingEscrowWallet is IWallet { * @param _frequency vesting frequency * @param _startTime vesting start time */ - function editSchedule( + function modifySchedule( address _beneficiary, uint256 _index, uint256 _numberOfTokens, @@ -251,16 +252,13 @@ contract VestingEscrowWallet is IWallet { if (_numberOfTokens <= schedule.lockedTokens) { unassignedTokens = unassignedTokens.add(schedule.lockedTokens - _numberOfTokens); } else { - require((_numberOfTokens - schedule.lockedTokens) <= unassignedTokens, "Not enough tokens"); + if (_numberOfTokens - schedule.lockedTokens > unassignedTokens) { + _depositTokens(_numberOfTokens - schedule.lockedTokens - unassignedTokens); + } unassignedTokens = unassignedTokens.sub(_numberOfTokens - schedule.lockedTokens); } - schedule.numberOfTokens = _numberOfTokens; - schedule.lockedTokens = _numberOfTokens; - schedule.duration = _duration; - schedule.frequency = _frequency; - schedule.startTime = _startTime; - schedule.nextTime = _startTime.add(schedule.frequency); - emit EditSchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); + dataMap[_beneficiary].schedules[_index] = Schedule(_numberOfTokens, _numberOfTokens, _duration, _frequency, _startTime, _startTime.add(_frequency), State.CREATED); + emit ModifySchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); } /** @@ -342,9 +340,10 @@ contract VestingEscrowWallet is IWallet { * @notice Used to bulk send available tokens for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses */ - function batchSendAvailableTokens(address[] _beneficiaries) external withPerm(ADMIN) { + function pushAvailableTokensMulti(address[] _beneficiaries) external withPerm(ADMIN) { + require(_beneficiaries.length > 1, "Array size should be greater than one"); for (uint256 i = 0; i < _beneficiaries.length; i++) { - sendAvailableTokens(_beneficiaries[i]); + pushAvailableTokens(_beneficiaries[i]); } } @@ -356,7 +355,7 @@ contract VestingEscrowWallet is IWallet { * @param _frequency vesting frequency * @param _startTime vesting start time */ - function batchAddSchedule( + function addScheduleMulti( address[] _beneficiaries, uint256 _numberOfTokens, uint256 _duration, @@ -377,9 +376,9 @@ contract VestingEscrowWallet is IWallet { * @param _index index of the template * @param _startTime vesting start time */ - function batchAddScheduleFromTemplate(address[] _beneficiaries, uint256 _index, uint256 _startTime) external withPerm(ADMIN) { + function addScheduleFromTemplateMulti(address[] _beneficiaries, uint256 _index, uint256 _startTime) external withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { - addScheduleFromTemplate(_beneficiaries[i], _index, _startTime); + _addScheduleFromTemplate(_beneficiaries[i], _index, _startTime); } } @@ -387,14 +386,14 @@ contract VestingEscrowWallet is IWallet { * @notice Used to bulk revoke vesting schedules for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses */ - function batchRevokeSchedules(address[] _beneficiaries) external withPerm(ADMIN) { + function revokeSchedulesMulti(address[] _beneficiaries) external withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { revokeSchedules(_beneficiaries[i]); } } /** - * @notice Used to bulk edit vesting schedules for each of beneficiaries + * @notice Used to bulk modify vesting schedules for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses * @param _indexes array of beneficiary's indexes of schedule * @param _numberOfTokens number of tokens @@ -402,7 +401,7 @@ contract VestingEscrowWallet is IWallet { * @param _frequency vesting frequency * @param _startTime vesting start time */ - function batchEditSchedule( + function modifyScheduleMulti( address[] _beneficiaries, uint256[] _indexes, uint256 _numberOfTokens, @@ -415,7 +414,7 @@ contract VestingEscrowWallet is IWallet { { require(_beneficiaries.length == _indexes.length, "Arrays sizes mismatch"); for (uint256 i = 0; i < _beneficiaries.length; i++) { - editSchedule(_beneficiaries[i], _indexes[i], _numberOfTokens, _duration, _frequency, _startTime); + modifySchedule(_beneficiaries[i], _indexes[i], _numberOfTokens, _duration, _frequency, _startTime); } } @@ -426,7 +425,7 @@ contract VestingEscrowWallet is IWallet { uint256 _frequency, uint256 _startTime ) - private + internal view { require(_beneficiary != address(0), "Invalid address"); @@ -434,14 +433,14 @@ contract VestingEscrowWallet is IWallet { require(now < _startTime, "Date in the past"); } - function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) private pure { + function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) internal pure { require(_numberOfTokens > 0, "Zero amount"); require(_duration % _frequency == 0, "Duration and frequency mismatch"); uint256 periodCount = _duration.div(_frequency); require(_numberOfTokens % periodCount == 0, "Tokens and periods mismatch"); } - function _sendTokens(address _beneficiary) private { + function _sendTokens(address _beneficiary) internal { Data storage data = dataMap[_beneficiary]; uint256 amount = data.availableTokens; require(amount > 0, "No available tokens"); @@ -459,7 +458,7 @@ contract VestingEscrowWallet is IWallet { _update(_beneficiary); } - function _update(address _beneficiary) private { + function _update(address _beneficiary) internal { Data storage data = dataMap[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { Schedule storage schedule = data.schedules[i]; @@ -486,13 +485,13 @@ contract VestingEscrowWallet is IWallet { _updateAll(); } - function _updateAll() private { + function _updateAll() internal { for (uint256 i = 0; i < beneficiaries.length; i++) { _update(beneficiaries[i]); } } - function _revokeSchedules(address _beneficiary) private { + function _revokeSchedules(address _beneficiary) internal { //can be removed if (dataMap[_beneficiary].availableTokens == 0) { uint256 index = dataMap[_beneficiary].index; diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 20cac61b6..3565e5b29 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -1,7 +1,7 @@ -import {setUpPolymathNetwork, deployGPMAndVerifyed, deployVestingEscrowWalletAndVerifyed} from "./helpers/createInstances"; +import {deployGPMAndVerifyed, deployVestingEscrowWalletAndVerifyed, setUpPolymathNetwork} from "./helpers/createInstances"; import latestTime from "./helpers/latestTime"; import {duration as durationUtil, latestBlock, promisifyLogWatch} from "./helpers/utils"; -import {catchRevert, catchPermission} from "./helpers/exceptions"; +import {catchPermission, catchRevert} from "./helpers/exceptions"; import {increaseTime} from "./helpers/time"; import {encodeModuleCall} from "./helpers/encodeCall"; @@ -256,9 +256,9 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), 0); }); - it("Should fail to send available tokens -- fail because beneficiary doesn't have available tokens", async () => { + it("Should fail to push available tokens -- fail because beneficiary doesn't have available tokens", async () => { catchRevert( - I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: wallet_admin}) + I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: wallet_admin}) ); }); @@ -274,7 +274,7 @@ contract('VestingEscrowWallet', accounts => { await increaseTime(timeShift + frequency); await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_admin}); - const tx = await I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens / 3); @@ -284,14 +284,14 @@ contract('VestingEscrowWallet', accounts => { await I_PolyToken.transfer(token_owner, balance, {from: account_beneficiary3}); }); - it("Should fail to edit vesting schedule -- fail because schedule already started", async () => { + it("Should fail to modify vesting schedule -- fail because schedule already started", async () => { let numberOfTokens = 75000; let duration = durationUtil.seconds(30); let frequency = durationUtil.seconds(10); let timeShift = durationUtil.seconds(100); let startTime = latestTime() + timeShift; await catchRevert( - I_VestingEscrowWallet.editSchedule(account_beneficiary3, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) + I_VestingEscrowWallet.modifySchedule(account_beneficiary3, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) ); await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); @@ -368,7 +368,7 @@ contract('VestingEscrowWallet', accounts => { }); - describe("Adding, editing and revoking vesting schedule", async () => { + describe("Adding, modifying and revoking vesting schedule", async () => { let schedules = [ { @@ -391,12 +391,6 @@ contract('VestingEscrowWallet', accounts => { } ]; - it("Should fail to add vesting schedule to the beneficiary address -- fail because not enough unassigned tokens", async () => { - await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) - ); - }); - it("Should fail to add vesting schedule to the beneficiary address -- fail because address in invalid", async () => { await catchRevert( I_VestingEscrowWallet.addSchedule(0, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) @@ -460,8 +454,7 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); - let log = tx.logs[0]; - checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(tx.logs[0], account_beneficiary1, numberOfTokens, duration, frequency, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 1); @@ -470,35 +463,45 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); }); - it("Should fail to edit vesting schedule -- fail because schedule not found", async () => { + it("Should add vesting schedule without depositing to the beneficiary address", async () => { let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; - await catchRevert( - I_VestingEscrowWallet.editSchedule(account_beneficiary1, 1, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) - ); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + + assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); + checkScheduleLog(tx.logs[1], account_beneficiary1, numberOfTokens, duration, frequency, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); + assert.equal(scheduleCount, 2); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 1); + checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + + await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); - it("Should fail to edit vesting schedule -- fail because not enough unassigned tokens", async () => { - let numberOfTokens = schedules[0].numberOfTokens * 2; + it("Should fail to modify vesting schedule -- fail because schedule not found", async () => { + let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; await catchRevert( - I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) + I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 2, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) ); }); - it("Should edit vesting schedule for the beneficiary's address", async () => { + it("Should modify vesting schedule for the beneficiary's address", async () => { let numberOfTokens = schedules[1].numberOfTokens; let duration = schedules[1].duration; let frequency = schedules[1].frequency; let startTime = schedules[1].startTime; - const tx = await I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); - let log = tx.logs[0]; - checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(tx.logs[0], account_beneficiary1, numberOfTokens, duration, frequency, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 1); @@ -508,16 +511,29 @@ contract('VestingEscrowWallet', accounts => { let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); assert.equal(unassignedTokens.toNumber(), schedules[0].numberOfTokens - schedules[1].numberOfTokens); + + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); - it("Should fail edit vesting schedule to the beneficiary address", async () => { + it("Should modify vesting schedule without depositing for the beneficiary's address", async () => { let numberOfTokens = schedules[0].numberOfTokens + schedules[1].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; - await catchRevert( - I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) - ); + await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); + const tx = await I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + + assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), schedules[0].numberOfTokens); + checkScheduleLog(tx.logs[1], account_beneficiary1, numberOfTokens, duration, frequency, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); + assert.equal(scheduleCount, 1); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); + checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + assert.equal(unassignedTokens.toNumber(), 0); }); it("Should fail to revoke vesting schedule -- fail because address is invalid", async () => { @@ -560,8 +576,7 @@ contract('VestingEscrowWallet', accounts => { let startTime = schedules[i].startTime; const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary2, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); - let log = tx.logs[0]; - checkScheduleLog(log, account_beneficiary2, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(tx.logs[0], account_beneficiary2, numberOfTokens, duration, frequency, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); assert.equal(scheduleCount, i + 1); @@ -656,8 +671,7 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); const tx = await I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_admin}); - let log = tx.logs[0]; - checkScheduleLog(log, account_beneficiary1, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(tx.logs[0], account_beneficiary1, numberOfTokens, duration, frequency, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 1); @@ -685,7 +699,7 @@ contract('VestingEscrowWallet', accounts => { }); - describe("Tests for batch operations", async () => { + describe("Tests for multi operations", async () => { it("Should add schedules for 3 beneficiaries", async () => { let numberOfTokens = 30000; @@ -697,7 +711,7 @@ contract('VestingEscrowWallet', accounts => { await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); - let tx = await I_VestingEscrowWallet.batchAddSchedule(beneficiaries, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + let tx = await I_VestingEscrowWallet.addScheduleMulti(beneficiaries, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; @@ -712,7 +726,7 @@ contract('VestingEscrowWallet', accounts => { } }); - it("Should edit vesting schedule for 3 beneficiary's addresses", async () => { + it("Should modify vesting schedule for 3 beneficiary's addresses", async () => { let numberOfTokens = 25000; let duration = durationUtil.seconds(50); let frequency = durationUtil.seconds(10); @@ -721,11 +735,11 @@ contract('VestingEscrowWallet', accounts => { let indexes = [0, 0, 0, 0]; await catchRevert( - I_VestingEscrowWallet.batchEditSchedule(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) + I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) ); }); - it("Should edit vesting schedule for 3 beneficiary's addresses", async () => { + it("Should modify vesting schedule for 3 beneficiary's addresses", async () => { let numberOfTokens = 25000; let duration = durationUtil.seconds(50); let frequency = durationUtil.seconds(10); @@ -733,7 +747,7 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + timeShift; let indexes = [0, 0, 0]; - const tx = await I_VestingEscrowWallet.batchEditSchedule(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency); for (let i = 0; i < beneficiaries.length; i++) { @@ -752,10 +766,16 @@ contract('VestingEscrowWallet', accounts => { assert.equal(unassignedTokens.toNumber(), 5000 * beneficiaries.length); }); + it("Should not be able to send available tokens to the beneficiaries addresses -- fail because of array size", async () => { + await catchRevert( + I_VestingEscrowWallet.pushAvailableTokensMulti([account_beneficiary1], {from: wallet_admin}) + ); + }); + it("Should send available tokens to the beneficiaries addresses", async () => { await I_VestingEscrowWallet.updateAll({from: wallet_admin}); - const tx = await I_VestingEscrowWallet.batchSendAvailableTokens(beneficiaries, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.pushAvailableTokensMulti(beneficiaries, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; @@ -783,7 +803,7 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); - let tx = await I_VestingEscrowWallet.batchAddScheduleFromTemplate(beneficiaries, 0, startTime, {from: wallet_admin}); + let tx = await I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, 0, startTime, {from: wallet_admin}); await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { @@ -801,7 +821,7 @@ contract('VestingEscrowWallet', accounts => { }); it("Should revoke vesting schedule from the 3 beneficiary's addresses", async () => { - const tx = await I_VestingEscrowWallet.batchRevokeSchedules(beneficiaries, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.revokeSchedulesMulti(beneficiaries, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; @@ -833,7 +853,7 @@ contract('VestingEscrowWallet', accounts => { it("Should not be able to send available tokens", async () => { await catchPermission( - I_VestingEscrowWallet.sendAvailableTokens(account_beneficiary3, {from: account_beneficiary1}) + I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: account_beneficiary1}) ); }); @@ -861,9 +881,9 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should not be able to edit schedule", async () => { + it("Should not be able to modify schedule", async () => { await catchPermission( - I_VestingEscrowWallet.editSchedule(account_beneficiary1, 0, 10000, 4, 1, latestTime(), {from: account_beneficiary1}) + I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 0, 10000, 4, 1, latestTime(), {from: account_beneficiary1}) ); }); @@ -881,31 +901,31 @@ contract('VestingEscrowWallet', accounts => { it("Should not be able to send available tokens to the beneficiaries", async () => { await catchPermission( - I_VestingEscrowWallet.batchSendAvailableTokens([account_beneficiary1], {from: account_beneficiary1}) + I_VestingEscrowWallet.pushAvailableTokensMulti([account_beneficiary1], {from: account_beneficiary1}) ); }); it("Should not be able to add schedules to the beneficiaries", async () => { await catchPermission( - I_VestingEscrowWallet.batchAddSchedule([account_beneficiary1], 10000, 4, 1, latestTime(), {from: account_beneficiary1}) + I_VestingEscrowWallet.addScheduleMulti([account_beneficiary1], 10000, 4, 1, latestTime(), {from: account_beneficiary1}) ); }); it("Should not be able to add schedules from template to the beneficiaries", async () => { await catchPermission( - I_VestingEscrowWallet.batchAddScheduleFromTemplate([account_beneficiary1], 0, latestTime(), {from: account_beneficiary1}) + I_VestingEscrowWallet.addScheduleFromTemplateMulti([account_beneficiary1], 0, latestTime(), {from: account_beneficiary1}) ); }); it("Should not be able to revoke schedules of the beneficiaries", async () => { await catchPermission( - I_VestingEscrowWallet.batchRevokeSchedules([account_beneficiary1], {from: account_beneficiary1}) + I_VestingEscrowWallet.revokeSchedulesMulti([account_beneficiary1], {from: account_beneficiary1}) ); }); - it("Should not be able to edit schedules for the beneficiaries", async () => { + it("Should not be able to modify schedules for the beneficiaries", async () => { await catchPermission( - I_VestingEscrowWallet.batchEditSchedule([account_beneficiary1], [0], 10000, 4, 1, latestTime(), {from: account_beneficiary1}) + I_VestingEscrowWallet.modifyScheduleMulti([account_beneficiary1], [0], 10000, 4, 1, latestTime(), {from: account_beneficiary1}) ); }); From 6f10ec0ea61503aeaa445b5d53113fd712bbd4f1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 22 Nov 2018 19:59:10 +0200 Subject: [PATCH 155/582] review comments: use ST instead of configuring by tokens --- .../modules/Wallet/VestingEscrowWallet.sol | 13 +-- test/z_vesting_escrow_wallet.js | 92 ++++++++++++++----- 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 7cf9b8aea..85d51ad8c 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -11,7 +11,6 @@ import "./IWallet.sol"; */ contract VestingEscrowWallet is IWallet { using SafeMath for uint256; - using SafeERC20 for ERC20; bytes32 public constant ADMIN = "ADMIN"; @@ -40,7 +39,6 @@ contract VestingEscrowWallet is IWallet { enum State {CREATED, STARTED, COMPLETED} - ERC20 public token; address public treasury; uint256 public unassignedTokens; @@ -87,17 +85,16 @@ contract VestingEscrowWallet is IWallet { * @notice Function used to initialize the different variables * @param _treasury Address of the treasury */ - function configure(address _treasury, address _token) public onlyFactory { + function configure(address _treasury) public onlyFactory { require(_treasury != address(0), "Invalid address"); treasury = _treasury; - token = ERC20(_token); } /** * @notice This function returns the signature of the configure function */ function getInitFunction() public pure returns (bytes4) { - return bytes4(keccak256("configure(address,address)")); + return bytes4(keccak256("configure(address)")); } /** @@ -109,7 +106,7 @@ contract VestingEscrowWallet is IWallet { function _depositTokens(uint256 _numberOfTokens) internal { require(_numberOfTokens > 0, "Should be greater than zero"); - token.safeTransferFrom(treasury, this, _numberOfTokens); + ISecurityToken(securityToken).transferFrom(treasury, this, _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); emit DepositTokens(_numberOfTokens); } @@ -120,7 +117,7 @@ contract VestingEscrowWallet is IWallet { function sendToTreasury() external withPerm(ADMIN) { uint256 amount = unassignedTokens; unassignedTokens = 0; - token.safeTransfer(treasury, amount); + ISecurityToken(securityToken).transfer(treasury, amount); emit SendToTreasury(amount); } @@ -446,7 +443,7 @@ contract VestingEscrowWallet is IWallet { require(amount > 0, "No available tokens"); data.availableTokens = 0; data.claimedTokens = data.claimedTokens.add(amount); - token.safeTransfer(_beneficiary, amount); + ISecurityToken(securityToken).transfer(_beneficiary, amount); emit SendTokens(_beneficiary, amount); } diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 3565e5b29..4b8146395 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -25,7 +25,6 @@ contract('VestingEscrowWallet', accounts => { let account_beneficiary1; let account_beneficiary2; let account_beneficiary3; - let account_beneficiary4; let beneficiaries; @@ -75,7 +74,6 @@ contract('VestingEscrowWallet', accounts => { account_beneficiary1 = accounts[6]; account_beneficiary2 = accounts[7]; account_beneficiary3 = accounts[8]; - account_beneficiary4 = accounts[9]; beneficiaries = [ account_beneficiary1, @@ -174,8 +172,8 @@ contract('VestingEscrowWallet', accounts => { it("Should successfully attach the VestingEscrowWallet with the security token", async () => { let bytesData = encodeModuleCall( - ["address", "address"], - [token_owner, I_PolyToken.address] + ["address"], + [token_owner] ); await I_SecurityToken.changeGranularity(1, {from: token_owner}); @@ -191,6 +189,50 @@ contract('VestingEscrowWallet', accounts => { I_VestingEscrowWallet = VestingEscrowWallet.at(tx.logs[2].args._module); }); + it("Should Buy the tokens for token_owner", async() => { + // Add the Investor in to the whitelist + let tx = await I_GeneralTransferManager.modifyWhitelist( + token_owner, + latestTime(), + latestTime(), + latestTime() + durationUtil.days(10), + true, + { + from: token_owner, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), token_owner.toLowerCase(), "Failed in adding the token_owner in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(token_owner, web3.utils.toWei('1', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(token_owner)).toNumber(), + web3.utils.toWei('1', 'ether') + ); + + }); + + it("Should whitelist investors", async() => { + // Add the Investor in to the whitelist + let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + [I_VestingEscrowWallet.address, account_beneficiary1, account_beneficiary2, account_beneficiary3], + [latestTime(), latestTime(), latestTime(), latestTime()], + [latestTime(), latestTime(), latestTime(), latestTime()], + [latestTime() + durationUtil.days(10), latestTime() + durationUtil.days(10), latestTime() + durationUtil.days(10), latestTime() + durationUtil.days(10)], + [true, true, true, true], + { + from: token_owner, + gas: 6000000 + }); + + assert.equal(tx.logs[0].args._investor, I_VestingEscrowWallet.address); + assert.equal(tx.logs[1].args._investor, account_beneficiary1); + assert.equal(tx.logs[2].args._investor, account_beneficiary2); + assert.equal(tx.logs[3].args._investor, account_beneficiary3); + }); + it("Should successfully add the delegate", async() => { let tx = await I_GeneralPermissionManager.addDelegate(wallet_admin, delegateDetails, { from: token_owner}); assert.equal(tx.logs[0].args._delegate, wallet_admin); @@ -231,7 +273,7 @@ contract('VestingEscrowWallet', accounts => { it("Should deposit tokens for new vesting schedules", async () => { let numberOfTokens = 25000; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); const tx = await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); @@ -239,7 +281,7 @@ contract('VestingEscrowWallet', accounts => { let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); assert.equal(unassignedTokens, numberOfTokens); - let balance = await I_PolyToken.balanceOf.call(I_VestingEscrowWallet.address); + let balance = await I_SecurityToken.balanceOf.call(I_VestingEscrowWallet.address); assert.equal(balance.toNumber(), numberOfTokens); }); @@ -252,7 +294,7 @@ contract('VestingEscrowWallet', accounts => { let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); assert.equal(unassignedTokens, 0); - let balance = await I_PolyToken.balanceOf.call(I_VestingEscrowWallet.address); + let balance = await I_SecurityToken.balanceOf.call(I_VestingEscrowWallet.address); assert.equal(balance.toNumber(), 0); }); @@ -268,7 +310,7 @@ contract('VestingEscrowWallet', accounts => { let frequency = durationUtil.seconds(10); let timeShift = durationUtil.seconds(100); let startTime = latestTime() + timeShift; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency); @@ -278,10 +320,10 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens / 3); - let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); + let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens / 3); - await I_PolyToken.transfer(token_owner, balance, {from: account_beneficiary3}); + await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); }); it("Should fail to modify vesting schedule -- fail because schedule already started", async () => { @@ -304,7 +346,7 @@ contract('VestingEscrowWallet', accounts => { let frequency = durationUtil.seconds(10); let timeShift = durationUtil.seconds(100); let startTime = latestTime() + timeShift; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency * 3); @@ -316,10 +358,10 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); - let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); + let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens); - await I_PolyToken.transfer(token_owner, balance, {from: account_beneficiary3}); + await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); @@ -339,7 +381,7 @@ contract('VestingEscrowWallet', accounts => { ]; let totalNumberOfTokens = getTotalNumberOfTokens(schedules); - await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); for (let i = 0; i < schedules.length; i++) { let numberOfTokens = schedules[i].numberOfTokens; @@ -358,10 +400,10 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); - let balance = await I_PolyToken.balanceOf.call(account_beneficiary3); + let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens); - await I_PolyToken.transfer(token_owner, balance, {from: account_beneficiary3}); + await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); @@ -450,7 +492,7 @@ contract('VestingEscrowWallet', accounts => { let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); @@ -468,7 +510,7 @@ contract('VestingEscrowWallet', accounts => { let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); @@ -520,7 +562,7 @@ contract('VestingEscrowWallet', accounts => { let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); const tx = await I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), schedules[0].numberOfTokens); @@ -567,7 +609,7 @@ contract('VestingEscrowWallet', accounts => { it("Should add 3 vesting schedules to the beneficiary address", async () => { let totalNumberOfTokens = getTotalNumberOfTokens(schedules); - await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); for (let i = 0; i < schedules.length; i++) { let numberOfTokens = schedules[i].numberOfTokens; @@ -667,7 +709,7 @@ contract('VestingEscrowWallet', accounts => { let duration = schedules[2].duration; let frequency = schedules[2].frequency; let startTime = schedules[2].startTime; - await I_PolyToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); const tx = await I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_admin}); @@ -708,7 +750,7 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + durationUtil.seconds(100); let totalNumberOfTokens = numberOfTokens * 3; - await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); let tx = await I_VestingEscrowWallet.addScheduleMulti(beneficiaries, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); @@ -783,10 +825,10 @@ contract('VestingEscrowWallet', accounts => { assert.equal(log.args._beneficiary, beneficiary); assert.equal(log.args._numberOfTokens.toNumber(), 5000); - let balance = await I_PolyToken.balanceOf.call(beneficiary); + let balance = await I_SecurityToken.balanceOf.call(beneficiary); assert.equal(balance.toNumber(), 5000); - await I_PolyToken.transfer(token_owner, balance, {from: beneficiary}); + await I_SecurityToken.transfer(token_owner, balance, {from: beneficiary}); await I_VestingEscrowWallet.revokeSchedules(beneficiary, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); } @@ -799,7 +841,7 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + durationUtil.seconds(100); let totalNumberOfTokens = numberOfTokens * 3; - await I_PolyToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); From e0b29883cf394e799c96c9c2e95da03f5a694589 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Thu, 22 Nov 2018 15:29:31 -0300 Subject: [PATCH 156/582] Flow changes --- CLI/commands/ST20Generator.js | 16 ++-- CLI/commands/sto_manager.js | 105 ++++++++++++----------- CLI/commands/token_manager.js | 156 ++++++++++++++++++++++------------ CLI/polymath-cli.js | 7 +- 4 files changed, 165 insertions(+), 119 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 556baf8eb..727c112b4 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -1,10 +1,11 @@ -var readlineSync = require('readline-sync'); -var BigNumber = require('bignumber.js'); -var moment = require('moment'); -var chalk = require('chalk'); -var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis'); -var common = require('./common/common_functions'); +const readlineSync = require('readline-sync'); +const BigNumber = require('bignumber.js'); +const moment = require('moment'); +const chalk = require('chalk'); +const tokenManager = require('./token_manager'); +const contracts = require('./helpers/contract_addresses'); +const abis = require('./helpers/contract_abis'); +const common = require('./common/common_functions'); //////////////////////// let securityTokenRegistryAddress; @@ -31,6 +32,7 @@ async function executeApp(_ticker, _transferOwnership, _name, _details, _divisib await step_transfer_ticker_ownership(_transferOwnership); await step_token_deploy(_name, _details, _divisible); } + await tokenManager.executeApp(tokenSymbol); } catch (err) { console.log(err); return; diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 257a223bc..8943ec5d4 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -61,59 +61,6 @@ async function executeApp() { } }; -async function setup(){ - try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - - let polytokenAddress = await contracts.polyToken(); - let polytokenABI = abis.polyToken(); - polyToken = new web3.eth.Contract(polytokenABI, polytokenAddress); - polyToken.setProvider(web3.currentProvider); - - //TODO: Use proper DAI token here - let usdTokenAddress = await contracts.usdToken(); - usdToken = new web3.eth.Contract(polytokenABI, usdTokenAddress); - usdToken.setProvider(web3.currentProvider); - } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); - process.exit(0); - } -} - -async function selectToken() { - let result = null; - - let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); - if (userTokens.length == 0) { - console.log(chalk.red(`You have not issued any Security Token yet!`)); - } else if (userTokens.length == 1) { - let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(userTokens[0]).call(); - console.log(chalk.yellow(`You have only one token. ${tokenData[0]} will be selected automatically.`)); - result = tokenData[0]; - } else { - let tokenDataArray = await Promise.all(userTokens.map(async function (t) { - let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); - return {tokenData: tokenData, address: t}; - })); - let options = tokenDataArray.map(function (t) { - return `${t.tokenData[0]} - Deployed at ${t.address}`; - }); - - let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); - if (index != -1) { - result = tokenDataArray[index][0]; - } else { - process.exit(); - } - } - - return result; -} - function selectExistingSTO(stoModules, showPaused) { let filteredModules = stoModules; if (!showPaused) { @@ -886,6 +833,58 @@ function welcome() { console.log("Issuer Account: " + Issuer.address + "\n"); } +async function setup(){ + try { + let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); + let securityTokenRegistryABI = abis.securityTokenRegistry(); + securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); + securityTokenRegistry.setProvider(web3.currentProvider); + + let polytokenAddress = await contracts.polyToken(); + let polytokenABI = abis.polyToken(); + polyToken = new web3.eth.Contract(polytokenABI, polytokenAddress); + polyToken.setProvider(web3.currentProvider); + + //TODO: Use proper DAI token here + let usdTokenAddress = await contracts.usdToken(); + usdToken = new web3.eth.Contract(polytokenABI, usdTokenAddress); + usdToken.setProvider(web3.currentProvider); + } catch (err) { + console.log(err) + console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); + process.exit(0); + } +} + +async function selectToken() { + let result = null; + + let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); + let tokenDataArray = await Promise.all(userTokens.map(async function (t) { + let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); + return {symbol: tokenData[0], address: t}; + })); + let options = tokenDataArray.map(function (t) { + return `${t.symbol} - Deployed at ${t.address}`; + }); + options.push('Enter token symbol manually'); + + let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); + switch (options[index]) { + case 'Enter token symbol manually': + result = readlineSync.question('Enter the token symbol: '); + break; + case 'Exit': + process.exit(); + break; + default: + result = tokenDataArray[index].symbol; + break; + } + + return result; +} + module.exports = { executeApp: async function(_tokenSymbol) { await initialize(_tokenSymbol); diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 5c9d7fd6c..47361cb12 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -1,8 +1,9 @@ // Libraries for terminal prompts const readlineSync = require('readline-sync'); const chalk = require('chalk'); -var whitelist = require('./whitelist'); -var multimint = require('./multi_mint'); +const whitelist = require('./whitelist'); +const multimint = require('./multi_mint'); +const stoManager = require('./sto_manager'); const common = require('./common/common_functions'); const gbl = require('./common/global'); @@ -16,6 +17,7 @@ let featureRegistry; let securityToken; let allModules; +let tokenSymbol async function setup() { try { @@ -42,54 +44,14 @@ async function setup() { // Start function async function executeApp() { - common.logAsciiBull(); - console.log(`*****************************************`); - console.log(`Welcome to the Command-Line Token Manager`); - console.log(`*****************************************`); - console.log("The following script will allow you to manage your ST-20 tokens"); - console.log("Issuer Account: " + Issuer.address + "\n"); - - await setup(); - await showUserInfo(Issuer.address); - - securityToken = await selectToken(); - while (securityToken) { - allModules = await getAllModules(); - await displayTokenData(); - await displayModules(); - await selectAction(); - } -}; - -async function selectToken() { - let stAddress; - let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); - if (userTokens.length == 0) { - console.log(chalk.red(`You have not issued any Security Token yet!`)); - process.exit(0); - } else if (userTokens.length == 1) { - console.log(chalk.yellow(`You have only one token. It will be selected automatically.`)); - stAddress = userTokens[0]; - } else { - let options = await Promise.all(userTokens.map(async function (t) { - let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); - return `${tokenData[0]} - Deployed at ${t}`; - })); - - let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); - if (index == -1) { - process.exit(0); - } else { - stAddress = userTokens[index]; - } + await showUserInfo(Issuer.address); + while (securityToken) { + allModules = await getAllModules(); + await displayTokenData(); + await displayModules(); + await selectAction(); } - - let securityTokenABI = abis.securityToken(); - let securityToken = new web3.eth.Contract(securityTokenABI, stAddress); - - return securityToken; -} +}; async function displayTokenData() { let displayTokenSymbol = await securityToken.methods.symbol().call(); @@ -374,8 +336,6 @@ async function mintToSingleAddress(_investor, _amount) { } async function multi_mint_tokens() { - let tokenSymbol = await securityToken.methods.symbol().call(); - await whitelist.executeApp(tokenSymbol, 75); console.log(chalk.green(`\nCongratulations! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); @@ -449,17 +409,44 @@ async function listModuleOptions() { // Modules a actions async function addModule() { - console.log(chalk.red(` + let options = ['Permission Manager', 'Transfer Manager', 'Security Token Offering', 'Dividends', 'Burn']; + let index = readlineSync.keyInSelect(options, 'What type of module whould you like to add?', {cancel: 'Return'}); + switch (options[index]) { + case 'Permission Manager': + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************`)); + break; + case 'Transfer Manager': + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************`)); + break; + case 'Security Token Offering': + await stoManager.addSTOModule(tokenSymbol) + break; + case 'Dividends': + console.log(chalk.red(` ********************************* This option is not yet available. *********************************`)); + break; + case 'Burn': + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************`)); + break; + } } async function pauseModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); let index = readlineSync.keyInSelect(options, 'Which module whould you like to pause?'); if (index != -1) { - console.log("\nSelected: ",options[index]); + console.log("\nSelected:",options[index]); let moduleABI; if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { moduleABI = abis.ISTO(); @@ -594,8 +581,65 @@ async function getAllModules() { return modules; } +async function initialize(_tokenSymbol) { + welcome(); + await setup(); + if (typeof _tokenSymbol === 'undefined') { + tokenSymbol = await selectToken(); + } else { + tokenSymbol = _tokenSymbol; + } + let securityTokenAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); + if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { + console.log(chalk.red(`Selected Security Token ${tokenSymbol} does not exist.`)); + process.exit(0); + } + let securityTokenABI = abis.securityToken(); + securityToken = new web3.eth.Contract(securityTokenABI, securityTokenAddress); + securityToken.setProvider(web3.currentProvider); +} + +function welcome() { + common.logAsciiBull(); + console.log(`*****************************************`); + console.log(`Welcome to the Command-Line Token Manager`); + console.log(`*****************************************`); + console.log("The following script will allow you to manage your ST-20 tokens"); + console.log("Issuer Account: " + Issuer.address + "\n"); +} + +async function selectToken() { + let result = null; + + let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); + let tokenDataArray = await Promise.all(userTokens.map(async function (t) { + let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); + return {symbol: tokenData[0], address: t}; + })); + let options = tokenDataArray.map(function (t) { + return `${t.symbol} - Deployed at ${t.address}`; + }); + options.push('Enter token symbol manually'); + + let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); + switch (options[index]) { + case 'Enter token symbol manually': + result = readlineSync.question('Enter the token symbol: '); + break; + case 'Exit': + process.exit(); + break; + default: + result = tokenDataArray[index].symbol; + break; + } + + return result; +} + module.exports = { - executeApp: async function() { - return executeApp(); - } + executeApp: async function(_tokenSymbol) { + await initialize(_tokenSymbol) + return executeApp(); + } } diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index cbe38921b..c15d62c41 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -42,9 +42,9 @@ program program .command('sto_manager') + .alias('sto') .option('-t, --securityToken ', 'Selects a ST to manage modules') .option('-l, --launch ', 'Uses configuration file to configure and launch a STO') - .alias('sto') .description('Wizard-like script that will guide technical users in the creation of an STO') .action(async function(cmd) { await gbl.initialize(program.remoteNode); @@ -77,10 +77,11 @@ program program .command('token_manager') .alias('stm') + .option('-t, --securityToken ', 'Selects a ST to manage') .description('Manage your Security Tokens, mint tokens, add modules and change config') - .action(async function() { + .action(async function(cmd) { await gbl.initialize(program.remoteNode); - await token_manager.executeApp(); + await token_manager.executeApp(cmd.securityToken); }); program From 1f4e9c17846a4b6140147e30281a7ad909780178 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 23 Nov 2018 00:00:08 +0530 Subject: [PATCH 157/582] remove some require statements --- ...ictionTM.sol => LockUpTransferManager.sol} | 91 ++++----- ...y.sol => LockUpTransferManagerFactory.sol} | 18 +- test/helpers/createInstances.js | 6 +- ...anager.js => w_lockup_transfer_manager.js} | 193 +++++++----------- 4 files changed, 130 insertions(+), 178 deletions(-) rename contracts/modules/Experimental/TransferManager/{LockupVolumeRestrictionTM.sol => LockUpTransferManager.sol} (96%) rename contracts/modules/Experimental/TransferManager/{LockupVolumeRestrictionTMFactory.sol => LockUpTransferManagerFactory.sol} (76%) rename test/{w_lockup_volume_restriction_transfer_manager.js => w_lockup_transfer_manager.js} (82%) diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol similarity index 96% rename from contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol rename to contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol index 887f78d3a..f1a8dddea 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol @@ -3,7 +3,7 @@ pragma solidity ^0.4.24; import "./../../TransferManager/ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -contract LockupVolumeRestrictionTM is ITransferManager { +contract LockUpTransferManager is ITransferManager { using SafeMath for uint256; @@ -265,6 +265,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { require(_userAddress != address(0), "Invalid address"); LockUp[] memory userLockup = lockUps[_userAddress]; uint256 totalRemainingLockedAmount = 0; + for (uint256 i = 0; i < userLockup.length; i++) { // Find out the remaining locked amount for a given lockup uint256 remainingLockedAmount = userLockup[i].lockupAmount.sub(_getUnlockedAmountForLockup(userLockup, i)); @@ -274,6 +275,45 @@ contract LockupVolumeRestrictionTM is ITransferManager { return totalRemainingLockedAmount; } + /** + * @notice Checks whether the transfer is allowed + * @param _userAddress Address of the user whose lock ups should be checked + * @param _amount Amount of tokens that need to transact + */ + function _checkIfValidTransfer(address _userAddress, uint256 _amount) internal view returns (Result) { + uint256 totalRemainingLockedAmount = getLockedTokenToUser(_userAddress); + // Present balance of the user + uint256 currentBalance = ISecurityToken(securityToken).balanceOf(_userAddress); + if ((currentBalance.sub(_amount)) >= totalRemainingLockedAmount) { + return Result.NA; + } + return Result.INVALID; + } + + /** + * @notice Provide the unlock amount for the given lockup for a particular user + */ + function _getUnlockedAmountForLockup(LockUp[] userLockup, uint256 _lockupIndex) internal view returns (uint256) { + /*solium-disable-next-line security/no-block-members*/ + if (userLockup[_lockupIndex].startTime > now) { + return 0; + } else if (userLockup[_lockupIndex].startTime.add(userLockup[_lockupIndex].lockUpPeriodSeconds) <= now) { + return userLockup[_lockupIndex].lockupAmount; + } else { + // Calculate the no. of periods for a lockup + uint256 noOfPeriods = (userLockup[_lockupIndex].lockUpPeriodSeconds).div(userLockup[_lockupIndex].releaseFrequencySeconds); + // Calculate the transaction time lies in which period + /*solium-disable-next-line security/no-block-members*/ + uint256 elapsedPeriod = (now.sub(userLockup[_lockupIndex].startTime)).div(userLockup[_lockupIndex].releaseFrequencySeconds); + // Calculate the allowed unlocked amount per period + uint256 amountPerPeriod = (userLockup[_lockupIndex].lockupAmount).div(noOfPeriods); + // Find out the unlocked amount for a given lockup + uint256 unLockedAmount = elapsedPeriod.mul(amountPerPeriod); + return unLockedAmount; + } + + } + function _modifyLockUp( address _userAddress, uint256 _lockupAmount, @@ -363,43 +403,6 @@ contract LockupVolumeRestrictionTM is ITransferManager { ); } - /** - * @notice Checks whether the transfer is allowed - * @param _userAddress Address of the user whose lock ups should be checked - * @param _amount Amount of tokens that need to transact - */ - function _checkIfValidTransfer(address _userAddress, uint256 _amount) internal view returns (Result) { - uint256 totalRemainingLockedAmount = getLockedTokenToUser(_userAddress); - // Present balance of the user - uint256 currentBalance = ISecurityToken(securityToken).balanceOf(_userAddress); - if ((currentBalance.sub(_amount)) >= totalRemainingLockedAmount) { - return Result.NA; - } - return Result.INVALID; - } - - /** - * @notice Provide the unlock amount for the given lockup for a particular user - */ - function _getUnlockedAmountForLockup(LockUp[] userLockup, uint256 _lockupIndex) internal view returns (uint256) { - /*solium-disable-next-line security/no-block-members*/ - if (userLockup[_lockupIndex].startTime > now) { - return 0; - } else { - // Calculate the no. of periods for a lockup - uint256 noOfPeriods = (userLockup[_lockupIndex].lockUpPeriodSeconds).div(userLockup[_lockupIndex].releaseFrequencySeconds); - // Calculate the transaction time lies in which period - /*solium-disable-next-line security/no-block-members*/ - uint256 elapsedPeriod = (now.sub(userLockup[_lockupIndex].startTime)).div(userLockup[_lockupIndex].releaseFrequencySeconds); - // Calculate the allowed unlocked amount per period - uint256 amountPerPeriod = (userLockup[_lockupIndex].lockupAmount).div(noOfPeriods); - // Find out the unlocked amount for a given lockup - uint256 unLockedAmount = elapsedPeriod.mul(amountPerPeriod); - return unLockedAmount; - } - - } - /** * @notice Parameter checking function for creating or editing a lockup. This function will cause an exception if any of the parameters are bad. * @param _userAddress Address whom lockup is being applied @@ -432,18 +435,6 @@ contract LockupVolumeRestrictionTM is ITransferManager { _lockUpPeriodSeconds % _releaseFrequencySeconds == 0, "lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds" ); - - // make sure the amount to be released per period is not too granular for the token - uint256 totalPeriods = _lockUpPeriodSeconds.div(_releaseFrequencySeconds); - uint256 amountPerPeriod = _lockupAmount.div(totalPeriods); - require( - amountPerPeriod.mul(totalPeriods) == _lockupAmount, - "lockup amount should be completely divisible by the amount per period" - ); - require( - amountPerPeriod % ISecurityToken(securityToken).granularity() == 0, - "The amount to be released per period is more granular than allowed by the token" - ); } /** diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol similarity index 76% rename from contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol rename to contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol index 5be77b6e0..2a79e2528 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol @@ -1,12 +1,12 @@ pragma solidity ^0.4.24; import "./../../ModuleFactory.sol"; -import "./LockupVolumeRestrictionTM.sol"; +import "./LockUpTransferManager.sol"; /** - * @title Factory for deploying ManualApprovalTransferManager module + * @title Factory for deploying LockUpTransferManager module */ -contract LockupVolumeRestrictionTMFactory is ModuleFactory { +contract LockUpTransferManagerFactory is ModuleFactory { /** * @notice Constructor @@ -19,8 +19,8 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; - name = "LockupVolumeRestrictionTM"; - title = "Lockup Volume Restriction Transfer Manager"; + name = "LockUpTransferManager"; + title = "LockUp Transfer Manager"; description = "Manage transfers using lock ups over time"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); @@ -33,10 +33,10 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - LockupVolumeRestrictionTM lockupVolumeRestrictionTransferManager = new LockupVolumeRestrictionTM(msg.sender, address(polyToken)); + LockUpTransferManager lockUpTransferManager = new LockUpTransferManager(msg.sender, address(polyToken)); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(lockupVolumeRestrictionTransferManager), getName(), address(this), msg.sender, now); - return address(lockupVolumeRestrictionTransferManager); + emit GenerateModuleFromFactory(address(lockUpTransferManager), getName(), address(this), msg.sender, now); + return address(lockUpTransferManager); } /** @@ -61,7 +61,7 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { */ function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](2); - availableTags[0] = "Volume"; + availableTags[0] = "LockUp"; availableTags[1] = "Transfer Restriction"; return availableTags; } diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 2021d350e..7c0f42487 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -23,7 +23,7 @@ const STFactory = artifacts.require("./STFactory.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); -const VolumeRestrictionTransferManagerFactory = artifacts.require("./LockupVolumeRestrictionTMFactory"); +const LockUpTransferManagerFactory = artifacts.require("./LockUpTransferManagerFactory"); const PreSaleSTOFactory = artifacts.require("./PreSaleSTOFactory.sol"); const PolyToken = artifacts.require("./PolyToken.sol"); const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); @@ -244,11 +244,11 @@ export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInst } export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_VolumeRestrictionTransferManagerFactory = await LockUpTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_VolumeRestrictionTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", - "VolumeRestrictionTransferManagerFactory contract was not deployed" + "LockUpTransferManagerFactory contract was not deployed" ); await registerAndVerifyByMR(I_VolumeRestrictionTransferManagerFactory.address, accountPolymath, MRProxyInstance); diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_transfer_manager.js similarity index 82% rename from test/w_lockup_volume_restriction_transfer_manager.js rename to test/w_lockup_transfer_manager.js index 2e0db1844..86031e94b 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -7,14 +7,14 @@ import { catchRevert } from "./helpers/exceptions"; const SecurityToken = artifacts.require('./SecurityToken.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const LockUpVolumeRestrictionTM = artifacts.require('./LockupVolumeRestrictionTM'); +const LockUpTransferManager = artifacts.require('./LockUpTransferManager'); const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); const Web3 = require('web3'); const BigNumber = require('bignumber.js'); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port -contract('LockupVolumeRestrictionTransferManager', accounts => { +contract('LockUpTransferManager', accounts => { // Accounts Variable declaration let account_polymath; @@ -33,13 +33,13 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { let message = "Transaction Should Fail!"; // Contract Instance Declaration - let P_LockUpVolumeRestrictionTMFactory; + let P_LockUpTransferManagerFactory; let I_SecurityTokenRegistryProxy; - let P_LockUpVolumeRestrictionTM; + let P_LockUpTransferManager; let I_GeneralTransferManagerFactory; - let I_LockUpVolumeRestrictionTMFactory; + let I_LockUpTransferManagerFactory; let I_GeneralPermissionManager; - let I_LockUpVolumeRestrictionTM; + let I_LockUpTransferManager; let I_GeneralTransferManager; let I_ModuleRegistryProxy; let I_ModuleRegistry; @@ -103,9 +103,9 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ] = instances; // STEP 4(c): Deploy the LockUpVolumeRestrictionTMFactory - [I_LockUpVolumeRestrictionTMFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_LockUpTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); // STEP 4(d): Deploy the LockUpVolumeRestrictionTMFactory - [P_LockUpVolumeRestrictionTMFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + [P_LockUpTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); // Printing all the contract addresses console.log(` @@ -121,7 +121,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} LockupVolumeRestrictionTransferManagerFactory: - ${I_LockUpVolumeRestrictionTMFactory.address} + ${I_LockUpTransferManagerFactory.address} ----------------------------------------------------------------------------- `); }); @@ -278,50 +278,50 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should unsuccessfully attach the LockUpVolumeRestrictionTM factory with the security token -- failed because Token is not paid", async () => { + it("Should unsuccessfully attach the LockUpTransferManager factory with the security token -- failed because Token is not paid", async () => { await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); await catchRevert( - I_SecurityToken.addModule(P_LockUpVolumeRestrictionTMFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) + I_SecurityToken.addModule(P_LockUpTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) ) }); - it("Should successfully attach the LockUpVolumeRestrictionTM factory with the security token", async () => { + it("Should successfully attach the LockUpTransferManager factory with the security token", async () => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_LockUpVolumeRestrictionTMFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + const tx = await I_SecurityToken.addModule(P_LockUpTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), - "LockupVolumeRestrictionTM", - "LockUpVolumeRestrictionTM module was not added" + "LockUpTransferManager", + "LockUpTransferManager module was not added" ); - P_LockUpVolumeRestrictionTM = LockUpVolumeRestrictionTM.at(tx.logs[3].args._module); + P_LockUpTransferManager = LockUpTransferManager.at(tx.logs[3].args._module); await revertToSnapshot(snapId); }); it("Should successfully attach the LockUpVolumeRestrictionTMFactory with the non-divisible security token", async () => { - const tx = await I_SecurityToken.addModule(I_LockUpVolumeRestrictionTMFactory.address, 0, 0, 0, { from: token_owner }); + const tx = await I_SecurityToken.addModule(I_LockUpTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), - "LockupVolumeRestrictionTM", - "LockUpVolumeRestrictionTM module was not added" + "LockUpTransferManager", + "LockUpTransferManager module was not added" ); - I_LockUpVolumeRestrictionTM = LockUpVolumeRestrictionTM.at(tx.logs[2].args._module); + I_LockUpTransferManager = LockUpTransferManager.at(tx.logs[2].args._module); }); it("Should successfully attach the LockUpVolumeRestrictionTMFactory with the divisible security token", async () => { - const tx = await I_SecurityToken_div.addModule(I_LockUpVolumeRestrictionTMFactory.address, 0, 0, 0, { from: token_owner }); + const tx = await I_SecurityToken_div.addModule(I_LockUpTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), - "LockupVolumeRestrictionTM", - "LockUpVolumeRestrictionTM module was not added" + "LockUpTransferManager", + "LockUpTransferManager module was not added" ); - I_LockUpVolumeRestrictionTM_div = LockUpVolumeRestrictionTM.at(tx.logs[2].args._module); + I_LockUpVolumeRestrictionTM_div = LockUpTransferManager.at(tx.logs[2].args._module); }); it("Add a new token holder", async() => { @@ -349,7 +349,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); it("Should pause the tranfers at transferManager level", async() => { - let tx = await I_LockUpVolumeRestrictionTM.pause({from: token_owner}); + let tx = await I_LockUpTransferManager.pause({from: token_owner}); }); it("Should still be able to transfer between existing token holders up to limit", async() => { @@ -363,14 +363,14 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); it("Should unpause the tranfers at transferManager level", async() => { - await I_LockUpVolumeRestrictionTM.unpause({from: token_owner}); + await I_LockUpTransferManager.unpause({from: token_owner}); }); it("Should prevent the creation of a lockup with bad parameters where the lockupAmount is zero", async() => { // create a lockup // this will generate an exception because the lockupAmount is zero await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUp( + I_LockUpTransferManager.addLockUp( account_investor2, 0, latestTime() + + duration.seconds(1), @@ -387,7 +387,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // create a lockup // this will generate an exception because the releaseFrequencySeconds is zero await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUp( + I_LockUpTransferManager.addLockUp( account_investor2, web3.utils.toWei('1', 'ether'), latestTime() + duration.seconds(1), @@ -404,7 +404,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // create a lockup // this will generate an exception because the lockUpPeriodSeconds is zero await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUp( + I_LockUpTransferManager.addLockUp( account_investor2, web3.utils.toWei('1', 'ether'), latestTime() + duration.seconds(1), @@ -422,7 +422,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // create a lockup // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUp( + I_LockUpTransferManager.addLockUp( account_investor2, web3.utils.toWei('0.5', 'ether'), latestTime() + + duration.seconds(1), @@ -477,7 +477,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // over 17 seconds total, with 4 periods. // this will generate an exception because 17 is not evenly divisble by 4. await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUp( + I_LockUpTransferManager.addLockUp( account_investor2, web3.utils.toWei('4', 'ether'), latestTime(), @@ -490,53 +490,13 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should prevent the creation of a lockup with bad parameters where the total amount being locked up isn't evenly divisible by the number of total periods", async() => { - - // create a lockup for a balance of 1 eth - await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUp( - account_investor2, - web3.utils.toWei('1', 'ether'), - latestTime(), - duration.seconds(400000), - duration.seconds(100000), - { - from: token_owner - } - ) - ); - }); - - it("Should prevent the creation of a lockup with bad parameters where the amount to be released per period is too granular for the token", async() => { - - // balance should be 9000000000000000000 here (9 eth) - let balance = await I_SecurityToken.balanceOf(account_investor2) - - // create a lockup for their entire balance - // over 16 seconds total, with 4 periods of 4 seconds each. - // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 - await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUp( - account_investor2, - balance, - latestTime() + duration.seconds(1), - 16, - 4, - { - from: token_owner - } - ) - ); - - }); - it("Should prevent the transfer of tokens in a lockup", async() => { let balance = await I_SecurityToken.balanceOf(account_investor2) console.log("balance", balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); // create a lockup for their entire balance - // over 12 seconds total, with 3 periods of 4 seconds each. - await I_LockUpVolumeRestrictionTM.addLockUp( + // over 12 seconds total, with 3 periods of 20 seconds each. + await I_LockUpTransferManager.addLockUp( account_investor2, balance, latestTime() + duration.seconds(1), @@ -547,7 +507,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { } ); await increaseTime(2); - let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); console.log("Amount get unlocked:", (tx[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) @@ -557,7 +517,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { // wait 20 seconds await increaseTime(duration.seconds(20)); - let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); console.log("Amount get unlocked:", (tx[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }) @@ -565,13 +525,13 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { - let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); console.log("Amount get unlocked:", (tx[4].toNumber())); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); }); it("Should again transfer of tokens in a lockup if a period has passed", async() => { - let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); console.log("Amount get unlocked:", (tx[4].toNumber())); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); }); @@ -580,7 +540,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // wait 20 more seconds + 1 to get rid of same block time await increaseTime(duration.seconds(21)); - let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); console.log("Amount get unlocked:", (tx[4].toNumber())); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); }); @@ -609,8 +569,8 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { let balance = await I_SecurityToken.balanceOf(account_investor2) // wait 20 more seconds + 1 to get rid of same block time - await increaseTime(duration.seconds(20)); - + await increaseTime(duration.seconds(21)); + console.log((await I_LockUpTransferManager.getLockedTokenToUser.call(account_investor2)).toNumber()); await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); assert.equal( (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), @@ -620,7 +580,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUpMulti( + I_LockUpTransferManager.addLockUpMulti( [account_investor3], [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], @@ -635,7 +595,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUpMulti( + I_LockUpTransferManager.addLockUpMulti( [account_investor3, account_investor3], [], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], @@ -650,7 +610,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUpMulti( + I_LockUpTransferManager.addLockUpMulti( [account_investor3, account_investor3], [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], @@ -665,7 +625,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_LockUpVolumeRestrictionTM.addLockUpMulti( + I_LockUpTransferManager.addLockUpMulti( [account_investor3, account_investor3], [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], @@ -679,7 +639,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }) it("Should add the multiple lockup to a address", async() => { - await I_LockUpVolumeRestrictionTM.addLockUpMulti( + await I_LockUpTransferManager.addLockUpMulti( [account_investor3, account_investor3], [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], @@ -691,8 +651,8 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); await increaseTime(1); - let tx = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor3, 0); - let tx2 = await I_LockUpVolumeRestrictionTM.getLockUp.call(account_investor3, 1); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor3, 0); + let tx2 = await I_LockUpTransferManager.getLockUp.call(account_investor3, 1); console.log("Total Amount get unlocked:", (tx[4].toNumber()) + (tx2[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor3 }) @@ -733,7 +693,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should remove multiple lockup --failed because of bad owner", async() => { await catchRevert( - I_LockUpVolumeRestrictionTM.removeLockUpMulti( + I_LockUpTransferManager.removeLockUpMulti( [account_investor3, account_investor3], [0,1], { @@ -745,7 +705,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should remove the multiple lockup -- failed because of invalid index", async() => { await catchRevert( - I_LockUpVolumeRestrictionTM.removeLockUpMulti( + I_LockUpTransferManager.removeLockUpMulti( [account_investor3, account_investor3], [0,3], { @@ -756,7 +716,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }) it("Should remove the multiple lockup", async() => { - await I_LockUpVolumeRestrictionTM.removeLockUpMulti( + await I_LockUpTransferManager.removeLockUpMulti( [account_investor3, account_investor3], [1,0], { @@ -770,7 +730,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should fail to modify the lockup -- because of bad owner", async() => { await I_SecurityToken.mint(account_investor3, web3.utils.toWei("9"), {from: token_owner}); - let tx = await I_LockUpVolumeRestrictionTM.addLockUp( + let tx = await I_LockUpTransferManager.addLockUp( account_investor3, web3.utils.toWei("9"), latestTime() + duration.minutes(5), @@ -783,7 +743,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { temp = (tx.logs[0].args.lockupIndex).toNumber(); await catchRevert( // edit the lockup - I_LockUpVolumeRestrictionTM.modifyLockUp( + I_LockUpTransferManager.modifyLockUp( account_investor3, web3.utils.toWei("9"), latestTime() + duration.seconds(1), @@ -800,7 +760,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Modify the lockup when startTime is in past -- failed because startTime is in the past", async() => { await catchRevert( // edit the lockup - I_LockUpVolumeRestrictionTM.modifyLockUp( + I_LockUpTransferManager.modifyLockUp( account_investor3, web3.utils.toWei("9"), latestTime() - duration.seconds(50), @@ -817,7 +777,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Modify the lockup when startTime is in past -- failed because of invalid index", async() => { await catchRevert( // edit the lockup - I_LockUpVolumeRestrictionTM.modifyLockUp( + I_LockUpTransferManager.modifyLockUp( account_investor3, web3.utils.toWei("9"), latestTime() + duration.seconds(50), @@ -833,7 +793,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("should successfully modify the lockup", async() => { // edit the lockup - await I_LockUpVolumeRestrictionTM.modifyLockUp( + await I_LockUpTransferManager.modifyLockUp( account_investor3, web3.utils.toWei("9"), latestTime() + duration.seconds(50), @@ -855,7 +815,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // create a lockup for their entire balance // over 16 seconds total, with 4 periods of 4 seconds each. - await I_LockUpVolumeRestrictionTM.addLockUp( + await I_LockUpTransferManager.addLockUp( account_investor1, balance, latestTime() + duration.minutes(5), @@ -871,10 +831,11 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); // check and get the lockup - let lockUpCount = await I_LockUpVolumeRestrictionTM.getLockUpsLength(account_investor1); + let lockUpCount = await I_LockUpTransferManager.getLockUpsLength(account_investor1); assert.equal(lockUpCount, 1) - let lockUp = await I_LockUpVolumeRestrictionTM.getLockUp(account_investor1, 0); + let lockUp = await I_LockUpTransferManager.getLockUp(account_investor1, 0); + console.log(lockUp); // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount assert.equal( lockUp[0].dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber(), @@ -886,7 +847,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // edit the lockup temp = latestTime() + duration.seconds(1); - await I_LockUpVolumeRestrictionTM.modifyLockUp( + await I_LockUpTransferManager.modifyLockUp( account_investor1, balance, temp, @@ -913,11 +874,11 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Modify the lockup during the lockup periods --fail because already tokens get unlocked", async() => { let balance = await I_SecurityToken.balanceOf(account_investor1) - let lockUp = await I_LockUpVolumeRestrictionTM.getLockUp(account_investor1, 0); + let lockUp = await I_LockUpTransferManager.getLockUp(account_investor1, 0); console.log(lockUp[4].dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); // edit the lockup await catchRevert( - I_LockUpVolumeRestrictionTM.modifyLockUp( + I_LockUpTransferManager.modifyLockUp( account_investor1, balance, temp, @@ -933,48 +894,48 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should succesfully get the lockup - fail because array index out of bound", async() => { await catchRevert( - I_LockUpVolumeRestrictionTM.getLockUp(account_investor1, 9) + I_LockUpTransferManager.getLockUp(account_investor1, 9) ); }) it("Should get configuration function signature", async() => { - let sig = await I_LockUpVolumeRestrictionTM.getInitFunction.call(); + let sig = await I_LockUpTransferManager.getInitFunction.call(); assert.equal(web3.utils.hexToNumber(sig), 0); }); it("Should get the permission", async() => { - let perm = await I_LockUpVolumeRestrictionTM.getPermissions.call(); + let perm = await I_LockUpTransferManager.getPermissions.call(); assert.equal(perm.length, 1); assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "ADMIN") }); }); - describe("LockUpVolumeRestrictionTM Transfer Manager Factory test cases", async() => { + describe("LockUpTransferManager Transfer Manager Factory test cases", async() => { it("Should get the exact details of the factory", async() => { - assert.equal(await I_LockUpVolumeRestrictionTMFactory.getSetupCost.call(),0); - assert.equal((await I_LockUpVolumeRestrictionTMFactory.getTypes.call())[0],2); - assert.equal(web3.utils.toAscii(await I_LockUpVolumeRestrictionTMFactory.getName.call()) + assert.equal(await I_LockUpTransferManagerFactory.getSetupCost.call(),0); + assert.equal((await I_LockUpTransferManagerFactory.getTypes.call())[0],2); + assert.equal(web3.utils.toAscii(await I_LockUpTransferManagerFactory.getName.call()) .replace(/\u0000/g, ''), - "LockupVolumeRestrictionTM", + "LockUpTransferManager", "Wrong Module added"); - assert.equal(await I_LockUpVolumeRestrictionTMFactory.description.call(), + assert.equal(await I_LockUpTransferManagerFactory.description.call(), "Manage transfers using lock ups over time", "Wrong Module added"); - assert.equal(await I_LockUpVolumeRestrictionTMFactory.title.call(), - "Lockup Volume Restriction Transfer Manager", + assert.equal(await I_LockUpTransferManagerFactory.title.call(), + "LockUp Transfer Manager", "Wrong Module added"); - assert.equal(await I_LockUpVolumeRestrictionTMFactory.getInstructions.call(), + assert.equal(await I_LockUpTransferManagerFactory.getInstructions.call(), "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", "Wrong Module added"); - assert.equal(await I_LockUpVolumeRestrictionTMFactory.version.call(), "1.0.0"); + assert.equal(await I_LockUpTransferManagerFactory.version.call(), "1.0.0"); }); it("Should get the tags of the factory", async() => { - let tags = await I_LockUpVolumeRestrictionTMFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Volume"); + let tags = await I_LockUpTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "LockUp"); }); }); From c26a8caaaea74654fe3d35042a9ae6b835172e71 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 23 Nov 2018 00:41:12 +0200 Subject: [PATCH 158/582] review comments: simplified data structure --- .../modules/Wallet/VestingEscrowWallet.sol | 77 +++++++++---------- test/z_vesting_escrow_wallet.js | 62 ++++++++------- 2 files changed, 71 insertions(+), 68 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 85d51ad8c..ed5b41fae 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -16,19 +16,16 @@ contract VestingEscrowWallet is IWallet { struct Schedule { uint256 numberOfTokens; - uint256 lockedTokens; + uint256 releasedTokens; + uint256 availableTokens; uint256 duration; uint256 frequency; uint256 startTime; - uint256 nextTime; - State state; } struct Data { uint256 index; Schedule[] schedules; - uint256 availableTokens; - uint256 claimedTokens; } struct Template { @@ -38,6 +35,7 @@ contract VestingEscrowWallet is IWallet { } enum State {CREATED, STARTED, COMPLETED} + //TODO add method for getting state address public treasury; uint256 public unassignedTokens; @@ -197,11 +195,7 @@ contract VestingEscrowWallet is IWallet { dataMap[_beneficiary].index = beneficiaries.length; beneficiaries.push(_beneficiary); } - dataMap[_beneficiary].schedules.push( - Schedule( - _numberOfTokens, _numberOfTokens, _duration, _frequency, _startTime, _startTime.add(_frequency), State.CREATED - ) - ); + dataMap[_beneficiary].schedules.push(Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime)); emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); } @@ -246,15 +240,15 @@ contract VestingEscrowWallet is IWallet { Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; /*solium-disable-next-line security/no-block-members*/ require(now < schedule.startTime, "Schedule started"); - if (_numberOfTokens <= schedule.lockedTokens) { - unassignedTokens = unassignedTokens.add(schedule.lockedTokens - _numberOfTokens); + if (_numberOfTokens <= schedule.numberOfTokens) { + unassignedTokens = unassignedTokens.add(schedule.numberOfTokens - _numberOfTokens); } else { - if (_numberOfTokens - schedule.lockedTokens > unassignedTokens) { - _depositTokens(_numberOfTokens - schedule.lockedTokens - unassignedTokens); + if (_numberOfTokens - schedule.numberOfTokens > unassignedTokens) { + _depositTokens(_numberOfTokens - schedule.numberOfTokens - unassignedTokens); } - unassignedTokens = unassignedTokens.sub(_numberOfTokens - schedule.lockedTokens); + unassignedTokens = unassignedTokens.sub(_numberOfTokens - schedule.numberOfTokens); } - dataMap[_beneficiary].schedules[_index] = Schedule(_numberOfTokens, _numberOfTokens, _duration, _frequency, _startTime, _startTime.add(_frequency), State.CREATED); + dataMap[_beneficiary].schedules[_index] = Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime); emit ModifySchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); } @@ -267,7 +261,7 @@ contract VestingEscrowWallet is IWallet { require(_beneficiary != address(0), "Invalid address"); require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); Schedule[] storage schedules = dataMap[_beneficiary].schedules; - unassignedTokens = unassignedTokens.add(schedules[_index].lockedTokens); + unassignedTokens = unassignedTokens.add(schedules[_index].numberOfTokens - schedules[_index].releasedTokens); schedules[_index] = schedules[schedules.length - 1]; schedules.length--; if (schedules.length == 0) { @@ -285,7 +279,7 @@ contract VestingEscrowWallet is IWallet { require(_beneficiary != address(0), "Invalid address"); Data storage data = dataMap[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { - unassignedTokens = unassignedTokens.add(data.schedules[i].lockedTokens); + unassignedTokens = unassignedTokens.add(data.schedules[i].numberOfTokens - data.schedules[i].releasedTokens); } delete dataMap[_beneficiary].schedules; _revokeSchedules(_beneficiary); @@ -298,18 +292,15 @@ contract VestingEscrowWallet is IWallet { * @param _index index of the schedule * @return beneficiary's schedule */ - function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256, uint256, uint256, State) { + function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256) { require(_beneficiary != address(0), "Invalid address"); require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; return ( schedule.numberOfTokens, - schedule.lockedTokens, schedule.duration, schedule.frequency, - schedule.startTime, - schedule.nextTime, - schedule.state + schedule.startTime ); } @@ -329,8 +320,16 @@ contract VestingEscrowWallet is IWallet { * @return available tokens for beneficiary */ function getAvailableTokens(address _beneficiary) external view returns(uint256) { + return _getAvailableTokens(_beneficiary); + } + + function _getAvailableTokens(address _beneficiary) internal view returns(uint256) { require(_beneficiary != address(0)); - return dataMap[_beneficiary].availableTokens; + uint256 availableTokens; + for (uint256 i = 0; i < dataMap[_beneficiary].schedules.length; i++) { + availableTokens = availableTokens.add(dataMap[_beneficiary].schedules[i].availableTokens); + } + return availableTokens; } /** @@ -438,11 +437,11 @@ contract VestingEscrowWallet is IWallet { } function _sendTokens(address _beneficiary) internal { - Data storage data = dataMap[_beneficiary]; - uint256 amount = data.availableTokens; + uint256 amount = _getAvailableTokens(_beneficiary); require(amount > 0, "No available tokens"); - data.availableTokens = 0; - data.claimedTokens = data.claimedTokens.add(amount); + for (uint256 i = 0; i < dataMap[_beneficiary].schedules.length; i++) { + dataMap[_beneficiary].schedules[i].availableTokens = 0; + } ISecurityToken(securityToken).transfer(_beneficiary, amount); emit SendTokens(_beneficiary, amount); } @@ -459,17 +458,17 @@ contract VestingEscrowWallet is IWallet { Data storage data = dataMap[_beneficiary]; for (uint256 i = 0; i < data.schedules.length; i++) { Schedule storage schedule = data.schedules[i]; - /*solium-disable-next-line security/no-block-members*/ - if (schedule.state != State.COMPLETED && schedule.nextTime <= now) { + if (schedule.releasedTokens < schedule.numberOfTokens) { uint256 periodCount = schedule.duration.div(schedule.frequency); - uint256 numberOfTokens = schedule.numberOfTokens.div(periodCount); - data.availableTokens = data.availableTokens.add(numberOfTokens); - schedule.lockedTokens = schedule.lockedTokens.sub(numberOfTokens); - if (schedule.nextTime == schedule.startTime.add(schedule.duration)) { - schedule.state = State.COMPLETED; - } else { - schedule.state = State.STARTED; - schedule.nextTime = schedule.nextTime.add(schedule.frequency); + /*solium-disable-next-line security/no-block-members*/ + uint256 periodNumber = (now.sub(schedule.startTime)).div(schedule.frequency); + if (periodNumber > periodCount) { + periodNumber = periodCount; + } + uint256 releasedTokens = schedule.numberOfTokens.mul(periodNumber).div(periodCount); + if (schedule.releasedTokens < releasedTokens) { + schedule.availableTokens = schedule.availableTokens.add(releasedTokens - schedule.releasedTokens); + schedule.releasedTokens = releasedTokens; } } } @@ -490,7 +489,7 @@ contract VestingEscrowWallet is IWallet { function _revokeSchedules(address _beneficiary) internal { //can be removed - if (dataMap[_beneficiary].availableTokens == 0) { + if (_getAvailableTokens(_beneficiary) == 0) { uint256 index = dataMap[_beneficiary].index; beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; beneficiaries.length--; diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 4b8146395..ee274a50d 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -366,17 +366,22 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); - it("Should withdraw available tokens by 3 schedules to the beneficiary address", async () => { + it("Should withdraw available tokens by 2 schedules to the beneficiary address", async () => { let schedules = [ + { + numberOfTokens: 100000, + duration: durationUtil.minutes(4), + frequency: durationUtil.minutes(1) + }, { numberOfTokens: 30000, - duration: durationUtil.seconds(6), - frequency: durationUtil.seconds(1) + duration: durationUtil.minutes(6), + frequency: durationUtil.minutes(1) }, { numberOfTokens: 2000, - duration: durationUtil.seconds(10), - frequency: durationUtil.seconds(1) + duration: durationUtil.minutes(10), + frequency: durationUtil.minutes(1) } ]; @@ -390,12 +395,11 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + durationUtil.seconds(100); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); } - await increaseTime(durationUtil.minutes(5)); - let stepCount = 4; - for (let i = 0; i < stepCount; i++) { - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_admin}); - } - let numberOfTokens = (30000 / 6 * stepCount) + (2000 / 10 * stepCount); + let stepCount = 6; + await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); + await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_admin}); + + let numberOfTokens = 100000 + (30000 / 6 * stepCount) + (2000 / 10 * stepCount); const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); @@ -408,6 +412,8 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); + //TODO add test like previous one, but with withdrawing tokens + }); describe("Adding, modifying and revoking vesting schedule", async () => { @@ -433,6 +439,8 @@ contract('VestingEscrowWallet', accounts => { } ]; + //TODO add test for checking pushing during revoking + it("Should fail to add vesting schedule to the beneficiary address -- fail because address in invalid", async () => { await catchRevert( I_VestingEscrowWallet.addSchedule(0, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) @@ -502,7 +510,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); - checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); }); it("Should add vesting schedule without depositing to the beneficiary address", async () => { @@ -520,7 +528,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 2); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 1); - checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); @@ -549,7 +557,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); - checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); assert.equal(unassignedTokens.toNumber(), schedules[0].numberOfTokens - schedules[1].numberOfTokens); @@ -572,7 +580,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); - checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); assert.equal(unassignedTokens.toNumber(), 0); @@ -624,7 +632,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, i + 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, i); - checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); } }); @@ -639,8 +647,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 2); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, 1); - checkSchedule(schedule, schedules[2].numberOfTokens, schedules[2].numberOfTokens, schedules[2].duration, schedules[2].frequency, - schedules[2].startTime, schedules[2].startTime + schedules[2].frequency, CREATED); + checkSchedule(schedule, schedules[2].numberOfTokens, schedules[2].duration, schedules[2].frequency, schedules[2].startTime); }); it("Should revoke 2 vesting schedules from the beneficiary address", async () => { @@ -719,7 +726,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); - checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); @@ -764,7 +771,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); - checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); } }); @@ -801,7 +808,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); - checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); } let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); @@ -857,7 +864,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount.toNumber(), 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); - checkSchedule(schedule, numberOfTokens, numberOfTokens, duration, frequency, startTime, startTime + frequency, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); } }); @@ -995,14 +1002,11 @@ function checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, assert.equal(log.args._startTime.toNumber(), startTime); } -function checkSchedule(schedule, numberOfTokens, lockedTokens, duration, frequency, startTime, nextTime, state) { +function checkSchedule(schedule, numberOfTokens, duration, frequency, startTime) { assert.equal(schedule[0].toNumber(), numberOfTokens); - assert.equal(schedule[1].toNumber(), lockedTokens); - assert.equal(schedule[2].toNumber(), duration); - assert.equal(schedule[3].toNumber(), frequency); - assert.equal(schedule[4].toNumber(), startTime); - assert.equal(schedule[5].toNumber(), nextTime); - assert.equal(schedule[6], state); + assert.equal(schedule[1].toNumber(), duration); + assert.equal(schedule[2].toNumber(), frequency); + assert.equal(schedule[3].toNumber(), startTime); } function getTotalNumberOfTokens(schedules) { From 03437b8654968f6e79b664cb81bc986e4453809a Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 23 Nov 2018 10:14:09 +0200 Subject: [PATCH 159/582] review comments: removed redundant functions --- .../modules/Wallet/VestingEscrowWallet.sol | 50 +++++++------------ test/z_vesting_escrow_wallet.js | 14 ++---- 2 files changed, 20 insertions(+), 44 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index ed5b41fae..29400e895 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -446,44 +446,28 @@ contract VestingEscrowWallet is IWallet { emit SendTokens(_beneficiary, amount); } - /** - * @notice manually triggers update outside for beneficiary's schedule (can be used to reduce user gas costs) - * @param _beneficiary beneficiary's address of the schedule - */ - function update(address _beneficiary) external withPerm(ADMIN) { - _update(_beneficiary); - } - - function _update(address _beneficiary) internal { - Data storage data = dataMap[_beneficiary]; - for (uint256 i = 0; i < data.schedules.length; i++) { - Schedule storage schedule = data.schedules[i]; - if (schedule.releasedTokens < schedule.numberOfTokens) { - uint256 periodCount = schedule.duration.div(schedule.frequency); - /*solium-disable-next-line security/no-block-members*/ - uint256 periodNumber = (now.sub(schedule.startTime)).div(schedule.frequency); - if (periodNumber > periodCount) { - periodNumber = periodCount; - } - uint256 releasedTokens = schedule.numberOfTokens.mul(periodNumber).div(periodCount); - if (schedule.releasedTokens < releasedTokens) { - schedule.availableTokens = schedule.availableTokens.add(releasedTokens - schedule.releasedTokens); - schedule.releasedTokens = releasedTokens; - } - } - } - } - /** * @notice manually triggers update outside for all schedules (can be used to reduce user gas costs) */ function updateAll() external withPerm(ADMIN) { - _updateAll(); - } - - function _updateAll() internal { for (uint256 i = 0; i < beneficiaries.length; i++) { - _update(beneficiaries[i]); + Data storage data = dataMap[beneficiaries[i]]; + for (uint256 j = 0; j < data.schedules.length; j++) { + Schedule storage schedule = data.schedules[j]; + if (schedule.releasedTokens < schedule.numberOfTokens) { + uint256 periodCount = schedule.duration.div(schedule.frequency); + /*solium-disable-next-line security/no-block-members*/ + uint256 periodNumber = (now.sub(schedule.startTime)).div(schedule.frequency); + if (periodNumber > periodCount) { + periodNumber = periodCount; + } + uint256 releasedTokens = schedule.numberOfTokens.mul(periodNumber).div(periodCount); + if (schedule.releasedTokens < releasedTokens) { + schedule.availableTokens = schedule.availableTokens.add(releasedTokens - schedule.releasedTokens); + schedule.releasedTokens = releasedTokens; + } + } + } } } diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index ee274a50d..318600a9c 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -314,7 +314,7 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency); - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.updateAll({from: wallet_admin}); const tx = await I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); @@ -350,9 +350,7 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency * 3); - for (let i = 0; i < 4; i++) { - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_admin}); - } + await I_VestingEscrowWallet.updateAll({from: wallet_admin}); const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); @@ -397,7 +395,7 @@ contract('VestingEscrowWallet', accounts => { } let stepCount = 6; await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); - await I_VestingEscrowWallet.update(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.updateAll({from: wallet_admin}); let numberOfTokens = 100000 + (30000 / 6 * stepCount) + (2000 / 10 * stepCount); const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); @@ -978,12 +976,6 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should not be able update schedule", async () => { - await catchPermission( - I_VestingEscrowWallet.update(account_beneficiary1, {from: account_beneficiary1}) - ); - }); - it("Should not be able update all schedules", async () => { await catchPermission( I_VestingEscrowWallet.updateAll({from: account_beneficiary1}) From 4add551c8585f7f94179fab848a64bf0491d7476 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 23 Nov 2018 11:25:53 +0200 Subject: [PATCH 160/582] removed dataMap --- .../modules/Wallet/VestingEscrowWallet.sol | 70 +++++++++---------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 29400e895..a5a6973d1 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -23,11 +23,6 @@ contract VestingEscrowWallet is IWallet { uint256 startTime; } - struct Data { - uint256 index; - Schedule[] schedules; - } - struct Template { uint256 numberOfTokens; uint256 duration; @@ -40,7 +35,7 @@ contract VestingEscrowWallet is IWallet { address public treasury; uint256 public unassignedTokens; - mapping (address => Data) public dataMap; + mapping (address => Schedule[]) public schedules; address[] public beneficiaries; Template[] public templates; @@ -191,11 +186,10 @@ contract VestingEscrowWallet is IWallet { } unassignedTokens = unassignedTokens.sub(_numberOfTokens); //add beneficiary to the schedule list only if adding first schedule - if (dataMap[_beneficiary].schedules.length == 0) { - dataMap[_beneficiary].index = beneficiaries.length; + if (schedules[_beneficiary].length == 0) { beneficiaries.push(_beneficiary); } - dataMap[_beneficiary].schedules.push(Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime)); + schedules[_beneficiary].push(Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime)); emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); } @@ -236,8 +230,8 @@ contract VestingEscrowWallet is IWallet { withPerm(ADMIN) { _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); - require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); - Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; + require(_index < schedules[_beneficiary].length, "Schedule not found"); + Schedule storage schedule = schedules[_beneficiary][_index]; /*solium-disable-next-line security/no-block-members*/ require(now < schedule.startTime, "Schedule started"); if (_numberOfTokens <= schedule.numberOfTokens) { @@ -248,7 +242,7 @@ contract VestingEscrowWallet is IWallet { } unassignedTokens = unassignedTokens.sub(_numberOfTokens - schedule.numberOfTokens); } - dataMap[_beneficiary].schedules[_index] = Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime); + schedules[_beneficiary][_index] = Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime); emit ModifySchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); } @@ -259,12 +253,12 @@ contract VestingEscrowWallet is IWallet { */ function revokeSchedule(address _beneficiary, uint256 _index) external withPerm(ADMIN) { require(_beneficiary != address(0), "Invalid address"); - require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); - Schedule[] storage schedules = dataMap[_beneficiary].schedules; - unassignedTokens = unassignedTokens.add(schedules[_index].numberOfTokens - schedules[_index].releasedTokens); - schedules[_index] = schedules[schedules.length - 1]; - schedules.length--; - if (schedules.length == 0) { + require(_index < schedules[_beneficiary].length, "Schedule not found"); + Schedule[] storage userSchedules = schedules[_beneficiary]; + unassignedTokens = unassignedTokens.add(userSchedules[_index].numberOfTokens - userSchedules[_index].releasedTokens); + userSchedules[_index] = userSchedules[userSchedules.length - 1]; + userSchedules.length--; + if (userSchedules.length == 0) { _revokeSchedules(_beneficiary); } emit RevokeSchedule(_beneficiary, _index); @@ -277,11 +271,11 @@ contract VestingEscrowWallet is IWallet { */ function revokeSchedules(address _beneficiary) public withPerm(ADMIN) { require(_beneficiary != address(0), "Invalid address"); - Data storage data = dataMap[_beneficiary]; - for (uint256 i = 0; i < data.schedules.length; i++) { - unassignedTokens = unassignedTokens.add(data.schedules[i].numberOfTokens - data.schedules[i].releasedTokens); + Schedule[] storage data = schedules[_beneficiary]; + for (uint256 i = 0; i < data.length; i++) { + unassignedTokens = unassignedTokens.add(data[i].numberOfTokens - data[i].releasedTokens); } - delete dataMap[_beneficiary].schedules; + delete schedules[_beneficiary]; _revokeSchedules(_beneficiary); emit RevokeSchedules(_beneficiary); } @@ -294,8 +288,8 @@ contract VestingEscrowWallet is IWallet { */ function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256) { require(_beneficiary != address(0), "Invalid address"); - require(_index < dataMap[_beneficiary].schedules.length, "Schedule not found"); - Schedule storage schedule = dataMap[_beneficiary].schedules[_index]; + require(_index < schedules[_beneficiary].length, "Schedule not found"); + Schedule storage schedule = schedules[_beneficiary][_index]; return ( schedule.numberOfTokens, schedule.duration, @@ -311,7 +305,7 @@ contract VestingEscrowWallet is IWallet { */ function getScheduleCount(address _beneficiary) external view returns(uint256) { require(_beneficiary != address(0), "Invalid address"); - return dataMap[_beneficiary].schedules.length; + return schedules[_beneficiary].length; } /** @@ -326,8 +320,8 @@ contract VestingEscrowWallet is IWallet { function _getAvailableTokens(address _beneficiary) internal view returns(uint256) { require(_beneficiary != address(0)); uint256 availableTokens; - for (uint256 i = 0; i < dataMap[_beneficiary].schedules.length; i++) { - availableTokens = availableTokens.add(dataMap[_beneficiary].schedules[i].availableTokens); + for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { + availableTokens = availableTokens.add(schedules[_beneficiary][i].availableTokens); } return availableTokens; } @@ -439,8 +433,8 @@ contract VestingEscrowWallet is IWallet { function _sendTokens(address _beneficiary) internal { uint256 amount = _getAvailableTokens(_beneficiary); require(amount > 0, "No available tokens"); - for (uint256 i = 0; i < dataMap[_beneficiary].schedules.length; i++) { - dataMap[_beneficiary].schedules[i].availableTokens = 0; + for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { + schedules[_beneficiary][i].availableTokens = 0; } ISecurityToken(securityToken).transfer(_beneficiary, amount); emit SendTokens(_beneficiary, amount); @@ -451,9 +445,9 @@ contract VestingEscrowWallet is IWallet { */ function updateAll() external withPerm(ADMIN) { for (uint256 i = 0; i < beneficiaries.length; i++) { - Data storage data = dataMap[beneficiaries[i]]; - for (uint256 j = 0; j < data.schedules.length; j++) { - Schedule storage schedule = data.schedules[j]; + Schedule[] storage data = schedules[beneficiaries[i]]; + for (uint256 j = 0; j < data.length; j++) { + Schedule storage schedule = data[j]; if (schedule.releasedTokens < schedule.numberOfTokens) { uint256 periodCount = schedule.duration.div(schedule.frequency); /*solium-disable-next-line security/no-block-members*/ @@ -474,13 +468,15 @@ contract VestingEscrowWallet is IWallet { function _revokeSchedules(address _beneficiary) internal { //can be removed if (_getAvailableTokens(_beneficiary) == 0) { - uint256 index = dataMap[_beneficiary].index; + uint256 index; + for (uint256 i = 0; i < beneficiaries.length; i++) { + if (_beneficiary == beneficiaries[i]) { + index = i; + } + } beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; beneficiaries.length--; - if (index != beneficiaries.length) { - dataMap[beneficiaries[index]].index = index; - } - delete dataMap[_beneficiary]; + delete schedules[_beneficiary]; } } From 42e6817b9b8dc5de79e3bbbbfd497b98aec46ae7 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 23 Nov 2018 12:41:47 +0200 Subject: [PATCH 161/582] refactored revoke methods --- .../modules/Wallet/VestingEscrowWallet.sol | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index a5a6973d1..0a0e463aa 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -254,29 +254,31 @@ contract VestingEscrowWallet is IWallet { function revokeSchedule(address _beneficiary, uint256 _index) external withPerm(ADMIN) { require(_beneficiary != address(0), "Invalid address"); require(_index < schedules[_beneficiary].length, "Schedule not found"); +// _sendTokens(_beneficiary); Schedule[] storage userSchedules = schedules[_beneficiary]; unassignedTokens = unassignedTokens.add(userSchedules[_index].numberOfTokens - userSchedules[_index].releasedTokens); - userSchedules[_index] = userSchedules[userSchedules.length - 1]; + if (_index != userSchedules.length - 1) { + userSchedules[_index] = userSchedules[userSchedules.length - 1]; + } userSchedules.length--; if (userSchedules.length == 0) { - _revokeSchedules(_beneficiary); + _removeBeneficiary(_beneficiary); } emit RevokeSchedule(_beneficiary, _index); } - /** * @notice Revokes all beneficiary's schedules * @param _beneficiary beneficiary's address */ function revokeSchedules(address _beneficiary) public withPerm(ADMIN) { require(_beneficiary != address(0), "Invalid address"); +// _sendTokens(_beneficiary); Schedule[] storage data = schedules[_beneficiary]; for (uint256 i = 0; i < data.length; i++) { unassignedTokens = unassignedTokens.add(data[i].numberOfTokens - data[i].releasedTokens); } - delete schedules[_beneficiary]; - _revokeSchedules(_beneficiary); + _removeBeneficiary(_beneficiary); emit RevokeSchedules(_beneficiary); } @@ -465,19 +467,20 @@ contract VestingEscrowWallet is IWallet { } } - function _revokeSchedules(address _beneficiary) internal { - //can be removed - if (_getAvailableTokens(_beneficiary) == 0) { - uint256 index; - for (uint256 i = 0; i < beneficiaries.length; i++) { - if (_beneficiary == beneficiaries[i]) { - index = i; - } + function _removeBeneficiary(address _beneficiary) internal { + bool isFound = false; + uint256 index; + for (uint256 i = 0; i < beneficiaries.length; i++) { + if (_beneficiary == beneficiaries[i]) { + isFound = true; + index = i; } + } + if (isFound && index != beneficiaries.length - 1) { beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; - beneficiaries.length--; - delete schedules[_beneficiary]; } + beneficiaries.length--; + delete schedules[_beneficiary]; } /** From 210fbb92bd6446c024cf4178115af5b3f2ab2f67 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 23 Nov 2018 14:39:27 +0200 Subject: [PATCH 162/582] test for pushing during revoking, getState method --- .../modules/Wallet/VestingEscrowWallet.sol | 32 +++-- test/z_vesting_escrow_wallet.js | 131 +++++++++++++----- 2 files changed, 121 insertions(+), 42 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 0a0e463aa..a1d98c7e0 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -30,7 +30,6 @@ contract VestingEscrowWallet is IWallet { } enum State {CREATED, STARTED, COMPLETED} - //TODO add method for getting state address public treasury; uint256 public unassignedTokens; @@ -254,7 +253,7 @@ contract VestingEscrowWallet is IWallet { function revokeSchedule(address _beneficiary, uint256 _index) external withPerm(ADMIN) { require(_beneficiary != address(0), "Invalid address"); require(_index < schedules[_beneficiary].length, "Schedule not found"); -// _sendTokens(_beneficiary); + _sendTokens(_beneficiary); Schedule[] storage userSchedules = schedules[_beneficiary]; unassignedTokens = unassignedTokens.add(userSchedules[_index].numberOfTokens - userSchedules[_index].releasedTokens); if (_index != userSchedules.length - 1) { @@ -273,7 +272,7 @@ contract VestingEscrowWallet is IWallet { */ function revokeSchedules(address _beneficiary) public withPerm(ADMIN) { require(_beneficiary != address(0), "Invalid address"); -// _sendTokens(_beneficiary); + _sendTokens(_beneficiary); Schedule[] storage data = schedules[_beneficiary]; for (uint256 i = 0; i < data.length; i++) { unassignedTokens = unassignedTokens.add(data[i].numberOfTokens - data[i].releasedTokens); @@ -288,7 +287,7 @@ contract VestingEscrowWallet is IWallet { * @param _index index of the schedule * @return beneficiary's schedule */ - function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256) { + function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256, State) { require(_beneficiary != address(0), "Invalid address"); require(_index < schedules[_beneficiary].length, "Schedule not found"); Schedule storage schedule = schedules[_beneficiary][_index]; @@ -296,10 +295,22 @@ contract VestingEscrowWallet is IWallet { schedule.numberOfTokens, schedule.duration, schedule.frequency, - schedule.startTime + schedule.startTime, + _getScheduleState(_beneficiary, _index) ); } + function _getScheduleState(address _beneficiary, uint256 _index) internal view returns(State) { + Schedule memory schedule = schedules[_beneficiary][_index]; + if (now < schedule.startTime) { + return State.CREATED; + } else if (now > schedule.startTime && now < schedule.startTime.add(schedule.duration)) { + return State.STARTED; + } else { + return State.COMPLETED; + } + } + /** * @notice Returns count of beneficiary's schedules * @param _beneficiary beneficiary's address @@ -434,12 +445,13 @@ contract VestingEscrowWallet is IWallet { function _sendTokens(address _beneficiary) internal { uint256 amount = _getAvailableTokens(_beneficiary); - require(amount > 0, "No available tokens"); - for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { - schedules[_beneficiary][i].availableTokens = 0; + if (amount > 0) { + for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { + schedules[_beneficiary][i].availableTokens = 0; + } + ISecurityToken(securityToken).transfer(_beneficiary, amount); + emit SendTokens(_beneficiary, amount); } - ISecurityToken(securityToken).transfer(_beneficiary, amount); - emit SendTokens(_beneficiary, amount); } /** diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 318600a9c..ae2866075 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -17,6 +17,8 @@ const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); contract('VestingEscrowWallet', accounts => { const CREATED = 0; + const STARTED = 1; + const COMPLETED = 2; // Accounts Variable declaration let account_polymath; @@ -298,12 +300,6 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), 0); }); - it("Should fail to push available tokens -- fail because beneficiary doesn't have available tokens", async () => { - catchRevert( - I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: wallet_admin}) - ); - }); - it("Should send available tokens to the beneficiary address", async () => { let numberOfTokens = 75000; let duration = durationUtil.seconds(30); @@ -359,12 +355,15 @@ contract('VestingEscrowWallet', accounts => { let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary3, 0); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, COMPLETED); + await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); - it("Should withdraw available tokens by 2 schedules to the beneficiary address", async () => { + it("Should withdraw available tokens 2 times by 3 schedules to the beneficiary address", async () => { let schedules = [ { numberOfTokens: 100000, @@ -405,13 +404,23 @@ contract('VestingEscrowWallet', accounts => { let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens); + stepCount = 4; + await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); + await I_VestingEscrowWallet.updateAll({from: wallet_admin}); + + numberOfTokens = (2000 / 10 * stepCount); + const tx2 = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); + assert.equal(tx2.logs[0].args._beneficiary, account_beneficiary3); + assert.equal(tx2.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + + balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toNumber(), totalNumberOfTokens); + await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); - //TODO add test like previous one, but with withdrawing tokens - }); describe("Adding, modifying and revoking vesting schedule", async () => { @@ -508,7 +517,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); }); it("Should add vesting schedule without depositing to the beneficiary address", async () => { @@ -526,7 +535,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 2); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 1); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); @@ -555,7 +564,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); assert.equal(unassignedTokens.toNumber(), schedules[0].numberOfTokens - schedules[1].numberOfTokens); @@ -578,12 +587,23 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); assert.equal(unassignedTokens.toNumber(), 0); }); + it("Should revoke vesting schedule from the beneficiary address", async () => { + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_admin}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); + assert.equal(tx.logs[0].args._index, 0); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); + assert.equal(scheduleCount, 0); + }); + it("Should fail to revoke vesting schedule -- fail because address is invalid", async () => { await catchRevert( I_VestingEscrowWallet.revokeSchedule(0, 0, {from: wallet_admin}) @@ -596,17 +616,6 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should revoke vesting schedule from the beneficiary address", async () => { - const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_admin}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); - - assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); - assert.equal(tx.logs[0].args._index, 0); - - let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); - assert.equal(scheduleCount, 0); - }); - it("Should fail to revoke vesting schedules -- fail because address is invalid", async () => { await catchRevert( I_VestingEscrowWallet.revokeSchedules(0, {from: wallet_admin}) @@ -630,7 +639,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, i + 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, i); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); } }); @@ -645,7 +654,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 2); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, 1); - checkSchedule(schedule, schedules[2].numberOfTokens, schedules[2].duration, schedules[2].frequency, schedules[2].startTime); + checkSchedule(schedule, schedules[2].numberOfTokens, schedules[2].duration, schedules[2].frequency, schedules[2].startTime, CREATED); }); it("Should revoke 2 vesting schedules from the beneficiary address", async () => { @@ -658,6 +667,63 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 0); }); + it("Should push available tokens during revoking vesting schedule", async () => { + let schedules = [ + { + numberOfTokens: 100000, + duration: durationUtil.minutes(4), + frequency: durationUtil.minutes(1) + }, + { + numberOfTokens: 30000, + duration: durationUtil.minutes(6), + frequency: durationUtil.minutes(1) + }, + { + numberOfTokens: 2000, + duration: durationUtil.minutes(10), + frequency: durationUtil.minutes(1) + } + ]; + + let totalNumberOfTokens = getTotalNumberOfTokens(schedules); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + for (let i = 0; i < schedules.length; i++) { + let numberOfTokens = schedules[i].numberOfTokens; + let duration = schedules[i].duration; + let frequency = schedules[i].frequency; + let startTime = latestTime() + durationUtil.seconds(100); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + } + let stepCount = 6; + await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); + await I_VestingEscrowWallet.updateAll({from: wallet_admin}); + + let numberOfTokens = 100000 + (30000 / 6 * stepCount) + (2000 / 10 * stepCount); + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary3, 0, {from: wallet_admin}); + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + + let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toNumber(), numberOfTokens); + + stepCount = 4; + await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); + await I_VestingEscrowWallet.updateAll({from: wallet_admin}); + + numberOfTokens = (2000 / 10 * stepCount); + const tx2 = await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); + assert.equal(tx2.logs[0].args._beneficiary, account_beneficiary3); + assert.equal(tx2.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + + balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toNumber(), totalNumberOfTokens); + + await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + }); + }); describe("Adding, using and removing templates", async () => { @@ -724,7 +790,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); @@ -769,11 +835,11 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); } }); - it("Should modify vesting schedule for 3 beneficiary's addresses", async () => { + it("Should not be able modify vesting schedule for 3 beneficiary's addresses", async () => { let numberOfTokens = 25000; let duration = durationUtil.seconds(50); let frequency = durationUtil.seconds(10); @@ -806,7 +872,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, STARTED); } let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); @@ -862,7 +928,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount.toNumber(), 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); } }); @@ -994,11 +1060,12 @@ function checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, assert.equal(log.args._startTime.toNumber(), startTime); } -function checkSchedule(schedule, numberOfTokens, duration, frequency, startTime) { +function checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, state) { assert.equal(schedule[0].toNumber(), numberOfTokens); assert.equal(schedule[1].toNumber(), duration); assert.equal(schedule[2].toNumber(), frequency); assert.equal(schedule[3].toNumber(), startTime); + assert.equal(schedule[4].toNumber(), state); } function getTotalNumberOfTokens(schedules) { From 752a5e67a2bf8ea069e894f076c5dbc299b893b7 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 23 Nov 2018 19:59:10 +0530 Subject: [PATCH 163/582] Skip emiting event when no tokens purchased --- contracts/modules/STO/USDTieredSTO.sol | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 464cb7948..92a3157df 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -618,7 +618,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { tierData.mintedTotal = tierData.mintedTotal.add(tierPurchasedTokens); } // Now, if there is any remaining USD to be invested, purchase at non-discounted rate - if ((investedUSD > 0) && (tierData.tokenTotal.sub(tierData.mintedTotal) > 0)) { + if (investedUSD > 0 && + tierData.tokenTotal.sub(tierData.mintedTotal) > 0 && + tierData.tokensDiscountPoly == tierData.mintedDiscountPoly + ) { (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), investedUSD, _tier); spentUSD = spentUSD.add(tierSpentUSD); tierData.minted[uint8(_fundRaiseType)] = tierData.minted[uint8(_fundRaiseType)].add(tierPurchasedTokens); @@ -650,7 +653,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _investedUSD = _investedUSD.sub(spentUSD); } // Now, if there is any remaining USD to be invested, purchase at non-discounted rate - if ((_investedUSD > 0) && (tierData.tokenTotal.sub(tierData.mintedTotal.add(tokensMinted)) > 0)) { + if (_investedUSD > 0 && + tierData.tokenTotal.sub(tierData.mintedTotal.add(tokensMinted)) > 0 && + tierData.tokensDiscountPoly == tierData.mintedDiscountPoly + ) { (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTierAmount(tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), _investedUSD); spentUSD = spentUSD.add(tierSpentUSD); tokensMinted = tokensMinted.add(tierPurchasedTokens); @@ -668,8 +674,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) { (spentUSD, purchasedTokens, gotoNextTier) = _purchaseTierAmount(_tierPrice, _tierRemaining, _investedUSD); - require(ISecurityToken(securityToken).mint(_beneficiary, purchasedTokens), "Error in minting"); - emit TokenPurchase(msg.sender, _beneficiary, purchasedTokens, spentUSD, _tierPrice, _tier); + if (purchasedTokens > 0) { + require(ISecurityToken(securityToken).mint(_beneficiary, purchasedTokens), "Error in minting"); + emit TokenPurchase(msg.sender, _beneficiary, purchasedTokens, spentUSD, _tierPrice, _tier); + } } function _purchaseTierAmount( From 401156bbee0d036f9dd40da2309b3a9b0a1771c4 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 23 Nov 2018 20:05:26 +0530 Subject: [PATCH 164/582] typo fix --- contracts/modules/STO/USDTieredSTO.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 92a3157df..baba70472 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -620,7 +620,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Now, if there is any remaining USD to be invested, purchase at non-discounted rate if (investedUSD > 0 && tierData.tokenTotal.sub(tierData.mintedTotal) > 0 && - tierData.tokensDiscountPoly == tierData.mintedDiscountPoly + (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly) ) { (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), investedUSD, _tier); spentUSD = spentUSD.add(tierSpentUSD); @@ -655,7 +655,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Now, if there is any remaining USD to be invested, purchase at non-discounted rate if (_investedUSD > 0 && tierData.tokenTotal.sub(tierData.mintedTotal.add(tokensMinted)) > 0 && - tierData.tokensDiscountPoly == tierData.mintedDiscountPoly + (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly) ) { (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTierAmount(tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), _investedUSD); spentUSD = spentUSD.add(tierSpentUSD); From baf0ec962bc64cc2a6b352ece2890dd795f7ee67 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 23 Nov 2018 16:52:04 +0200 Subject: [PATCH 165/582] fixed coverage failure --- test/z_vesting_escrow_wallet.js | 229 +++++++++++++++++--------------- 1 file changed, 125 insertions(+), 104 deletions(-) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index ae2866075..ed5998751 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -1,7 +1,7 @@ import {deployGPMAndVerifyed, deployVestingEscrowWalletAndVerifyed, setUpPolymathNetwork} from "./helpers/createInstances"; import latestTime from "./helpers/latestTime"; import {duration as durationUtil, latestBlock, promisifyLogWatch} from "./helpers/utils"; -import {catchPermission, catchRevert} from "./helpers/exceptions"; +import {catchRevert} from "./helpers/exceptions"; import {increaseTime} from "./helpers/time"; import {encodeModuleCall} from "./helpers/encodeCall"; @@ -273,6 +273,14 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should not be able to deposit -- fail because of permissions check", async () => { + let numberOfTokens = 25000; + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await catchRevert( + I_VestingEscrowWallet.depositTokens(25000, {from: account_beneficiary1}) + ); + }); + it("Should deposit tokens for new vesting schedules", async () => { let numberOfTokens = 25000; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); @@ -287,6 +295,12 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), numberOfTokens); }); + it("Should not be able to withdraw tokens to a treasury -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.sendToTreasury({from: account_beneficiary1}) + ); + }); + it("Should withdraw tokens to a treasury", async () => { let numberOfTokens = 25000; const tx = await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); @@ -300,7 +314,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), 0); }); - it("Should send available tokens to the beneficiary address", async () => { + it("Should not be able to push available tokens -- fail because of permissions check", async () => { let numberOfTokens = 75000; let duration = durationUtil.seconds(30); let frequency = durationUtil.seconds(10); @@ -312,6 +326,19 @@ contract('VestingEscrowWallet', accounts => { await increaseTime(timeShift + frequency); await I_VestingEscrowWallet.updateAll({from: wallet_admin}); + await catchRevert( + I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: account_beneficiary1}) + ); + }); + + it("Should not be able update all schedules -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.updateAll({from: account_beneficiary1}) + ); + }); + + it("Should push available tokens to the beneficiary address", async () => { + let numberOfTokens = 75000; const tx = await I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens / 3); @@ -446,8 +473,6 @@ contract('VestingEscrowWallet', accounts => { } ]; - //TODO add test for checking pushing during revoking - it("Should fail to add vesting schedule to the beneficiary address -- fail because address in invalid", async () => { await catchRevert( I_VestingEscrowWallet.addSchedule(0, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) @@ -502,6 +527,19 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should not be able to add schedule -- fail because of permissions check", async () => { + let numberOfTokens = schedules[0].numberOfTokens; + let duration = schedules[0].duration; + let frequency = schedules[0].frequency; + let startTime = schedules[0].startTime; + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + await catchRevert( + I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: account_beneficiary1}) + ); + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + }); + it("Should add vesting schedule to the beneficiary address", async () => { let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; @@ -551,6 +589,12 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should not be able to modify schedule -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 0, 10000, 4, 1, latestTime() + 100, {from: account_beneficiary1}) + ); + }); + it("Should modify vesting schedule for the beneficiary's address", async () => { let numberOfTokens = schedules[1].numberOfTokens; let duration = schedules[1].duration; @@ -593,6 +637,12 @@ contract('VestingEscrowWallet', accounts => { assert.equal(unassignedTokens.toNumber(), 0); }); + it("Should not be able to revoke schedule -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: account_beneficiary1}) + ); + }); + it("Should revoke vesting schedule from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); @@ -643,6 +693,12 @@ contract('VestingEscrowWallet', accounts => { } }); + it("Should not be able to revoke schedules -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeSchedules(account_beneficiary1, {from: account_beneficiary1}) + ); + }); + it("Should revoke vesting schedule from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, 1, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); @@ -749,6 +805,12 @@ contract('VestingEscrowWallet', accounts => { } ]; + it("Should not be able to add template -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.addTemplate(25000, 4, 1, {from: account_beneficiary1}) + ); + }); + it("Should add 3 Templates", async () => { for (let i = 0; i < schedules.length; i++) { let numberOfTokens = schedules[i].numberOfTokens; @@ -762,6 +824,12 @@ contract('VestingEscrowWallet', accounts => { } }); + it("Should not be able to remove template -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.removeTemplate(1, {from: account_beneficiary1}) + ); + }); + it("Should remove template", async () => { const tx = await I_VestingEscrowWallet.removeTemplate(1, {from: wallet_admin}); @@ -775,6 +843,12 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should not be able to add schedule from template -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 0, latestTime(), {from: account_beneficiary1}) + ); + }); + it("Should add vesting schedule from template", async () => { let numberOfTokens = schedules[2].numberOfTokens; let duration = schedules[2].duration; @@ -814,6 +888,12 @@ contract('VestingEscrowWallet', accounts => { describe("Tests for multi operations", async () => { + it("Should not be able to add schedules to the beneficiaries -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.addScheduleMulti([account_beneficiary1], 10000, 4, 1, latestTime() + 100, {from: account_beneficiary1}) + ); + }); + it("Should add schedules for 3 beneficiaries", async () => { let numberOfTokens = 30000; let duration = durationUtil.weeks(4); @@ -852,6 +932,19 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should not be able to modify schedules for the beneficiaries -- fail because of permissions check", async () => { + let numberOfTokens = 25000; + let duration = durationUtil.seconds(50); + let frequency = durationUtil.seconds(10); + let timeShift = durationUtil.seconds(100); + let startTime = latestTime() + timeShift; + + let indexes = [0, 0, 0]; + await catchRevert( + I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: account_beneficiary1}) + ); + }); + it("Should modify vesting schedule for 3 beneficiary's addresses", async () => { let numberOfTokens = 25000; let duration = durationUtil.seconds(50); @@ -885,6 +978,12 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should not be able to send available tokens to the beneficiaries -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.pushAvailableTokensMulti([account_beneficiary1], {from: account_beneficiary1}) + ); + }); + it("Should send available tokens to the beneficiaries addresses", async () => { await I_VestingEscrowWallet.updateAll({from: wallet_admin}); @@ -905,6 +1004,22 @@ contract('VestingEscrowWallet', accounts => { } }); + it("Should not be able to add schedules from template to the beneficiaries -- fail because of permissions check", async () => { + let numberOfTokens = 18000; + let duration = durationUtil.weeks(3); + let frequency = durationUtil.weeks(1); + let startTime = latestTime() + durationUtil.seconds(100); + + let totalNumberOfTokens = numberOfTokens * 3; + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); + + await catchRevert( + I_VestingEscrowWallet.addScheduleFromTemplateMulti([account_beneficiary1, account_beneficiary2], 0, startTime, {from: account_beneficiary1}) + ); + }); + it("Should add schedules from template for 3 beneficiaries", async () => { let numberOfTokens = 18000; let duration = durationUtil.weeks(3); @@ -933,6 +1048,12 @@ contract('VestingEscrowWallet', accounts => { }); + it("Should not be able to revoke schedules of the beneficiaries -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeSchedulesMulti([account_beneficiary1], {from: account_beneficiary1}) + ); + }); + it("Should revoke vesting schedule from the 3 beneficiary's addresses", async () => { const tx = await I_VestingEscrowWallet.revokeSchedulesMulti(beneficiaries, {from: wallet_admin}); @@ -950,106 +1071,6 @@ contract('VestingEscrowWallet', accounts => { }); - describe("Check permissions", async () => { - - it("Should not be able to deposit", async () => { - await catchPermission( - I_VestingEscrowWallet.depositTokens(25000, {from: account_beneficiary1}) - ); - }); - - it("Should not be able to withdraw tokens to a treasury", async () => { - await catchPermission( - I_VestingEscrowWallet.sendToTreasury({from: account_beneficiary1}) - ); - }); - - it("Should not be able to send available tokens", async () => { - await catchPermission( - I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: account_beneficiary1}) - ); - }); - - it("Should not be able to add template", async () => { - await catchPermission( - I_VestingEscrowWallet.addTemplate(25000, 4, 1, {from: account_beneficiary1}) - ); - }); - - it("Should not be able to remove template", async () => { - await catchPermission( - I_VestingEscrowWallet.removeTemplate(0, {from: account_beneficiary1}) - ); - }); - - it("Should not be able to add schedule", async () => { - await catchPermission( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 10000, 4, 1, latestTime(), {from: account_beneficiary1}) - ); - }); - - it("Should not be able to add schedule from template", async () => { - await catchPermission( - I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 0, latestTime(), {from: account_beneficiary1}) - ); - }); - - it("Should not be able to modify schedule", async () => { - await catchPermission( - I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 0, 10000, 4, 1, latestTime(), {from: account_beneficiary1}) - ); - }); - - it("Should not be able to revoke schedule", async () => { - await catchPermission( - I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: account_beneficiary1}) - ); - }); - - it("Should not be able to revoke schedules", async () => { - await catchPermission( - I_VestingEscrowWallet.revokeSchedules(account_beneficiary1, {from: account_beneficiary1}) - ); - }); - - it("Should not be able to send available tokens to the beneficiaries", async () => { - await catchPermission( - I_VestingEscrowWallet.pushAvailableTokensMulti([account_beneficiary1], {from: account_beneficiary1}) - ); - }); - - it("Should not be able to add schedules to the beneficiaries", async () => { - await catchPermission( - I_VestingEscrowWallet.addScheduleMulti([account_beneficiary1], 10000, 4, 1, latestTime(), {from: account_beneficiary1}) - ); - }); - - it("Should not be able to add schedules from template to the beneficiaries", async () => { - await catchPermission( - I_VestingEscrowWallet.addScheduleFromTemplateMulti([account_beneficiary1], 0, latestTime(), {from: account_beneficiary1}) - ); - }); - - it("Should not be able to revoke schedules of the beneficiaries", async () => { - await catchPermission( - I_VestingEscrowWallet.revokeSchedulesMulti([account_beneficiary1], {from: account_beneficiary1}) - ); - }); - - it("Should not be able to modify schedules for the beneficiaries", async () => { - await catchPermission( - I_VestingEscrowWallet.modifyScheduleMulti([account_beneficiary1], [0], 10000, 4, 1, latestTime(), {from: account_beneficiary1}) - ); - }); - - it("Should not be able update all schedules", async () => { - await catchPermission( - I_VestingEscrowWallet.updateAll({from: account_beneficiary1}) - ); - }); - - }); - }); function checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime) { From bd0f693f4aa271ecf5379ea839bba7fbab5305d5 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 23 Nov 2018 20:53:16 +0200 Subject: [PATCH 166/582] test for factory --- test/z_vesting_escrow_wallet.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index ed5998751..9728f0140 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -263,6 +263,13 @@ contract('VestingEscrowWallet', accounts => { assert.equal(web3.utils.toAscii(tags[1]).replace(/\u0000/g, ""), "Escrow"); }); + it("Should get the instructions of the factory", async () => { + assert.equal( + (await I_VestingEscrowWalletFactory.getInstructions.call()).replace(/\u0000/g, ""), + "Issuer can send tokens to and then select the address that would be able to withdraw them according to their specific vesting schedule." + + ""); + }); + }); describe("Depositing and withdrawing tokens", async () => { From b40a44989a77b2c702d230a5a37eaaa50bfd5547 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Fri, 23 Nov 2018 16:23:11 -0300 Subject: [PATCH 167/582] dev-2.1.0 changes --- CLI/commands/transfer_manager.js | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index c2b299d93..2103304c2 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -117,7 +117,7 @@ async function start_explorer() { let isTranferVerified = await securityToken.methods.verifyTransfer(Issuer.address, transferTo, web3.utils.toWei(transferAmount), web3.utils.fromAscii("")).call(); if (isTranferVerified) { let transferAction = securityToken.methods.transfer(transferTo, web3.utils.toWei(transferAmount)); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice); + let receipt = await common.sendTransaction(transferAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(chalk.green(`${event.from} transferred ${web3.utils.fromWei(event.value)} ${tokenSymbol} to ${event.to} successfully!`)); console.log(`Balance of ${Issuer.address} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call())} ${tokenSymbol}`); @@ -157,7 +157,7 @@ async function forcedTransfers() { case 'Disable controller': if (readlineSync.keyInYNStrict()) { let disableControllerAction = securityToken.methods.disableController(); - await common.sendTransaction(Issuer, disableControllerAction, defaultGasPrice); + await common.sendTransaction(disableControllerAction); console.log(chalk.green(`Forced transfers have been disabled permanently`)); } break; @@ -171,7 +171,7 @@ async function forcedTransfers() { }); let rollerAction = securityToken.methods.setController(controllerAddress); - let setControllerReceipt = await common.sendTransaction(Issuer, setControllerAction, defaultGasPrice); + let setControllerReceipt = await common.sendTransaction(setControllerAction); let setControllerEvent = common.getEventFromLogs(securityToken._jsonInterface, setControllerReceipt.logs, 'SetController'); console.log(chalk.green(`New controller is ${setControllerEvent._newController}`)); break; @@ -201,7 +201,7 @@ async function forcedTransfers() { let data = readlineSync.question('Enter the data to indicate validation: '); let log = readlineSync.question('Enter the data attached to the transfer by controller to emit in event: '); let forceTransferAction = securityToken.methods.forceTransfer(from, to, web3.utils.toWei(amount), web3.utils.asciiToHex(data), web3.utils.asciiToHex(log)); - let forceTransferReceipt = await common.sendTransaction(Issuer, forceTransferAction, defaultGasPrice, 0, 1.5); + let forceTransferReceipt = await common.sendTransaction(forceTransferAction, { factor: 1.5 }); let forceTransferEvent = common.getEventFromLogs(securityToken._jsonInterface, forceTransferReceipt.logs, 'ForceTransfer'); console.log(chalk.green(` ${forceTransferEvent._controller} has successfully forced a transfer of ${web3.utils.fromWei(forceTransferEvent._value)} ${tokenSymbol} from ${forceTransferEvent._from} to ${forceTransferEvent._to} @@ -345,7 +345,7 @@ async function addTransferManagerModule() { } let selectedTMFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.TRANSFER, options[index]); let addModuleAction = securityToken.methods.addModule(selectedTMFactoryAddress, bytes, 0, 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); + let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`Module deployed at address: ${event._module}`); } @@ -410,7 +410,7 @@ async function generalTransferManager() { let expiryTime = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); - let modifyWhitelistReceipt = await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); + let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); let modifyWhitelistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); console.log(chalk.green(`${modifyWhitelistEvent._investor} has been whitelisted sucessfully!`)); break; @@ -449,7 +449,7 @@ async function generalTransferManager() { limitMessage: "Must be a valid address" }); let changeIssuanceAddressAction = currentTransferManager.methods.changeIssuanceAddress(issuanceAddress); - let changeIssuanceAddressReceipt = await common.sendTransaction(Issuer, changeIssuanceAddressAction, defaultGasPrice); + let changeIssuanceAddressReceipt = await common.sendTransaction(changeIssuanceAddressAction); let changeIssuanceAddressEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeIssuanceAddressReceipt.logs, 'ChangeIssuanceAddress'); console.log(chalk.green(`${changeIssuanceAddressEvent._issuanceAddress} is the new address for the issuance!`)); break; @@ -461,14 +461,14 @@ async function generalTransferManager() { limitMessage: "Must be a valid address" }); let changeSigningAddressAction = currentTransferManager.methods.changeSigningAddress(signingAddress); - let changeSigningAddressReceipt = await common.sendTransaction(Issuer, changeSigningAddressAction, defaultGasPrice); + let changeSigningAddressReceipt = await common.sendTransaction(changeSigningAddressAction); let changeSigningAddressEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeSigningAddressReceipt.logs, 'ChangeSigningAddress'); console.log(chalk.green(`${changeSigningAddressEvent._signingAddress} is the new address for the signing!`)); break; case 'Allow all transfers': case 'Disallow all transfers': let changeAllowAllTransfersAction = currentTransferManager.methods.changeAllowAllTransfers(!displayAllowAllTransfers); - let changeAllowAllTransfersReceipt = await common.sendTransaction(Issuer, changeAllowAllTransfersAction, defaultGasPrice); + let changeAllowAllTransfersReceipt = await common.sendTransaction(changeAllowAllTransfersAction); let changeAllowAllTransfersEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllTransfersReceipt.logs, 'AllowAllTransfers'); if (changeAllowAllTransfersEvent._allowAllTransfers) { console.log(chalk.green(`All transfers are allowed!`)); @@ -479,7 +479,7 @@ async function generalTransferManager() { case 'Allow all whitelist transfers': case 'Disallow all whitelist transfers': let changeAllowAllWhitelistTransfersAction = currentTransferManager.methods.changeAllowAllWhitelistTransfers(!displayAllowAllWhitelistTransfers); - let changeAllowAllWhitelistTransfersReceipt = await common.sendTransaction(Issuer, changeAllowAllWhitelistTransfersAction, defaultGasPrice); + let changeAllowAllWhitelistTransfersReceipt = await common.sendTransaction(changeAllowAllWhitelistTransfersAction); let changeAllowAllWhitelistTransfersEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllWhitelistTransfersReceipt.logs, 'AllowAllWhitelistTransfers'); if (changeAllowAllWhitelistTransfersEvent._allowAllWhitelistTransfers) { console.log(chalk.green(`Time locks from whitelist are ignored for transfers!`)); @@ -490,7 +490,7 @@ async function generalTransferManager() { case 'Allow all whitelist issuances': case 'Disallow all whitelist issuances': let changeAllowAllWhitelistIssuancesAction = currentTransferManager.methods.changeAllowAllWhitelistIssuances(!displayAllowAllWhitelistIssuances); - let changeAllowAllWhitelistIssuancesReceipt = await common.sendTransaction(Issuer, changeAllowAllWhitelistIssuancesAction, defaultGasPrice); + let changeAllowAllWhitelistIssuancesReceipt = await common.sendTransaction(changeAllowAllWhitelistIssuancesAction); let changeAllowAllWhitelistIssuancesEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllWhitelistIssuancesReceipt.logs, 'AllowAllWhitelistIssuances'); if (changeAllowAllWhitelistIssuancesEvent._allowAllWhitelistIssuances) { console.log(chalk.green(`Time locks from whitelist are ignored for issuances!`)); @@ -501,7 +501,7 @@ async function generalTransferManager() { case 'Allow all burn transfers': case 'Disallow all burn transfers': let changeAllowAllBurnTransfersAction = currentTransferManager.methods.changeAllowAllBurnTransfers(!displayAllowAllBurnTransfers); - let changeAllowAllBurnTransfersReceipt = await common.sendTransaction(Issuer, changeAllowAllBurnTransfersAction, defaultGasPrice); + let changeAllowAllBurnTransfersReceipt = await common.sendTransaction(changeAllowAllBurnTransfersAction); let changeAllowAllBurnTransfersEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeAllowAllBurnTransfersReceipt.logs, 'AllowAllBurnTransfers'); if (changeAllowAllBurnTransfersEvent._allowAllWhitelistTransfers) { console.log(chalk.green(`To burn tokens is allowed!`)); @@ -553,7 +553,7 @@ async function singleTradeVolumeRestrictionTM() { case 'Allow primary issuance': case 'Disallow primary issuance': let disallowPrimaryIssuanceAction = currentTransferManager.methods.setAllowPrimaryIssuance(!displayAllowPrimaryIssuance); - await common.sendTransaction(Issuer, disallowPrimaryIssuanceAction, defaultGasPrice); + await common.sendTransaction(disallowPrimaryIssuanceAction); break; case 'Add exempted wallet': let walletToExempt = readlineSync.question('Enter the wallet to exempt: ', { @@ -563,7 +563,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be a valid address" }); let addExemptWalletAction = currentTransferManager.methods.addExemptWallet(walletToExempt); - let addExemptWalletReceipt = await common.sendTransaction(Issuer, addExemptWalletAction, defaultGasPrice); + let addExemptWalletReceipt = await common.sendTransaction(addExemptWalletAction); let addExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addExemptWalletReceipt.logs, 'ExemptWalletAdded'); console.log(chalk.green(`${addExemptWalletEvent._wallet} has been exempted sucessfully!`)); break; @@ -575,7 +575,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be a valid address" }); let removeExemptWalletAction = currentTransferManager.methods.removeExemptWallet(exemptedWallet); - let removeExemptWalletReceipt = await common.sendTransaction(Issuer, removeExemptWalletAction, defaultGasPrice); + let removeExemptWalletReceipt = await common.sendTransaction(removeExemptWalletAction); let removeExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeExemptWalletReceipt.logs, 'ExemptWalletRemoved'); console.log(chalk.green(`${removeExemptWalletEvent._wallet} has been removed from exempt wallets sucessfully!`)); break; @@ -587,7 +587,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be greater than zero" })); let changeTransferLimitToTokensAction = currentTransferManager.methods.changeTransferLimitToTokens(newDefaultLimitInTokens); - let changeTransferLimitToTokensReceipt = await common.sendTransaction(Issuer, changeTransferLimitToTokensAction, defaultGasPrice); + let changeTransferLimitToTokensReceipt = await common.sendTransaction(changeTransferLimitToTokensAction); let changeTransferLimitToTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeTransferLimitToTokensEvent._amount)} ${tokenSymbol}`)); @@ -600,7 +600,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be greater than 0 and less than 100" })); let changeTransferLimitToPercentageAction = currentTransferManager.methods.changeTransferLimitToPercentage(newDefaultLimitInPercentage); - let changeTransferLimitToPercentageReceipt = await common.sendTransaction(Issuer, changeTransferLimitToPercentageAction, defaultGasPrice); + let changeTransferLimitToPercentageReceipt = await common.sendTransaction(changeTransferLimitToPercentageAction); let changeTransferLimitToPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeTransferLimitToPercentageEvent._percentage)} %`)); @@ -613,7 +613,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be greater than 0 and less than 100" })); let changeGlobalLimitInPercentageAction = currentTransferManager.methods.changeGlobalLimitInPercentage(defaultLimitInPercentage); - let changeGlobalLimitInPercentageReceipt = await common.sendTransaction(Issuer, changeGlobalLimitInPercentageAction, defaultGasPrice); + let changeGlobalLimitInPercentageReceipt = await common.sendTransaction(changeGlobalLimitInPercentageAction); let changeGlobalLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeGlobalLimitInPercentageEvent._percentage)} %`)); break; @@ -625,7 +625,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be greater than zero" })); let changeGlobalLimitInTokensAction = currentTransferManager.methods.changeGlobalLimitInTokens(defaultLimitInTokens); - let changeGlobalLimitInTokensReceipt = await common.sendTransaction(Issuer, changeGlobalLimitInTokensAction, defaultGasPrice); + let changeGlobalLimitInTokensReceipt = await common.sendTransaction(changeGlobalLimitInTokensAction); let changeGlobalLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeGlobalLimitInTokensEvent._amount)} ${tokenSymbol}`)); break; @@ -643,7 +643,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be greater than 0 and less than 100" })); let setTransferLimitInPercentageAction = currentTransferManager.methods.setTransferLimitInPercentage(percentageAccount, accountLimitInPercentage); - let setTransferLimitInPercentageReceipt = await common.sendTransaction(Issuer, setTransferLimitInPercentageAction, defaultGasPrice); + let setTransferLimitInPercentageReceipt = await common.sendTransaction(setTransferLimitInPercentageAction); let setTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageSet'); console.log(chalk.green(`The transfer limit for ${setTransferLimitInPercentageEvent._wallet} is ${fromWeiPercentage(setTransferLimitInPercentageEvent._percentage)} %`)); break; @@ -661,7 +661,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be greater than zero" })); let setTransferLimitInTokensAction = currentTransferManager.methods.setTransferLimitInTokens(tokensAccount, accountLimitInTokens); - let setTransferLimitInTokensReceipt = await common.sendTransaction(Issuer, setTransferLimitInTokensAction, defaultGasPrice); + let setTransferLimitInTokensReceipt = await common.sendTransaction(setTransferLimitInTokensAction); let setTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensSet'); console.log(chalk.green(`The transfer limit for ${setTransferLimitInTokensEvent._wallet} is ${web3.utils.fromWei(setTransferLimitInTokensEvent._amount)} ${tokenSymbol}`)); break; @@ -673,7 +673,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be a valid address" }); let removeTransferLimitInPercentageAction = currentTransferManager.methods.removeTransferLimitInPercentage(percentageAccountToRemove); - let removeTransferLimitInPercentageReceipt = await common.sendTransaction(Issuer, removeTransferLimitInPercentageAction, defaultGasPrice); + let removeTransferLimitInPercentageReceipt = await common.sendTransaction(removeTransferLimitInPercentageAction); let removeTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageRemoved'); console.log(chalk.green(`The transfer limit for ${removeTransferLimitInPercentageEvent._wallet} is the default limit`)); break; @@ -685,7 +685,7 @@ async function singleTradeVolumeRestrictionTM() { limitMessage: "Must be a valid address" }); let removeTransferLimitInTokensAction = currentTransferManager.methods.removeTransferLimitInTokens(tokensAccountToRemove); - let removeTransferLimitInTokensReceipt = await common.sendTransaction(Issuer, removeTransferLimitInTokensAction, defaultGasPrice); + let removeTransferLimitInTokensReceipt = await common.sendTransaction(removeTransferLimitInTokensAction); let removeTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensRemoved'); console.log(chalk.green(`The transfer limit for ${removeTransferLimitInTokensEvent._wallet} is the default limit`)); break; From 3da80db4f065e7c0fc6f7fd3af2ffc32da33f2d4 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Fri, 23 Nov 2018 17:47:12 -0300 Subject: [PATCH 168/582] General fixes --- CLI/commands/transfer_manager.js | 214 +++++++++++++++++++------------ 1 file changed, 135 insertions(+), 79 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 2103304c2..c4147b073 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -3,6 +3,7 @@ var chalk = require('chalk'); var common = require('./common/common_functions'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); +var gbl = require('./common/global'); // App flow let tokenSymbol; @@ -12,68 +13,31 @@ let network; let currentTransferManager; async function executeApp() { - common.logAsciiBull(); - console.log("*********************************************"); - console.log("Welcome to the Command-Line Transfer Manager."); - console.log("*********************************************"); - console.log("Issuer Account: " + Issuer.address + "\n"); - - await setup(); - try { - await start_explorer(); - } catch (err) { - console.log(err); - return; - } -}; - -async function setup(){ - try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); - process.exit(0); - } -} - -async function start_explorer() { - console.log('\n\x1b[34m%s\x1b[0m',"Transfer Manager - Main Menu"); - - if (!tokenSymbol) - tokenSymbol = readlineSync.question('Enter the token symbol: '); - - let result = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); - if (result == "0x0000000000000000000000000000000000000000") { - tokenSymbol = undefined; - console.log(chalk.red(`Token symbol provided is not a registered Security Token.`)); - } else { - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI,result); + let exit = false; + while (!exit) { + console.log('\n', chalk.blue('Transfer Manager - Main Menu', '\n')); - let tmModules = []; - let tmModuleAddresses = await securityToken.methods.getModulesByType(MODULES_TYPES.TRANSFER).call(); - for (const address of tmModuleAddresses) { - tmModules.push(await securityToken.methods.getModule(address).call()); + let tmModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.TRANSFER); + let nonArchivedModules = tmModules.filter(m => !m.archived); + if (nonArchivedModules.length > 0) { + console.log(`Transfer Manager modules attached:`); + nonArchivedModules.map(m => console.log(`- ${m.name} at ${m.address}`)) + } else { + console.log(`There are no Transfer Manager modules attached`); } - // Show non-archived attached TM modules - console.log(); - console.log(`Transfer Manager modules attached:`); - tmModules.filter(m => m[3] == false).map(m => console.log(` - ${web3.utils.hexToAscii(m[0])} at ${m[1]}`)) - let options = ['Verify transfer', 'Transfer']; let forcedTransferDisabled = await securityToken.methods.controllerDisabled().call(); if (!forcedTransferDisabled) { options.push('Forced transfers'); } - options.push('Config existing modules', 'Add new Transfer Manager module'); + if (nonArchivedModules.length > 0) { + options.push('Config existing modules'); + } + options.push('Add new Transfer Manager module'); - let index = readlineSync.keyInSelect(options, 'Choose one:'); - let optionSelected = index != -1 ? options[index] : 'Cancel'; + let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Exit'}); + let optionSelected = index != -1 ? options[index] : 'Exit'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Verify transfer': @@ -130,18 +94,16 @@ async function start_explorer() { await forcedTransfers(); break; case 'Config existing modules': - await configExistingModules(tmModules); + await configExistingModules(nonArchivedModules); break; case 'Add new Transfer Manager module': await addTransferManagerModule(); break; - case 'Cancel': - process.exit(0); + case 'Exit': + exit = true; + break } } - - //Restart - await start_explorer(); } async function forcedTransfers() { @@ -150,9 +112,9 @@ async function forcedTransfers() { if (controller == Issuer.address) { options.push('Force Transfer'); } - let index = readlineSync.keyInSelect(options, 'What do you want to do?'); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Return'}); + let optionSelected = index != -1 ? options[index] : 'Return'; + console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Disable controller': if (readlineSync.keyInYNStrict()) { @@ -169,8 +131,7 @@ async function forcedTransfers() { limitMessage: "Must be a valid address", defaultInput: Issuer.address }); - let - rollerAction = securityToken.methods.setController(controllerAddress); + let setControllerAction = securityToken.methods.setController(controllerAddress); let setControllerReceipt = await common.sendTransaction(setControllerAction); let setControllerEvent = common.getEventFromLogs(securityToken._jsonInterface, setControllerReceipt.logs, 'SetController'); console.log(chalk.green(`New controller is ${setControllerEvent._newController}`)); @@ -215,16 +176,14 @@ async function forcedTransfers() { } async function configExistingModules(tmModules) { - let nonArchivedModules = tmModules.filter(m => m[3] == false); - - let options = nonArchivedModules.map(m => `${web3.utils.hexToAscii(m[0])} at ${m[1]}`); - let index = readlineSync.keyInSelect(options, 'Which module do you want to config? '); - console.log('Selected:', index != -1 ? options[index] : 'Cancel', '\n'); - let moduleNameSelected = web3.utils.hexToUtf8(nonArchivedModules[index][0]); + let options = tmModules.map(m => `${m.name} at ${m.address}`); + let index = readlineSync.keyInSelect(options, 'Which module do you want to config? ', {cancel: 'Return'}); + console.log('Selected:', index != -1 ? options[index] : 'Return', '\n'); + let moduleNameSelected = tmModules[index].name; switch (moduleNameSelected) { case 'GeneralTransferManager': - currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), nonArchivedModules[index][1]); + currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), nonArchivedModules[index].address); currentTransferManager.setProvider(web3.currentProvider); await generalTransferManager(); break; @@ -253,7 +212,7 @@ async function configExistingModules(tmModules) { )); break; case 'SingleTradeVolumeRestrictionTM': - currentTransferManager = new web3.eth.Contract(abis.singleTradeVolumeRestrictionTM(), nonArchivedModules[index][1]); + currentTransferManager = new web3.eth.Contract(abis.singleTradeVolumeRestrictionTM(), nonArchivedModules[index].address); currentTransferManager.setProvider(web3.currentProvider); await singleTradeVolumeRestrictionTM(); break; @@ -272,7 +231,7 @@ async function addTransferManagerModule() { let options = ['GeneralTransferManager', 'ManualApprovalTransferManager', 'PercentageTransferManager', 'CountTransferManager', 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM']; - let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? '); + let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', {cancel: 'Return'}); if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { let bytes; switch (options[index]) { @@ -312,7 +271,7 @@ async function addTransferManagerModule() { limit: function(input) { return parseInt(input) > 0; }, - limitMessage: "Must be greater than zero" + limitMessage: "Must be greater than 0" })); } let allowPrimaryIssuance = readlineSync.keyInYNStrict(`Do you want to allow all primary issuance transfers? `); @@ -347,13 +306,12 @@ async function addTransferManagerModule() { let addModuleAction = securityToken.methods.addModule(selectedTMFactoryAddress, bytes, 0, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); - console.log(`Module deployed at address: ${event._module}`); + console.log(chalk.green(`Module deployed at address: ${event._module}`)); } } async function generalTransferManager() { - console.log(chalk.blue(`General Transfer Manager at ${currentTransferManager.options.address}`)); - console.log(); + console.log(chalk.blue(`General Transfer Manager at ${currentTransferManager.options.address}`), '\n'); // Show current data let displayIssuanceAddress = await currentTransferManager.methods.issuanceAddress().call(); @@ -715,8 +673,106 @@ function fromWeiPercentage(number) { return web3.utils.fromWei(new web3.utils.BN(number).muln(100)); } +async function getAllModulesByType(type) { + function ModuleInfo(_moduleType, _name, _address, _factoryAddress, _archived, _paused) { + this.name = _name; + this.type = _moduleType; + this.address = _address; + this.factoryAddress = _factoryAddress; + this.archived = _archived; + this.paused = _paused; + } + + let modules = []; + + let allModules = await securityToken.methods.getModulesByType(type).call(); + + for (let i = 0; i < allModules.length; i++) { + let details = await securityToken.methods.getModule(allModules[i]).call(); + let nameTemp = web3.utils.hexToUtf8(details[0]); + let pausedTemp = null; + if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER) { + let abiTemp = JSON.parse(require('fs').readFileSync(`./build/contracts/${nameTemp}.json`).toString()).abi; + let contractTemp = new web3.eth.Contract(abiTemp, details[1]); + pausedTemp = await contractTemp.methods.paused().call(); + } + modules.push(new ModuleInfo(type, nameTemp, details[1], details[2], details[3], pausedTemp)); + } + + return modules; +} + +async function initialize(_tokenSymbol) { + welcome(); + await setup(); + if (typeof _tokenSymbol === 'undefined') { + tokenSymbol = await selectToken(); + } else { + tokenSymbol = _tokenSymbol; + } + let securityTokenAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); + if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { + console.log(chalk.red(`Selected Security Token ${tokenSymbol} does not exist.`)); + process.exit(0); + } + let securityTokenABI = abis.securityToken(); + securityToken = new web3.eth.Contract(securityTokenABI, securityTokenAddress); + securityToken.setProvider(web3.currentProvider); +} + +function welcome() { + common.logAsciiBull(); + console.log("*********************************************"); + console.log("Welcome to the Command-Line Transfer Manager."); + console.log("*********************************************"); + console.log("Issuer Account: " + Issuer.address + "\n"); +} + +async function setup(){ + try { + let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); + let securityTokenRegistryABI = abis.securityTokenRegistry(); + securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); + securityTokenRegistry.setProvider(web3.currentProvider); + } catch (err) { + console.log(err) + console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); + process.exit(0); + } +} + +async function selectToken() { + let result = null; + + let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); + let tokenDataArray = await Promise.all(userTokens.map(async function (t) { + let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); + return {symbol: tokenData[0], address: t}; + })); + let options = tokenDataArray.map(function (t) { + return `${t.symbol} - Deployed at ${t.address}`; + }); + options.push('Enter token symbol manually'); + + let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); + switch (options[index]) { + case 'Enter token symbol manually': + result = readlineSync.question('Enter the token symbol: '); + break; + case 'Exit': + process.exit(); + break; + default: + result = tokenDataArray[index].symbol; + break; + } + + return result; +} + module.exports = { - executeApp: async function(type) { - return executeApp(type); + executeApp: async function(_tokenSymbol) { + await initialize(_tokenSymbol); + return executeApp(); } } \ No newline at end of file From 56261ba69db7edfde26db24db53c96d39bfea5d4 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Fri, 23 Nov 2018 18:17:06 -0300 Subject: [PATCH 169/582] Minor fixes --- CLI/commands/transfer_manager.js | 39 +++++++++++++++++++------------- CLI/polymath-cli.js | 5 ++-- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index c4147b073..8b79cf436 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -183,7 +183,7 @@ async function configExistingModules(tmModules) { switch (moduleNameSelected) { case 'GeneralTransferManager': - currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), nonArchivedModules[index].address); + currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), tmModules[index].address); currentTransferManager.setProvider(web3.currentProvider); await generalTransferManager(); break; @@ -205,17 +205,17 @@ async function configExistingModules(tmModules) { break; case 'CountTransferManager': //await countTransferManager(); + break; + case 'SingleTradeVolumeRestrictionTM': + //currentTransferManager = new web3.eth.Contract(abis.singleTradeVolumeRestrictionTM(), tmModules[index].address); + //currentTransferManager.setProvider(web3.currentProvider); + //await singleTradeVolumeRestrictionTM(); console.log(chalk.red(` ********************************* This option is not yet available. *********************************` )); break; - case 'SingleTradeVolumeRestrictionTM': - currentTransferManager = new web3.eth.Contract(abis.singleTradeVolumeRestrictionTM(), nonArchivedModules[index].address); - currentTransferManager.setProvider(web3.currentProvider); - await singleTradeVolumeRestrictionTM(); - break; case 'LookupVolumeRestrictionTM': //await lookupVolumeRestrictionTM(); console.log(chalk.red(` @@ -228,12 +228,12 @@ async function configExistingModules(tmModules) { } async function addTransferManagerModule() { - let options = ['GeneralTransferManager', 'ManualApprovalTransferManager', 'PercentageTransferManager', - 'CountTransferManager', 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM']; + let options = ['GeneralTransferManager'/*, 'ManualApprovalTransferManager', 'PercentageTransferManager', +'CountTransferManager', 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM'*/]; let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', {cancel: 'Return'}); if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { - let bytes; + let bytes = web3.utils.fromAscii('', 16); switch (options[index]) { case 'ManualApprovalTransferManager': console.log(chalk.red(` @@ -257,6 +257,7 @@ async function addTransferManagerModule() { )); break; case 'SingleTradeVolumeRestrictionTM': + /* let isTransferLimitInPercentage = !!readlineSync.keyInSelect(['In tokens', 'In percentage'], 'How do you want to set the transfer limit? ', {cancel: false}); let globalTransferLimitInPercentageOrToken; if (isTransferLimitInPercentage) { @@ -291,6 +292,12 @@ async function addTransferManagerModule() { } ] }, [isTransferLimitInPercentage, globalTransferLimitInPercentageOrToken, allowPrimaryIssuance]); + */ + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************` + )); break; case 'LookupVolumeRestrictionTM': console.log(chalk.red(` @@ -298,11 +305,9 @@ async function addTransferManagerModule() { This option is not yet available. *********************************` )); - break; - default: - bytes = web3.utils.fromAscii('', 16); + break; } - let selectedTMFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.TRANSFER, options[index]); + let selectedTMFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.TRANSFER, options[index]); let addModuleAction = securityToken.methods.addModule(selectedTMFactoryAddress, bytes, 0, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); @@ -363,9 +368,11 @@ async function generalTransferManager() { }, limitMessage: "Must be a valid address" }); - let fromTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); - let toTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); - let expiryTime = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); + let now = Math.floor(Date.now() / 1000); + let fromTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens (now = ${now}): `, {defaultInput: now}); + let toTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (now = ${now}): `, {defaultInput: now}); + let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); + let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated (after that investor need to do re-KYC) (1 hour from now = ${oneHourFromNow}): `, {defaultInput: oneHourFromNow}); let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index f2248b25a..fde89935d 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -119,10 +119,11 @@ program program .command('transfer_manager') .alias('tm') + .option('-t, --securityToken ', 'Selects a ST to manage transfer modules') .description('Runs transfer_manager') - .action(async function() { + .action(async function(cmd) { await gbl.initialize(program.remoteNode); - await transfer_manager.executeApp(); + await transfer_manager.executeApp(cmd.securityToken); }); program From 3455d948bc77345c9b2df03a8505412ca2457b61 Mon Sep 17 00:00:00 2001 From: satyam Date: Sat, 24 Nov 2018 03:10:59 +0530 Subject: [PATCH 170/582] global + individual check added --- .../TransferManager/VolumeRestrictionTM.sol | 339 ++++++++++-------- test/z_volume_restriction_tm.js | 96 +++-- 2 files changed, 249 insertions(+), 186 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index e9f2c9d9c..b1e80875c 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -13,6 +13,8 @@ contract VolumeRestrictionTM is ITransferManager { enum RestrictionType { Fixed, Variable } + enum Scope { Global, Individual } + struct VolumeRestriction { uint256 allowedTokens; uint256 allowedPercentageOfTokens; @@ -25,22 +27,19 @@ contract VolumeRestrictionTM is ITransferManager { struct BucketDetails { uint256[] timestamps; uint256 sumOfLastPeriod; - uint256 daysCovered; - uint256 latestTimestampIndex; } - uint256 globalSumOfLastPeriod; - VolumeRestriction globalRestriction; mapping(address => VolumeRestriction) public individualRestriction; - // Storing _from => day's timestamp => total amount transact in a day + // Storing _from => day's timestamp => total amount transact in a day --individual mapping(address => mapping(uint256 => uint256)) internal bucket; // Storing the information that used to validate the transaction mapping(address => BucketDetails) internal bucketToUser; // List of wallets that are exempted from all the restrictions applied by the this contract mapping(address => bool) public exemptList; - mapping(address => BucketDetails) internal globalBucketToUser; + + address[] globalUsers; event ChangedExemptWalletList(address indexed _wallet, bool _change); @@ -110,153 +109,6 @@ contract VolumeRestrictionTM is ITransferManager { } } - function _checkRestriction(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { - if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { - BucketDetails memory _bucketDetails = bucketToUser[_from]; - uint256 _diffDays; - if (_bucketDetails.timestamps[0] == 0) { - _diffDays = BokkyPooBahsDateTimeLibrary.diffDays(individualRestriction[_from].startTime, now); - return _individualBucketCheck( - individualRestriction[_from].startTime, - _diffDays, - _from, - individualRestriction[_from], - _amount, - _isTransfer - ); - } else { - _diffDays = BokkyPooBahsDateTimeLibrary.diffDays(_bucketDetails.timestamps[_bucketDetails.latestTimestampIndex], now); - return _individualBucketCheck( - _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex], - _diffDays, - _from, - individualRestriction[_from], - _amount, - _isTransfer - ); - } - } else if (now <= globalRestriction.endTime && now >= globalRestriction.startTime) { - // TODO: Add the global bucket check - // Algorithm should be loop to all(who doesn't have the individual restriction) the individualBucketCheck - // and get the amount that was transacted till now. - // Calculate the sum of that amount + new txn amount and compare with allowed percentage or fixed amount - // amount of tokens - _globalBucketCheck(); - } else { - return Result.NA; - } - } - - function _globalBucketCheck() internal { - // TODO: Definition pending - } - - function _individualBucketCheck( - uint256 _fromTime, - uint256 _diffDays, - address _from, - VolumeRestriction _restriction, - uint256 _amount, - bool _isTransfer - ) - internal - returns (Result) - { - BucketDetails memory _bucketDetails = bucketToUser[_from]; - uint256[] memory passedTimestamps = new uint256[](_diffDays); - uint256[] memory counters = new uint256[](_diffDays); - // using the existing memory variable instead of creating new one (avoiding stack too deep error) - // uint256 counter = _bucketDetails.latestTimestampIndex; - uint256 i = 0; - if (_diffDays != 0) { - for (i = 0; i < _diffDays; i++) { - // calculating the timestamp that will used as an index of the next bucket - // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... - // where T1,T2,T3 are timestamps having 24 hrs difference - _fromTime = _fromTime.add(1 days); - // Creating the round array - if (_bucketDetails.latestTimestampIndex == _restriction.rollingPeriodInDays -1) { - _bucketDetails.latestTimestampIndex = 0; - } - // This condition is to check whether the first rolling period is covered or not - // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting - // the earlier value at that index - if (_bucketDetails.daysCovered < _restriction.rollingPeriodInDays -1) { - _bucketDetails.daysCovered++; - } else { - // temporarily storing the previous value of timestamp at the "_bucketDetails.latestTimestampIndex" index - uint256 _previousTimestamp = _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex]; - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.sub(bucket[_from][_previousTimestamp]); - } - // Adding the last amount that is transacted on the _fromTime - //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); - // increasing the value of latest timestamp Index - _bucketDetails.latestTimestampIndex++; - // Storing the passed timestamp in the array - _bucketDetails.timestamps[_bucketDetails.latestTimestampIndex] = _fromTime; - // Storing all those timestamps whose total transacted value is 0 - passedTimestamps[i] = _fromTime; - counters[i] = _bucketDetails.latestTimestampIndex; - } - } - if (_checkValidAmountToTransact(_bucketDetails.sumOfLastPeriod, _amount, _restriction)) { - if (_isTransfer) { - _updateStorage(passedTimestamps, counters, _from, _fromTime, _diffDays, _amount, _bucketDetails); - } - return Result.NA; - } - - return Result.INVALID; - - } - event LogA(uint256 _sum, uint256 _amount, uint256 _allowedAmount); - function _updateStorage(uint256[] passedTimestamps, uint256[] counters, address _from, uint256 _fromTime, uint256 _diffDays, uint256 _amount, BucketDetails _bucketDetails) internal { - if (_diffDays != 0) { - for (uint256 i = 0; i < passedTimestamps.length; i++) { - // Assigning the sum of transacted amount on the passed day - bucket[_from][passedTimestamps[i]] = 0; - // To save gas by not assigning a memory timestamp array to storage timestamp array. - bucketToUser[_from].timestamps[counters[i]] = _bucketDetails.timestamps[counters[i]]; - } - bucketToUser[_from].daysCovered = _bucketDetails.daysCovered; - // Storing the index of the latest timestamp from the array of timestamp that is being processed - bucketToUser[_from].latestTimestampIndex = _bucketDetails.latestTimestampIndex; - } - // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) - if (_bucketDetails.timestamps[0] == 0) { - bucketToUser[_from].timestamps[_bucketDetails.latestTimestampIndex] = _fromTime; - } - bucketToUser[_from].sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(_amount); - // Re-using the local variable to avoid stack too deep error - _fromTime = bucketToUser[_from].timestamps[_bucketDetails.latestTimestampIndex]; - bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); - } - - function _checkValidAmountToTransact( - uint256 _sumOfLastPeriod, - uint256 _amountToTransact, - VolumeRestriction _restriction - ) - internal - view - returns (bool) - { - uint256 _allowedAmount = 0; - if (_restriction.typeOfRestriction == RestrictionType.Variable) { - _allowedAmount = (_restriction.allowedTokens.mul(ISecurityToken(securityToken).totalSupply()))/ 10 ** 18; - } else { - _allowedAmount = _restriction.allowedTokens; - } - emit LogA(_sumOfLastPeriod, _amountToTransact, _allowedAmount); - // Validation on the amount to transact - if (_allowedAmount >= _sumOfLastPeriod.add(_amountToTransact)) { - return true; - } else { - return false; - } - } - /** * @notice Add/Remove wallet address from the exempt list * @param _wallet Ethereum wallet/contract address that need to be exempted @@ -491,6 +343,179 @@ contract VolumeRestrictionTM is ITransferManager { ); } + function _checkRestriction(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + uint256 _fromTimestamp; + BucketDetails memory _bucketDetails = bucketToUser[_from]; + if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { + if (_bucketDetails.timestamps.length == 0) { + _fromTimestamp = individualRestriction[_from].startTime; + } else { + _fromTimestamp = _bucketDetails.timestamps[_bucketDetails.timestamps.length - 1]; + } + return _bucketCheck( + _fromTimestamp, + BokkyPooBahsDateTimeLibrary.diffDays(_fromTimestamp, now), + _from, + _amount, + _isTransfer, + Scope.Individual, + individualRestriction[_from] + ); + } else if (now <= globalRestriction.endTime && now >= globalRestriction.startTime) { + // Algorithm should be loop to all(who doesn't have the individual restriction) the individualBucketCheck + // and get the amount that was transacted till now. + // Calculate the sum of that amount + new txn amount and compare with allowed percentage or fixed amount + // amount of tokens + if (_bucketDetails.timestamps.length == 0) { + _fromTimestamp = globalRestriction.startTime; + } else { + _fromTimestamp = _bucketDetails.timestamps[_bucketDetails.timestamps.length - 1]; + } + return _bucketCheck( + _fromTimestamp, + BokkyPooBahsDateTimeLibrary.diffDays(_fromTimestamp, now), + _from, + _amount, + _isTransfer, + Scope.Global, + globalRestriction + ); + } else { + return Result.NA; + } + } + + function _bucketCheck( + uint256 _fromTime, + uint256 _diffDays, + address _from, + uint256 _amount, + bool _isTransfer, + Scope _scope, + VolumeRestriction _restriction + ) + internal + returns (Result) + { + BucketDetails memory _bucketDetails = bucketToUser[_from]; + uint256[] memory passedTimestamps = new uint256[](_diffDays); + // using the existing memory variable instead of creating new one (avoiding stack too deep error) + uint256 counter = _bucketDetails.timestamps.length; + uint256 i = 0; + if (_diffDays != 0) { + for (i = 0; i < _diffDays; i++) { + // calculating the timestamp that will used as an index of the next bucket + // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... + // where T1,T2,T3 are timestamps having 24 hrs difference + _fromTime = _fromTime.add(1 days); + + // This condition is to check whether the first rolling period is covered or not + // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting + // the earlier value at that index + if (counter >= _restriction.rollingPeriodInDays) { + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. + sub(bucket[_from][_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); + } + + // Adding the last amount that is transacted on the _fromTime + //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); + // Storing all those timestamps whose total transacted value is 0 + passedTimestamps[i] = _fromTime; + counter++; + } + } + if (_scope == Scope.Global) { + i = _getTotalSumOfLastPeriod(_bucketDetails.sumOfLastPeriod, _from); + } else { + i = _bucketDetails.sumOfLastPeriod; + } + if (_checkValidAmountToTransact(i, _amount, _restriction)) { + if (_isTransfer) { + _updateStorage( + passedTimestamps, + _from, + _fromTime, + _amount, + _diffDays, + _scope, + _bucketDetails.sumOfLastPeriod + ); + } + return Result.NA; + } + return Result.INVALID; + } + + function _getTotalSumOfLastPeriod(uint256 _sumOfuser, address _from) internal view returns(uint256 globalSumOfLastPeriod) { + for (uint256 i = 0; i < globalUsers.length; i++) { + if (globalUsers[i] == _from) { + globalSumOfLastPeriod.add(_sumOfuser); + } else { + uint256 _latestTimestampIndex = bucketToUser[globalUsers[i]].timestamps.length - 1; + uint256 _latestTimestamp = bucketToUser[globalUsers[i]].timestamps[_latestTimestampIndex]; + if (BokkyPooBahsDateTimeLibrary.diffDays(_latestTimestamp, now) < globalRestriction.rollingPeriodInDays) + globalSumOfLastPeriod.add(bucketToUser[globalUsers[i]].sumOfLastPeriod); + } + } + } + + function _checkValidAmountToTransact( + uint256 _sumOfLastPeriod, + uint256 _amountToTransact, + VolumeRestriction _restriction + ) + internal + view + returns (bool) + { + uint256 _allowedAmount = 0; + if (_restriction.typeOfRestriction == RestrictionType.Variable) { + _allowedAmount = (_restriction.allowedPercentageOfTokens.mul(ISecurityToken(securityToken).totalSupply()))/ 10 ** 18; + } else { + _allowedAmount = _restriction.allowedTokens; + } + // Validation on the amount to transact + if (_allowedAmount >= _sumOfLastPeriod.add(_amountToTransact)) { + return true; + } else { + return false; + } + } + + function _updateStorage( + uint256[] passedTimestamps, + address _from, + uint256 _fromTime, + uint256 _amount, + uint256 _diffDays, + Scope _scope, + uint256 _sumOfLastPeriod + ) + internal + { + if (bucketToUser[_from].timestamps.length == 0 && _scope == Scope.Global) { + globalUsers.push(_from); + } + if (_diffDays != 0) { + for (uint256 i = 0; i < passedTimestamps.length; i++) { + // Assigning the sum of transacted amount on the passed day + // bucket[_from][passedTimestamps[i]] = 0; + // To save gas by not assigning a memory timestamp array to storage timestamp array. + bucketToUser[_from].timestamps.push(passedTimestamps[i]); + } + } + // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) + if (bucketToUser[_from].timestamps.length == 0) { + bucketToUser[_from].timestamps.push(_fromTime); + } + bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + + // Re-using the local variable to avoid stack too deep error + _fromTime = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; + bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); + } + function _modifyIndividualRestriction( address _holder, uint256 _allowedTokens, @@ -513,7 +538,6 @@ contract VolumeRestrictionTM is ITransferManager { _endTime, RestrictionType(_restrictionType) ); - bucketToUser[_holder] = BucketDetails(new uint256[](_rollingPeriodInDays), 0, 0, 0); emit ModifyIndividualRestriction( _holder, _allowedTokens, @@ -551,7 +575,6 @@ contract VolumeRestrictionTM is ITransferManager { _endTime, RestrictionType(_restrictionType) ); - bucketToUser[_holder] = BucketDetails(new uint256[](_rollingPeriodInDays), 0, 0, 0); emit AddNewIndividualRestriction( _holder, _allowedTokens, @@ -609,12 +632,10 @@ contract VolumeRestrictionTM is ITransferManager { ); } - function getBucketDetailsToUser(address _user) external view returns(uint256[], uint256, uint256, uint256) { + function getBucketDetailsToUser(address _user) external view returns(uint256[], uint256) { return( bucketToUser[_user].timestamps, - bucketToUser[_user].sumOfLastPeriod, - bucketToUser[_user].daysCovered, - bucketToUser[_user].latestTimestampIndex + bucketToUser[_user].sumOfLastPeriod ); } diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js index 83f6add28..138068b8f 100644 --- a/test/z_volume_restriction_tm.js +++ b/test/z_volume_restriction_tm.js @@ -68,6 +68,8 @@ contract('VolumeRestrictionTransferManager', accounts => { const transferManagerKey = 2; const stoKey = 3; + let tempAmount = new BigNumber(0); + // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -245,13 +247,13 @@ contract('VolumeRestrictionTransferManager', accounts => { for (let i = 0; i < data[0].length; i++) { console.log(` Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} `); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Days Covered : ${data[2].toNumber()} - Last Timestamp Index : ${data[3].toNumber()} + Last Timestamp Index : ${data[0].length -1} `); }) @@ -267,13 +269,13 @@ contract('VolumeRestrictionTransferManager', accounts => { for (let i = 0; i < data[0].length; i++) { console.log(` Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} `); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Days Covered : ${data[2].toNumber()} - Last Timestamp Index : ${data[3].toNumber()} + Last Timestamp Index : ${data[0].length -1} `); }); @@ -297,13 +299,13 @@ contract('VolumeRestrictionTransferManager', accounts => { for (let i = 0; i < data[0].length; i++) { console.log(` Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} `); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Days Covered : ${data[2].toNumber()} - Last Timestamp Index : ${data[3].toNumber()} + Last Timestamp Index : ${data[0].length - 1} `); }); @@ -314,15 +316,15 @@ contract('VolumeRestrictionTransferManager', accounts => { for (let i = 0; i < data[0].length; i++) { console.log(` Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} `); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Days Covered : ${data[2].toNumber()} - Last Timestamp Index : ${data[3].toNumber()} + Last Timestamp Index : ${data[0].length - 1} `); - assert.equal(data[2].toNumber(), 2); + assert.equal(data[0].length - 1, 2); }); it("Should successfully transfer the tokens in the last day of rolling period", async() => { @@ -344,13 +346,13 @@ contract('VolumeRestrictionTransferManager', accounts => { for (let i = 0; i < data[0].length; i++) { console.log(` Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} `); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Days Covered : ${data[2].toNumber()} - Last Timestamp Index : ${data[3].toNumber()} + Last Timestamp Index : ${data[0].length - 1} `); }); @@ -372,35 +374,75 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should transfer the tokens in a new rolling period", async() => { let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + let firstDayAmount; + tempAmount = new BigNumber(0); for (let i = 0; i < oldData[0].length; i++) { console.log(` Timestamps array index ${i}: ${oldData[0][i].toNumber()} - Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])) + .dividedBy(new BigNumber(10).pow(18))} `); + if (i != 2) { + firstDayAmount = await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][0]); + tempAmount = tempAmount.plus(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])); + } } + console.log(` SumOfLastPeriod : ${web3.utils.fromWei((oldData[1].toNumber()).toString())} - Days Covered : ${oldData[2].toNumber()} - Last Timestamp Index : ${oldData[3].toNumber()} + Last Timestamp Index : ${oldData[0].length -1} `); + + let currentDayAmount = firstDayAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))); + let tx = await I_SecurityToken.transfer(account_investor3, currentDayAmount, {from: account_investor1}); + tempAmount = tempAmount.minus(currentDayAmount); - let tx = await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(".3"), {from: account_investor1}); console.log('\n'); - console.log(tx.logs); let newData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - for (let i = 0; i < newData[0].length; i++) { + for (let i = 2; i < newData[0].length; i++) { console.log(` Timestamps array index ${i}: ${newData[0][i].toNumber()} - Total Trade till now: ${await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) + .dividedBy(new BigNumber(10).pow(18))} `); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((newData[1].toNumber()).toString())} - Days Covered : ${newData[2].toNumber()} - Last Timestamp Index : ${newData[3].toNumber()} + Last Timestamp Index : ${newData[0].length -1} + `); + assert.notEqual(oldData[0][0].toNumber(), newData[0][3].toNumber()); + assert.notEqual(oldData[0][1].toNumber(), newData[0][4].toNumber()); + }); + + it("Should transfer the more tokens on the same day", async() => { + // Check the balance of the investors + let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + console.log(tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber()); + await I_SecurityToken.transfer(account_investor3, tempAmount, {from: account_investor1}); + + // Check the balance of the investors + let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.closeTo( + (balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), + tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(), + 0.01 + ); + + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 2; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length -1} `); - assert.notEqual(oldData[0][0].toNumber(), newData[0][0].toNumber()); - assert.notEqual(oldData[0][1].toNumber(), newData[0][1].toNumber()); }); + + }); }); \ No newline at end of file From 8d462aaa820008ae617f28bde43a63123b474175 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Sat, 24 Nov 2018 13:00:15 -0300 Subject: [PATCH 171/582] Revert "STRV TM added to migration script" This reverts commit d7e97bbaec22a7af6f99f5dbe6449d28fd742917. --- migrations/2_deploy_contracts.js | 51 +++++++++++--------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 0809dcb08..694fdf03e 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -2,7 +2,6 @@ const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') -const SingleTradeVolumeRestrictionTMFactory = artifacts.require('./SingleTradeVolumeRestrictionTMFactory.sol') const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') @@ -158,10 +157,6 @@ module.exports = function (deployer, network, accounts) { // D) Deploy the CountTransferManagerFactory Contract (Factory used to generate the CountTransferManager contract use // to track the counts of the investors of the security token) return deployer.deploy(CountTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // D) Deploy the SingleTradeVolumeRestrictionTMFactory Contract (Factory used to generate the SingleTradeVolumeRestrictionTM contract use - // to impose volume restriction on a single trade that the investors could do for a particular security token) - return deployer.deploy(SingleTradeVolumeRestrictionTMFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // D) Deploy the PercentageTransferManagerFactory Contract (Factory used to generate the PercentageTransferManager contract use // to track the percentage of investment the investors could do for a particular security token) @@ -201,10 +196,6 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // Update all addresses into the registry contract by calling the function updateFromregistry return moduleRegistry.updateFromRegistry({from: PolymathAccount}); - }).then(() => { - // D) Register the SingleTradeVolumeRestrictionTMFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the SingleTradeVolumeRestrictionTM contract. - return moduleRegistry.registerModule(SingleTradeVolumeRestrictionTMFactory.address, {from: PolymathAccount}); }).then(() => { // D) Register the PercentageTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the PercentageTransferManager contract. @@ -248,11 +239,6 @@ module.exports = function (deployer, network, accounts) { // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(PercentageTransferManagerFactory.address, true, {from: PolymathAccount}); - }).then(() => { - // G) Once the SingleTradeVolumeRestrictionTMFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(SingleTradeVolumeRestrictionTMFactory.address, true, {from: PolymathAccount}); }).then(() => { // G) Once the GeneralPermissionManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. @@ -308,28 +294,27 @@ module.exports = function (deployer, network, accounts) { console.log('\n'); console.log(` ----------------------- Polymath Network Smart Contracts: ----------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistry (Proxy): ${SecurityTokenRegistryProxy.address} - ModuleRegistry (Proxy): ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistry (Proxy): ${SecurityTokenRegistryProxy.address} + ModuleRegistry (Proxy): ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} + + ETHOracle: ${ETHOracle} + POLYOracle: ${POLYOracle} - ETHOracle: ${ETHOracle} - POLYOracle: ${POLYOracle} + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - CappedSTOFactory: ${CappedSTOFactory.address} - USDTieredSTOFactory: ${USDTieredSTOFactory.address} - USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} + CappedSTOFactory: ${CappedSTOFactory.address} + USDTieredSTOFactory: ${USDTieredSTOFactory.address} + USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} - CountTransferManagerFactory: ${CountTransferManagerFactory.address} - PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} - ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} - SingleTradeVolumeRestrictionTMFactory: ${SingleTradeVolumeRestrictionTMFactory.address} - EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} - ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} + CountTransferManagerFactory: ${CountTransferManagerFactory.address} + PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} + ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} + EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} + ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} --------------------------------------------------------------------------------- `); console.log('\n'); From 4c0f8de9c3fafd8f5ed6e580dc903ff99ebee95d Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sat, 24 Nov 2018 17:11:10 +0000 Subject: [PATCH 172/582] WIP --- .../GeneralTransferManager.sol | 83 +++++++++++-------- test/h_general_transfer_manager.js | 38 ++++----- test/helpers/signData.js | 2 +- truffle-config.js | 2 +- 4 files changed, 71 insertions(+), 54 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 814d54d7b..eea89494d 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -21,17 +21,30 @@ contract GeneralTransferManager is ITransferManager { //from and to timestamps that an investor can send / receive tokens respectively struct TimeRestriction { - uint256 fromTime; - uint256 toTime; - uint256 expiryTime; - bool canBuyFromSTO; + uint64 fromTime; + uint64 toTime; + uint64 expiryTime; + uint8 canBuyFromSTO; + uint8 added; } + // Allows all TimeRestrictions to be offset + struct Offset { + uint64 offset; + uint8 isForward; + } + + // Offset to be applied to all timings (except KYC expiry) + Offset public offset; + + // List of all addresses that have been added to the GTM at some point + address[] public investors; + // An address can only send / receive tokens once their corresponding uint256 > block.number // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) mapping (address => TimeRestriction) public whitelist; // Map of used nonces by customer - mapping(address => mapping(uint256 => bool)) public nonceMap; + mapping(address => mapping(uint256 => bool)) public nonceMap; //If true, there are no transfer restrictions, for any addresses bool public allowAllTransfers = false; @@ -59,10 +72,10 @@ contract GeneralTransferManager is ITransferManager { address _investor, uint256 _dateAdded, address _addedBy, - uint256 _fromTime, - uint256 _toTime, - uint256 _expiryTime, - bool _canBuyFromSTO + uint64 _fromTime, + uint64 _toTime, + uint64 _expiryTime, + uint8 _canBuyFromSTO ); /** @@ -169,15 +182,15 @@ contract GeneralTransferManager is ITransferManager { return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA; } if (allowAllWhitelistIssuances && _from == issuanceAddress) { - if (!whitelist[_to].canBuyFromSTO && _isSTOAttached()) { + if ((whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { return Result.NA; } return _onWhitelist(_to) ? Result.VALID : Result.NA; } //Anyone on the whitelist can transfer provided the blocknumber is large enough /*solium-disable-next-line security/no-block-members*/ - return ((_onWhitelist(_from) && whitelist[_from].fromTime <= now) && - (_onWhitelist(_to) && whitelist[_to].toTime <= now)) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return ((_onWhitelist(_from) && whitelist[_from].fromTime <= uint64(now)) && + (_onWhitelist(_to) && whitelist[_to].toTime <= uint64(now))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -192,16 +205,18 @@ contract GeneralTransferManager is ITransferManager { */ function modifyWhitelist( address _investor, - uint256 _fromTime, - uint256 _toTime, - uint256 _expiryTime, - bool _canBuyFromSTO + uint64 _fromTime, + uint64 _toTime, + uint64 _expiryTime, + uint8 _canBuyFromSTO ) public withPerm(WHITELIST) { - //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); + if (whitelist[_investor].added == uint8(0)) { + investors.push(_investor); + } + whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO, uint8(1)); /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -216,10 +231,10 @@ contract GeneralTransferManager is ITransferManager { */ function modifyWhitelistMulti( address[] _investors, - uint256[] _fromTimes, - uint256[] _toTimes, - uint256[] _expiryTimes, - bool[] _canBuyFromSTO + uint64[] _fromTimes, + uint64[] _toTimes, + uint64[] _expiryTimes, + uint8[] _canBuyFromSTO ) public withPerm(WHITELIST) { require(_investors.length == _fromTimes.length, "Mismatched input lengths"); require(_fromTimes.length == _toTimes.length, "Mismatched input lengths"); @@ -246,29 +261,31 @@ contract GeneralTransferManager is ITransferManager { */ function modifyWhitelistSigned( address _investor, - uint256 _fromTime, - uint256 _toTime, - uint256 _expiryTime, - bool _canBuyFromSTO, - uint256 _validFrom, - uint256 _validTo, + uint64 _fromTime, + uint64 _toTime, + uint64 _expiryTime, + uint8 _canBuyFromSTO, + uint64 _validFrom, + uint64 _validTo, uint256 _nonce, uint8 _v, bytes32 _r, bytes32 _s ) public { /*solium-disable-next-line security/no-block-members*/ - require(_validFrom <= now, "ValidFrom is too early"); + require(_validFrom <= uint64(now), "ValidFrom is too early"); /*solium-disable-next-line security/no-block-members*/ - require(_validTo >= now, "ValidTo is too late"); + require(_validTo >= uint64(now), "ValidTo is too late"); require(!nonceMap[_investor][_nonce], "Already used signature"); nonceMap[_investor][_nonce] = true; bytes32 hash = keccak256( abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) ); _checkSig(hash, _v, _r, _s); - //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); + if (whitelist[_investor].added == uint8(0)) { + investors.push(_investor); + } + whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO, uint8(1)); /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -290,7 +307,7 @@ contract GeneralTransferManager is ITransferManager { */ function _onWhitelist(address _investor) internal view returns(bool) { return (((whitelist[_investor].fromTime != 0) || (whitelist[_investor].toTime != 0)) && - (whitelist[_investor].expiryTime >= now)); /*solium-disable-line security/no-block-members*/ + (whitelist[_investor].expiryTime >= uint64(now))); /*solium-disable-line security/no-block-members*/ } /** diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 3e060c288..b7f14ed31 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -150,7 +150,7 @@ contract("GeneralTransferManager", accounts => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); let _blockNo = latestBlock(); let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - + console.log(JSON.stringify(tx)); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); @@ -187,7 +187,7 @@ contract("GeneralTransferManager", accounts => { [latestTime() + duration.days(30), latestTime() + duration.days(30)], [latestTime() + duration.days(90), latestTime() + duration.days(90)], [latestTime() + duration.years(1), latestTime() + duration.years(1)], - [false, false], + [0, 0], { from: account_issuer, gas: 6000000 @@ -291,7 +291,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -320,7 +320,7 @@ contract("GeneralTransferManager", accounts => { it("Should fail in buying the tokens from the STO -- because amount is 0", async() => { await catchRevert( I_DummySTO.generateTokens(account_investor1, 0, { from: token_owner }) - ); + ); }); it("Should fail in buying the tokens from the STO -- because STO is paused", async() => { @@ -359,7 +359,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -376,7 +376,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -403,7 +403,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -420,7 +420,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -447,7 +447,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -464,7 +464,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -491,7 +491,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - true, + 1, validFrom, validTo, nonce, @@ -507,7 +507,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - true, + 1, validFrom, validTo, nonce, @@ -547,7 +547,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - true, + 1, validFrom, validTo, nonce, @@ -563,7 +563,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - true, + 1, validFrom, validTo, nonce, @@ -670,7 +670,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [true, true], + [1, 1], { from: account_delegate, gas: 6000000 @@ -690,7 +690,7 @@ contract("GeneralTransferManager", accounts => { [fromTime], [toTime, toTime], [expiryTime, expiryTime], - [true, true], + [1, 1], { from: account_delegate, gas: 6000000 @@ -710,7 +710,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime], [expiryTime, expiryTime], - [true, true], + [1, 1], { from: account_delegate, gas: 6000000 @@ -730,7 +730,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime], - [true, true], + [1, 1], { from: account_delegate, gas: 6000000 @@ -749,7 +749,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [true, true], + [1, 1], { from: token_owner, gas: 6000000 diff --git a/test/helpers/signData.js b/test/helpers/signData.js index ea7476cc3..2e5c1ad61 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -6,7 +6,7 @@ const ethUtil = require("ethereumjs-util"); function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce, pk) { let packedData = utils .solidityKeccak256( - ["address", "address", "uint256", "uint256", "uint256", "bool", "uint256", "uint256", "uint256"], + ["address", "address", "uint64", "uint64", "uint64", "uint8", "uint64", "uint64", "uint256"], [tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce] ) .slice(2); diff --git a/truffle-config.js b/truffle-config.js index c993327ea..2a84351bd 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -11,7 +11,7 @@ module.exports = { host: 'localhost', port: 8545, network_id: '*', // Match any network id - gas: 7900000, + gas: 9000000, }, mainnet: { host: 'localhost', From 191b788617ae16719267cd0d2dd557bacdb7b29f Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sat, 24 Nov 2018 21:07:49 +0000 Subject: [PATCH 173/582] WIP --- contracts/modules/Module.sol | 19 ++---- contracts/modules/ModuleStorage.sol | 30 ++++++++++ .../GeneralTransferManager.sol | 59 +------------------ .../GeneralTransferManagerFactory.sol | 9 ++- .../GeneralTransferManagerStorage.sol | 55 +++++++++++++++++ .../proxy/GeneralTransferManagerProxy.sol | 47 +++++++++++++++ migrations/2_deploy_contracts.js | 8 ++- test/helpers/createInstances.js | 20 ++++++- 8 files changed, 169 insertions(+), 78 deletions(-) create mode 100644 contracts/modules/ModuleStorage.sol create mode 100644 contracts/modules/TransferManager/GeneralTransferManagerStorage.sol create mode 100644 contracts/proxy/GeneralTransferManagerProxy.sol diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index aa3e6d865..1566a3428 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -2,32 +2,23 @@ pragma solidity ^0.4.24; import "../interfaces/IModule.sol"; import "../interfaces/ISecurityToken.sol"; -import "../interfaces/IERC20.sol"; +import "./ModuleStorage.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; /** * @title Interface that any module contract should implement * @notice Contract is abstract */ -contract Module is IModule { - - address public factory; - - address public securityToken; - - bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; - - IERC20 public polyToken; +contract Module is IModule, ModuleStorage { /** * @notice Constructor * @param _securityToken Address of the security token * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public { - securityToken = _securityToken; - factory = msg.sender; - polyToken = IERC20(_polyAddress); + constructor (address _securityToken, address _polyAddress) public + ModuleStorage(_securityToken, _polyAddress) + { } //Allows owner, factory or permissioned delegate diff --git a/contracts/modules/ModuleStorage.sol b/contracts/modules/ModuleStorage.sol new file mode 100644 index 000000000..cd52c9de2 --- /dev/null +++ b/contracts/modules/ModuleStorage.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../interfaces/IERC20.sol"; + +/** + * @title Storage for Module contract + * @notice Contract is abstract + */ +contract ModuleStorage { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) public { + securityToken = _securityToken; + factory = msg.sender; + polyToken = IERC20(_polyAddress); + } + + address public factory; + + address public securityToken; + + bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; + + IERC20 public polyToken; + +} diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index eea89494d..247ac8374 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -1,60 +1,16 @@ pragma solidity ^0.4.24; import "./ITransferManager.sol"; +import "./GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Transfer Manager module for core transfer validation functionality */ -contract GeneralTransferManager is ITransferManager { +contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManager { using SafeMath for uint256; - //Address from which issuances come - address public issuanceAddress = address(0); - - //Address which can sign whitelist changes - address public signingAddress = address(0); - - bytes32 public constant WHITELIST = "WHITELIST"; - bytes32 public constant FLAGS = "FLAGS"; - - //from and to timestamps that an investor can send / receive tokens respectively - struct TimeRestriction { - uint64 fromTime; - uint64 toTime; - uint64 expiryTime; - uint8 canBuyFromSTO; - uint8 added; - } - - // Allows all TimeRestrictions to be offset - struct Offset { - uint64 offset; - uint8 isForward; - } - - // Offset to be applied to all timings (except KYC expiry) - Offset public offset; - - // List of all addresses that have been added to the GTM at some point - address[] public investors; - - // An address can only send / receive tokens once their corresponding uint256 > block.number - // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) - mapping (address => TimeRestriction) public whitelist; - // Map of used nonces by customer - mapping(address => mapping(uint256 => bool)) public nonceMap; - - //If true, there are no transfer restrictions, for any addresses - bool public allowAllTransfers = false; - //If true, time lock is ignored for transfers (address must still be on whitelist) - bool public allowAllWhitelistTransfers = false; - //If true, time lock is ignored for issuances (address must still be on whitelist) - bool public allowAllWhitelistIssuances = true; - //If true, time lock is ignored for burn transactions - bool public allowAllBurnTransfers = false; - // Emit when Issuance address get changed event ChangeIssuanceAddress(address _issuanceAddress); // Emit when there is change in the flag variable called allowAllTransfers @@ -78,17 +34,6 @@ contract GeneralTransferManager is ITransferManager { uint8 _canBuyFromSTO ); - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) - public - Module(_securityToken, _polyAddress) - { - } - /** * @notice This function returns the signature of configure function */ diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index c15eb52aa..c37ab8b4b 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./GeneralTransferManager.sol"; +import "../../proxy/GeneralTransferManagerProxy.sol"; import "../ModuleFactory.sol"; /** @@ -8,11 +8,13 @@ import "../ModuleFactory.sol"; */ contract GeneralTransferManagerFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; @@ -21,6 +23,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { description = "Manage transfers using a time based whitelist"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } @@ -31,7 +34,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - address generalTransferManager = new GeneralTransferManager(msg.sender, address(polyToken)); + address generalTransferManager = new GeneralTransferManagerProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(generalTransferManager); diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol new file mode 100644 index 000000000..7dae02ebb --- /dev/null +++ b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol @@ -0,0 +1,55 @@ +pragma solidity ^0.4.24; + +import "./ITransferManager.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract GeneralTransferManagerStorage { + + //Address from which issuances come + address public issuanceAddress = address(0); + + //Address which can sign whitelist changes + address public signingAddress = address(0); + + bytes32 public constant WHITELIST = "WHITELIST"; + bytes32 public constant FLAGS = "FLAGS"; + + //from and to timestamps that an investor can send / receive tokens respectively + struct TimeRestriction { + uint64 fromTime; + uint64 toTime; + uint64 expiryTime; + uint8 canBuyFromSTO; + uint8 added; + } + + // Allows all TimeRestrictions to be offset + struct Offset { + uint64 offset; + uint8 isForward; + } + + // Offset to be applied to all timings (except KYC expiry) + Offset public offset; + + // List of all addresses that have been added to the GTM at some point + address[] public investors; + + // An address can only send / receive tokens once their corresponding uint256 > block.number + // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) + mapping (address => TimeRestriction) public whitelist; + // Map of used nonces by customer + mapping(address => mapping(uint256 => bool)) public nonceMap; + + //If true, there are no transfer restrictions, for any addresses + bool public allowAllTransfers = false; + //If true, time lock is ignored for transfers (address must still be on whitelist) + bool public allowAllWhitelistTransfers = false; + //If true, time lock is ignored for issuances (address must still be on whitelist) + bool public allowAllWhitelistIssuances = true; + //If true, time lock is ignored for burn transactions + bool public allowAllBurnTransfers = false; + +} diff --git a/contracts/proxy/GeneralTransferManagerProxy.sol b/contracts/proxy/GeneralTransferManagerProxy.sol new file mode 100644 index 000000000..cc5999bad --- /dev/null +++ b/contracts/proxy/GeneralTransferManagerProxy.sol @@ -0,0 +1,47 @@ +pragma solidity ^0.4.24; + +import "../modules/TransferManager/GeneralTransferManagerStorage.sol"; +import "./Proxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract GeneralTransferManagerProxy is ModuleStorage, Pausable, GeneralTransferManagerStorage, Proxy { + + // Address of the current implementation + address internal __implementation; + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + + /** + * @notice Internal function to provide the address of the implementation contract + */ + function _implementation() internal view returns (address) { + return __implementation; + } + + /** + * @dev Tells the address of the current implementation + * @return address of the current implementation + */ + function implementation() external view returns (address) { + return _implementation(); + } +} diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 694fdf03e..e903789b2 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,5 +1,6 @@ const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') +const GeneralTransferManagerLogic = artifacts.require('./GeneralTransferManager.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); @@ -145,10 +146,15 @@ module.exports = function (deployer, network, accounts) { moduleRegistry = ModuleRegistry.at(ModuleRegistryProxy.address); // Add module registry to polymath registry return polymathRegistry.changeAddress("ModuleRegistry", ModuleRegistryProxy.address, {from: PolymathAccount}); + }).then(() => { + console.log("deployinglogic") + // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(GeneralTransferManagerLogic, {from: PolymathAccount}); }).then(() => { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, GeneralTransferManagerLogic.address, {from: PolymathAccount}); }).then(() => { // C) Deploy the GeneralPermissionManagerFactory Contract (Factory used to generate the GeneralPermissionManager contract and // this manager attach with the securityToken contract at the time of deployment) diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 2021d350e..c2201ec12 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -82,7 +82,9 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { let b = await deployFeatureRegistry(account_polymath); // STEP 3: Deploy the ModuleRegistry let c = await deployModuleRegistry(account_polymath); - // STEP 4: Deploy the GeneralTransferManagerFactory + // STEP 4a: Deploy the GeneralTransferManagerFactory + let logic = await deployGTMLogic(account_polymath); + // STEP 4b: Deploy the GeneralTransferManagerFactory let d = await deployGTM(account_polymath); // Step 6: Deploy the STversionProxy contract let e = await deploySTFactory(account_polymath); @@ -127,8 +129,20 @@ async function deployModuleRegistry(account_polymath) { return new Array(I_ModuleRegistry, I_ModuleRegistryProxy, I_MRProxied); } +async function deployGTMLogic(account_polymath) { + I_GeneralTransferManagerLogic = await GeneralTransferManager.new({ from: account_polymath }); + + assert.notEqual( + I_GeneralTransferManagerLogic.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerLogic contract was not deployed" + ); + + return new Array(I_GeneralTransferManagerLogic); +} + async function deployGTM(account_polymath) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); assert.notEqual( I_GeneralTransferManagerFactory.address.valueOf(), @@ -193,7 +207,7 @@ async function registerAndVerifyByMR(factoryAdrress, owner, mr) { /// Deploy the TransferManagers export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(polyToken, setupCost, 0, 0, I_GeneralTransferManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), From 9f0e2efe8c28223b63a62369388f5f6734b6adff Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sat, 24 Nov 2018 21:57:34 +0000 Subject: [PATCH 174/582] Fixes --- .../TransferManager/GeneralTransferManager.sol | 11 +++++++++++ contracts/proxy/GeneralTransferManagerProxy.sol | 2 +- migrations/2_deploy_contracts.js | 4 ++-- test/h_general_transfer_manager.js | 2 +- test/helpers/createInstances.js | 4 +++- test/u_module_registry_proxy.js | 5 ++++- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 247ac8374..f15a522da 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -34,6 +34,17 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag uint8 _canBuyFromSTO ); + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { + } + /** * @notice This function returns the signature of configure function */ diff --git a/contracts/proxy/GeneralTransferManagerProxy.sol b/contracts/proxy/GeneralTransferManagerProxy.sol index cc5999bad..9732b76db 100644 --- a/contracts/proxy/GeneralTransferManagerProxy.sol +++ b/contracts/proxy/GeneralTransferManagerProxy.sol @@ -8,7 +8,7 @@ import "../modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality */ -contract GeneralTransferManagerProxy is ModuleStorage, Pausable, GeneralTransferManagerStorage, Proxy { +contract GeneralTransferManagerProxy is GeneralTransferManagerStorage, ModuleStorage, Pausable, Proxy { // Address of the current implementation address internal __implementation; diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index e903789b2..63b2a8231 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -147,10 +147,9 @@ module.exports = function (deployer, network, accounts) { // Add module registry to polymath registry return polymathRegistry.changeAddress("ModuleRegistry", ModuleRegistryProxy.address, {from: PolymathAccount}); }).then(() => { - console.log("deployinglogic") // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(GeneralTransferManagerLogic, {from: PolymathAccount}); + return deployer.deploy(GeneralTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); }).then(() => { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) @@ -309,6 +308,7 @@ module.exports = function (deployer, network, accounts) { POLYOracle: ${POLYOracle} STFactory: ${STFactory.address} + GeneralTransferManagerLogic: ${GeneralTransferManagerLogic.address} GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index b7f14ed31..5137d8e9e 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -150,7 +150,7 @@ contract("GeneralTransferManager", accounts => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); let _blockNo = latestBlock(); let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - console.log(JSON.stringify(tx)); + // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index c2201ec12..35be83d95 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -20,6 +20,7 @@ const USDTieredSTOProxyFactory = artifacts.require("./USDTieredSTOProxyFactory") const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); const FeatureRegistry = artifacts.require("./FeatureRegistry.sol"); const STFactory = artifacts.require("./STFactory.sol"); +const GeneralTransferManager = artifacts.require("./GeneralTransferManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); @@ -49,6 +50,7 @@ let I_EtherDividendCheckpointFactory; let I_CountTransferManagerFactory; let I_ERC20DividendCheckpointFactory; let I_GeneralPermissionManagerFactory; +let I_GeneralTransferManagerLogic; let I_GeneralTransferManagerFactory; let I_GeneralTransferManager; let I_ModuleRegistryProxy; @@ -130,7 +132,7 @@ async function deployModuleRegistry(account_polymath) { } async function deployGTMLogic(account_polymath) { - I_GeneralTransferManagerLogic = await GeneralTransferManager.new({ from: account_polymath }); + I_GeneralTransferManagerLogic = await GeneralTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); assert.notEqual( I_GeneralTransferManagerLogic.address.valueOf(), diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 6d00b8fe2..877d173d4 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -9,6 +9,7 @@ const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); const ModuleRegistry = artifacts.require("./ModuleRegistry.sol"); const STFactory = artifacts.require("./STFactory.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); +const GeneralTransferManagerLogic = artifacts.require("./GeneralTransferManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); @@ -122,7 +123,9 @@ contract("ModuleRegistryProxy", accounts => { await I_MRProxied.updateFromRegistry({ from: account_polymath }); // STEP 4: Deploy the GeneralTransferManagerFactory - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { + let I_GeneralTransferManagerLogic = await GeneralTransferManagerLogic.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); From 3234d152f1e492ec6652e65e32dbd8e0c4c825f4 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sat, 24 Nov 2018 22:01:58 +0000 Subject: [PATCH 175/582] Update config --- truffle-config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle-config.js b/truffle-config.js index 2a84351bd..c993327ea 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -11,7 +11,7 @@ module.exports = { host: 'localhost', port: 8545, network_id: '*', // Match any network id - gas: 9000000, + gas: 7900000, }, mainnet: { host: 'localhost', From 14d5890a2f68b42d6d1d9132fad9c18e53e7009e Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sat, 24 Nov 2018 22:23:09 +0000 Subject: [PATCH 176/582] Log gas for 50 txs --- test/h_general_transfer_manager.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 5137d8e9e..9871f5e3c 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -197,6 +197,28 @@ contract("GeneralTransferManager", accounts => { assert.equal(tx.logs[1].args._investor, account_affiliates2); }); + it("Should whitelist lots of addresses and check gas", async () => { + let mockInvestors = []; + for (let i = 0; i < 50; i++) { + mockInvestors.push("0x0000000000000000000000000000000000000000".substring(0,42-i.toString().length) + i.toString()); + } + + let times = range1(50); + let bools = rangeB(50); + let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + mockInvestors, + times, + times, + times, + bools, + { + from: account_issuer, + gas: 7900000 + } + ); + console.log("Multi Whitelist x 50: " + tx.receipt.gasUsed); + }); + it("Should mint the tokens to the affiliates", async () => { await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [100 * Math.pow(10, 18), 100 * Math.pow(10, 18)], { from: account_issuer, @@ -836,3 +858,6 @@ contract("GeneralTransferManager", accounts => { }) }); }); + +function range1(i) {return i?range1(i-1).concat(i):[]} +function rangeB(i) {return i?rangeB(i-1).concat(0):[]} From a2784768745db24552c694737c109c0cbf2e58c8 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sat, 24 Nov 2018 23:40:53 +0000 Subject: [PATCH 177/582] WIP --- .../GeneralTransferManager.sol | 36 ++++++- .../GeneralTransferManagerStorage.sol | 2 +- test/h_general_transfer_manager.js | 97 ++++++++++++++++++- 3 files changed, 129 insertions(+), 6 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index f15a522da..c64c99c34 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -24,6 +24,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag // Emit when there is change in the flag variable called signingAddress event ChangeSigningAddress(address _signingAddress); // Emit when investor details get modified related to their whitelisting + event OffsetModified(uint64 _time, uint8 _isForward); + event ModifyWhitelist( address _investor, uint256 _dateAdded, @@ -45,6 +47,12 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag { } + function modifyOffset(uint64 _time, uint8 _isForward) public withPerm(FLAGS) { + offset.time = _time; + offset.isForward = _isForward; + emit OffsetModified(_time, _isForward); + } + /** * @notice This function returns the signature of configure function */ @@ -137,16 +145,21 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag //Anyone on the whitelist can transfer, regardless of time return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA; } - if (allowAllWhitelistIssuances && _from == issuanceAddress) { + if (_from == issuanceAddress && (whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { if ((whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { return Result.NA; } + } + if (allowAllWhitelistIssuances && _from == issuanceAddress) { return _onWhitelist(_to) ? Result.VALID : Result.NA; } + if (_from == issuanceAddress) { + return (_onWhitelist(_to) && _adjustTimes(whitelist[_to].toTime) <= uint64(now)) ? Result.VALID : Result.NA; + } //Anyone on the whitelist can transfer provided the blocknumber is large enough /*solium-disable-next-line security/no-block-members*/ - return ((_onWhitelist(_from) && whitelist[_from].fromTime <= uint64(now)) && - (_onWhitelist(_to) && whitelist[_to].toTime <= uint64(now))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return ((_onWhitelist(_from) && _adjustTimes(whitelist[_from].fromTime) <= uint64(now)) && + (_onWhitelist(_to) && _adjustTimes(whitelist[_to].toTime) <= uint64(now))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -274,6 +287,23 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag return attached; } + function _adjustTimes(uint64 _time) internal view returns(uint64) { + if (offset.isForward != 0) { + require(_time + offset.time > _time); + return _time + offset.time; + } else { + require(_time >= offset.time); + return _time - offset.time; + } + } + + /** + * @dev Returns list of all investors + */ + function getInvestors() external view returns(address[]) { + return investors; + } + /** * @notice Return the permissions flag that are associated with general trnasfer manager */ diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol index 7dae02ebb..6cfb29e21 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol @@ -27,7 +27,7 @@ contract GeneralTransferManagerStorage { // Allows all TimeRestrictions to be offset struct Offset { - uint64 offset; + uint64 time; uint8 isForward; } diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 9871f5e3c..b5f2b3d91 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -172,14 +172,14 @@ contract("GeneralTransferManager", accounts => { await catchRevert( I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}) ); - }) + }); it("Should attach the paid GTM", async() => { let snap_id = await takeSnapshot(); await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); await I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}); await revertToSnapshot(snap_id); - }) + }); it("Should whitelist the affiliates before the STO attached", async () => { let tx = await I_GeneralTransferManager.modifyWhitelistMulti( @@ -195,6 +195,7 @@ contract("GeneralTransferManager", accounts => { ); assert.equal(tx.logs[0].args._investor, account_affiliates1); assert.equal(tx.logs[1].args._investor, account_affiliates2); + assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2]); }); it("Should whitelist lots of addresses and check gas", async () => { @@ -217,6 +218,7 @@ contract("GeneralTransferManager", accounts => { } ); console.log("Multi Whitelist x 50: " + tx.receipt.gasUsed); + assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2].concat(mockInvestors)); }); it("Should mint the tokens to the affiliates", async () => { @@ -364,6 +366,97 @@ contract("GeneralTransferManager", accounts => { }); }); + describe("Buy tokens using on-chain whitelist and negative offset", async () => { + // let snap_id; + + it("Should Buy the tokens", async () => { + // Add the Investor in to the whitelist + // snap_id = await takeSnapshot(); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime() + duration.days(10), + latestTime() + duration.days(10), + latestTime() + duration.days(20), + 1, + { + from: account_issuer, + gas: 6000000 + } + ); + + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor1.toLowerCase(), + "Failed in adding the investor in whitelist" + ); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + + await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("3", "ether")); + }); + + it("Add an offset and check transfers are disabled", async () => { + let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 0, {from: token_owner}); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("3", "ether")); + tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); + // await revertToSnapshot(snap_id); + }); + + }); + + + describe("Buy tokens using on-chain whitelist and positive offset", async () => { + // let snap_id; + + it("Should Buy the tokens", async () => { + // Add the Investor in to the whitelist + // snap_id = await takeSnapshot(); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime(), + 1, + { + from: account_issuer, + gas: 6000000 + } + ); + + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor1.toLowerCase(), + "Failed in adding the investor in whitelist" + ); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + console.log(await I_GeneralTransferManager.offset.call()); + await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + }); + + it("Add an offset and check transfers are disabled", async () => { + let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 1, {from: token_owner}); + await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); + await increaseTime(duration.days(10)); + I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); + // await revertToSnapshot(snap_id); + }); + + }); + describe("Buy tokens using off-chain whitelist", async () => { it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { await catchRevert(I_DummySTO.generateTokens(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner })); From 165f6c7e4c02010f3c5743ad5d0b37c334c690fc Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sat, 24 Nov 2018 23:49:38 +0000 Subject: [PATCH 178/582] update --- test/h_general_transfer_manager.js | 91 +++++++++++++++--------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index b5f2b3d91..9105c63e6 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -411,51 +411,52 @@ contract("GeneralTransferManager", accounts => { }); - describe("Buy tokens using on-chain whitelist and positive offset", async () => { - // let snap_id; - - it("Should Buy the tokens", async () => { - // Add the Investor in to the whitelist - // snap_id = await takeSnapshot(); - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime(), - 1, - { - from: account_issuer, - gas: 6000000 - } - ); - - assert.equal( - tx.logs[0].args._investor.toLowerCase(), - account_investor1.toLowerCase(), - "Failed in adding the investor in whitelist" - ); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - console.log(await I_GeneralTransferManager.offset.call()); - await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); - }); - - it("Add an offset and check transfers are disabled", async () => { - let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 1, {from: token_owner}); - await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); - await increaseTime(duration.days(10)); - I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); - tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); - // await revertToSnapshot(snap_id); - }); - - }); + // describe("Buy tokens using on-chain whitelist and positive offset", async () => { + // // let snap_id; + // + // it("Should Buy the tokens", async () => { + // + // // Add the Investor in to the whitelist + // // snap_id = await takeSnapshot(); + // let tx = await I_GeneralTransferManager.modifyWhitelist( + // account_investor1, + // latestTime(), + // latestTime(), + // latestTime(), + // 1, + // { + // from: account_issuer, + // gas: 6000000 + // } + // ); + // + // assert.equal( + // tx.logs[0].args._investor.toLowerCase(), + // account_investor1.toLowerCase(), + // "Failed in adding the investor in whitelist" + // ); + // + // // Jump time + // await increaseTime(5000); + // + // // Mint some tokens + // console.log(await I_GeneralTransferManager.offset.call()); + // await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + // + // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); + // await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + // }); + // + // it("Add an offset and check transfers are disabled", async () => { + // let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 1, {from: token_owner}); + // await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); + // await increaseTime(duration.days(10)); + // await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + // tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); + // // await revertToSnapshot(snap_id); + // }); + // + // }); describe("Buy tokens using off-chain whitelist", async () => { it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { From 9f1970d4feb328ccb850074cc428daf0c7d85b9b Mon Sep 17 00:00:00 2001 From: satyam Date: Sun, 25 Nov 2018 16:55:11 +0530 Subject: [PATCH 179/582] finalised the logic of sc --- .../TransferManager/VolumeRestrictionTM.sol | 464 +++++++++++--- test/z_volume_restriction_tm.js | 566 +++++++++++++++++- 2 files changed, 921 insertions(+), 109 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index b1e80875c..60d244758 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -13,8 +13,6 @@ contract VolumeRestrictionTM is ITransferManager { enum RestrictionType { Fixed, Variable } - enum Scope { Global, Individual } - struct VolumeRestriction { uint256 allowedTokens; uint256 allowedPercentageOfTokens; @@ -26,11 +24,16 @@ contract VolumeRestrictionTM is ITransferManager { struct BucketDetails { uint256[] timestamps; - uint256 sumOfLastPeriod; + uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays } - VolumeRestriction globalRestriction; - + // Global restriction that applies to all token holders + VolumeRestriction public globalRestriction; + // Daily global restriction that applies to all token holders (Total ST traded daily is restricted) + VolumeRestriction public dailyGlobalRestriction; + // Variable stores the data matrix for the globa restrictions + BucketDetails internal globalBucketDetails; + // Restriction stored corresponds to a particular token holder mapping(address => VolumeRestriction) public individualRestriction; // Storing _from => day's timestamp => total amount transact in a day --individual mapping(address => mapping(uint256 => uint256)) internal bucket; @@ -38,11 +41,12 @@ contract VolumeRestrictionTM is ITransferManager { mapping(address => BucketDetails) internal bucketToUser; // List of wallets that are exempted from all the restrictions applied by the this contract mapping(address => bool) public exemptList; + // Store the amount of tokens get transacted in a day + mapping(uint256 => uint256) public globalBucket; - address[] globalUsers; - + // Emit when the token holder is added/removed from the exemption list event ChangedExemptWalletList(address indexed _wallet, bool _change); - + // Emit when the new individual restriction is added corresponds to new token holders event AddNewIndividualRestriction( address indexed _holder, uint256 _allowedTokens, @@ -52,7 +56,7 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _endTime, uint256 _typeOfRestriction ); - + // Emit when the individual restriction is modified for a given address event ModifyIndividualRestriction( address indexed _holder, uint256 _allowedTokens, @@ -62,8 +66,8 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _endTime, uint256 _typeOfRestriction ); - - event AddNewGlobalRestriction( + // Emit when the new global restriction is added + event AddGlobalRestriction( uint256 _allowedTokens, uint256 _allowedPercentageOfTokens, uint256 _startTime, @@ -71,7 +75,16 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _endTime, uint256 _typeOfRestriction ); - + // Emit when the new daily (global) restriction is added + event AddDailyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when global restriction get modified event ModifyGlobalRestriction( uint256 _allowedTokens, uint256 _allowedPercentageOfTokens, @@ -80,6 +93,21 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _endTime, uint256 _typeOfRestriction ); + // Emit when daily global restriction get modified + event ModifyDailyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when the individual restriction gets removed + event IndividualRestrictionRemoved(address _user); + // Emit when the global restriction gets removed + event GlobalRestrictionRemoved(); + // Emit when the daily global restriction gets removed + event DailyGlobalRestrictionRemoved(); /** * @notice Constructor @@ -101,12 +129,19 @@ contract VolumeRestrictionTM is ITransferManager { * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable */ function verifyTransfer(address _from, address /*_to */, uint256 _amount, bytes /*_data*/, bool _isTransfer) public returns (Result) { + // If `_from` is present in the exemptionList or it is `0x0` address then it will not follow the vol restriction if (!paused && _from != address(0) && !exemptList[_from]) { - require(msg.sender == securityToken || !_isTransfer); - return _checkRestriction(_from, _amount, _isTransfer); - } else { - return Result.NA; + // Function must only be called by the associated security token if _isTransfer == true + require(msg.sender == securityToken || !_isTransfer, "Sender is not the owner"); + // Checking the individual restriction if the `_from` comes in the individual category + if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { + return _individualRestrictionCheck(_from, _amount, _isTransfer); + // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically + } else if (globalRestriction.endTime >= now && globalRestriction.startTime <= now) { + return _globalRestrictionCheck(_from, _amount, _isTransfer); + } } + return Result.NA; } /** @@ -207,7 +242,7 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _endTime, uint256 _restrictionType ) - public + external withPerm(ADMIN) { require( @@ -223,7 +258,7 @@ contract VolumeRestrictionTM is ITransferManager { _endTime, RestrictionType(_restrictionType) ); - emit AddNewGlobalRestriction( + emit AddGlobalRestriction( _allowedTokens, _allowedPercentageOfTokens, _startTime, @@ -233,6 +268,85 @@ contract VolumeRestrictionTM is ITransferManager { ); } + /** + * @notice Use to add the new global daily restriction for all token holder + * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function addDailyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + require( + dailyGlobalRestriction.endTime == 0 || dailyGlobalRestriction.endTime > now, + "Restriction already present" + ); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); + dailyGlobalRestriction = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddDailyGlobalRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + 1, + _endTime, + _restrictionType + ); + } + + /** + * @notice use to remove the individual restriction for a given address + * @param _user Address of the user + */ + function removeIndividualRestriction(address _user) external withPerm(ADMIN) { + _removeIndividualRestriction(_user); + } + + /** + * @notice use to remove the individual restriction for a given address + * @param _users Array of address of the user + */ + function removeIndividualRestrictionMulti(address[] _users) external withPerm(ADMIN) { + for (uint256 i = 0; i < _users.length; i++) { + _removeIndividualRestriction(_users[i]); + } + } + + /** + * @notice Use to remove the global restriction + */ + function removeGlobalRestriction() external withPerm(ADMIN) { + require(globalRestriction.endTime != 0, "Not present"); + globalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); + globalBucketDetails.timestamps.length = 0; + globalBucketDetails.sumOfLastPeriod = 0; + emit GlobalRestrictionRemoved(); + } + + /** + * @notice Use to remove the daily global restriction + */ + function removeDailyGlobalRestriction() external withPerm(ADMIN) { + require(dailyGlobalRestriction.endTime != 0, "Not present"); + dailyGlobalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); + emit DailyGlobalRestrictionRemoved(); + } + /** * @notice Use to modify the existing individual restriction for a given token holder * @param _holder Address of the token holder, whom restriction will be implied @@ -320,7 +434,7 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _endTime, uint256 _restrictionType ) - public + external withPerm(ADMIN) { require(globalRestriction.startTime > now, "Not allowed to modify"); @@ -343,63 +457,139 @@ contract VolumeRestrictionTM is ITransferManager { ); } - function _checkRestriction(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { - uint256 _fromTimestamp; - BucketDetails memory _bucketDetails = bucketToUser[_from]; - if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { - if (_bucketDetails.timestamps.length == 0) { - _fromTimestamp = individualRestriction[_from].startTime; - } else { - _fromTimestamp = _bucketDetails.timestamps[_bucketDetails.timestamps.length - 1]; - } - return _bucketCheck( - _fromTimestamp, - BokkyPooBahsDateTimeLibrary.diffDays(_fromTimestamp, now), - _from, - _amount, - _isTransfer, - Scope.Individual, - individualRestriction[_from] - ); - } else if (now <= globalRestriction.endTime && now >= globalRestriction.startTime) { - // Algorithm should be loop to all(who doesn't have the individual restriction) the individualBucketCheck - // and get the amount that was transacted till now. - // Calculate the sum of that amount + new txn amount and compare with allowed percentage or fixed amount - // amount of tokens - if (_bucketDetails.timestamps.length == 0) { - _fromTimestamp = globalRestriction.startTime; - } else { - _fromTimestamp = _bucketDetails.timestamps[_bucketDetails.timestamps.length - 1]; - } - return _bucketCheck( - _fromTimestamp, - BokkyPooBahsDateTimeLibrary.diffDays(_fromTimestamp, now), - _from, - _amount, - _isTransfer, - Scope.Global, - globalRestriction - ); + /** + * @notice Use to modify the daily global restriction for all token holder + * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function modifyDailyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + require(dailyGlobalRestriction.startTime > now, "Not allowed to modify"); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + dailyGlobalRestriction = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyDailyGlobalRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + /** + * @notice Internal function have a logic to validate the txn amount with global restriction + */ + function _globalRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + uint256[] memory timestamps = globalBucketDetails.timestamps; + uint256 fromTimestamp; + uint256 sumOfLastPeriod = 0; + if (timestamps.length == 0) { + // It will execute when the txn is performed first time after the addition of global restriction + fromTimestamp = globalRestriction.startTime; } else { + // picking up the preivous timestamp + fromTimestamp = timestamps[timestamps.length -1]; + } + // Calculating the difference of days + uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); + uint256[] memory passedTimestamps = new uint256[](diffDays); + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod + // re-using the local variables to avoid the stack too deep error. + (sumOfLastPeriod, fromTimestamp, passedTimestamps) = _bucketCheck( + fromTimestamp, + diffDays, + _from, + globalBucketDetails, + true, + globalRestriction + ); + // Total amout that is transacted uptill now for `fromTimestamp` day + uint256 txSumOfDay = globalBucket[fromTimestamp]; + // Global transaction check + if (_globalTxCheck(sumOfLastPeriod, txSumOfDay, _amount)) { + // allow modification in storage when `_isTransfer` equals true + if(_isTransfer) { + // update the global storage + _updateGlobalStorage( + passedTimestamps, + fromTimestamp, + _amount, + diffDays, + sumOfLastPeriod + ); + } return Result.NA; } + return Result.INVALID; } + /** + * @notice Internal function to update the state variables related to global restriction + */ + function _updateGlobalStorage( + uint256[] passedTimestamps, + uint256 _fromTime, + uint256 _amount, + uint256 _diffDays, + uint256 _sumOfLastPeriod + ) + internal + { + if (_diffDays != 0) { + for (uint256 i = 0; i < passedTimestamps.length; i++) { + // Add the timestamp that is already passed + globalBucketDetails.timestamps.push(passedTimestamps[i]); + } + } + // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) + if (globalBucketDetails.timestamps.length == 0) { + globalBucketDetails.timestamps.push(_fromTime); + } + if(_amount != 0) { + // updating the sumOfLastPeriod + globalBucketDetails.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + + // Re-using the local variable to avoid stack too deep error + _fromTime = globalBucketDetails.timestamps[globalBucketDetails.timestamps.length -1]; + globalBucket[_fromTime] = globalBucket[_fromTime].add(_amount); + } + } + + /// Internal function for the bucket check function _bucketCheck( uint256 _fromTime, uint256 _diffDays, address _from, - uint256 _amount, - bool _isTransfer, - Scope _scope, + BucketDetails _bucketDetails, + bool _isGlobal, VolumeRestriction _restriction ) internal - returns (Result) + view + returns (uint256, uint256, uint256[]) { - BucketDetails memory _bucketDetails = bucketToUser[_from]; uint256[] memory passedTimestamps = new uint256[](_diffDays); - // using the existing memory variable instead of creating new one (avoiding stack too deep error) uint256 counter = _bucketDetails.timestamps.length; uint256 i = 0; if (_diffDays != 0) { @@ -413,51 +603,97 @@ contract VolumeRestrictionTM is ITransferManager { // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting // the earlier value at that index if (counter >= _restriction.rollingPeriodInDays) { - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. - sub(bucket[_from][_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); + if (_isGlobal) { + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. + sub(globalBucket[_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); + } else { + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. + sub(bucket[_from][_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); + } + } - // Adding the last amount that is transacted on the _fromTime + // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand + // the alogrithm //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); // Storing all those timestamps whose total transacted value is 0 passedTimestamps[i] = _fromTime; counter++; } } - if (_scope == Scope.Global) { - i = _getTotalSumOfLastPeriod(_bucketDetails.sumOfLastPeriod, _from); + return (_bucketDetails.sumOfLastPeriod, _fromTime, passedTimestamps); + } + + /** + * @notice Internal function used to validate the transaction for a given address + * If it validates then it also update the storage corressponds to the individual restriction + */ + function _individualRestrictionCheck( + address _from, + uint256 _amount, + bool _isTransfer + ) + internal + returns(Result) + { + uint256 fromTimestamp; + uint256 sumOfLastPeriod = 0; + if (bucketToUser[_from].timestamps.length == 0) { + // It will execute when the txn is performed first time after the addition of individual restriction + fromTimestamp = individualRestriction[_from].startTime; } else { - i = _bucketDetails.sumOfLastPeriod; + // Picking up the last timestamp + fromTimestamp = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; } - if (_checkValidAmountToTransact(i, _amount, _restriction)) { + // Calculating the difference of days + uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); + uint256[] memory passedTimestamps = new uint256[](diffDays); + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod + // re-using the local variables to avoid the stack too deep error. + (sumOfLastPeriod, fromTimestamp, passedTimestamps) = _bucketCheck( + fromTimestamp, + diffDays, + _from, + bucketToUser[_from], + false, + individualRestriction[_from] + ); + if (_checkValidAmountToTransact(sumOfLastPeriod, _amount, individualRestriction[_from])) { if (_isTransfer) { - _updateStorage( + _updateIndividualStorage( passedTimestamps, _from, - _fromTime, + fromTimestamp, _amount, - _diffDays, - _scope, - _bucketDetails.sumOfLastPeriod + diffDays, + sumOfLastPeriod ); } return Result.NA; } - return Result.INVALID; + return Result.INVALID; } - function _getTotalSumOfLastPeriod(uint256 _sumOfuser, address _from) internal view returns(uint256 globalSumOfLastPeriod) { - for (uint256 i = 0; i < globalUsers.length; i++) { - if (globalUsers[i] == _from) { - globalSumOfLastPeriod.add(_sumOfuser); - } else { - uint256 _latestTimestampIndex = bucketToUser[globalUsers[i]].timestamps.length - 1; - uint256 _latestTimestamp = bucketToUser[globalUsers[i]].timestamps[_latestTimestampIndex]; - if (BokkyPooBahsDateTimeLibrary.diffDays(_latestTimestamp, now) < globalRestriction.rollingPeriodInDays) - globalSumOfLastPeriod.add(bucketToUser[globalUsers[i]].sumOfLastPeriod); - } + + function _globalTxCheck( + uint256 _sumOfLastPeriod, + uint256 _dailyAmount, + uint256 _amount + ) + internal + view + returns(bool) + { + // Checking whether the global day restriction is added or not if yes then calculate + // the total amount get traded on a particular day (~ _fromTime) + if (!_checkValidAmountToTransact(_dailyAmount, _amount, dailyGlobalRestriction) && + now <= dailyGlobalRestriction.endTime && now >= dailyGlobalRestriction.startTime + ) { + return false; } + return _checkValidAmountToTransact(_sumOfLastPeriod, _amount, globalRestriction); } function _checkValidAmountToTransact( @@ -483,25 +719,19 @@ contract VolumeRestrictionTM is ITransferManager { } } - function _updateStorage( + function _updateIndividualStorage( uint256[] passedTimestamps, address _from, uint256 _fromTime, uint256 _amount, uint256 _diffDays, - Scope _scope, uint256 _sumOfLastPeriod ) internal { - if (bucketToUser[_from].timestamps.length == 0 && _scope == Scope.Global) { - globalUsers.push(_from); - } if (_diffDays != 0) { for (uint256 i = 0; i < passedTimestamps.length; i++) { - // Assigning the sum of transacted amount on the passed day - // bucket[_from][passedTimestamps[i]] = 0; - // To save gas by not assigning a memory timestamp array to storage timestamp array. + // Add the timestamp that is already passed bucketToUser[_from].timestamps.push(passedTimestamps[i]); } } @@ -509,11 +739,23 @@ contract VolumeRestrictionTM is ITransferManager { if (bucketToUser[_from].timestamps.length == 0) { bucketToUser[_from].timestamps.push(_fromTime); } - bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + if(_amount != 0) { + bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + + // Re-using the local variable to avoid stack too deep error + _fromTime = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; + bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); + } + + } - // Re-using the local variable to avoid stack too deep error - _fromTime = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; - bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); + function _removeIndividualRestriction(address _user) internal { + require(_user != address(0), "Invalid address"); + require(individualRestriction[_user].endTime != 0, "Not present"); + individualRestriction[_user] = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); + bucketToUser[_user].timestamps.length = 0; + bucketToUser[_user].sumOfLastPeriod = 0; + emit IndividualRestrictionRemoved(_user); } function _modifyIndividualRestriction( @@ -607,6 +849,7 @@ contract VolumeRestrictionTM is ITransferManager { ); } require(_startTime > 0 && _endTime > _startTime); + // Maximum limit for the rollingPeriod is 365 days require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365); require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays); } @@ -632,6 +875,12 @@ contract VolumeRestrictionTM is ITransferManager { ); } + /** + * @notice Use to get the bucket details for a given address + * @param _user Address of the token holder for whom the bucket details has queried + * @return uint256 Array of the timestamps + * @return uint256 sumOfLastPeriod + */ function getBucketDetailsToUser(address _user) external view returns(uint256[], uint256) { return( bucketToUser[_user].timestamps, @@ -639,10 +888,29 @@ contract VolumeRestrictionTM is ITransferManager { ); } + /** + * @notice Use to get the volume of token that being traded at a particular day (`_at` + 24 hours) for a given user + * @param _user Address of the token holder + * @param _at Timestamp + */ function getTotalTradeByuser(address _user, uint256 _at) external view returns(uint256) { return bucket[_user][_at]; } + /** + * @notice Use to get the global bucket details + * @return uint256 Array of timestamps + * @return uint256 sumOfLastPeriod + * @return uint256 Total amount traded on the latest timestamp + */ + function getGlobalBucketDetails() external view returns(uint256[], uint256, uint256) { + return( + globalBucketDetails.timestamps, + globalBucketDetails.sumOfLastPeriod, + globalBucket[globalBucketDetails.timestamps[globalBucketDetails.timestamps.length - 1]] + ); + } + /** * @notice This function returns the signature of configure function */ diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js index 138068b8f..298fc18c8 100644 --- a/test/z_volume_restriction_tm.js +++ b/test/z_volume_restriction_tm.js @@ -69,6 +69,9 @@ contract('VolumeRestrictionTransferManager', accounts => { const stoKey = 3; let tempAmount = new BigNumber(0); + let tempArray = new Array(); + let tempArrayVariable = new Array(); + let tempArrayGlobal = new Array(); // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -84,6 +87,7 @@ contract('VolumeRestrictionTransferManager', accounts => { account_investor1 = accounts[8]; account_investor2 = accounts[9]; account_investor3 = accounts[4]; + account_investor4 = accounts[3]; account_delegate = accounts[7]; account_delegate2 = accounts[6]; account_delegate3 = accounts[5]; @@ -250,38 +254,52 @@ contract('VolumeRestrictionTransferManager', accounts => { Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) .dividedBy(new BigNumber(10).pow(18))} `); + assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), 0.3); + assert.equal(data[0][i].toNumber(), (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber()) } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} Last Timestamp Index : ${data[0].length -1} `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 0.3); + assert.equal(data[0].length -1, 0); + tempArray.push(0.3); }) it("Should successfully transact the tokens after 1 and half days", async() => { await increaseTime(duration.days(1.5)); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor1}); // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 33.7); - + tempArray.push(1); let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 0; i < data[0].length; i++) { console.log(` Timestamps array index ${i}: ${data[0][i].toNumber()} Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} + .dividedBy(new BigNumber(10).pow(18)).toNumber()} `); + assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i]); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} Last Timestamp Index : ${data[0].length -1} `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1.3); + assert.equal(data[0].length -1, 1); }); it("Should successfully transact more tokens on the same day (Fuzz test)", async() => { // Check the balance of the investors let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); let totalAmountTransacted = 0; for (let i = 0; i < 10; i++) { let amount = Math.random(); @@ -294,44 +312,63 @@ contract('VolumeRestrictionTransferManager', accounts => { let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - + tempArray[1] = tempArray[1] + totalAmountTransacted; let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 0; i < data[0].length; i++) { console.log(` Timestamps array index ${i}: ${data[0][i].toNumber()} Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) .dividedBy(new BigNumber(10).pow(18))} `); + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} Last Timestamp Index : ${data[0].length - 1} `); + assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 1.3 + totalAmountTransacted, 0.000001); + assert.equal(data[0].length -1, 1); }); it("Should successfully transfer the tokens after half days-- should increase the day covered by 1", async() => { + let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); await increaseTime(duration.days(.5)); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + tempArray.push(2); + for (let i = 0; i < data[0].length; i++) { console.log(` Timestamps array index ${i}: ${data[0][i].toNumber()} Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) .dividedBy(new BigNumber(10).pow(18))} `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); } + console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} Last Timestamp Index : ${data[0].length - 1} `); assert.equal(data[0].length - 1, 2); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), + (oldData[1].plus(new BigNumber(2).times(new BigNumber(10).pow(18)))) + .dividedBy(new BigNumber(10).pow(18)).toNumber()); }); it("Should successfully transfer the tokens in the last day of rolling period", async() => { // Check the balance of the investors let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); let totalAmountTransacted = 0; - for (let i = 0; i < 3; i++) { + for (let i = 0; i < 2; i++) { let amount = Math.random(); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); @@ -341,7 +378,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - + tempArray[2] = tempArray[2] + totalAmountTransacted; let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); for (let i = 0; i < data[0].length; i++) { console.log(` @@ -349,11 +386,18 @@ contract('VolumeRestrictionTransferManager', accounts => { Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) .dividedBy(new BigNumber(10).pow(18))} `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); } + console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} Last Timestamp Index : ${data[0].length - 1} `); + assert.equal(data[0].length - 1, 2); + assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), + oldData[1].dividedBy(new BigNumber(10).pow(18)).toNumber() + totalAmountTransacted, 0.00001); }); it("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { @@ -374,6 +418,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should transfer the tokens in a new rolling period", async() => { let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); let firstDayAmount; tempAmount = new BigNumber(0); for (let i = 0; i < oldData[0].length; i++) { @@ -396,7 +441,8 @@ contract('VolumeRestrictionTransferManager', accounts => { let currentDayAmount = firstDayAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))); let tx = await I_SecurityToken.transfer(account_investor3, currentDayAmount, {from: account_investor1}); tempAmount = tempAmount.minus(currentDayAmount); - + tempArray.push(0); + tempArray.push(currentDayAmount.dividedBy(new BigNumber(10).pow(18)).toNumber()); console.log('\n'); let newData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); for (let i = 2; i < newData[0].length; i++) { @@ -405,19 +451,20 @@ contract('VolumeRestrictionTransferManager', accounts => { Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) .dividedBy(new BigNumber(10).pow(18))} `); + assert.equal(newData[0][i].toNumber(), startTime + duration.days(i)) + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.00001); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((newData[1].toNumber()).toString())} Last Timestamp Index : ${newData[0].length -1} `); - assert.notEqual(oldData[0][0].toNumber(), newData[0][3].toNumber()); - assert.notEqual(oldData[0][1].toNumber(), newData[0][4].toNumber()); }); it("Should transfer the more tokens on the same day", async() => { // Check the balance of the investors let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - console.log(tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber()); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); await I_SecurityToken.transfer(account_investor3, tempAmount, {from: account_investor1}); // Check the balance of the investors @@ -428,7 +475,7 @@ contract('VolumeRestrictionTransferManager', accounts => { tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(), 0.01 ); - + tempArray[tempArray.length -1] = tempArray[tempArray.length -1] + tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(); let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); for (let i = 2; i < data[0].length; i++) { console.log(` @@ -436,13 +483,510 @@ contract('VolumeRestrictionTransferManager', accounts => { Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) .dividedBy(new BigNumber(10).pow(18))} `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.00001); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} Last Timestamp Index : ${data[0].length -1} `); + let sumOflastperiod = 0; + for (let i = tempArray.length - 1; i >= tempArray.length - 3; i--) { + sumOflastperiod += tempArray[i]; + } + assert.equal(data[0].length - 1, 4); + assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), sumOflastperiod, 0.00001); + }); + }); + + describe("Test case for the variable individual restriction", async() => { + it("Should add the restriction succesfully", async() => { + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor2, + 0, + new BigNumber(20).times(new BigNumber(10).pow(16)), + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 1, + { + from: token_owner + } + ); + + assert.equal(tx.logs[0].args._holder, account_investor2); + assert.equal(tx.logs[0].args._typeOfRestriction, 1); }); - + it("Should not successfully transact the tokens -- failed because volume is above the limit", async() => { + await increaseTime(duration.seconds(10)); + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei("15"), { from: account_investor2}) + ); + }); + + it("Should succesfully transact the tokens just after the starttime", async() => { + // Check the transfer will be valid or not by calling the verifyTransfer() directly by using _isTransfer = false + let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor2, account_investor3, web3.utils.toWei('.3'), "0x0", false); + console.log(result); + assert.equal(result.toNumber(), 1); + // Perform the transaction + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('.3'), {from: account_investor2}); + // Check the balance of the investors + let bal1 = await I_SecurityToken.balanceOf.call(account_investor2); + // Verifying the balances + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 29.7); + + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); + console.log('\n'); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), 0.3); + assert.equal(data[0][i].toNumber(), (await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber()) + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length -1} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 0.3); + assert.equal(data[0].length -1, 0); + tempArrayVariable.push(0.3); + }); + + it("Should successfully transact the tokens after 1 and half days", async() => { + await increaseTime(duration.days(1.5)); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor2}); + // Check the balance of the investors + let bal1 = await I_SecurityToken.balanceOf.call(account_investor2); + // Verifying the balances + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 28.7); + tempArrayVariable.push(1); + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayVariable[i]); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length -1} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1.3); + assert.equal(data[0].length -1, 1); + }); + + it("Should successfully transact more tokens on the same day (Fuzz test)", async() => { + // Check the balance of the investors + let balBefore = await I_SecurityToken.balanceOf.call(account_investor2); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(); + let totalAmountTransacted = 0; + for (let i = 0; i < 10; i++) { + let amount = Math.random(); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor2}); + console.log(`${i}: Restricted investor 2 able to transact ${amount} tokens to investor 3`); + totalAmountTransacted += amount; + } + + // Check the balance of the investors + let balAfter = await I_SecurityToken.balanceOf.call(account_investor2); + tempArrayVariable[1] = tempArrayVariable[1] + totalAmountTransacted; + // Verifying the balances + assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); + + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayVariable[i], 0.000001); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + `); + assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 1.3 + totalAmountTransacted, 0.000001); + assert.equal(data[0].length -1, 1); + }); + + it("Should successfully transfer the tokens after half days-- should increase the day covered by 1", async() => { + let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(); + await increaseTime(duration.days(.5)); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor2}); + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); + tempArrayVariable.push(2); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayVariable[i], 0.000001); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + `); + assert.equal(data[0].length - 1, 2); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), + (oldData[1].plus(new BigNumber(2).times(new BigNumber(10).pow(18)))) + .dividedBy(new BigNumber(10).pow(18)).toNumber()); + }); + + it("Should fail to transfer the tokens on third day -- because it is more than the rolling period allowed", async() => { + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); + let res = await I_VolumeRestrictionTM.individualRestriction.call(account_investor2); + let allowedAmount = (res[1].mul(await I_SecurityToken.totalSupply.call())).dividedBy(new BigNumber(10).pow(18)); + let remainingAmount = allowedAmount.minus(data[1]); + + await catchRevert( + I_SecurityToken.transfer( + account_investor3, + remainingAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))), + { + from: account_investor2 + } + ) + ); + tempAmount = remainingAmount; + }); + + it("Should successfully transfer tokens more than the allowed as totalsupply get increased", async() => { + await I_SecurityToken.mint(account_investor2, web3.utils.toWei("10"), { from: token_owner }); + + await I_SecurityToken.transfer( + account_investor3, + tempAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))), + { + from: account_investor2 + } + ); + }); }); + + describe("Add the test cases for global restriction", async() => { + + it("Should successfully add the global restriction", async() => { + await I_VolumeRestrictionTM.addGlobalRestriction( + web3.utils.toWei("20"), + 0, + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ); + + let data = await I_VolumeRestrictionTM.globalRestriction.call(); + assert.equal(data[0], web3.utils.toWei("20")); + assert.equal(data[3], 3); + }); + + it("Should successfully add the 2 more address in the whitelist", async() => { + await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor4, account_delegate3], + [latestTime(), latestTime()], + [latestTime(), latestTime()], + [latestTime() + duration.days(30), latestTime() + duration.days(30)], + [true, true], + { + from: token_owner + } + ); + + // Mint some tokens and transferred to whitelisted addresses + await I_SecurityToken.mint(account_investor4, web3.utils.toWei("40", "ether"), {from: token_owner}); + await I_SecurityToken.mint(account_delegate3, web3.utils.toWei("30", "ether"), {from: token_owner}); + + // Check the balance of the investors + let bal1 = await I_SecurityToken.balanceOf.call(account_investor4); + let bal2 = await I_SecurityToken.balanceOf.call(account_delegate3); + // Verifying the balances + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 40); + assert.equal(web3.utils.fromWei((bal2.toNumber()).toString()), 30); + }); + + it("Should successfully transfer the tokens with in the global range", async() => { + let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor4}); + let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + let latestTimestamp = 0; + tempArrayGlobal.push(1); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1); + assert.equal(data[0].length - 1, 0); + + console.log(`Transfer the tokens from the another investor comes under the global category`); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4"), {from: account_delegate3}); + tempArrayGlobal[tempArrayGlobal.length - 1] += 4; + data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); + latestTimestamp = data[0][i]; + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 5); + assert.equal(data[0].length - 1, 0); + assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 5); + }); + + it("Should transfer the tokens on the another day", async() => { + await increaseTime(duration.days(1.2)); + let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("5"), { from: account_investor3}); + tempArrayGlobal.push(5); + let latestTimestamp = 0; + let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); + latestTimestamp = data[0][i]; + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 10); + assert.equal(data[0].length - 1, 1); + assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 5); + }); + + it("Should transfer tokens on the third day of rolling period", async() => { + await increaseTime(duration.days(1)); + let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("6"), {from: account_investor4}); + let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + tempArrayGlobal.push(6); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 16); + assert.equal(data[0].length - 1, 2); + assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 6); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4"), {from: account_delegate3}); + data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + tempArrayGlobal[tempArrayGlobal.length -1] += 4; + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 20); + assert.equal(data[0].length - 1, 2); + assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 10); + }) + + it("Should transfer of tokens get failed - limit of global token txn get reached", async() => { + let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + let latestTimestamp = 0; + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + latestTimestamp = data[0][i]; + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} + `); + + // Already 20 tokens transferred + await catchRevert( + I_SecurityToken.transfer(account_delegate3, web3.utils.toWei("5"), {from: account_investor3}) + ); + }); + + it("Should allow to transact on the next rolling period", async() => { + await increaseTime(duration.days(1.7)); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor4}); + let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + let latestTimestamp = 0; + tempArrayGlobal.push(1); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); + latestTimestamp = data[0][i]; + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 16); + assert.equal(data[0].length - 1, 3); + assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 1); + }); + + it("Should add the daily restriction successfully", async() => { + await I_VolumeRestrictionTM.addDailyGlobalRestriction( + web3.utils.toWei("5"), + 0, + latestTime() + duration.seconds(2), + latestTime() + duration.days(3), + 0, + { + from: token_owner + } + ); + let data = await I_VolumeRestrictionTM.dailyGlobalRestriction.call(); + assert.equal(data[0].dividedBy(new BigNumber(10).pow(18)).toNumber(), 5); + assert.equal(data[1].toNumber(), 0); + assert.equal(data[5].toNumber(), 0); + }); + + it("Should failed to transact tokens -- failed because amount of tx is more than the daily limit",async() => { + let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + await increaseTime(duration.days(2)); + // Failed because amount of tokens is greater than the daily limit + await catchRevert( + I_SecurityToken.transfer(account_delegate3, web3.utils.toWei("5.1"), {from: account_investor4}) + ); + }); + + it("Should transfer the tokens with in the daily limit", async() => { + let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + await I_SecurityToken.transfer(account_delegate3, web3.utils.toWei("4.9"), {from: account_investor4}); + tempArrayGlobal.push(0); + tempArrayGlobal.push(4.9); + let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 5.9); + assert.equal(data[0].length - 1, 5); + assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 4.9); + }); + + it("Should transact the tokens more than the daily limit because daily limit restriction is ended", async() => { + let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + await increaseTime(duration.days(1)); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_delegate3}); + tempArrayGlobal.push(10); + let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} + `); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 14.9); + assert.equal(data[0].length - 1, 6); + assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 10); + }); + }) + + describe("Test for the exemptlist", async() => { + + it("Should add the token holder in the exemption list", async() => { + + }) + }) }); \ No newline at end of file From 61262019aef2dd8e6edc8750564d542904ab574e Mon Sep 17 00:00:00 2001 From: satyam Date: Sun, 25 Nov 2018 17:30:00 +0530 Subject: [PATCH 180/582] minor fixes --- .../TransferManager/VolumeRestrictionTM.sol | 4 ++-- .../TransferManager/VolumeRestrictionTMFactory.sol | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index 60d244758..b05842b75 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -174,7 +174,7 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _endTime, uint256 _restrictionType ) - public + external withPerm(ADMIN) { _addIndividualRestriction( @@ -366,7 +366,7 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _endTime, uint256 _restrictionType ) - public + external withPerm(ADMIN) { _modifyIndividualRestriction( diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol index 5065b42d7..e1636fbe0 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol @@ -30,10 +30,10 @@ contract VolumeRestrictionTMFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Sufficent Allowance is not provided"); - address VolumeRestrictionTransferManager = new VolumeRestrictionTM(msg.sender, address(polyToken)); + address volumeRestrictionTransferManager = new VolumeRestrictionTM(msg.sender, address(polyToken)); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(VolumeRestrictionTransferManager), getName(), address(this), msg.sender, setupCost, now); - return address(VolumeRestrictionTransferManager); + emit GenerateModuleFromFactory(volumeRestrictionTransferManager, getName(), address(this), msg.sender, setupCost, now); + return volumeRestrictionTransferManager; } @@ -51,17 +51,18 @@ contract VolumeRestrictionTMFactory is ModuleFactory { */ function getInstructions() external view returns(string) { /*solium-disable-next-line max-len*/ - return ""; /// TODO - need to add the Instruction for module + return "Module used to restrict the volume of tokens traded by the token holders"; } /** * @notice Get the tags related to the module factory */ function getTags() public view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](2); + bytes32[] memory availableTags = new bytes32[](3); availableTags[0] = "Maximum Volume"; availableTags[1] = "Transfer Restriction"; availableTags[2] = "Daily Restriction"; + availableTags[3] = "Individual Restriction"; return availableTags; } From b069122054a94ba46eff367ceff789ef36464def Mon Sep 17 00:00:00 2001 From: satyam Date: Sun, 25 Nov 2018 17:41:10 +0530 Subject: [PATCH 181/582] reduce the error strings to lower the sixe of the contract --- .../TransferManager/VolumeRestrictionTM.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index b05842b75..7fee7d66c 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -132,7 +132,7 @@ contract VolumeRestrictionTM is ITransferManager { // If `_from` is present in the exemptionList or it is `0x0` address then it will not follow the vol restriction if (!paused && _from != address(0) && !exemptList[_from]) { // Function must only be called by the associated security token if _isTransfer == true - require(msg.sender == securityToken || !_isTransfer, "Sender is not the owner"); + require(msg.sender == securityToken || !_isTransfer); // Checking the individual restriction if the `_from` comes in the individual category if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { return _individualRestrictionCheck(_from, _amount, _isTransfer); @@ -150,7 +150,7 @@ contract VolumeRestrictionTM is ITransferManager { * @param _change Boolean value used to add (i.e true) or remove (i.e false) from the list */ function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { - require(_wallet != address(0), "0x0 address not allowed"); + require(_wallet != address(0), "Invalid address"); exemptList[_wallet] = _change; emit ChangedExemptWalletList(_wallet, _change); } @@ -211,7 +211,7 @@ contract VolumeRestrictionTM is ITransferManager { withPerm(ADMIN) { _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); - require(_holders.length == _allowedTokens.length, "Array length mismatch"); + require(_holders.length == _allowedTokens.length, "Length mismatch"); for (uint256 i = 0; i < _holders.length; i++) { _addIndividualRestriction( _holders[i], @@ -247,7 +247,7 @@ contract VolumeRestrictionTM is ITransferManager { { require( globalRestriction.endTime == 0 || globalRestriction.endTime > now, - "Restriction already present" + "Not allowed" ); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); globalRestriction = VolumeRestriction( @@ -288,7 +288,7 @@ contract VolumeRestrictionTM is ITransferManager { { require( dailyGlobalRestriction.endTime == 0 || dailyGlobalRestriction.endTime > now, - "Restriction already present" + "Not Allowed" ); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); dailyGlobalRestriction = VolumeRestriction( @@ -403,7 +403,7 @@ contract VolumeRestrictionTM is ITransferManager { withPerm(ADMIN) { _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); - require(_holders.length == _allowedTokens.length, "Array length mismatch"); + require(_holders.length == _allowedTokens.length, "Length mismatch"); for (uint256 i = 0; i < _holders.length; i++) { _modifyIndividualRestriction( _holders[i], @@ -437,7 +437,7 @@ contract VolumeRestrictionTM is ITransferManager { external withPerm(ADMIN) { - require(globalRestriction.startTime > now, "Not allowed to modify"); + require(globalRestriction.startTime > now, "Not allowed"); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); globalRestriction = VolumeRestriction( _allowedTokens, @@ -477,7 +477,7 @@ contract VolumeRestrictionTM is ITransferManager { external withPerm(ADMIN) { - require(dailyGlobalRestriction.startTime > now, "Not allowed to modify"); + require(dailyGlobalRestriction.startTime > now, "Not allowed"); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); dailyGlobalRestriction = VolumeRestriction( _allowedTokens, From e8ad72317cc3270d78f7100b8064ca0df3dc5c80 Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Sun, 25 Nov 2018 14:33:05 -0300 Subject: [PATCH 182/582] Update CHANGELOG.md --- CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c2ec5fdf..db3d8dcde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,19 +5,17 @@ All notable changes to this project will be documented in this file. [__2.1.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-09-18__ -## Added +# USDTieredSTO 2.0.1 * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. * Added `getSTODetails` to USDTSTO. * Added an Array of Tiers that will hold data about every tier in USDTSTO. * Added `buyWithETHRateLimited`, `buyWithPOLYRateLimited` and `buyWithUSDRateLimited` to USDTSTO. * Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. +* Removed individual mappings for tier data removed in UDSTSTO. ##Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. -## Removed -* Individual mappings for tier data removed in UDSTSTO. - # v1.5.0 [__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ From f1216963784eb6bd66f5ba8bbabbcbc66d54930b Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 25 Nov 2018 17:52:56 +0000 Subject: [PATCH 183/582] Fix tests --- test/h_general_transfer_manager.js | 100 ++++++++++++++++------------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 9105c63e6..750a4cfbc 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -411,52 +411,60 @@ contract("GeneralTransferManager", accounts => { }); - // describe("Buy tokens using on-chain whitelist and positive offset", async () => { - // // let snap_id; - // - // it("Should Buy the tokens", async () => { - // - // // Add the Investor in to the whitelist - // // snap_id = await takeSnapshot(); - // let tx = await I_GeneralTransferManager.modifyWhitelist( - // account_investor1, - // latestTime(), - // latestTime(), - // latestTime(), - // 1, - // { - // from: account_issuer, - // gas: 6000000 - // } - // ); - // - // assert.equal( - // tx.logs[0].args._investor.toLowerCase(), - // account_investor1.toLowerCase(), - // "Failed in adding the investor in whitelist" - // ); - // - // // Jump time - // await increaseTime(5000); - // - // // Mint some tokens - // console.log(await I_GeneralTransferManager.offset.call()); - // await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); - // - // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); - // await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); - // }); - // - // it("Add an offset and check transfers are disabled", async () => { - // let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 1, {from: token_owner}); - // await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); - // await increaseTime(duration.days(10)); - // await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); - // tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); - // // await revertToSnapshot(snap_id); - // }); - // - // }); + describe("Buy tokens using on-chain whitelist and positive offset", async () => { + // let snap_id; + + it("Should Buy the tokens", async () => { + + // Add the Investor in to the whitelist + // snap_id = await takeSnapshot(); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(20), + 1, + { + from: account_issuer, + gas: 6000000 + } + ); + + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor1.toLowerCase(), + "Failed in adding the investor in whitelist" + ); + + // Jump time + await increaseTime(5000); + // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); + // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); + + // Mint some tokens + console.log(await I_GeneralTransferManager.offset.call()); + await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + }); + + it("Add an offset and check transfers are disabled", async () => { + let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 1, {from: token_owner}); + // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); + // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); + + await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); + await increaseTime(duration.days(10)); + // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); + // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); + + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); + // await revertToSnapshot(snap_id); + }); + + }); describe("Buy tokens using off-chain whitelist", async () => { it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { From 094769752bdf0c8f238388c5de56c6de25db22f5 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 25 Nov 2018 18:05:30 +0000 Subject: [PATCH 184/582] Fix typo --- contracts/modules/TransferManager/GeneralTransferManager.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index c64c99c34..d9b7857ac 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -146,9 +146,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA; } if (_from == issuanceAddress && (whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { - if ((whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { - return Result.NA; - } + return Result.NA; } if (allowAllWhitelistIssuances && _from == issuanceAddress) { return _onWhitelist(_to) ? Result.VALID : Result.NA; From af1a97e3dabfc8574d3714f2e88ba2850c4d8a4f Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 25 Nov 2018 18:12:55 +0000 Subject: [PATCH 185/582] Change onWhitelist logic --- contracts/modules/TransferManager/GeneralTransferManager.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index d9b7857ac..a7029caa1 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -273,8 +273,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag * @param _investor Address of the investor */ function _onWhitelist(address _investor) internal view returns(bool) { - return (((whitelist[_investor].fromTime != 0) || (whitelist[_investor].toTime != 0)) && - (whitelist[_investor].expiryTime >= uint64(now))); /*solium-disable-line security/no-block-members*/ + return (whitelist[_investor].expiryTime >= uint64(now)); /*solium-disable-line security/no-block-members*/ } /** From 67037aa0dccbfcb0d22bb410ad87ddcd75d6dfda Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 25 Nov 2018 18:20:27 +0000 Subject: [PATCH 186/582] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db3d8dcde..0e19e93ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,12 @@ All notable changes to this project will be documented in this file. * Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. * Removed individual mappings for tier data removed in UDSTSTO. +# GeneralTransferManager +* Add an Offset that can be used to move all from & to dates forwards or backwards by a fixed offset. +* Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`) +* Fix for when `allowAllWhitelistIssuances` is FALSE +* Make GTM a Proxy based implementation to reduce deployment gas costs + ##Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. From 492127f8366f1ad955bf6e450f2bd7e8b113c446 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 25 Nov 2018 18:30:57 +0000 Subject: [PATCH 187/582] Update all test cases --- test/b_capped_sto.js | 14 +++++------ test/c_checkpoints.js | 6 ++--- test/d_count_transfer_manager.js | 8 +++---- test/e_erc20_dividends.js | 12 +++++----- test/f_ether_dividends.js | 12 +++++----- test/i_Issuance.js | 4 ++-- test/j_manual_approval_transfer_manager.js | 6 ++--- test/l_percentage_transfer_manager.js | 8 +++---- test/m_presale_sto.js | 6 ++--- test/o_security_token.js | 20 ++++++++-------- test/p_usd_tiered_sto.js | 18 +++++++------- test/q_usd_tiered_sto_sim.js | 6 ++--- test/r_concurrent_STO.js | 6 ++--- test/v_tracked_redemptions.js | 6 ++--- ...kup_volume_restriction_transfer_manager.js | 14 +++++------ test/x_single_trade_volume_restriction.js | 24 +++++++++---------- test/y_scheduled_checkpoints.js | 6 ++--- 17 files changed, 88 insertions(+), 88 deletions(-) diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index d89fe6eba..fe59d9c03 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -130,7 +130,7 @@ contract("CappedSTO", accounts => { // STEP 5: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - + // STEP 6: Deploy the CappedSTOFactory I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); @@ -360,7 +360,7 @@ contract("CappedSTO", accounts => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { from: account_issuer }); @@ -443,7 +443,7 @@ contract("CappedSTO", accounts => { fromTime, toTime + duration.days(20), expiryTime, - true, + 1, { from: account_issuer } @@ -565,7 +565,7 @@ contract("CappedSTO", accounts => { it("Should successfully whitelist investor 3", async () => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { from: account_issuer, gas: 500000 }); @@ -733,7 +733,7 @@ contract("CappedSTO", accounts => { "Tokens are not transfered properly" ); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, P_fromTime, P_toTime, P_expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, P_fromTime, P_toTime, P_expiryTime, 1, { from: account_issuer, gas: 500000 }); @@ -800,7 +800,7 @@ contract("CappedSTO", accounts => { P_fromTime, P_toTime + duration.days(20), P_expiryTime, - true, + 1, { from: account_issuer, gas: 500000 @@ -997,7 +997,7 @@ contract("CappedSTO", accounts => { await I_PolyToken.getTokens(polyToInvest * Math.pow(10, 18), account_investor3); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, 1, { from: account_issuer, gas: 500000 }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 6a08b6dea..2ba198f83 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -149,7 +149,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - false, + 0, { from: account_issuer, gas: 6000000 @@ -176,7 +176,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - false, + 0, { from: account_issuer, gas: 6000000 @@ -201,7 +201,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - false, + 0, { from: account_issuer, gas: 6000000 diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 1a1e7717a..4e86bdbb6 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -200,7 +200,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -230,7 +230,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -257,7 +257,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -282,7 +282,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index b832bcee2..6a4baeab6 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -89,7 +89,7 @@ contract("ERC20DividendCheckpoint", accounts => { account_investor4 = accounts[9]; account_temp = accounts[2]; account_manager = accounts[5]; - + // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -202,7 +202,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -232,7 +232,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -372,7 +372,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(20), - true, + 1, { from: account_issuer, gas: 500000 @@ -434,7 +434,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -970,7 +970,7 @@ contract("ERC20DividendCheckpoint", accounts => { let expiry = latestTime() + duration.days(10); let exclusions = [1]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); - await I_SecurityToken.createCheckpoint({ from: token_owner }); + await I_SecurityToken.createCheckpoint({ from: token_owner }); await catchRevert(I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index b4e5bbf2b..68c11f72f 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -200,7 +200,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -230,7 +230,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -364,7 +364,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(20), - true, + 1, { from: account_issuer, gas: 500000 @@ -415,7 +415,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -719,7 +719,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -851,7 +851,7 @@ contract("EtherDividendCheckpoint", accounts => { let expiry = latestTime() + duration.days(10); let exclusions = [1]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); - await I_SecurityToken.createCheckpoint({ from: token_owner }); + await I_SecurityToken.createCheckpoint({ from: token_owner }); await catchRevert(I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, diff --git a/test/i_Issuance.js b/test/i_Issuance.js index ac1fcdd37..efcf0db96 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -215,7 +215,7 @@ contract("Issuance", accounts => { fromTime + duration.days(70), toTime + duration.days(90), expiryTime + duration.days(50), - true, + 1, { from: account_polymath } @@ -271,7 +271,7 @@ contract("Issuance", accounts => { }); it("should add the investor into the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { from: account_delegate, gas: 7000000 }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 0461f287a..c817f5c44 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -171,7 +171,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -201,7 +201,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -290,7 +290,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index b15ee41a0..530b202c8 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -120,7 +120,7 @@ contract("PercentageTransferManager", accounts => { // STEP 4(b): Deploy the PercentageTransferManager [P_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); - + // Printing all the contract addresses console.log(` --------------------- Polymath Network Smart Contracts: --------------------- @@ -192,7 +192,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -222,7 +222,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -287,7 +287,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index a89932dc4..35a348c30 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -236,7 +236,7 @@ contract("PreSaleSTO", accounts => { expiryTime = toTime + duration.days(100); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { from: account_issuer, gas: 6000000 }); @@ -277,7 +277,7 @@ contract("PreSaleSTO", accounts => { expiryTime = toTime + duration.days(100); // Add the Investor in to the whitelist - let tx1 = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { + let tx1 = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { from: account_issuer, gas: 6000000 }); @@ -285,7 +285,7 @@ contract("PreSaleSTO", accounts => { assert.equal(tx1.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); // Add the Investor in to the whitelist - let tx2 = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { + let tx2 = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { from: account_issuer, gas: 6000000 }); diff --git a/test/o_security_token.js b/test/o_security_token.js index 52521181e..7d2722a20 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -193,7 +193,7 @@ contract("SecurityToken", accounts => { let toTime = fromTime + duration.days(100); let expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 6000000 }); @@ -212,7 +212,7 @@ contract("SecurityToken", accounts => { let toTime = fromTime + duration.days(100); let expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 6000000 }); @@ -517,7 +517,7 @@ contract("SecurityToken", accounts => { toTime = fromTime + duration.days(100); expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 6000000 }); @@ -614,7 +614,7 @@ contract("SecurityToken", accounts => { }); it("Should transfer from whitelist investor1 to whitelist investor 2", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 500000 }); @@ -636,7 +636,7 @@ contract("SecurityToken", accounts => { it("Should transferFrom from one investor to other", async () => { await I_SecurityToken.approve(account_investor1, 2 * Math.pow(10, 18), { from: account_investor2 }); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 500000 }); @@ -682,7 +682,7 @@ contract("SecurityToken", accounts => { }); it("Should add the investor in the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, 1, { from: account_delegate, gas: 6000000 }); @@ -722,7 +722,7 @@ contract("SecurityToken", accounts => { }); it("Should remove investor from the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, 0, 0, 0, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, 0, 0, 0, 1, { from: account_delegate, gas: 6000000 }); @@ -751,7 +751,7 @@ contract("SecurityToken", accounts => { }); it("Should fail in buying to tokens", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, 1, { from: account_delegate, gas: 6000000 }); @@ -939,7 +939,7 @@ contract("SecurityToken", accounts => { latestTime(), latestTime() + duration.seconds(2), latestTime() + duration.days(50), - true, + 1, { from: account_delegate, gas: 6000000 @@ -982,7 +982,7 @@ contract("SecurityToken", accounts => { latestTime(), latestTime() + duration.seconds(2), latestTime() + duration.days(50), - true, + 1, { from: account_delegate, gas: 6000000 diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 604eb1aaf..8a274942a 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -222,7 +222,7 @@ contract("USDTieredSTO", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 4: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, I_PolyToken.address, 0); @@ -1005,7 +1005,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1105,7 +1105,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1160,7 +1160,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1230,7 +1230,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1285,7 +1285,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime(); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1353,7 +1353,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER @@ -4482,7 +4482,7 @@ contract("USDTieredSTO", accounts => { "fundsRaisedUSD not changed as expected" ); }); - + it("should return minted tokens in a tier", async () => { let totalMinted = (await I_USDTieredSTO_Array[0].getTokensSoldByTier.call(0)).toNumber(); let individualMinted = await I_USDTieredSTO_Array[0].getTokensMintedByTier.call(0); @@ -4564,7 +4564,7 @@ contract("USDTieredSTO", accounts => { assert.equal((await I_USDTieredSTOFactory.getSetupCost.call()).toNumber(), STOSetupCost); assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0], 3); assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), "USDTieredSTO", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.description.call(), + assert.equal(await I_USDTieredSTOFactory.description.call(), "It allows both accredited and non-accredited investors to contribute into the STO. Non-accredited investors will be capped at a maximum investment limit (as a default or specific to their jurisdiction). Tokens will be sold according to tiers sequentially & each tier has its own price and volume of tokens to sell. Upon receipt of funds (ETH, POLY or DAI), security tokens will automatically transfer to investor’s wallet address", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.title.call(), "USD Tiered STO", "Wrong Module added"); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 55f84f2b3..31929ade5 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -195,7 +195,7 @@ contract("USDTieredSTO Sim", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 5: Deploy the USDTieredSTOFactory @@ -353,13 +353,13 @@ contract("USDTieredSTO Sim", accounts => { let fromTime = latestTime() + duration.days(15); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = true; + let canBuyFromSTO = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, 0, { from: ISSUER }); await increaseTime(duration.days(3)); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 7912658a4..36761308e 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -2,7 +2,7 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import { takeSnapshot, increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; -import { +import { setUpPolymathNetwork, deployDummySTOAndVerifyed, deployCappedSTOAndVerifyed, @@ -94,7 +94,7 @@ contract("Concurrent STO", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + // STEP 2: Deploy the STO Factories [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, STOSetupCost); @@ -159,7 +159,7 @@ contract("Concurrent STO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = true; + let canBuyFromSTO = 1; let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: account_issuer, diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 159564651..eacddd87e 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -102,7 +102,7 @@ contract("TrackedRedemption", accounts => { I_STRProxied ] = instances; - + // STEP 4: Deploy the TrackedRedemption [I_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); [P_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); @@ -190,7 +190,7 @@ contract("TrackedRedemption", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -220,7 +220,7 @@ contract("TrackedRedemption", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index fe06f3f5c..7646fb031 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -112,7 +112,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { STFactory: ${I_STFactory.address} GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} - LockupVolumeRestrictionTransferManagerFactory: + LockupVolumeRestrictionTransferManagerFactory: ${I_VolumeRestrictionTransferManagerFactory.address} ----------------------------------------------------------------------------- `); @@ -165,7 +165,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer }); @@ -192,7 +192,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer }); @@ -249,7 +249,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer }); @@ -346,14 +346,14 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // balance should be 9000000000000000000 here (9 eth) let balance = await I_SecurityToken.balanceOf(account_investor2) - + // create a lockup for their entire balance // over 16 seconds total, with 4 periods of 4 seconds each. // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 await catchRevert( I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }) ); - + }); it("Should prevent the transfer of tokens in a lockup", async() => { @@ -572,7 +572,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); it("Should revert if the parameters are bad when creating multiple lockups", async() => { - + await catchRevert( // pass in the wrong number of params. txn should revert I_VolumeRestrictionTransferManager.addLockUpMulti( diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index 15c01e68c..25243a638 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -107,7 +107,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); - + }); describe("Generate the SecurityToken", async () => { @@ -165,7 +165,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer }); @@ -193,7 +193,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer }); @@ -212,7 +212,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { // it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { let managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); await catchRevert( I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { from: token_owner}) @@ -222,7 +222,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); - + let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); @@ -291,7 +291,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]) ); - await catchRevert( + await catchRevert( I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { from: token_owner }) ); @@ -342,7 +342,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { await catchRevert ( I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { from: token_owner }) ); - // Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage + // Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage await catchRevert ( I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { from: token_owner }) ); @@ -393,7 +393,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { from: token_owner }); assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - + //Global limit can be set by non-admins await catchRevert( I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89) @@ -542,7 +542,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer } ); @@ -552,7 +552,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer } ); @@ -562,7 +562,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer } ); @@ -667,7 +667,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { }); it('should change transfer limits to tokens', async () => { - // Should not change to percentage again + // Should not change to percentage again await catchRevert( I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { from: token_owner }) ); diff --git a/test/y_scheduled_checkpoints.js b/test/y_scheduled_checkpoints.js index 5fcc03a74..864c6b9a1 100644 --- a/test/y_scheduled_checkpoints.js +++ b/test/y_scheduled_checkpoints.js @@ -192,7 +192,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -235,7 +235,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -270,7 +270,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 From 704751d3ed72e06605e29e460fe4148efb3bd582 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 26 Nov 2018 10:42:33 +0530 Subject: [PATCH 188/582] Add whitelist optimization --- .../GeneralTransferManager.sol | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index a7029caa1..566ee19d1 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -179,6 +179,26 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag ) public withPerm(WHITELIST) + { + _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + } + + /** + * @notice Adds or removes addresses from the whitelist. + * @param _investor is the address to whitelist + * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens + * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others + * @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC + * @param _canBuyFromSTO is used to know whether the investor is restricted investor or not. + */ + function _modifyWhitelist( + address _investor, + uint64 _fromTime, + uint64 _toTime, + uint64 _expiryTime, + uint8 _canBuyFromSTO + ) + internal { if (whitelist[_investor].added == uint8(0)) { investors.push(_investor); @@ -208,7 +228,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag require(_toTimes.length == _expiryTimes.length, "Mismatched input lengths"); require(_canBuyFromSTO.length == _toTimes.length, "Mismatched input length"); for (uint256 i = 0; i < _investors.length; i++) { - modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); + _modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); } } From f44d05372852c7355e0a7dd2f46d9c3cadc96d40 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 26 Nov 2018 12:53:27 +0530 Subject: [PATCH 189/582] minor fixes --- .../TransferManager/VolumeRestrictionTM.sol | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index 7fee7d66c..e61743445 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -246,10 +246,13 @@ contract VolumeRestrictionTM is ITransferManager { withPerm(ADMIN) { require( - globalRestriction.endTime == 0 || globalRestriction.endTime > now, + globalRestriction.endTime < now, "Not allowed" ); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + if (globalRestriction.endTime != 0) { + removeGlobalRestriction(); + } globalRestriction = VolumeRestriction( _allowedTokens, _allowedPercentageOfTokens, @@ -287,7 +290,7 @@ contract VolumeRestrictionTM is ITransferManager { withPerm(ADMIN) { require( - dailyGlobalRestriction.endTime == 0 || dailyGlobalRestriction.endTime > now, + dailyGlobalRestriction.endTime < now, "Not Allowed" ); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); @@ -330,7 +333,7 @@ contract VolumeRestrictionTM is ITransferManager { /** * @notice Use to remove the global restriction */ - function removeGlobalRestriction() external withPerm(ADMIN) { + function removeGlobalRestriction() public withPerm(ADMIN) { require(globalRestriction.endTime != 0, "Not present"); globalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); globalBucketDetails.timestamps.length = 0; @@ -437,7 +440,7 @@ contract VolumeRestrictionTM is ITransferManager { external withPerm(ADMIN) { - require(globalRestriction.startTime > now, "Not allowed"); + require(globalRestriction.startTime < now, "Not allowed"); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); globalRestriction = VolumeRestriction( _allowedTokens, @@ -477,7 +480,7 @@ contract VolumeRestrictionTM is ITransferManager { external withPerm(ADMIN) { - require(dailyGlobalRestriction.startTime > now, "Not allowed"); + require(dailyGlobalRestriction.startTime < now, "Not allowed"); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); dailyGlobalRestriction = VolumeRestriction( _allowedTokens, @@ -770,8 +773,8 @@ contract VolumeRestrictionTM is ITransferManager { internal { _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - require(individualRestriction[_holder].startTime > now, "Not allowed to modify"); - + require(individualRestriction[_holder].startTime < now, "Not allowed to modify"); + individualRestriction[_holder] = VolumeRestriction( _allowedTokens, _allowedPercentageOfTokens, @@ -803,12 +806,15 @@ contract VolumeRestrictionTM is ITransferManager { internal { require( - individualRestriction[_holder].endTime == 0 || individualRestriction[_holder].endTime > now, + individualRestriction[_holder].endTime < now, "Restriction already present" ); require(_holder != address(0) && !exemptList[_holder], "Invalid address"); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + if (individualRestriction[_holder].endTime != 0) { + _removeIndividualRestriction(_holder); + } individualRestriction[_holder] = VolumeRestriction( _allowedTokens, _allowedPercentageOfTokens, @@ -837,7 +843,7 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _restrictionType ) internal - pure + view { require(_restrictionType == 0 || _restrictionType == 1, "Invalid restriction type"); if (_restrictionType == uint256(RestrictionType.Fixed)) { @@ -848,7 +854,7 @@ contract VolumeRestrictionTM is ITransferManager { "Percentage of tokens not within (0,100]" ); } - require(_startTime > 0 && _endTime > _startTime); + require(_startTime >= now && _endTime > _startTime); // Maximum limit for the rollingPeriod is 365 days require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365); require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays); From 96bf749123ecf16e3abc5799ee19da856c3861b1 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 26 Nov 2018 13:50:15 +0530 Subject: [PATCH 190/582] add more test cases --- test/z_volume_restriction_tm.js | 395 +++++++++++++++++++++++++++++++- 1 file changed, 391 insertions(+), 4 deletions(-) diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js index 298fc18c8..f59e06486 100644 --- a/test/z_volume_restriction_tm.js +++ b/test/z_volume_restriction_tm.js @@ -209,6 +209,176 @@ contract('VolumeRestrictionTransferManager', accounts => { describe("Test for the addIndividualRestriction", async() => { + it("Should add the restriction -- failed because of bad owner", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei("12"), + 0, + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 0, + { + from: account_polymath + } + ) + ); + }) + + it("Should add the restriction -- failed because of bad parameters i.e invalid restriction type", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei("12"), + 0, + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 3, + { + from: token_owner + } + ) + ); + }) + + it("Should add the restriction -- failed because of bad parameters i.e Invalid value of allowed tokens", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + 0, + 0, + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ) + ); + }) + + it("Should add the restriction -- failed because of bad parameters i.e Percentage of tokens not within (0,100]", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + 0, + 0, + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 1, + { + from: token_owner + } + ) + ); + }) + + it("Should add the restriction -- failed because of bad parameters i.e Percentage of tokens not within (0,100]", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + 0, + web3.utils.toWei("10"), + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 1, + { + from: token_owner + } + ) + ); + }) + + it("Should add the restriction -- failed because of bad parameters i.e invalid dates", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei("10"), + 0, + latestTime() - duration.seconds(5), + 3, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ) + ); + }) + + it("Should add the restriction -- failed because of bad parameters i.e invalid dates", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei("10"), + 0, + latestTime() + duration.days(2), + 3, + latestTime() + duration.days(1), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei("10"), + 0, + latestTime() + duration.days(2), + 0, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei("10"), + 0, + latestTime() + duration.days(2), + 366, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei("10"), + 0, + latestTime() + duration.days(2), + 3, + latestTime() + duration.days(3), + 0, + { + from: token_owner + } + ) + ); + }); + it("Should add the restriction succesfully", async() => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -216,7 +386,7 @@ contract('VolumeRestrictionTransferManager', accounts => { 0, latestTime() + duration.seconds(2), 3, - latestTime() + duration.days(10), + latestTime() + duration.days(5), 0, { from: token_owner @@ -227,6 +397,211 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._typeOfRestriction, 0); }); + it("Should add the restriction for multiple investor -- failed because of bad owner", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], + [0,0,0], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3,4,5], + [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], + [0,0,0], + { + from: account_polymath + } + ) + ) + }); + + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3], + [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], + [0,0,0], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3,4,5], + [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], + [0,0,0], + { + from: token_owner + } + ) + ) + }); + + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [web3.utils.toWei("12"), web3.utils.toWei("10")], + [0,0,0], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3,4,5], + [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], + [0,0,0], + { + from: account_polymath + } + ) + ) + }); + + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], + [0,0], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3,4,5], + [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], + [0,0,0], + { + from: token_owner + } + ) + ) + }); + + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], + [0,0,0], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3,4,5], + [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], + [0,0,0], + { + from: token_owner + } + ) + ) + }); + + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], + [0,0,0], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3], + [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], + [0,0,0], + { + from: token_owner + } + ) + ) + }); + + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], + [0,0,0], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3, 4, 5], + [latestTime() + duration.days(5)], + [0,0,0], + { + from: token_owner + } + ) + ) + }); + + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], + [0,0,0], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3, 4, 5], + [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], + [], + { + from: token_owner + } + ) + ) + }); + + it("Should add the restriction for multiple investor successfully", async() => { + await I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], + [0,0,0], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3, 4, 5], + [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], + [0,0,0], + { + from: token_owner + } + ); + assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 3); + assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3))[3].toNumber(), 4); + assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor4))[3].toNumber(), 5); + }); + + it("Should remove the restriction multi -- failed because of address is 0", async() => { + await catchRevert( + I_VolumeRestrictionTM.removeIndividualRestrictionMulti( + [0, account_delegate3, account_investor4], + { + from: token_owner + } + ) + ); + }); + + it("Should successfully remove the restriction", async() => { + await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, {from: token_owner}); + assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 0); + }); + + it("Should remove the restriction -- failed because restriction not present anymore", async() => { + await catchRevert( + I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, {from: token_owner}) + ); + }); + + it("Should remove the restriction multi", async() => { + await I_VolumeRestrictionTM.removeIndividualRestrictionMulti( + [account_delegate3, account_investor4], + { + from: token_owner + } + ) + }); + + it("Should add the restriction succesfully after the expiry of previous one", async() => { + await increaseTime(duration.days(5.1)); + + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei("12"), + 0, + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ); + + assert.equal(tx.logs[1].args._holder, account_investor1); + assert.equal(tx.logs[1].args._typeOfRestriction, 0); + }); + it("Should not successfully transact the tokens -- failed because volume is above the limit", async() => { await increaseTime(duration.seconds(10)); await catchRevert( @@ -985,8 +1360,20 @@ contract('VolumeRestrictionTransferManager', accounts => { describe("Test for the exemptlist", async() => { + it("Should add the token holder in the exemption list -- failed because of bad owner", async() => { + await catchRevert( + I_VolumeRestrictionTM.changeExemptWalletList(account_investor4, true, {from: account_polymath}) + ); + }); + it("Should add the token holder in the exemption list", async() => { - - }) - }) + await I_VolumeRestrictionTM.changeExemptWalletList(account_investor4, true, {from: token_owner}); + let beforeBal = await I_SecurityToken.balanceOf.call(account_investor4); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("3"), {from: account_investor4}); + let afterBal = await I_SecurityToken.balanceOf.call(account_investor4); + let diff = beforeBal.minus(afterBal); + assert.equal(web3.utils.fromWei((diff.toNumber()).toString()), 3); + }); + }); + }); \ No newline at end of file From 8e44d1b8c6eed3088556b188c3ace1dfed545501 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 26 Nov 2018 14:34:48 +0530 Subject: [PATCH 191/582] remove the reason strings --- .../TransferManager/VolumeRestrictionTM.sol | 14 +++++++------- .../TransferManager/VolumeRestrictionTMFactory.sol | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index e61743445..9e16d60ef 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -334,7 +334,7 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Use to remove the global restriction */ function removeGlobalRestriction() public withPerm(ADMIN) { - require(globalRestriction.endTime != 0, "Not present"); + require(globalRestriction.endTime != 0); globalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); globalBucketDetails.timestamps.length = 0; globalBucketDetails.sumOfLastPeriod = 0; @@ -345,7 +345,7 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Use to remove the daily global restriction */ function removeDailyGlobalRestriction() external withPerm(ADMIN) { - require(dailyGlobalRestriction.endTime != 0, "Not present"); + require(dailyGlobalRestriction.endTime != 0); dailyGlobalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); emit DailyGlobalRestrictionRemoved(); } @@ -773,7 +773,7 @@ contract VolumeRestrictionTM is ITransferManager { internal { _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - require(individualRestriction[_holder].startTime < now, "Not allowed to modify"); + require(individualRestriction[_holder].startTime < now, "Not allowed"); individualRestriction[_holder] = VolumeRestriction( _allowedTokens, @@ -807,7 +807,7 @@ contract VolumeRestrictionTM is ITransferManager { { require( individualRestriction[_holder].endTime < now, - "Restriction already present" + "Already present" ); require(_holder != address(0) && !exemptList[_holder], "Invalid address"); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); @@ -845,13 +845,13 @@ contract VolumeRestrictionTM is ITransferManager { internal view { - require(_restrictionType == 0 || _restrictionType == 1, "Invalid restriction type"); + require(_restrictionType == 0 || _restrictionType == 1, "Invalid type"); if (_restrictionType == uint256(RestrictionType.Fixed)) { - require(_allowedTokens > 0, "Invalid value of allowed tokens"); + require(_allowedTokens > 0, "Invalid value"); } else { require( _allowedPercentageOfTokens > 0 && _allowedPercentageOfTokens <= 100 * 10 ** 16, - "Percentage of tokens not within (0,100]" + "Percentage is not within (0,100]" ); } require(_startTime >= now && _endTime > _startTime); diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol index e1636fbe0..4609ea2ff 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol @@ -29,7 +29,7 @@ contract VolumeRestrictionTMFactory is ModuleFactory { */ function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Sufficent Allowance is not provided"); + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent Allowance"); address volumeRestrictionTransferManager = new VolumeRestrictionTM(msg.sender, address(polyToken)); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(volumeRestrictionTransferManager, getName(), address(this), msg.sender, setupCost, now); From 6e95bc68cc63714657ccfbf2d60bd0a78ddb0ac4 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Mon, 26 Nov 2018 12:13:14 +0100 Subject: [PATCH 192/582] updated description for cappedSTO --- contracts/modules/STO/CappedSTOFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 89f3311d2..3dcd0af72 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -19,7 +19,7 @@ contract CappedSTOFactory is ModuleFactory { version = "1.0.0"; name = "CappedSTO"; title = "Capped STO"; - description = "Use to collects the funds and once the cap is reached then investment will be no longer entertained"; + description = "This smart contract creates a maximum number of tokens (i.e. hard cap) which the total aggregate of tokens acquired by all investors cannot exceed. Security tokens are sent to the investor upon reception of the funds (ETH or POLY), and any security tokens left upon termination of the offering will not be minted."; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } From b8935b3d4bddde76058588c4ff6c49e2e402cc7c Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Mon, 26 Nov 2018 12:37:23 +0100 Subject: [PATCH 193/582] fix test --- test/b_capped_sto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index d89fe6eba..fce1ee5e5 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -855,7 +855,7 @@ contract("CappedSTO", accounts => { assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), "CappedSTO", "Wrong Module added"); assert.equal( await I_CappedSTOFactory.description.call(), - "Use to collects the funds and once the cap is reached then investment will be no longer entertained", + "This smart contract creates a maximum number of tokens (i.e. hard cap) which the total aggregate of tokens acquired by all investors cannot exceed. Security tokens are sent to the investor upon reception of the funds (ETH or POLY), and any security tokens left upon termination of the offering will not be minted.", "Wrong Module added" ); assert.equal(await I_CappedSTOFactory.title.call(), "Capped STO", "Wrong Module added"); From 29dd21ce593b60577fb3173c8e59ecd7e416c734 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Mon, 26 Nov 2018 11:17:20 -0300 Subject: [PATCH 194/582] Minor fix --- CLI/commands/ST20Generator.js | 2 +- CLI/polymath-cli.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 727c112b4..1288fc17f 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -138,7 +138,7 @@ async function step_token_deploy(_name, _details, _divisible) { let divisibility; if (typeof _divisible !== 'undefined') { - divisibility = _divisible == 'true'; + divisibility = _divisible.toString() == 'true'; console.log(`Divisible: ${divisibility.toString()}`) } else { let divisible = readlineSync.question('Press "N" for Non-divisible type token or hit Enter for divisible type token (Default): '); diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 5ba286242..29bea752d 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -33,7 +33,7 @@ program .option('-o, --transferOwnership ', `Transfers the ticker's ownership to newOwner account. If newOwner is 'false', this step is skipped`) .option('-n, --tokenName ', 'Token name') .option('-d, --details
', 'Off-chain details of the token') - .option('-D, --divisible [div]', 'If token is divisible or not [true]', /^(true|false)/, 'true') + .option('-D, --divisible
', 'If token is divisible or not [true]', /^(true|false)/) .description('Wizard-like script that will guide technical users in the creation and deployment of an ST-20 token') .action(async function(cmd) { await gbl.initialize(program.remoteNode); From babb4cb4a04fd11131618e489f4fbb65e8ced97a Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 26 Nov 2018 14:31:10 +0000 Subject: [PATCH 195/582] Make Dividend modules proxies --- .../modules/Checkpoint/DividendCheckpoint.sol | 37 +--------- .../Checkpoint/DividendCheckpointStorage.sol | 50 +++++++++++++ .../Checkpoint/ERC20DividendCheckpoint.sol | 39 +++++----- .../ERC20DividendCheckpointFactory.sol | 9 ++- .../ERC20DividendCheckpointStorage.sol | 11 +++ .../Checkpoint/EtherDividendCheckpoint.sol | 25 +++---- .../EtherDividendCheckpointFactory.sol | 9 ++- .../GeneralTransferManager.sol | 6 ++ .../GeneralTransferManagerFactory.sol | 1 + .../GeneralTransferManagerStorage.sol | 2 - .../proxy/ERC20DividendCheckpointProxy.sol | 48 +++++++++++++ .../proxy/EtherDividendCheckpointProxy.sol | 47 ++++++++++++ scripts/compareStorageLayout.js | 71 +++++++++++++++++++ 13 files changed, 280 insertions(+), 75 deletions(-) create mode 100644 contracts/modules/Checkpoint/DividendCheckpointStorage.sol create mode 100644 contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol create mode 100644 contracts/proxy/ERC20DividendCheckpointProxy.sol create mode 100644 contracts/proxy/EtherDividendCheckpointProxy.sol create mode 100644 scripts/compareStorageLayout.js diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 452a48b13..3a345af25 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -8,6 +8,7 @@ pragma solidity ^0.4.24; import "./ICheckpoint.sol"; +import "./DividendCheckpointStorage.sol"; import "../Module.sol"; import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -17,43 +18,9 @@ import "openzeppelin-solidity/contracts/math/Math.sol"; * @title Checkpoint module for issuing ether dividends * @dev abstract contract */ -contract DividendCheckpoint is ICheckpoint, Module { +contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { using SafeMath for uint256; - uint256 public EXCLUDED_ADDRESS_LIMIT = 50; - bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; - bytes32 public constant MANAGE = "MANAGE"; - bytes32 public constant CHECKPOINT = "CHECKPOINT"; - - struct Dividend { - uint256 checkpointId; - uint256 created; // Time at which the dividend was created - uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass - uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - - // set to very high value to bypass - uint256 amount; // Dividend amount in WEI - uint256 claimedAmount; // Amount of dividend claimed so far - uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) - bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend - uint256 dividendWithheld; - uint256 dividendWithheldReclaimed; - mapping (address => bool) claimed; // List of addresses which have claimed dividend - mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends - bytes32 name; // Name/title - used for identification - } - - // List of all dividends - Dividend[] public dividends; - - // List of addresses which cannot claim dividends - address[] public excluded; - - // Mapping from address to withholding tax as a percentage * 10**16 - mapping (address => uint256) public withholdingTax; - - // Total amount of ETH withheld per investor - mapping (address => uint256) public investorWithheld; - event SetDefaultExcludedAddresses(address[] _excluded, uint256 _timestamp); event SetWithholding(address[] _investors, uint256[] _withholding, uint256 _timestamp); event SetWithholdingFixed(address[] _investors, uint256 _withholding, uint256 _timestamp); diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol new file mode 100644 index 000000000..bf86191e6 --- /dev/null +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -0,0 +1,50 @@ +/** + * DISCLAIMER: Under certain conditions, the function pushDividendPayment + * may fail due to block gas limits. + * If the total number of investors that ever held tokens is greater than ~15,000 then + * the function may fail. If this happens investors can pull their dividends, or the Issuer + * can use pushDividendPaymentToAddresses to provide an explict address list in batches + */ +pragma solidity ^0.4.24; + +/** + * @title Checkpoint module for issuing ether dividends + * @dev abstract contract + */ +contract DividendCheckpointStorage { + + uint256 public EXCLUDED_ADDRESS_LIMIT = 50; + bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; + bytes32 public constant MANAGE = "MANAGE"; + bytes32 public constant CHECKPOINT = "CHECKPOINT"; + + struct Dividend { + uint256 checkpointId; + uint256 created; // Time at which the dividend was created + uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass + uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - + // set to very high value to bypass + uint256 amount; // Dividend amount in WEI + uint256 claimedAmount; // Amount of dividend claimed so far + uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) + bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend + uint256 dividendWithheld; + uint256 dividendWithheldReclaimed; + mapping (address => bool) claimed; // List of addresses which have claimed dividend + mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends + bytes32 name; // Name/title - used for identification + } + + // List of all dividends + Dividend[] public dividends; + + // List of addresses which cannot claim dividends + address[] public excluded; + + // Mapping from address to withholding tax as a percentage * 10**16 + mapping (address => uint256) public withholdingTax; + + // Total amount of ETH withheld per investor + mapping (address => uint256) public investorWithheld; + +} diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 1f7f25cd5..b779088f7 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -1,17 +1,16 @@ pragma solidity ^0.4.24; import "./DividendCheckpoint.sol"; +import "./ERC20DividendCheckpointStorage.sol"; import "../../interfaces/IOwnable.sol"; import "../../interfaces/IERC20.sol"; /** * @title Checkpoint module for issuing ERC20 dividends */ -contract ERC20DividendCheckpoint is DividendCheckpoint { +contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendCheckpoint { using SafeMath for uint256; - // Mapping to token address for each dividend - mapping (uint256 => address) public dividendTokens; event ERC20DividendDeposited( address indexed _depositor, uint256 _checkpointId, @@ -68,8 +67,8 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { address _token, uint256 _amount, bytes32 _name - ) - external + ) + external withPerm(MANAGE) { createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name); @@ -133,16 +132,16 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _name Name/Title for identification */ function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, address[] _excluded, bytes32 _name - ) + ) public - withPerm(MANAGE) + withPerm(MANAGE) { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, _excluded, _name); } @@ -158,15 +157,15 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _name Name/Title for identification */ function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, address[] _excluded, bytes32 _name - ) - internal + ) + internal { ISecurityToken securityTokenInstance = ISecurityToken(securityToken); require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); @@ -210,7 +209,7 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { } /** - * @notice Emits the ERC20DividendDeposited event. + * @notice Emits the ERC20DividendDeposited event. * Seperated into a different function as a workaround for stack too deep error */ function _emitERC20DividendDepositedEvent( diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 5fd158c26..a684e553b 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./ERC20DividendCheckpoint.sol"; +import "../../proxy/ERC20DividendCheckpointProxy.sol"; import "../ModuleFactory.sol"; /** @@ -8,6 +8,8 @@ import "../ModuleFactory.sol"; */ contract ERC20DividendCheckpointFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken @@ -15,7 +17,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; @@ -24,6 +26,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { description = "Create ERC20 dividends for token holders at a specific checkpoint"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,7 +36,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "insufficent allowance"); - address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender, address(polyToken)); + address erc20DividendCheckpoint = new ERC20DividendCheckpointProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return erc20DividendCheckpoint; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol new file mode 100644 index 000000000..8bbd13bb6 --- /dev/null +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.24; + +/** + * @title Checkpoint module for issuing ERC20 dividends + */ +contract ERC20DividendCheckpointStorage { + + // Mapping to token address for each dividend + mapping (uint256 => address) public dividendTokens; + +} diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index 4def51468..f5a916818 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -8,6 +8,7 @@ import "../../interfaces/IOwnable.sol"; */ contract EtherDividendCheckpoint is DividendCheckpoint { using SafeMath for uint256; + event EtherDividendDeposited( address indexed _depositor, uint256 _checkpointId, @@ -56,7 +57,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, uint256 _checkpointId, bytes32 _name - ) + ) external payable withPerm(MANAGE) @@ -76,7 +77,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, address[] _excluded, bytes32 _name - ) + ) public payable withPerm(MANAGE) @@ -94,10 +95,10 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _name Name/title for identification */ function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] _excluded, + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] _excluded, bytes32 _name ) public @@ -116,12 +117,12 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _name Name/title for identification */ function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] _excluded, + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] _excluded, bytes32 _name - ) + ) internal { require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); @@ -169,7 +170,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { */ function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee); - _dividend.claimed[_payee] = true; + _dividend.claimed[_payee] = true; uint256 claimAfterWithheld = claim.sub(withheld); if (claimAfterWithheld > 0) { /*solium-disable-next-line security/no-send*/ diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 315760be1..3129fba42 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./EtherDividendCheckpoint.sol"; +import "../../proxy/EtherDividendCheckpointProxy.sol"; import "../ModuleFactory.sol"; /** @@ -8,6 +8,8 @@ import "../ModuleFactory.sol"; */ contract EtherDividendCheckpointFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken @@ -15,7 +17,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; @@ -24,6 +26,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { description = "Create ETH dividends for token holders at a specific checkpoint"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,7 +36,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent allowance or balance"); - address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender, address(polyToken)); + address ethDividendCheckpoint = new EtherDividendCheckpointProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return ethDividendCheckpoint; diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 566ee19d1..04028fead 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -26,6 +26,11 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag // Emit when investor details get modified related to their whitelisting event OffsetModified(uint64 _time, uint8 _isForward); + // _fromTime is the time from which the _investor can send tokens + // _toTime is the time from which the _investor can receive tokens + // if allowAllWhitelistIssuances is TRUE, then _toTime is ignored when receiving tokens from the issuance address + // if allowAllWhitelistTransfers is TRUE, then _toTime and _fromTime is ignored when sending or receiving tokens + // in any case, any investor sending or receiving tokens, must have a _expiryTime in the future event ModifyWhitelist( address _investor, uint256 _dateAdded, @@ -200,6 +205,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag ) internal { + require(_investor != address(0), "Invalid investor"); if (whitelist[_investor].added == uint8(0)) { investors.push(_investor); } diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index c37ab8b4b..4c81be20a 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -17,6 +17,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid logic contract"); version = "1.0.0"; name = "GeneralTransferManager"; title = "General Transfer Manager"; diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol index 6cfb29e21..f5c162080 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol @@ -1,7 +1,5 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; - /** * @title Transfer Manager module for core transfer validation functionality */ diff --git a/contracts/proxy/ERC20DividendCheckpointProxy.sol b/contracts/proxy/ERC20DividendCheckpointProxy.sol new file mode 100644 index 000000000..33c27fd4e --- /dev/null +++ b/contracts/proxy/ERC20DividendCheckpointProxy.sol @@ -0,0 +1,48 @@ +pragma solidity ^0.4.24; + +import "../modules/Checkpoint/ERC20DividendCheckpointStorage.sol"; +import "../modules/Checkpoint/DividendCheckpointStorage.sol"; +import "./Proxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, DividendCheckpointStorage, ModuleStorage, Pausable, Proxy { + + // Address of the current implementation + address internal __implementation; + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + + /** + * @notice Internal function to provide the address of the implementation contract + */ + function _implementation() internal view returns (address) { + return __implementation; + } + + /** + * @dev Tells the address of the current implementation + * @return address of the current implementation + */ + function implementation() external view returns (address) { + return _implementation(); + } +} diff --git a/contracts/proxy/EtherDividendCheckpointProxy.sol b/contracts/proxy/EtherDividendCheckpointProxy.sol new file mode 100644 index 000000000..4786736ea --- /dev/null +++ b/contracts/proxy/EtherDividendCheckpointProxy.sol @@ -0,0 +1,47 @@ +pragma solidity ^0.4.24; + +import "../modules/Checkpoint/DividendCheckpointStorage.sol"; +import "./Proxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract EtherDividendCheckpointProxy is DividendCheckpointStorage, ModuleStorage, Pausable, Proxy { + + // Address of the current implementation + address internal __implementation; + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + + /** + * @notice Internal function to provide the address of the implementation contract + */ + function _implementation() internal view returns (address) { + return __implementation; + } + + /** + * @dev Tells the address of the current implementation + * @return address of the current implementation + */ + function implementation() external view returns (address) { + return _implementation(); + } +} diff --git a/scripts/compareStorageLayout.js b/scripts/compareStorageLayout.js new file mode 100644 index 000000000..5bf50a985 --- /dev/null +++ b/scripts/compareStorageLayout.js @@ -0,0 +1,71 @@ +const fs = require('fs'); +const logicContract = fs.readFileSync('./logic.sol', 'utf8'); +const proxyContract = fs.readFileSync('./proxy.sol', 'utf8'); +const _ = require('underscore'); +const solc = require('solc'); + +let logicInput = { + 'contracts': logicContract +} +let proxyInput = { + 'contracts': proxyContract +} + +function traverseAST(_input, _elements) { + if(_input.children) { + for(var i=0;i<_input.children.length;i++) { + traverseAST(_input.children[i], _elements); + } + } + _elements.push(_input); +} + +function compareStorageLayouts(oldLayout, newLayout) { + function makeComp(x) { + return [x.constant, x.name, x.scope, x.stateVariable, x.storageLocation, x.type, x.value, x.visibility].join(':'); + } + // if(newLayout.length < oldLayout.length) return false; + for(var i=0;i e.name == 'ContractDefinition'); + + // filter out all linearizedBaseContracts + // pick the last one as the last contract always has the full inheritance + const linearizedBaseContracts = _.last(_.map(contractDefinitions, e => e.attributes.linearizedBaseContracts)); + + // get all stateVariables + const stateVariables = _.filter(elements, e => e.attributes && e.attributes.stateVariable ) + + // group them by scope + const stateVariableMap = _.groupBy(stateVariables, e => e.attributes.scope); + + orderedStateVariables = _.reduceRight(linearizedBaseContracts, (a, b) => { + return a.concat(stateVariableMap[b] || []) + }, []); + return orderedStateVariables; +} + +// console.log(orderedStateVariables); +console.log(compareStorageLayouts(parseContract(logicInput), parseContract(proxyInput))); From 0c19bf2acf8ebc06cebe8ebb21c82e6d06a63569 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 26 Nov 2018 17:17:58 +0000 Subject: [PATCH 196/582] Updates --- .../proxy/ERC20DividendCheckpointProxy.sol | 21 +- .../proxy/EtherDividendCheckpointProxy.sol | 21 +- .../proxy/GeneralTransferManagerProxy.sol | 21 +- contracts/proxy/OwnedProxy.sol | 91 ++ migrations/2_deploy_contracts.js | 16 +- scripts/compareStorageLayout.js | 14 +- scripts/logic.sol | 1188 +++++++++++++++++ scripts/proxy.sol | 332 +++++ test/h_general_transfer_manager.js | 3 +- test/helpers/createInstances.js | 10 +- 10 files changed, 1648 insertions(+), 69 deletions(-) create mode 100644 contracts/proxy/OwnedProxy.sol create mode 100644 scripts/logic.sol create mode 100644 scripts/proxy.sol diff --git a/contracts/proxy/ERC20DividendCheckpointProxy.sol b/contracts/proxy/ERC20DividendCheckpointProxy.sol index 33c27fd4e..8839d30e1 100644 --- a/contracts/proxy/ERC20DividendCheckpointProxy.sol +++ b/contracts/proxy/ERC20DividendCheckpointProxy.sol @@ -2,17 +2,14 @@ pragma solidity ^0.4.24; import "../modules/Checkpoint/ERC20DividendCheckpointStorage.sol"; import "../modules/Checkpoint/DividendCheckpointStorage.sol"; -import "./Proxy.sol"; +import "./OwnedProxy.sol"; import "../Pausable.sol"; import "../modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality */ -contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, DividendCheckpointStorage, ModuleStorage, Pausable, Proxy { - - // Address of the current implementation - address internal __implementation; +contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { /** * @notice Constructor @@ -31,18 +28,4 @@ contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, Dividen __implementation = _implementation; } - /** - * @notice Internal function to provide the address of the implementation contract - */ - function _implementation() internal view returns (address) { - return __implementation; - } - - /** - * @dev Tells the address of the current implementation - * @return address of the current implementation - */ - function implementation() external view returns (address) { - return _implementation(); - } } diff --git a/contracts/proxy/EtherDividendCheckpointProxy.sol b/contracts/proxy/EtherDividendCheckpointProxy.sol index 4786736ea..40b1c1332 100644 --- a/contracts/proxy/EtherDividendCheckpointProxy.sol +++ b/contracts/proxy/EtherDividendCheckpointProxy.sol @@ -1,17 +1,14 @@ pragma solidity ^0.4.24; import "../modules/Checkpoint/DividendCheckpointStorage.sol"; -import "./Proxy.sol"; +import "./OwnedProxy.sol"; import "../Pausable.sol"; import "../modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality */ -contract EtherDividendCheckpointProxy is DividendCheckpointStorage, ModuleStorage, Pausable, Proxy { - - // Address of the current implementation - address internal __implementation; +contract EtherDividendCheckpointProxy is DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { /** * @notice Constructor @@ -30,18 +27,4 @@ contract EtherDividendCheckpointProxy is DividendCheckpointStorage, ModuleStorag __implementation = _implementation; } - /** - * @notice Internal function to provide the address of the implementation contract - */ - function _implementation() internal view returns (address) { - return __implementation; - } - - /** - * @dev Tells the address of the current implementation - * @return address of the current implementation - */ - function implementation() external view returns (address) { - return _implementation(); - } } diff --git a/contracts/proxy/GeneralTransferManagerProxy.sol b/contracts/proxy/GeneralTransferManagerProxy.sol index 9732b76db..cb9b69070 100644 --- a/contracts/proxy/GeneralTransferManagerProxy.sol +++ b/contracts/proxy/GeneralTransferManagerProxy.sol @@ -1,17 +1,14 @@ pragma solidity ^0.4.24; import "../modules/TransferManager/GeneralTransferManagerStorage.sol"; -import "./Proxy.sol"; +import "./OwnedProxy.sol"; import "../Pausable.sol"; import "../modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality */ -contract GeneralTransferManagerProxy is GeneralTransferManagerStorage, ModuleStorage, Pausable, Proxy { - - // Address of the current implementation - address internal __implementation; +contract GeneralTransferManagerProxy is GeneralTransferManagerStorage, ModuleStorage, Pausable, OwnedProxy { /** * @notice Constructor @@ -30,18 +27,4 @@ contract GeneralTransferManagerProxy is GeneralTransferManagerStorage, ModuleSto __implementation = _implementation; } - /** - * @notice Internal function to provide the address of the implementation contract - */ - function _implementation() internal view returns (address) { - return __implementation; - } - - /** - * @dev Tells the address of the current implementation - * @return address of the current implementation - */ - function implementation() external view returns (address) { - return _implementation(); - } } diff --git a/contracts/proxy/OwnedProxy.sol b/contracts/proxy/OwnedProxy.sol new file mode 100644 index 000000000..67d3822bc --- /dev/null +++ b/contracts/proxy/OwnedProxy.sol @@ -0,0 +1,91 @@ +pragma solidity ^0.4.18; + +import "./Proxy.sol"; + +/** + * @title OwnedUpgradeabilityProxy + * @dev This contract combines an upgradeability proxy with basic authorization control functionalities + */ +contract OwnedProxy is Proxy { + + // Owner of the contract + address private __owner; + + // Address of the current implementation + address internal __implementation; + + /** + * @dev Event to show ownership has been transferred + * @param _previousOwner representing the address of the previous owner + * @param _newOwner representing the address of the new owner + */ + event ProxyOwnershipTransferred(address _previousOwner, address _newOwner); + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier ifOwner() { + if (msg.sender == _owner()) { + _; + } else { + _fallback(); + } + } + + /** + * @dev the constructor sets the original owner of the contract to the sender account. + */ + constructor() public { + _setOwner(msg.sender); + } + + /** + * @dev Tells the address of the owner + * @return the address of the owner + */ + function _owner() internal view returns (address) { + return __owner; + } + + /** + * @dev Sets the address of the owner + */ + function _setOwner(address _newOwner) internal { + require(_newOwner != address(0), "Address should not be 0x"); + __owner = _newOwner; + } + + /** + * @notice Internal function to provide the address of the implementation contract + */ + function _implementation() internal view returns (address) { + return __implementation; + } + + /** + * @dev Tells the address of the proxy owner + * @return the address of the proxy owner + */ + function proxyOwner() external ifOwner returns (address) { + return _owner(); + } + + /** + * @dev Tells the address of the current implementation + * @return address of the current implementation + */ + function implementation() external ifOwner returns (address) { + return _implementation(); + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param _newOwner The address to transfer ownership to. + */ + function transferProxyOwnership(address _newOwner) external ifOwner { + require(_newOwner != address(0), "Address should not be 0x"); + emit ProxyOwnershipTransferred(_owner(), _newOwner); + _setOwner(_newOwner); + } + +} diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 63b2a8231..f25cfab35 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -5,6 +5,8 @@ const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionMa const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') +const EtherDividendCheckpointLogic = artifacts.require('./EtherDividendCheckpoint.sol') +const ERC20DividendCheckpointLogic = artifacts.require('./ERC20DividendCheckpoint.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); @@ -150,6 +152,14 @@ module.exports = function (deployer, network, accounts) { // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) return deployer.deploy(GeneralTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(ERC20DividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(EtherDividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); }).then(() => { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) @@ -169,11 +179,11 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // D) Deploy the EtherDividendCheckpointFactory Contract (Factory used to generate the EtherDividendCheckpoint contract use // to provide the functionality of the dividend in terms of ETH) - return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, EtherDividendCheckpointLogic.address, {from: PolymathAccount}); }).then(() => { // D) Deploy the ERC20DividendCheckpointFactory Contract (Factory used to generate the ERC20DividendCheckpoint contract use // to provide the functionality of the dividend in terms of ERC20 token) - return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, ERC20DividendCheckpointLogic.address, {from: PolymathAccount}); }).then(() => { // D) Deploy the ManualApprovalTransferManagerFactory Contract (Factory used to generate the ManualApprovalTransferManager contract use // to manual approve the transfer that will overcome the other transfer restrictions) @@ -319,6 +329,8 @@ module.exports = function (deployer, network, accounts) { CountTransferManagerFactory: ${CountTransferManagerFactory.address} PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} + EtherDividendCheckpointLogic: ${EtherDividendCheckpointLogic.address} + ERC20DividendCheckpointLogic: ${ERC20DividendCheckpointLogic.address} EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} --------------------------------------------------------------------------------- diff --git a/scripts/compareStorageLayout.js b/scripts/compareStorageLayout.js index 5bf50a985..502f27872 100644 --- a/scripts/compareStorageLayout.js +++ b/scripts/compareStorageLayout.js @@ -20,27 +20,27 @@ function traverseAST(_input, _elements) { _elements.push(_input); } -function compareStorageLayouts(oldLayout, newLayout) { +function compareStorageLayouts(logicLayout, proxyLayout) { function makeComp(x) { - return [x.constant, x.name, x.scope, x.stateVariable, x.storageLocation, x.type, x.value, x.visibility].join(':'); + return [x.constant, x.name, x.stateVariable, x.storageLocation, x.type, x.value, x.visibility].join(':'); } // if(newLayout.length < oldLayout.length) return false; - for(var i=0;i bool) claimed; // List of addresses which have claimed dividend + mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends + bytes32 name; // Name/title - used for identification + } + + // List of all dividends + Dividend[] public dividends; + + // List of addresses which cannot claim dividends + address[] public excluded; + + // Mapping from address to withholding tax as a percentage * 10**16 + mapping (address => uint256) public withholdingTax; + + // Total amount of ETH withheld per investor + mapping (address => uint256) public investorWithheld; + +} + +// File: contracts/modules/Checkpoint/ICheckpoint.sol + +/** + * @title Interface to be implemented by all checkpoint modules + */ +/*solium-disable-next-line no-empty-blocks*/ +interface ICheckpoint { + +} + +// File: openzeppelin-solidity/contracts/math/Math.sol + +/** + * @title Math + * @dev Assorted math operations + */ +library Math { + function max64(uint64 a, uint64 b) internal pure returns (uint64) { + return a >= b ? a : b; + } + + function min64(uint64 a, uint64 b) internal pure returns (uint64) { + return a < b ? a : b; + } + + function max256(uint256 a, uint256 b) internal pure returns (uint256) { + return a >= b ? a : b; + } + + function min256(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } +} + +// File: openzeppelin-solidity/contracts/math/SafeMath.sol + +/** + * @title SafeMath + * @dev Math operations with safety checks that throw on error + */ +library SafeMath { + + /** + * @dev Multiplies two numbers, throws on overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { + // Gas optimization: this is cheaper than asserting 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 + if (a == 0) { + return 0; + } + + c = a * b; + assert(c / a == b); + return c; + } + + /** + * @dev Integer division of two numbers, truncating the quotient. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + // assert(b > 0); // Solidity automatically throws when dividing by 0 + // uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return a / b; + } + + /** + * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + assert(b <= a); + return a - b; + } + + /** + * @dev Adds two numbers, throws on overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256 c) { + c = a + b; + assert(c >= a); + return c; + } +} + +// File: contracts/modules/Checkpoint/DividendCheckpoint.sol + +/** + * DISCLAIMER: Under certain conditions, the function pushDividendPayment + * may fail due to block gas limits. + * If the total number of investors that ever held tokens is greater than ~15,000 then + * the function may fail. If this happens investors can pull their dividends, or the Issuer + * can use pushDividendPaymentToAddresses to provide an explict address list in batches + */ +pragma solidity ^0.4.24; + +/** + * @title Checkpoint module for issuing ether dividends + * @dev abstract contract + */ +contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { + using SafeMath for uint256; + + event SetDefaultExcludedAddresses(address[] _excluded, uint256 _timestamp); + event SetWithholding(address[] _investors, uint256[] _withholding, uint256 _timestamp); + event SetWithholdingFixed(address[] _investors, uint256 _withholding, uint256 _timestamp); + + modifier validDividendIndex(uint256 _dividendIndex) { + require(_dividendIndex < dividends.length, "Invalid dividend"); + require(!dividends[_dividendIndex].reclaimed, "Dividend reclaimed"); + /*solium-disable-next-line security/no-block-members*/ + require(now >= dividends[_dividendIndex].maturity, "Dividend maturity in future"); + /*solium-disable-next-line security/no-block-members*/ + require(now < dividends[_dividendIndex].expiry, "Dividend expiry in past"); + _; + } + + /** + * @notice Init function i.e generalise function to maintain the structure of the module contract + * @return bytes4 + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(0); + } + + /** + * @notice Return the default excluded addresses + * @return List of excluded addresses + */ + function getDefaultExcluded() external view returns (address[]) { + return excluded; + } + + /** + * @notice Creates a checkpoint on the security token + * @return Checkpoint ID + */ + function createCheckpoint() public withPerm(CHECKPOINT) returns (uint256) { + return ISecurityToken(securityToken).createCheckpoint(); + } + + /** + * @notice Function to clear and set list of excluded addresses used for future dividends + * @param _excluded Addresses of investors + */ + function setDefaultExcluded(address[] _excluded) public withPerm(MANAGE) { + require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many excluded addresses"); + for (uint256 j = 0; j < _excluded.length; j++) { + require (_excluded[j] != address(0), "Invalid address"); + for (uint256 i = j + 1; i < _excluded.length; i++) { + require (_excluded[j] != _excluded[i], "Duplicate exclude address"); + } + } + excluded = _excluded; + /*solium-disable-next-line security/no-block-members*/ + emit SetDefaultExcludedAddresses(excluded, now); + } + + /** + * @notice Function to set withholding tax rates for investors + * @param _investors Addresses of investors + * @param _withholding Withholding tax for individual investors (multiplied by 10**16) + */ + function setWithholding(address[] _investors, uint256[] _withholding) public withPerm(MANAGE) { + require(_investors.length == _withholding.length, "Mismatched input lengths"); + /*solium-disable-next-line security/no-block-members*/ + emit SetWithholding(_investors, _withholding, now); + for (uint256 i = 0; i < _investors.length; i++) { + require(_withholding[i] <= 10**18, "Incorrect withholding tax"); + withholdingTax[_investors[i]] = _withholding[i]; + } + } + + /** + * @notice Function to set withholding tax rates for investors + * @param _investors Addresses of investor + * @param _withholding Withholding tax for all investors (multiplied by 10**16) + */ + function setWithholdingFixed(address[] _investors, uint256 _withholding) public withPerm(MANAGE) { + require(_withholding <= 10**18, "Incorrect withholding tax"); + /*solium-disable-next-line security/no-block-members*/ + emit SetWithholdingFixed(_investors, _withholding, now); + for (uint256 i = 0; i < _investors.length; i++) { + withholdingTax[_investors[i]] = _withholding; + } + } + + /** + * @notice Issuer can push dividends to provided addresses + * @param _dividendIndex Dividend to push + * @param _payees Addresses to which to push the dividend + */ + function pushDividendPaymentToAddresses( + uint256 _dividendIndex, + address[] _payees + ) + public + withPerm(DISTRIBUTE) + validDividendIndex(_dividendIndex) + { + Dividend storage dividend = dividends[_dividendIndex]; + for (uint256 i = 0; i < _payees.length; i++) { + if ((!dividend.claimed[_payees[i]]) && (!dividend.dividendExcluded[_payees[i]])) { + _payDividend(_payees[i], dividend, _dividendIndex); + } + } + } + + /** + * @notice Issuer can push dividends using the investor list from the security token + * @param _dividendIndex Dividend to push + * @param _start Index in investor list at which to start pushing dividends + * @param _iterations Number of addresses to push dividends for + */ + function pushDividendPayment( + uint256 _dividendIndex, + uint256 _start, + uint256 _iterations + ) + public + withPerm(DISTRIBUTE) + validDividendIndex(_dividendIndex) + { + Dividend storage dividend = dividends[_dividendIndex]; + address[] memory investors = ISecurityToken(securityToken).getInvestors(); + uint256 numberInvestors = Math.min256(investors.length, _start.add(_iterations)); + for (uint256 i = _start; i < numberInvestors; i++) { + address payee = investors[i]; + if ((!dividend.claimed[payee]) && (!dividend.dividendExcluded[payee])) { + _payDividend(payee, dividend, _dividendIndex); + } + } + } + + /** + * @notice Investors can pull their own dividends + * @param _dividendIndex Dividend to pull + */ + function pullDividendPayment(uint256 _dividendIndex) public validDividendIndex(_dividendIndex) + { + Dividend storage dividend = dividends[_dividendIndex]; + require(!dividend.claimed[msg.sender], "Dividend already claimed"); + require(!dividend.dividendExcluded[msg.sender], "msg.sender excluded from Dividend"); + _payDividend(msg.sender, dividend, _dividendIndex); + } + + /** + * @notice Internal function for paying dividends + * @param _payee Address of investor + * @param _dividend Storage with previously issued dividends + * @param _dividendIndex Dividend to pay + */ + function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal; + + /** + * @notice Issuer can reclaim remaining unclaimed dividend amounts, for expired dividends + * @param _dividendIndex Dividend to reclaim + */ + function reclaimDividend(uint256 _dividendIndex) external; + + /** + * @notice Calculate amount of dividends claimable + * @param _dividendIndex Dividend to calculate + * @param _payee Affected investor address + * @return claim, withheld amounts + */ + function calculateDividend(uint256 _dividendIndex, address _payee) public view returns(uint256, uint256) { + require(_dividendIndex < dividends.length, "Invalid dividend"); + Dividend storage dividend = dividends[_dividendIndex]; + if (dividend.claimed[_payee] || dividend.dividendExcluded[_payee]) { + return (0, 0); + } + uint256 balance = ISecurityToken(securityToken).balanceOfAt(_payee, dividend.checkpointId); + uint256 claim = balance.mul(dividend.amount).div(dividend.totalSupply); + uint256 withheld = claim.mul(withholdingTax[_payee]).div(uint256(10**18)); + return (claim, withheld); + } + + /** + * @notice Get the index according to the checkpoint id + * @param _checkpointId Checkpoint id to query + * @return uint256[] + */ + function getDividendIndex(uint256 _checkpointId) public view returns(uint256[]) { + uint256 counter = 0; + for(uint256 i = 0; i < dividends.length; i++) { + if (dividends[i].checkpointId == _checkpointId) { + counter++; + } + } + + uint256[] memory index = new uint256[](counter); + counter = 0; + for(uint256 j = 0; j < dividends.length; j++) { + if (dividends[j].checkpointId == _checkpointId) { + index[counter] = j; + counter++; + } + } + return index; + } + + /** + * @notice Allows issuer to withdraw withheld tax + * @param _dividendIndex Dividend to withdraw from + */ + function withdrawWithholding(uint256 _dividendIndex) external; + + /** + * @notice Return the permissions flag that are associated with this module + * @return bytes32 array + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](2); + allPermissions[0] = DISTRIBUTE; + allPermissions[1] = MANAGE; + return allPermissions; + } + +} + +// File: contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol + +/** + * @title Checkpoint module for issuing ERC20 dividends + */ +contract ERC20DividendCheckpointStorage { + + // Mapping to token address for each dividend + mapping (uint256 => address) public dividendTokens; + +} + +// File: contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol + +/** + * @title Checkpoint module for issuing ERC20 dividends + */ +contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendCheckpoint { + using SafeMath for uint256; + + event ERC20DividendDeposited( + address indexed _depositor, + uint256 _checkpointId, + uint256 _created, + uint256 _maturity, + uint256 _expiry, + address indexed _token, + uint256 _amount, + uint256 _totalSupply, + uint256 _dividendIndex, + bytes32 indexed _name + ); + event ERC20DividendClaimed( + address indexed _payee, + uint256 _dividendIndex, + address indexed _token, + uint256 _amount, + uint256 _withheld + ); + event ERC20DividendReclaimed( + address indexed _claimer, + uint256 _dividendIndex, + address indexed _token, + uint256 _claimedAmount + ); + event ERC20DividendWithholdingWithdrawn( + address indexed _claimer, + uint256 _dividendIndex, + address indexed _token, + uint256 _withheldAmount + ); + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) public + Module(_securityToken, _polyAddress) + { + } + + /** + * @notice Creates a dividend and checkpoint for the dividend + * @param _maturity Time from which dividend can be paid + * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer + * @param _token Address of ERC20 token in which dividend is to be denominated + * @param _amount Amount of specified token for dividend + * @param _name Name/Title for identification + */ + function createDividend( + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + bytes32 _name + ) + external + withPerm(MANAGE) + { + createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name); + } + + /** + * @notice Creates a dividend with a provided checkpoint + * @param _maturity Time from which dividend can be paid + * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer + * @param _token Address of ERC20 token in which dividend is to be denominated + * @param _amount Amount of specified token for dividend + * @param _checkpointId Checkpoint id from which to create dividends + * @param _name Name/Title for identification + */ + function createDividendWithCheckpoint( + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, + bytes32 _name + ) + external + withPerm(MANAGE) + { + _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, excluded, _name); + } + + /** + * @notice Creates a dividend and checkpoint for the dividend + * @param _maturity Time from which dividend can be paid + * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer + * @param _token Address of ERC20 token in which dividend is to be denominated + * @param _amount Amount of specified token for dividend + * @param _excluded List of addresses to exclude + * @param _name Name/Title for identification + */ + function createDividendWithExclusions( + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + address[] _excluded, + bytes32 _name + ) + public + withPerm(MANAGE) + { + uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); + _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, checkpointId, _excluded, _name); + } + + /** + * @notice Creates a dividend with a provided checkpoint + * @param _maturity Time from which dividend can be paid + * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer + * @param _token Address of ERC20 token in which dividend is to be denominated + * @param _amount Amount of specified token for dividend + * @param _checkpointId Checkpoint id from which to create dividends + * @param _excluded List of addresses to exclude + * @param _name Name/Title for identification + */ + function createDividendWithCheckpointAndExclusions( + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, + address[] _excluded, + bytes32 _name + ) + public + withPerm(MANAGE) + { + _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, _excluded, _name); + } + + /** + * @notice Creates a dividend with a provided checkpoint + * @param _maturity Time from which dividend can be paid + * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer + * @param _token Address of ERC20 token in which dividend is to be denominated + * @param _amount Amount of specified token for dividend + * @param _checkpointId Checkpoint id from which to create dividends + * @param _excluded List of addresses to exclude + * @param _name Name/Title for identification + */ + function _createDividendWithCheckpointAndExclusions( + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, + address[] _excluded, + bytes32 _name + ) + internal + { + ISecurityToken securityTokenInstance = ISecurityToken(securityToken); + require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); + require(_expiry > _maturity, "Expiry before maturity"); + /*solium-disable-next-line security/no-block-members*/ + require(_expiry > now, "Expiry in past"); + require(_amount > 0, "No dividend sent"); + require(_token != address(0), "Invalid token"); + require(_checkpointId <= securityTokenInstance.currentCheckpointId(), "Invalid checkpoint"); + require(IERC20(_token).transferFrom(msg.sender, address(this), _amount), "insufficent allowance"); + require(_name[0] != 0); + uint256 dividendIndex = dividends.length; + uint256 currentSupply = securityTokenInstance.totalSupplyAt(_checkpointId); + uint256 excludedSupply = 0; + dividends.push( + Dividend( + _checkpointId, + now, /*solium-disable-line security/no-block-members*/ + _maturity, + _expiry, + _amount, + 0, + 0, + false, + 0, + 0, + _name + ) + ); + + for (uint256 j = 0; j < _excluded.length; j++) { + require (_excluded[j] != address(0), "Invalid address"); + require(!dividends[dividendIndex].dividendExcluded[_excluded[j]], "duped exclude address"); + excludedSupply = excludedSupply.add(securityTokenInstance.balanceOfAt(_excluded[j], _checkpointId)); + dividends[dividendIndex].dividendExcluded[_excluded[j]] = true; + } + + dividends[dividendIndex].totalSupply = currentSupply.sub(excludedSupply); + dividendTokens[dividendIndex] = _token; + _emitERC20DividendDepositedEvent(_checkpointId, _maturity, _expiry, _token, _amount, currentSupply, dividendIndex, _name); + } + + /** + * @notice Emits the ERC20DividendDeposited event. + * Seperated into a different function as a workaround for stack too deep error + */ + function _emitERC20DividendDepositedEvent( + uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 currentSupply, + uint256 dividendIndex, + bytes32 _name + ) + internal + { + /*solium-disable-next-line security/no-block-members*/ + emit ERC20DividendDeposited(msg.sender, _checkpointId, now, _maturity, _expiry, _token, _amount, currentSupply, dividendIndex, _name); + } + + /** + * @notice Internal function for paying dividends + * @param _payee Address of investor + * @param _dividend Storage with previously issued dividends + * @param _dividendIndex Dividend to pay + */ + function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { + (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee); + _dividend.claimed[_payee] = true; + _dividend.claimedAmount = claim.add(_dividend.claimedAmount); + uint256 claimAfterWithheld = claim.sub(withheld); + if (claimAfterWithheld > 0) { + require(IERC20(dividendTokens[_dividendIndex]).transfer(_payee, claimAfterWithheld), "transfer failed"); + _dividend.dividendWithheld = _dividend.dividendWithheld.add(withheld); + investorWithheld[_payee] = investorWithheld[_payee].add(withheld); + emit ERC20DividendClaimed(_payee, _dividendIndex, dividendTokens[_dividendIndex], claim, withheld); + } + } + + /** + * @notice Issuer can reclaim remaining unclaimed dividend amounts, for expired dividends + * @param _dividendIndex Dividend to reclaim + */ + function reclaimDividend(uint256 _dividendIndex) external withPerm(MANAGE) { + require(_dividendIndex < dividends.length, "Invalid dividend"); + /*solium-disable-next-line security/no-block-members*/ + require(now >= dividends[_dividendIndex].expiry, "Dividend expiry in future"); + require(!dividends[_dividendIndex].reclaimed, "already claimed"); + dividends[_dividendIndex].reclaimed = true; + Dividend storage dividend = dividends[_dividendIndex]; + uint256 remainingAmount = dividend.amount.sub(dividend.claimedAmount); + address owner = IOwnable(securityToken).owner(); + require(IERC20(dividendTokens[_dividendIndex]).transfer(owner, remainingAmount), "transfer failed"); + emit ERC20DividendReclaimed(owner, _dividendIndex, dividendTokens[_dividendIndex], remainingAmount); + } + + /** + * @notice Allows issuer to withdraw withheld tax + * @param _dividendIndex Dividend to withdraw from + */ + function withdrawWithholding(uint256 _dividendIndex) external withPerm(MANAGE) { + require(_dividendIndex < dividends.length, "Invalid dividend"); + Dividend storage dividend = dividends[_dividendIndex]; + uint256 remainingWithheld = dividend.dividendWithheld.sub(dividend.dividendWithheldReclaimed); + dividend.dividendWithheldReclaimed = dividend.dividendWithheld; + address owner = IOwnable(securityToken).owner(); + require(IERC20(dividendTokens[_dividendIndex]).transfer(owner, remainingWithheld), "transfer failed"); + emit ERC20DividendWithholdingWithdrawn(owner, _dividendIndex, dividendTokens[_dividendIndex], remainingWithheld); + } + +} diff --git a/scripts/proxy.sol b/scripts/proxy.sol new file mode 100644 index 000000000..ed315955f --- /dev/null +++ b/scripts/proxy.sol @@ -0,0 +1,332 @@ +pragma solidity ^0.4.24; + +// File: contracts/Pausable.sol + +/** + * @title Utility contract to allow pausing and unpausing of certain functions + */ +contract Pausable { + + event Pause(uint256 _timestammp); + event Unpause(uint256 _timestamp); + + bool public paused = false; + + /** + * @notice Modifier to make a function callable only when the contract is not paused. + */ + modifier whenNotPaused() { + require(!paused, "Contract is paused"); + _; + } + + /** + * @notice Modifier to make a function callable only when the contract is paused. + */ + modifier whenPaused() { + require(paused, "Contract is not paused"); + _; + } + + /** + * @notice Called by the owner to pause, triggers stopped state + */ + function _pause() internal whenNotPaused { + paused = true; + /*solium-disable-next-line security/no-block-members*/ + emit Pause(now); + } + + /** + * @notice Called by the owner to unpause, returns to normal state + */ + function _unpause() internal whenPaused { + paused = false; + /*solium-disable-next-line security/no-block-members*/ + emit Unpause(now); + } + +} + +// File: contracts/modules/Checkpoint/DividendCheckpointStorage.sol + +/** + * DISCLAIMER: Under certain conditions, the function pushDividendPayment + * may fail due to block gas limits. + * If the total number of investors that ever held tokens is greater than ~15,000 then + * the function may fail. If this happens investors can pull their dividends, or the Issuer + * can use pushDividendPaymentToAddresses to provide an explict address list in batches + */ +pragma solidity ^0.4.24; + +/** + * @title Checkpoint module for issuing ether dividends + * @dev abstract contract + */ +contract DividendCheckpointStorage { + + uint256 public EXCLUDED_ADDRESS_LIMIT = 50; + bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; + bytes32 public constant MANAGE = "MANAGE"; + bytes32 public constant CHECKPOINT = "CHECKPOINT"; + + struct Dividend { + uint256 checkpointId; + uint256 created; // Time at which the dividend was created + uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass + uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - + // set to very high value to bypass + uint256 amount; // Dividend amount in WEI + uint256 claimedAmount; // Amount of dividend claimed so far + uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) + bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend + uint256 dividendWithheld; + uint256 dividendWithheldReclaimed; + mapping (address => bool) claimed; // List of addresses which have claimed dividend + mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends + bytes32 name; // Name/title - used for identification + } + + // List of all dividends + Dividend[] public dividends; + + // List of addresses which cannot claim dividends + address[] public excluded; + + // Mapping from address to withholding tax as a percentage * 10**16 + mapping (address => uint256) public withholdingTax; + + // Total amount of ETH withheld per investor + mapping (address => uint256) public investorWithheld; + +} + +// File: contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol + +/** + * @title Checkpoint module for issuing ERC20 dividends + */ +contract ERC20DividendCheckpointStorage { + + // Mapping to token address for each dividend + mapping (uint256 => address) public dividendTokens; + +} + +// File: contracts/interfaces/IERC20.sol + +/** + * @title ERC20 interface + * @dev see https://github.com/ethereum/EIPs/issues/20 + */ +interface IERC20 { + function decimals() external view returns (uint8); + function totalSupply() external view returns (uint256); + function balanceOf(address _owner) external view returns (uint256); + function allowance(address _owner, address _spender) external view returns (uint256); + function transfer(address _to, uint256 _value) external returns (bool); + function transferFrom(address _from, address _to, uint256 _value) external returns (bool); + function approve(address _spender, uint256 _value) external returns (bool); + function decreaseApproval(address _spender, uint _subtractedValue) external returns (bool); + function increaseApproval(address _spender, uint _addedValue) external returns (bool); + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); +} + +// File: contracts/modules/ModuleStorage.sol + +/** + * @title Storage for Module contract + * @notice Contract is abstract + */ +contract ModuleStorage { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) public { + securityToken = _securityToken; + factory = msg.sender; + polyToken = IERC20(_polyAddress); + } + + address public factory; + + address public securityToken; + + bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; + + IERC20 public polyToken; + +} + +// File: contracts/proxy/Proxy.sol + +/** + * @title Proxy + * @dev Gives the possibility to delegate any call to a foreign implementation. + */ +contract Proxy { + + /** + * @dev Tells the address of the implementation where every call will be delegated. + * @return address of the implementation to which it will be delegated + */ + function _implementation() internal view returns (address); + + /** + * @dev Fallback function. + * Implemented entirely in `_fallback`. + */ + function _fallback() internal { + _delegate(_implementation()); + } + + /** + * @dev Fallback function allowing to perform a delegatecall to the given implementation. + * This function will return whatever the implementation call returns + */ + function _delegate(address implementation) internal { + /*solium-disable-next-line security/no-inline-assembly*/ + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize) + + // Call the implementation. + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize) + + switch result + // delegatecall returns 0 on error. + case 0 { revert(0, returndatasize) } + default { return(0, returndatasize) } + } + } + + function () public payable { + _fallback(); + } +} + +// File: contracts/proxy/OwnedProxy.sol + +/** + * @title OwnedUpgradeabilityProxy + * @dev This contract combines an upgradeability proxy with basic authorization control functionalities + */ +contract OwnedProxy is Proxy { + + // Owner of the contract + address private __owner; + + // Address of the current implementation + address internal __implementation; + + /** + * @dev Event to show ownership has been transferred + * @param _previousOwner representing the address of the previous owner + * @param _newOwner representing the address of the new owner + */ + event ProxyOwnershipTransferred(address _previousOwner, address _newOwner); + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier ifOwner() { + if (msg.sender == _owner()) { + _; + } else { + _fallback(); + } + } + + /** + * @dev the constructor sets the original owner of the contract to the sender account. + */ + constructor() public { + _setOwner(msg.sender); + } + + /** + * @dev Tells the address of the owner + * @return the address of the owner + */ + function _owner() internal view returns (address) { + return __owner; + } + + /** + * @dev Sets the address of the owner + */ + function _setOwner(address _newOwner) internal { + require(_newOwner != address(0), "Address should not be 0x"); + __owner = _newOwner; + } + + /** + * @notice Internal function to provide the address of the implementation contract + */ + function _implementation() internal view returns (address) { + return __implementation; + } + + /** + * @dev Tells the address of the proxy owner + * @return the address of the proxy owner + */ + function proxyOwner() external ifOwner returns (address) { + return _owner(); + } + + /** + * @dev Tells the address of the current implementation + * @return address of the current implementation + */ + function implementation() external ifOwner returns (address) { + return _implementation(); + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param _newOwner The address to transfer ownership to. + */ + function transferProxyOwnership(address _newOwner) external ifOwner { + require(_newOwner != address(0), "Address should not be 0x"); + emit ProxyOwnershipTransferred(_owner(), _newOwner); + _setOwner(_newOwner); + } + +} + +// File: contracts/proxy/ERC20DividendCheckpointProxy.sol + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + +} diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 750a4cfbc..5dbcf5a6c 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -92,6 +92,7 @@ contract("GeneralTransferManager", accounts => { account_investor1 = accounts[8]; account_investor2 = accounts[9]; account_delegate = accounts[7]; + account_investor3 = accounts[5]; account_investor4 = accounts[6]; account_affiliates1 = accounts[3]; @@ -201,7 +202,7 @@ contract("GeneralTransferManager", accounts => { it("Should whitelist lots of addresses and check gas", async () => { let mockInvestors = []; for (let i = 0; i < 50; i++) { - mockInvestors.push("0x0000000000000000000000000000000000000000".substring(0,42-i.toString().length) + i.toString()); + mockInvestors.push("0x1000000000000000000000000000000000000000".substring(0,42-i.toString().length) + i.toString()); } let times = range1(50); diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 35be83d95..a6118741f 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -8,6 +8,8 @@ const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); +const ERC20DividendCheckpoint = artifacts.require("./ERC20DividendCheckpoint.sol"); +const EtherDividendCheckpoint = artifacts.require("./EtherDividendCheckpoint.sol"); const ERC20DividendCheckpointFactory = artifacts.require("./ERC20DividendCheckpointFactory.sol"); const EtherDividendCheckpointFactory = artifacts.require("./EtherDividendCheckpointFactory.sol"); const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); @@ -46,8 +48,10 @@ let I_SingleTradeVolumeRestrictionManagerFactory; let I_ManualApprovalTransferManagerFactory; let I_VolumeRestrictionTransferManagerFactory; let I_PercentageTransferManagerFactory; +let I_EtherDividendCheckpointLogic; let I_EtherDividendCheckpointFactory; let I_CountTransferManagerFactory; +let I_ERC20DividendCheckpointLogic; let I_ERC20DividendCheckpointFactory; let I_GeneralPermissionManagerFactory; let I_GeneralTransferManagerLogic; @@ -371,7 +375,8 @@ export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInst /// Deploy the Dividend Modules export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_ERC20DividendCheckpointLogic = await ERC20DividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(polyToken, setupCost, 0, 0, I_ERC20DividendCheckpointLogic.address, { from: accountPolymath }); assert.notEqual( I_ERC20DividendCheckpointFactory.address.valueOf(), @@ -383,7 +388,8 @@ export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyIns } export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_EtherDividendCheckpointLogic = await EtherDividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(polyToken, setupCost, 0, 0, I_EtherDividendCheckpointLogic.address, { from: accountPolymath }); assert.notEqual( I_EtherDividendCheckpointFactory.address.valueOf(), From ec96190736b08c66ef964ea540f1bcaa7ab18a34 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 26 Nov 2018 19:36:20 -0300 Subject: [PATCH 197/582] Linter fixes --- CLI/commands/transfer_manager.js | 133 ++++++++++++++++--------------- 1 file changed, 67 insertions(+), 66 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 8b79cf436..6725f3529 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -16,7 +16,7 @@ async function executeApp() { let exit = false; while (!exit) { console.log('\n', chalk.blue('Transfer Manager - Main Menu', '\n')); - + let tmModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.TRANSFER); let nonArchivedModules = tmModules.filter(m => !m.archived); if (nonArchivedModules.length > 0) { @@ -36,7 +36,7 @@ async function executeApp() { } options.push('Add new Transfer Manager module'); - let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Exit'}); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Exit' }); let optionSelected = index != -1 ? options[index] : 'Exit'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { @@ -112,9 +112,9 @@ async function forcedTransfers() { if (controller == Issuer.address) { options.push('Force Transfer'); } - let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Return'}); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); let optionSelected = index != -1 ? options[index] : 'Return'; - console.log('Selected:', optionSelected, '\n'); + console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Disable controller': if (readlineSync.keyInYNStrict()) { @@ -177,13 +177,13 @@ async function forcedTransfers() { async function configExistingModules(tmModules) { let options = tmModules.map(m => `${m.name} at ${m.address}`); - let index = readlineSync.keyInSelect(options, 'Which module do you want to config? ', {cancel: 'Return'}); + let index = readlineSync.keyInSelect(options, 'Which module do you want to config? ', { cancel: 'Return' }); console.log('Selected:', index != -1 ? options[index] : 'Return', '\n'); let moduleNameSelected = tmModules[index].name; - + switch (moduleNameSelected) { case 'GeneralTransferManager': - currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), tmModules[index].address); + currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), tmModules[index].address); currentTransferManager.setProvider(web3.currentProvider); await generalTransferManager(); break; @@ -230,8 +230,8 @@ async function configExistingModules(tmModules) { async function addTransferManagerModule() { let options = ['GeneralTransferManager'/*, 'ManualApprovalTransferManager', 'PercentageTransferManager', 'CountTransferManager', 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM'*/]; - - let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', {cancel: 'Return'}); + + let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', { cancel: 'Return' }); if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { let bytes = web3.utils.fromAscii('', 16); switch (options[index]) { @@ -333,9 +333,9 @@ async function generalTransferManager() { console.log(`- Allow all whitelist issuances: ${displayAllowAllWhitelistIssuances ? `YES` : `NO`}`); console.log(`- Allow all burn transfers: ${displayAllowAllBurnTransfers ? `YES` : `NO`}`); // ------------------ - + let options = ['Modify whitelist', 'Modify whitelist from CSV', /*'Modify Whitelist Signed',*/ - `Change issuance address`, 'Change signing address']; + `Change issuance address`, 'Change signing address']; if (displayAllowAllTransfers) { options.push('Disallow all transfers'); } else { @@ -363,16 +363,16 @@ async function generalTransferManager() { switch (optionSelected) { case 'Modify whitelist': let investor = readlineSync.question('Enter the address to whitelist: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" - }); + }); let now = Math.floor(Date.now() / 1000); - let fromTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens (now = ${now}): `, {defaultInput: now}); - let toTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (now = ${now}): `, {defaultInput: now}); + let fromTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens (now = ${now}): `, { defaultInput: now }); + let toTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (now = ${now}): `, { defaultInput: now }); let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated (after that investor need to do re-KYC) (1 hour from now = ${oneHourFromNow}): `, {defaultInput: oneHourFromNow}); + let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated (after that investor need to do re-KYC) (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); @@ -408,11 +408,11 @@ async function generalTransferManager() { */ case 'Change issuance address': let issuanceAddress = readlineSync.question('Enter the new issuance address: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" - }); + }); let changeIssuanceAddressAction = currentTransferManager.methods.changeIssuanceAddress(issuanceAddress); let changeIssuanceAddressReceipt = await common.sendTransaction(changeIssuanceAddressAction); let changeIssuanceAddressEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeIssuanceAddressReceipt.logs, 'ChangeIssuanceAddress'); @@ -420,11 +420,11 @@ async function generalTransferManager() { break; case 'Change signing address': let signingAddress = readlineSync.question('Enter the new signing address: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" - }); + }); let changeSigningAddressAction = currentTransferManager.methods.changeSigningAddress(signingAddress); let changeSigningAddressReceipt = await common.sendTransaction(changeSigningAddressAction); let changeSigningAddressEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeSigningAddressReceipt.logs, 'ChangeSigningAddress'); @@ -481,20 +481,20 @@ async function singleTradeVolumeRestrictionTM() { console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address}`)); console.log(); - // Show current data - let displayIsInPercentage = await currentTransferManager.methods.isTransferLimitInPercentage().call(); - let displayGlobalTransferLimit; - if (displayIsInPercentage) { - displayGlobalTransferLimit = fromWeiPercentage(await currentTransferManager.methods.globalTransferLimitInPercentage().call()); - } else { - displayGlobalTransferLimit = web3.utils.fromWei(await currentTransferManager.methods.globalTransferLimitInTokens().call()); - } - let displayAllowPrimaryIssuance = await currentTransferManager.methods.allowPrimaryIssuance().call(); - - console.log(`- Limit type: ${displayIsInPercentage ? `Percentage` : `Tokens`}`); - console.log(`- Default transfer limit: ${displayGlobalTransferLimit} ${displayIsInPercentage ? `%` : `${tokenSymbol}`}`); - console.log(`- Allow primary issuance: ${displayAllowPrimaryIssuance ? `YES` : `NO`}`); - // ------------------ + // Show current data + let displayIsInPercentage = await currentTransferManager.methods.isTransferLimitInPercentage().call(); + let displayGlobalTransferLimit; + if (displayIsInPercentage) { + displayGlobalTransferLimit = fromWeiPercentage(await currentTransferManager.methods.globalTransferLimitInPercentage().call()); + } else { + displayGlobalTransferLimit = web3.utils.fromWei(await currentTransferManager.methods.globalTransferLimitInTokens().call()); + } + let displayAllowPrimaryIssuance = await currentTransferManager.methods.allowPrimaryIssuance().call(); + + console.log(`- Limit type: ${displayIsInPercentage ? `Percentage` : `Tokens`}`); + console.log(`- Default transfer limit: ${displayGlobalTransferLimit} ${displayIsInPercentage ? `%` : `${tokenSymbol}`}`); + console.log(`- Allow primary issuance: ${displayAllowPrimaryIssuance ? `YES` : `NO`}`); + // ------------------ let options = []; if (displayAllowPrimaryIssuance) { @@ -504,11 +504,11 @@ async function singleTradeVolumeRestrictionTM() { } options.push('Add exempted wallet', 'Remove exempted wallet'); if (displayIsInPercentage) { - options.push('Change transfer limit to tokens', 'Change default percentage limit', - 'Set percentage transfer limit per account', 'Remove percentage transfer limit per account'); + options.push('Change transfer limit to tokens', 'Change default percentage limit', + 'Set percentage transfer limit per account', 'Remove percentage transfer limit per account'); } else { - options.push('Change transfer limit to percentage', 'Change default tokens limit', - 'Set tokens transfer limit per account', 'Remove tokens transfer limit per account'); + options.push('Change transfer limit to percentage', 'Change default tokens limit', + 'Set tokens transfer limit per account', 'Remove tokens transfer limit per account'); } let index = readlineSync.keyInSelect(options, 'What do you want to do?'); @@ -522,11 +522,11 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Add exempted wallet': let walletToExempt = readlineSync.question('Enter the wallet to exempt: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" - }); + }); let addExemptWalletAction = currentTransferManager.methods.addExemptWallet(walletToExempt); let addExemptWalletReceipt = await common.sendTransaction(addExemptWalletAction); let addExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addExemptWalletReceipt.logs, 'ExemptWalletAdded'); @@ -534,11 +534,11 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Remove exempted wallet': let exemptedWallet = readlineSync.question('Enter the wallet to remove from exempt: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" - }); + }); let removeExemptWalletAction = currentTransferManager.methods.removeExemptWallet(exemptedWallet); let removeExemptWalletReceipt = await common.sendTransaction(removeExemptWalletAction); let removeExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeExemptWalletReceipt.logs, 'ExemptWalletRemoved'); @@ -546,11 +546,11 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Change transfer limit to tokens': let newDefaultLimitInTokens = web3.utils.toWei(readlineSync.question('Enter the amount of tokens for default limit: ', { - limit: function(input) { + limit: function (input) { return parseInt(input) > 0; }, limitMessage: "Must be greater than zero" - })); + })); let changeTransferLimitToTokensAction = currentTransferManager.methods.changeTransferLimitToTokens(newDefaultLimitInTokens); let changeTransferLimitToTokensReceipt = await common.sendTransaction(changeTransferLimitToTokensAction); let changeTransferLimitToTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); @@ -559,11 +559,11 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Change transfer limit to percentage': let newDefaultLimitInPercentage = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { - limit: function(input) { + limit: function (input) { return (parseInt(input) > 0 && parseInt(input) <= 100); }, limitMessage: "Must be greater than 0 and less than 100" - })); + })); let changeTransferLimitToPercentageAction = currentTransferManager.methods.changeTransferLimitToPercentage(newDefaultLimitInPercentage); let changeTransferLimitToPercentageReceipt = await common.sendTransaction(changeTransferLimitToPercentageAction); let changeTransferLimitToPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); @@ -572,11 +572,11 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Change default percentage limit': let defaultLimitInPercentage = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { - limit: function(input) { + limit: function (input) { return (parseInt(input) > 0 && parseInt(input) <= 100); }, limitMessage: "Must be greater than 0 and less than 100" - })); + })); let changeGlobalLimitInPercentageAction = currentTransferManager.methods.changeGlobalLimitInPercentage(defaultLimitInPercentage); let changeGlobalLimitInPercentageReceipt = await common.sendTransaction(changeGlobalLimitInPercentageAction); let changeGlobalLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); @@ -584,11 +584,11 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Change default tokens limit': let defaultLimitInTokens = web3.utils.toWei(readlineSync.question('Enter the amount of tokens for default limit: ', { - limit: function(input) { + limit: function (input) { return parseInt(input) > 0; }, limitMessage: "Must be greater than zero" - })); + })); let changeGlobalLimitInTokensAction = currentTransferManager.methods.changeGlobalLimitInTokens(defaultLimitInTokens); let changeGlobalLimitInTokensReceipt = await common.sendTransaction(changeGlobalLimitInTokensAction); let changeGlobalLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); @@ -596,17 +596,17 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Set percentage transfer limit per account': let percentageAccount = readlineSync.question('Enter the wallet: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" }); let accountLimitInPercentage = toWeiPercentage(readlineSync.question(`Enter the transfer limit for ${percentageAccount} in percentage: `, { - limit: function(input) { + limit: function (input) { return (parseInt(input) > 0 && parseInt(input) <= 100); }, limitMessage: "Must be greater than 0 and less than 100" - })); + })); let setTransferLimitInPercentageAction = currentTransferManager.methods.setTransferLimitInPercentage(percentageAccount, accountLimitInPercentage); let setTransferLimitInPercentageReceipt = await common.sendTransaction(setTransferLimitInPercentageAction); let setTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageSet'); @@ -614,17 +614,17 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Set tokens transfer limit per account': let tokensAccount = readlineSync.question('Enter the wallet: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" }); let accountLimitInTokens = web3.utils.toWei(readlineSync.question(`Enter the transfer limit for ${tokensAccount} in amount of tokens: `, { - limit: function(input) { + limit: function (input) { return parseInt(input) > 0; }, limitMessage: "Must be greater than zero" - })); + })); let setTransferLimitInTokensAction = currentTransferManager.methods.setTransferLimitInTokens(tokensAccount, accountLimitInTokens); let setTransferLimitInTokensReceipt = await common.sendTransaction(setTransferLimitInTokensAction); let setTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensSet'); @@ -632,7 +632,7 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Remove percentage transfer limit per account': let percentageAccountToRemove = readlineSync.question('Enter the wallet to remove: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" @@ -644,7 +644,7 @@ async function singleTradeVolumeRestrictionTM() { break; case 'Remove tokens transfer limit per account': let tokensAccountToRemove = readlineSync.question('Enter the wallet to remove: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" @@ -656,6 +656,7 @@ async function singleTradeVolumeRestrictionTM() { break; } } + /* // Copied from tests function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, pk) { @@ -718,7 +719,7 @@ async function initialize(_tokenSymbol) { tokenSymbol = _tokenSymbol; } let securityTokenAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); - if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { + if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { console.log(chalk.red(`Selected Security Token ${tokenSymbol} does not exist.`)); process.exit(0); } @@ -735,7 +736,7 @@ function welcome() { console.log("Issuer Account: " + Issuer.address + "\n"); } -async function setup(){ +async function setup() { try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -743,25 +744,25 @@ async function setup(){ securityTokenRegistry.setProvider(web3.currentProvider); } catch (err) { console.log(err) - console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); + console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); process.exit(0); } } async function selectToken() { let result = null; - + let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); let tokenDataArray = await Promise.all(userTokens.map(async function (t) { let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); - return {symbol: tokenData[0], address: t}; + return { symbol: tokenData[0], address: t }; })); let options = tokenDataArray.map(function (t) { return `${t.symbol} - Deployed at ${t.address}`; }); options.push('Enter token symbol manually'); - let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); + let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); switch (options[index]) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); @@ -773,12 +774,12 @@ async function selectToken() { result = tokenDataArray[index].symbol; break; } - + return result; } module.exports = { - executeApp: async function(_tokenSymbol) { + executeApp: async function (_tokenSymbol) { await initialize(_tokenSymbol); return executeApp(); } From 3f60f88fab2093df8e52ececaa0e56369893121a Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 27 Nov 2018 10:40:34 +0530 Subject: [PATCH 198/582] minor cleanup --- .../modules/Checkpoint/DividendCheckpointStorage.sol | 9 +-------- .../Checkpoint/ERC20DividendCheckpointStorage.sol | 2 +- contracts/proxy/OwnedProxy.sol | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol index bf86191e6..4cf1f2838 100644 --- a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -1,14 +1,7 @@ -/** - * DISCLAIMER: Under certain conditions, the function pushDividendPayment - * may fail due to block gas limits. - * If the total number of investors that ever held tokens is greater than ~15,000 then - * the function may fail. If this happens investors can pull their dividends, or the Issuer - * can use pushDividendPaymentToAddresses to provide an explict address list in batches - */ pragma solidity ^0.4.24; /** - * @title Checkpoint module for issuing ether dividends + * @title Holds the storage variable for the DividendCheckpoint modules (i.e ERC20, Ether) * @dev abstract contract */ contract DividendCheckpointStorage { diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol index 8bbd13bb6..29401f8d9 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; /** - * @title Checkpoint module for issuing ERC20 dividends + * @title It holds the storage variables related to ERC20DividendCheckpoint module */ contract ERC20DividendCheckpointStorage { diff --git a/contracts/proxy/OwnedProxy.sol b/contracts/proxy/OwnedProxy.sol index 67d3822bc..b75142fbe 100644 --- a/contracts/proxy/OwnedProxy.sol +++ b/contracts/proxy/OwnedProxy.sol @@ -3,7 +3,7 @@ pragma solidity ^0.4.18; import "./Proxy.sol"; /** - * @title OwnedUpgradeabilityProxy + * @title OwnedProxy * @dev This contract combines an upgradeability proxy with basic authorization control functionalities */ contract OwnedProxy is Proxy { From 04763c3766d5537944bf07c6019fbe7f46c22f83 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 11:46:00 +0530 Subject: [PATCH 199/582] Added multiple stable coins support --- contracts/modules/STO/ISTO.sol | 4 +- contracts/modules/STO/USDTieredSTO.sol | 98 +++++++++++++++----------- 2 files changed, 58 insertions(+), 44 deletions(-) diff --git a/contracts/modules/STO/ISTO.sol b/contracts/modules/STO/ISTO.sol index 6ed1d5ba1..6f61e6d5b 100644 --- a/contracts/modules/STO/ISTO.sol +++ b/contracts/modules/STO/ISTO.sol @@ -11,7 +11,7 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; contract ISTO is Module, Pausable { using SafeMath for uint256; - enum FundRaiseType { ETH, POLY, DAI } + enum FundRaiseType { ETH, POLY, SC } mapping (uint8 => bool) public fundRaiseTypes; mapping (uint8 => uint256) public fundsRaised; @@ -76,7 +76,7 @@ contract ISTO is Module, Pausable { require(_fundRaiseTypes.length > 0, "Raise type is not specified"); fundRaiseTypes[uint8(FundRaiseType.ETH)] = false; fundRaiseTypes[uint8(FundRaiseType.POLY)] = false; - fundRaiseTypes[uint8(FundRaiseType.DAI)] = false; + fundRaiseTypes[uint8(FundRaiseType.SC)] = false; for (uint8 j = 0; j < _fundRaiseTypes.length; j++) { fundRaiseTypes[uint8(_fundRaiseTypes[j])] = true; } diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index baba70472..984cfe362 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -44,20 +44,21 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { string public ETH_ORACLE = "EthUsdOracle"; mapping (bytes32 => mapping (bytes32 => string)) oracleKeys; - IERC20 public usdToken; - // Determine whether users can invest on behalf of a beneficiary bool public allowBeneficialInvestments = false; // Whether or not the STO has been finalized bool public isFinalized; - // Address where ETH, POLY & DAI funds are delivered + // Address where ETH, POLY & Stable Coin funds are delivered address public wallet; // Address of issuer reserve wallet for unsold tokens address public reserveWallet; + // List of stable coin addresses + address[] public usdTokens; + // Current tier uint256 public currentTier; @@ -73,6 +74,9 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // List of accredited investors mapping (address => bool) public accredited; + // List of active stable coin addresses + mapping (address => bool) public usdTokenEnabled; + // Default limit in USD for non-accredited investors multiplied by 10**18 uint256 public nonAccreditedLimitUSD; @@ -116,7 +120,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { event SetAddresses( address indexed _wallet, address indexed _reserveWallet, - address indexed _usdToken + address[] _usdTokens ); event SetLimits( uint256 _nonAccreditedLimitUSD, @@ -149,8 +153,13 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _; } - modifier validDAI { - require(fundRaiseTypes[uint8(FundRaiseType.DAI)], "DAI not allowed"); + modifier validSC { + require(fundRaiseTypes[uint8(FundRaiseType.SC)], "Stable coins not allowed"); + _; + } + + modifier validUSDToken(address _usdToken) { + require(usdTokenEnabled[_usdToken], "Invalid USD token"); _; } @@ -176,7 +185,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @param _fundRaiseTypes Types of currency used to collect the funds * @param _wallet Ethereum account address to hold the funds * @param _reserveWallet Ethereum account address to receive unsold tokens - * @param _usdToken Contract address of the stable coin + * @param _usdTokens Array of contract addressess of the stable coins */ function configure( uint256 _startTime, @@ -190,14 +199,14 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { FundRaiseType[] _fundRaiseTypes, address _wallet, address _reserveWallet, - address _usdToken + address[] _usdTokens ) public onlyFactory { require(endTime == 0, "Already configured"); _modifyTimes(_startTime, _endTime); _modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); // NB - _setFundRaiseType must come before modifyAddresses _setFundRaiseType(_fundRaiseTypes); - _modifyAddresses(_wallet, _reserveWallet, _usdToken); + _modifyAddresses(_wallet, _reserveWallet, _usdTokens); _modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); } @@ -253,7 +262,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _endTime ) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ - require(now < startTime, "STO already started"); + //require(now < startTime, "STO already started"); _modifyTimes(_startTime, _endTime); } @@ -261,16 +270,16 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @dev Modifies addresses used as wallet, reserve wallet and usd token * @param _wallet Address of wallet where funds are sent * @param _reserveWallet Address of wallet where unsold tokens are sent - * @param _usdToken Address of usd token (DAI) + * @param _usdTokens Address of usd tokens */ function modifyAddresses( address _wallet, address _reserveWallet, - address _usdToken + address[] _usdTokens ) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); - _modifyAddresses(_wallet, _reserveWallet, _usdToken); + _modifyAddresses(_wallet, _reserveWallet, _usdTokens); } function _modifyLimits( @@ -319,16 +328,19 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { function _modifyAddresses( address _wallet, address _reserveWallet, - address _usdToken + address[] _usdTokens ) internal { require(_wallet != address(0) && _reserveWallet != address(0), "Invalid wallet"); - if (fundRaiseTypes[uint8(FundRaiseType.DAI)]) { - require(_usdToken != address(0), "Invalid usdToken"); - } wallet = _wallet; reserveWallet = _reserveWallet; - usdToken = IERC20(_usdToken); - emit SetAddresses(_wallet, _reserveWallet, _usdToken); + for(uint256 i = 0; i < usdTokens.length; i++) { + usdTokenEnabled[usdTokens[i]] = false; + } + usdTokens = _usdTokens; + for(i = 0; i < _usdTokens.length; i++) { + usdTokenEnabled[_usdTokens[i]] = true; + } + emit SetAddresses(_wallet, _reserveWallet, _usdTokens); } //////////////////// @@ -417,8 +429,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { buyWithPOLYRateLimited(_beneficiary, _investedPOLY, 0); } - function buyWithUSD(address _beneficiary, uint256 _investedDAI) external { - buyWithUSDRateLimited(_beneficiary, _investedDAI, 0); + function buyWithUSD(address _beneficiary, uint256 _investedSC, IERC20 _usdToken) external { + buyWithUSDRateLimited(_beneficiary, _investedSC, 0, _usdToken); } /** @@ -448,21 +460,24 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @param _minTokens Minumum number of tokens to buy or else revert */ function buyWithPOLYRateLimited(address _beneficiary, uint256 _investedPOLY, uint256 _minTokens) public validPOLY { - _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, _minTokens); + _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, _minTokens, polyToken); } /** - * @notice Purchase tokens using DAI + * @notice Purchase tokens using Stable coins * @param _beneficiary Address where security tokens will be sent - * @param _investedDAI Amount of DAI invested + * @param _investedSC Amount of Stable coins invested * @param _minTokens Minumum number of tokens to buy or else revert + * @param _usdToken Address of USD stable coin to buy tokens with */ - function buyWithUSDRateLimited(address _beneficiary, uint256 _investedDAI, uint256 _minTokens) public validDAI { - _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, _minTokens); + function buyWithUSDRateLimited(address _beneficiary, uint256 _investedSC, uint256 _minTokens, IERC20 _usdToken) + public validSC validUSDToken(_usdToken) + { + _buyWithTokens(_beneficiary, _investedSC, FundRaiseType.SC, _minTokens, _usdToken); } - function _buyWithTokens(address _beneficiary, uint256 _tokenAmount, FundRaiseType _fundRaiseType, uint256 _minTokens) internal { - require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI, "Invalid raise type"); + function _buyWithTokens(address _beneficiary, uint256 _tokenAmount, FundRaiseType _fundRaiseType, uint256 _minTokens, IERC20 _token) internal { + require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.SC, "Invalid raise type"); uint256 initialMinted = getTokensMinted(); uint256 rate = getRate(_fundRaiseType); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, _tokenAmount, rate, _fundRaiseType); @@ -470,17 +485,16 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Modify storage investorInvested[_beneficiary][uint8(_fundRaiseType)] = investorInvested[_beneficiary][uint8(_fundRaiseType)].add(spentValue); fundsRaised[uint8(_fundRaiseType)] = fundsRaised[uint8(_fundRaiseType)].add(spentValue); - // Forward DAI to issuer wallet - IERC20 token = _fundRaiseType == FundRaiseType.POLY ? polyToken : usdToken; - require(token.transferFrom(msg.sender, wallet, spentValue), "Transfer failed"); + // Forward coins to issuer wallet + require(_token.transferFrom(msg.sender, wallet, spentValue), "Transfer failed"); emit FundsReceived(msg.sender, _beneficiary, spentUSD, _fundRaiseType, _tokenAmount, spentValue, rate); } /** * @notice Low level token purchase * @param _beneficiary Address where security tokens will be sent - * @param _investmentValue Amount of POLY, ETH or DAI invested - * @param _fundRaiseType Fund raise type (POLY, ETH, DAI) + * @param _investmentValue Amount of POLY, ETH or Stable coins invested + * @param _fundRaiseType Fund raise type (POLY, ETH, SC) */ function _buyTokens( address _beneficiary, @@ -530,8 +544,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { /** * @notice Getter function for buyer to calculate how many tokens will they get * @param _beneficiary Address where security tokens are to be sent - * @param _investmentValue Amount of POLY, ETH or DAI invested - * @param _fundRaiseType Fund raise type (POLY, ETH, DAI) + * @param _investmentValue Amount of POLY, ETH or Stable coins invested + * @param _fundRaiseType Fund raise type (POLY, ETH, SC) */ function buyTokensView( address _beneficiary, @@ -542,7 +556,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { view returns(uint256 spentUSD, uint256 spentValue, uint256 tokensMinted) { - require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI || _fundRaiseType == FundRaiseType.ETH, "Invalid raise type"); + require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.SC || _fundRaiseType == FundRaiseType.ETH, "Invalid raise type"); uint256 rate = getRate(_fundRaiseType); uint256 originalUSD = DecimalMath.mul(rate, _investmentValue); uint256 allowedUSD = _buyTokensChecks(_beneficiary, _investmentValue, originalUSD); @@ -749,7 +763,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { return IOracle(_getOracle(bytes32("ETH"), bytes32("USD"))).getPrice(); } else if (_fundRaiseType == FundRaiseType.POLY) { return IOracle(_getOracle(bytes32("POLY"), bytes32("USD"))).getPrice(); - } else if (_fundRaiseType == FundRaiseType.DAI) { + } else if (_fundRaiseType == FundRaiseType.SC) { return 1 * 10**18; } else { revert("Incorrect funding"); @@ -803,7 +817,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { /** * @notice Return the total no. of tokens sold for the given fund raise type - * param _fundRaiseType The fund raising currency (e.g. ETH, POLY, DAI) to calculate sold tokens for + * param _fundRaiseType The fund raising currency (e.g. ETH, POLY, SC) to calculate sold tokens for * @return uint256 Total number of tokens sold for ETH */ function getTokensSoldFor(FundRaiseType _fundRaiseType) public view returns (uint256) { @@ -824,7 +838,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256[] memory tokensMinted = new uint256[](3); tokensMinted[0] = tiers[_tier].minted[uint8(FundRaiseType.ETH)]; tokensMinted[1] = tiers[_tier].minted[uint8(FundRaiseType.POLY)]; - tokensMinted[2] = tiers[_tier].minted[uint8(FundRaiseType.DAI)]; + tokensMinted[2] = tiers[_tier].minted[uint8(FundRaiseType.SC)]; return tokensMinted; } @@ -838,7 +852,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 tokensSold; tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.ETH)]); tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.POLY)]); - tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.DAI)]); + tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.SC)]); return tokensSold; } @@ -868,7 +882,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @return Amount of funds raised * @return Number of individual investors this STO have. * @return Amount of tokens sold. - * @return Array of bools to show if funding is allowed in ETH, POLY, DAI respectively + * @return Array of bools to show if funding is allowed in ETH, POLY, SC respectively */ function getSTODetails() public view returns(uint256, uint256, uint256, uint256[], uint256[], uint256, uint256, uint256, bool[]) { uint256[] memory cap = new uint256[](tiers.length); @@ -880,7 +894,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { bool[] memory _fundRaiseTypes = new bool[](3); _fundRaiseTypes[0] = fundRaiseTypes[uint8(FundRaiseType.ETH)]; _fundRaiseTypes[1] = fundRaiseTypes[uint8(FundRaiseType.POLY)]; - _fundRaiseTypes[2] = fundRaiseTypes[uint8(FundRaiseType.DAI)]; + _fundRaiseTypes[2] = fundRaiseTypes[uint8(FundRaiseType.SC)]; return ( startTime, endTime, From 7a82d720f4ede6cb24dba4a35879a22143424d5a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 11:46:16 +0530 Subject: [PATCH 200/582] Updated tests --- test/p_usd_tiered_sto.js | 34 +++++++++++++++++----------------- test/q_usd_tiered_sto_sim.js | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 604eb1aaf..b25791dfb 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -315,7 +315,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -388,7 +388,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -412,7 +412,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -500,7 +500,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -587,7 +587,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -626,7 +626,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -665,7 +665,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -696,7 +696,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ], [ _startTime[stoId], @@ -710,7 +710,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ], [ _startTime[stoId], @@ -724,7 +724,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ], [ _startTime[stoId], @@ -738,7 +738,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ] ]; for (var i = 0; i < config.length; i++) { @@ -764,7 +764,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -787,7 +787,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], wallet, _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -833,7 +833,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -857,7 +857,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -934,7 +934,7 @@ contract("USDTieredSTO", accounts => { await I_USDTieredSTO_Array[stoId].modifyAddresses( "0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", - address_zero, + [address_zero], { from: ISSUER } ); assert.equal( @@ -985,7 +985,7 @@ contract("USDTieredSTO", accounts => { I_USDTieredSTO_Array[stoId].modifyAddresses( "0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", - I_DaiToken.address, + [I_DaiToken.address], { from: ISSUER } ) ); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 55f84f2b3..9a5ee963a 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -285,7 +285,7 @@ contract("USDTieredSTO Sim", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); From 1cb134658aaaacb5b2c5d3b2df74a831c1cb51df Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 12:04:59 +0530 Subject: [PATCH 201/582] Updated function signature and selector --- contracts/modules/STO/USDTieredSTO.sol | 2 +- test/p_usd_tiered_sto.js | 44 +++++++++++++------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 984cfe362..fde74b55d 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -913,7 +913,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @return bytes4 Configure function signature */ function getInitFunction() public pure returns (bytes4) { - return 0xb0ff041e; + return 0xeac2f9e4; } function _getOracle(bytes32 _currency, bytes32 _denominatedCurrency) internal view returns (address) { diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index b25791dfb..d4308ea9f 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -157,8 +157,8 @@ contract("USDTieredSTO", accounts => { name: "_reserveWallet" }, { - type: "address", - name: "_usdToken" + type: "address[]", + name: "_usdTokens" } ] }; @@ -301,7 +301,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address); + _usdToken.push([I_DaiToken.address]); let config = [ _startTime[stoId], @@ -315,7 +315,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -388,7 +388,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -412,7 +412,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -486,7 +486,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address); + _usdToken.push([I_DaiToken.address]); let config = [ _startTime[stoId], @@ -500,7 +500,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -573,7 +573,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address); + _usdToken.push([I_DaiToken.address]); let config = [ _startTime[stoId], @@ -587,7 +587,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -612,7 +612,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address); + _usdToken.push([I_DaiToken.address]); let config = [ _startTime[stoId], @@ -626,7 +626,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -651,7 +651,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); - _usdToken.push(I_DaiToken.address); + _usdToken.push([I_DaiToken.address]); let config = [ _startTime[stoId], @@ -665,7 +665,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -696,7 +696,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ], [ _startTime[stoId], @@ -710,7 +710,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ], [ _startTime[stoId], @@ -724,7 +724,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ], [ _startTime[stoId], @@ -738,7 +738,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ] ]; for (var i = 0; i < config.length; i++) { @@ -764,7 +764,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -787,7 +787,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], wallet, _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -833,7 +833,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -857,7 +857,7 @@ contract("USDTieredSTO", accounts => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - [_usdToken[stoId]] + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); From 3270166ce991566b49e91d37adbbedb499f65803 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 12:27:55 +0530 Subject: [PATCH 202/582] tests fixed --- test/p_usd_tiered_sto.js | 45 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index d4308ea9f..1853c645b 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -365,7 +365,7 @@ contract("USDTieredSTO", accounts => { _reserveWallet[stoId], "Incorrect _reserveWallet in config" ); - assert.equal(await I_USDTieredSTO_Array[stoId].usdToken.call(), _usdToken[stoId], "Incorrect _usdToken in config"); + assert.equal(await I_USDTieredSTO_Array[stoId].usdTokens.call(0), _usdToken[stoId][0], "Incorrect _usdToken in config"); assert.equal( await I_USDTieredSTO_Array[stoId].getNumberOfTiers(), _tokensPerTierTotal[stoId].length, @@ -550,7 +550,7 @@ contract("USDTieredSTO", accounts => { _reserveWallet[stoId], "Incorrect _reserveWallet in config" ); - assert.equal(await I_USDTieredSTO_Array[stoId].usdToken.call(), _usdToken[stoId], "Incorrect _usdToken in config"); + assert.equal(await I_USDTieredSTO_Array[stoId].usdTokens.call(0), _usdToken[stoId][0], "Incorrect _usdToken in config"); assert.equal( await I_USDTieredSTO_Array[stoId].getNumberOfTiers(), _tokensPerTierTotal[stoId].length, @@ -809,7 +809,8 @@ contract("USDTieredSTO", accounts => { _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], - reserveWallet + reserveWallet, + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -948,7 +949,7 @@ contract("USDTieredSTO", accounts => { "STO Configuration doesn't set as expected" ); assert.equal( - await I_USDTieredSTO_Array[stoId].usdToken.call(), + await I_USDTieredSTO_Array[stoId].usdTokens.call(0), address_zero, "STO Configuration doesn't set as expected" ); @@ -1033,13 +1034,13 @@ contract("USDTieredSTO", accounts => { // NONACCREDITED POLY await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1 })); // NONACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 })); // ACCREDITED ETH await catchRevert(I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH })); // ACCREDITED POLY await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1 })); // ACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1 })); await revertToSnapshot(snapId); }); @@ -1082,7 +1083,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1 })); // NONACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 })); // ACCREDITED ETH await catchRevert(I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH })); @@ -1091,7 +1092,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1 })); // ACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1 })); await revertToSnapshot(snapId); }); @@ -1138,7 +1139,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1 })); // NONACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 })); // ACCREDITED ETH await catchRevert(I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH })); @@ -1147,7 +1148,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1 })); // ACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1 })); await revertToSnapshot(snapId); }); @@ -1196,7 +1197,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1 })); // NONACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 })); // ACCREDITED ETH await catchRevert(I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH })); @@ -1205,7 +1206,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1 })); // ACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1 })); // Unpause the STO await I_USDTieredSTO_Array[stoId].unpause({ from: ISSUER }); @@ -1213,11 +1214,11 @@ contract("USDTieredSTO", accounts => { await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { from: NONACCREDITED1, value: investment_ETH }); await I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1 }); - await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1 }); + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 }); await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH }); await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1 }); - await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1 }); + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1 }); await revertToSnapshot(snapId); }); @@ -1263,7 +1264,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1 })); // NONACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 })); // ACCREDITED ETH await catchRevert(I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH })); @@ -1272,7 +1273,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1 })); // ACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1 })); await revertToSnapshot(snapId); }); @@ -1325,7 +1326,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(NONACCREDITED1, investment_POLY, { from: NONACCREDITED1 })); // NONACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 })); // ACCREDITED ETH await catchRevert(I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { from: ACCREDITED1, value: investment_ETH })); @@ -1334,7 +1335,7 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { from: ACCREDITED1 })); // ACCREDITED DAI - await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1 })); + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1 })); await revertToSnapshot(snapId); }); @@ -1724,7 +1725,7 @@ contract("USDTieredSTO", accounts => { let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); // Buy With DAI - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1, gasPrice: GAS_PRICE }); @@ -2715,7 +2716,7 @@ contract("USDTieredSTO", accounts => { let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); - let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }); + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1, gasPrice: GAS_PRICE }); let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); console.log(" Gas buyWithUSD: ".grey + tx2.receipt.gasUsed.toString().grey); @@ -2954,7 +2955,7 @@ contract("USDTieredSTO", accounts => { // Buy with DAI NONACCREDITED await catchRevert( - I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, { from: NONACCREDITED1, gasPrice: GAS_PRICE }) + I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1, gasPrice: GAS_PRICE }) ); // Buy with ETH ACCREDITED @@ -2972,7 +2973,7 @@ contract("USDTieredSTO", accounts => { // Buy with DAI ACCREDITED await catchRevert( - I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, { from: ACCREDITED1, gasPrice: GAS_PRICE }) + I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1, gasPrice: GAS_PRICE }) ); }); From ff5fca0a86a15914346c5422a80949c7b5363bbb Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 12:46:35 +0530 Subject: [PATCH 203/582] Fixed simulation test --- test/q_usd_tiered_sto_sim.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 9a5ee963a..d885c6272 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -153,8 +153,8 @@ contract("USDTieredSTO Sim", accounts => { name: "_reserveWallet" }, { - type: "address", - name: "_usdToken" + type: "address[]", + name: "_usdTokens" } ] }; @@ -604,7 +604,7 @@ contract("USDTieredSTO Sim", accounts => { await I_DaiToken.getTokens(investment_DAI, _investor); await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, { from: _investor }); await catchRevert( - I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }) + I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, I_DaiToken.address, { from: _investor, gasPrice: GAS_PRICE }) ); } else await catchRevert( @@ -687,7 +687,7 @@ contract("USDTieredSTO Sim", accounts => { .yellow ); } else if (isDai && investment_DAI.gt(10)) { - tx = await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); + tx = await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, I_DaiToken.address, { from: _investor, gasPrice: GAS_PRICE }); gasCost = BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); console.log( `buyWithUSD: ${investment_Token.div(10 ** 18)} tokens for ${investment_DAI.div(10 ** 18)} DAI by ${_investor}` From c878e9afee2cac36d9e708e7d8ee4a5be62b3f1a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 13:04:51 +0530 Subject: [PATCH 204/582] Added separate function for changing usd tokens --- contracts/modules/STO/USDTieredSTO.sol | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index fde74b55d..27587a11f 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -262,7 +262,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _endTime ) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ - //require(now < startTime, "STO already started"); + require(now < startTime, "STO already started"); _modifyTimes(_startTime, _endTime); } @@ -282,6 +282,14 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _modifyAddresses(_wallet, _reserveWallet, _usdTokens); } + /** + * @dev Modifies addresses used as usd tokens + * @param _usdTokens Address of usd tokens + */ + function modifyUSDTokens(address[] _usdTokens) public onlyOwner { + _modifyUSDTokens(_usdTokens); + } + function _modifyLimits( uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD @@ -333,6 +341,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { require(_wallet != address(0) && _reserveWallet != address(0), "Invalid wallet"); wallet = _wallet; reserveWallet = _reserveWallet; + _modifyUSDTokens(_usdTokens); + } + + function _modifyUSDTokens(address[] _usdTokens) internal { for(uint256 i = 0; i < usdTokens.length; i++) { usdTokenEnabled[usdTokens[i]] = false; } @@ -340,7 +352,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { for(i = 0; i < _usdTokens.length; i++) { usdTokenEnabled[_usdTokens[i]] = true; } - emit SetAddresses(_wallet, _reserveWallet, _usdTokens); + emit SetAddresses(wallet, reserveWallet, _usdTokens); } //////////////////// From 728276f66ed1313b458ef4433141aacca84af493 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 13:14:02 +0530 Subject: [PATCH 205/582] Merge modifyUSDTokens function --- contracts/modules/STO/USDTieredSTO.sol | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 27587a11f..e3a16948c 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -278,18 +278,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { address[] _usdTokens ) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ - require(now < startTime, "STO already started"); + // require(now < startTime, "STO already started"); _modifyAddresses(_wallet, _reserveWallet, _usdTokens); } - /** - * @dev Modifies addresses used as usd tokens - * @param _usdTokens Address of usd tokens - */ - function modifyUSDTokens(address[] _usdTokens) public onlyOwner { - _modifyUSDTokens(_usdTokens); - } - function _modifyLimits( uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD From 420fdc6022c6aa9cd491d9a1dfa69cbee4f0fa87 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 13:14:14 +0530 Subject: [PATCH 206/582] Added test case --- test/p_usd_tiered_sto.js | 58 +++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 1853c645b..0af78cf01 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -977,20 +977,11 @@ contract("USDTieredSTO", accounts => { ) ); - let tempTime1 = latestTime(); + let tempTime1 = latestTime() + duration.days(1); let tempTime2 = latestTime() + duration.days(3); await catchRevert(I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER })); - await catchRevert( - I_USDTieredSTO_Array[stoId].modifyAddresses( - "0x0000000000000000000000000400000000000000", - "0x0000000000000000000003000000000000000000", - [I_DaiToken.address], - { from: ISSUER } - ) - ); - await revertToSnapshot(snapId); }); }); @@ -1223,6 +1214,53 @@ contract("USDTieredSTO", accounts => { await revertToSnapshot(snapId); }); + it("should allow changing stable coin address in middle of STO", async () => { + let stoId = 0; + let snapId = await takeSnapshot(); + + // Whitelist + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(15); + let expiryTime = toTime + duration.days(100); + let whitelisted = true; + + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); + + // Advance time to after STO start + await increaseTime(duration.days(3)); + + // Set as accredited + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + + // Prep for investments + let investment_DAI = web3.utils.toWei("500", "ether"); // Invest 10000 POLY + await I_DaiToken.getTokens(investment_DAI, NONACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, { from: NONACCREDITED1 }); + await I_DaiToken.getTokens(investment_DAI, ACCREDITED1); + await I_DaiToken.approve(I_USDTieredSTO_Array[stoId].address, investment_DAI, { from: ACCREDITED1 }); + + // Make sure buying works before changing + await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 }); + + // Change Stable coin address + await I_USDTieredSTO_Array[stoId].modifyAddresses(WALLET, RESERVEWALLET, [I_PolyToken.address], { from: ISSUER }); + + // NONACCREDITED DAI + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 })); + + // ACCREDITED DAI + await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1 })); + + // Revert stable coin address + await I_USDTieredSTO_Array[stoId].modifyAddresses(WALLET, RESERVEWALLET, [I_DaiToken.address], { from: ISSUER }); + + // Make sure buying works again + await I_USDTieredSTO_Array[stoId].buyWithUSD(ACCREDITED1, investment_DAI, I_DaiToken.address, { from: ACCREDITED1 }); + + await revertToSnapshot(snapId); + }); + it("should fail if after STO end time", async () => { let stoId = 3; let snapId = await takeSnapshot(); From d473a2d30285c61e6c59bb7c7ebe767a71482cbf Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 27 Nov 2018 14:02:33 +0530 Subject: [PATCH 207/582] make script dynamic --- package.json | 1 + scripts/compareStorageLayout.js | 88 ++- scripts/logic.sol | 1188 ----------------------------- scripts/proxy.sol | 332 -------- yarn.lock | 1247 ++----------------------------- 5 files changed, 151 insertions(+), 2705 deletions(-) delete mode 100644 scripts/logic.sol delete mode 100644 scripts/proxy.sol diff --git a/package.json b/package.json index ef2d76c38..58104d99b 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "ethers": "^3.0.15", "fs": "0.0.1-security", "openzeppelin-solidity": "1.10.0", + "prompt": "^1.0.0", "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", diff --git a/scripts/compareStorageLayout.js b/scripts/compareStorageLayout.js index 502f27872..c339bf095 100644 --- a/scripts/compareStorageLayout.js +++ b/scripts/compareStorageLayout.js @@ -1,15 +1,52 @@ const fs = require('fs'); -const logicContract = fs.readFileSync('./logic.sol', 'utf8'); -const proxyContract = fs.readFileSync('./proxy.sol', 'utf8'); const _ = require('underscore'); const solc = require('solc'); +const prompt = require('prompt'); +const path = require('path'); +const util = require('util'); +const exec = util.promisify(require('child_process').exec); -let logicInput = { - 'contracts': logicContract -} -let proxyInput = { - 'contracts': proxyContract -} +prompt.start(); + +prompt.get(['LogicContract', 'ProxyContract'], async(err, result) => { + + let logicContract; + let proxyContract; + + const fileList = walkSync('./contracts', []); + + let paths = findPath(result.LogicContract, result.ProxyContract, fileList); + + if (paths.length == 2) { + + console.log("Contracts exists \n"); + + await flatContracts(paths); + + if (path.basename(paths[0]) === result.LogicContract) { + logicContract = fs.readFileSync(`./flat/${path.basename(paths[0])}`, 'utf8'); + } else { + logicContract = fs.readFileSync(`./flat/${path.basename(paths[1])}`, 'utf8'); + } + if (path.basename(paths[0]) === result.ProxyContract) { + proxyContract = fs.readFileSync(`./flat/${path.basename(paths[0])}`, 'utf8'); + } else { + proxyContract = fs.readFileSync(`./flat/${path.basename(paths[1])}`, 'utf8'); + } + + let logicInput = { + 'contracts': logicContract + } + let proxyInput = { + 'contracts': proxyContract + } + + console.log(compareStorageLayouts(parseContract(logicInput), parseContract(proxyInput))); + + } else { + console.log("Contracts doesn't exists"); + } +}); function traverseAST(_input, _elements) { if(_input.children) { @@ -67,5 +104,36 @@ function parseContract(input) { return orderedStateVariables; } -// console.log(orderedStateVariables); -console.log(compareStorageLayouts(parseContract(logicInput), parseContract(proxyInput))); +var walkSync = function(dir, filelist) { + files = fs.readdirSync(dir); + filelist = filelist || []; + files.forEach(function(file) { + if (fs.statSync(path.join(dir, file)).isDirectory()) { + filelist = walkSync(path.join(dir, file), filelist); + } + else { + filelist.push(path.join(dir, file)); + } + }); + return filelist; +}; + +var findPath = function(logicContractName, proxyContractName, fileList) { + let paths = new Array(); + for (let i =0; i < fileList.length; i++) { + if ((logicContractName === path.basename(fileList[i]) || logicContractName === (path.basename(fileList[i])).split(".")[0]) || + (proxyContractName === path.basename(fileList[i]) || proxyContractName === (path.basename(fileList[i])).split(".")[0])) { + paths.push(fileList[i]); + } + } + return paths; +} + +async function flatContracts(_paths, _logic) { + let promises = new Array(); + for (let i = 0; i< _paths.length; i++) { + promises.push(await exec(`./node_modules/.bin/sol-merger ${_paths[i]} ./flat`)); + } + await Promise.all(promises); +} + diff --git a/scripts/logic.sol b/scripts/logic.sol deleted file mode 100644 index 828bc7213..000000000 --- a/scripts/logic.sol +++ /dev/null @@ -1,1188 +0,0 @@ -pragma solidity ^0.4.24; - -// File: contracts/interfaces/IERC20.sol - -/** - * @title ERC20 interface - * @dev see https://github.com/ethereum/EIPs/issues/20 - */ -interface IERC20 { - function decimals() external view returns (uint8); - function totalSupply() external view returns (uint256); - function balanceOf(address _owner) external view returns (uint256); - function allowance(address _owner, address _spender) external view returns (uint256); - function transfer(address _to, uint256 _value) external returns (bool); - function transferFrom(address _from, address _to, uint256 _value) external returns (bool); - function approve(address _spender, uint256 _value) external returns (bool); - function decreaseApproval(address _spender, uint _subtractedValue) external returns (bool); - function increaseApproval(address _spender, uint _addedValue) external returns (bool); - event Transfer(address indexed from, address indexed to, uint256 value); - event Approval(address indexed owner, address indexed spender, uint256 value); -} - -// File: contracts/interfaces/IOwnable.sol - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -interface IOwnable { - /** - * @dev Returns owner - */ - function owner() external view returns (address); - - /** - * @dev Allows the current owner to relinquish control of the contract. - */ - function renounceOwnership() external; - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param _newOwner The address to transfer ownership to. - */ - function transferOwnership(address _newOwner) external; - -} - -// File: contracts/interfaces/ISecurityToken.sol - -/** - * @title Interface for all security tokens - */ -interface ISecurityToken { - - // Standard ERC20 interface - function decimals() external view returns (uint8); - function totalSupply() external view returns (uint256); - function balanceOf(address _owner) external view returns (uint256); - function allowance(address _owner, address _spender) external view returns (uint256); - function transfer(address _to, uint256 _value) external returns (bool); - function transferFrom(address _from, address _to, uint256 _value) external returns (bool); - function approve(address _spender, uint256 _value) external returns (bool); - function decreaseApproval(address _spender, uint _subtractedValue) external returns (bool); - function increaseApproval(address _spender, uint _addedValue) external returns (bool); - event Transfer(address indexed from, address indexed to, uint256 value); - event Approval(address indexed owner, address indexed spender, uint256 value); - - //transfer, transferFrom must respect the result of verifyTransfer - function verifyTransfer(address _from, address _to, uint256 _value) external returns (bool success); - - /** - * @notice Mints new tokens and assigns them to the target _investor. - * Can only be called by the STO attached to the token (Or by the ST owner if there's no STO attached yet) - * @param _investor Address the tokens will be minted to - * @param _value is the amount of tokens that will be minted to the investor - */ - function mint(address _investor, uint256 _value) external returns (bool success); - - /** - * @notice Mints new tokens and assigns them to the target _investor. - * Can only be called by the STO attached to the token (Or by the ST owner if there's no STO attached yet) - * @param _investor Address the tokens will be minted to - * @param _value is The amount of tokens that will be minted to the investor - * @param _data Data to indicate validation - */ - function mintWithData(address _investor, uint256 _value, bytes _data) external returns (bool success); - - /** - * @notice Used to burn the securityToken on behalf of someone else - * @param _from Address for whom to burn tokens - * @param _value No. of tokens to be burned - * @param _data Data to indicate validation - */ - function burnFromWithData(address _from, uint256 _value, bytes _data) external; - - /** - * @notice Used to burn the securityToken - * @param _value No. of tokens to be burned - * @param _data Data to indicate validation - */ - function burnWithData(uint256 _value, bytes _data) external; - - event Minted(address indexed _to, uint256 _value); - event Burnt(address indexed _burner, uint256 _value); - - // Permissions this to a Permission module, which has a key of 1 - // If no Permission return false - note that IModule withPerm will allow ST owner all permissions anyway - // this allows individual modules to override this logic if needed (to not allow ST owner all permissions) - function checkPermission(address _delegate, address _module, bytes32 _perm) external view returns (bool); - - /** - * @notice Returns module list for a module type - * @param _module Address of the module - * @return bytes32 Name - * @return address Module address - * @return address Module factory address - * @return bool Module archived - * @return uint8 Module type - * @return uint256 Module index - * @return uint256 Name index - - */ - function getModule(address _module) external view returns(bytes32, address, address, bool, uint8, uint256, uint256); - - /** - * @notice Returns module list for a module name - * @param _name Name of the module - * @return address[] List of modules with this name - */ - function getModulesByName(bytes32 _name) external view returns (address[]); - - /** - * @notice Returns module list for a module type - * @param _type Type of the module - * @return address[] List of modules with this type - */ - function getModulesByType(uint8 _type) external view returns (address[]); - - /** - * @notice Queries totalSupply at a specified checkpoint - * @param _checkpointId Checkpoint ID to query as of - */ - function totalSupplyAt(uint256 _checkpointId) external view returns (uint256); - - /** - * @notice Queries balance at a specified checkpoint - * @param _investor Investor to query balance for - * @param _checkpointId Checkpoint ID to query as of - */ - function balanceOfAt(address _investor, uint256 _checkpointId) external view returns (uint256); - - /** - * @notice Creates a checkpoint that can be used to query historical balances / totalSuppy - */ - function createCheckpoint() external returns (uint256); - - /** - * @notice Gets length of investors array - * NB - this length may differ from investorCount if the list has not been pruned of zero-balance investors - * @return Length - */ - function getInvestors() external view returns (address[]); - - /** - * @notice returns an array of investors at a given checkpoint - * NB - this length may differ from investorCount as it contains all investors that ever held tokens - * @param _checkpointId Checkpoint id at which investor list is to be populated - * @return list of investors - */ - function getInvestorsAt(uint256 _checkpointId) external view returns(address[]); - - /** - * @notice generates subset of investors - * NB - can be used in batches if investor list is large - * @param _start Position of investor to start iteration from - * @param _end Position of investor to stop iteration at - * @return list of investors - */ - function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[]); - - /** - * @notice Gets current checkpoint ID - * @return Id - */ - function currentCheckpointId() external view returns (uint256); - - /** - * @notice Gets an investor at a particular index - * @param _index Index to return address from - * @return Investor address - */ - function investors(uint256 _index) external view returns (address); - - /** - * @notice Allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token. - * @dev Owner can transfer POLY to the ST which will be used to pay for modules that require a POLY fee. - * @param _tokenContract Address of the ERC20Basic compliance token - * @param _value Amount of POLY to withdraw - */ - function withdrawERC20(address _tokenContract, uint256 _value) external; - - /** - * @notice Allows owner to approve more POLY to one of the modules - * @param _module Module address - * @param _budget New budget - */ - function changeModuleBudget(address _module, uint256 _budget) external; - - /** - * @notice Changes the tokenDetails - * @param _newTokenDetails New token details - */ - function updateTokenDetails(string _newTokenDetails) external; - - /** - * @notice Allows the owner to change token granularity - * @param _granularity Granularity level of the token - */ - function changeGranularity(uint256 _granularity) external; - - /** - * @notice Removes addresses with zero balances from the investors list - * @param _start Index in investors list at which to start removing zero balances - * @param _iters Max number of iterations of the for loop - * NB - pruning this list will mean you may not be able to iterate over investors on-chain as of a historical checkpoint - */ - function pruneInvestors(uint256 _start, uint256 _iters) external; - - /** - * @notice Freezes all the transfers - */ - function freezeTransfers() external; - - /** - * @notice Un-freezes all the transfers - */ - function unfreezeTransfers() external; - - /** - * @notice Ends token minting period permanently - */ - function freezeMinting() external; - - /** - * @notice Mints new tokens and assigns them to the target investors. - * Can only be called by the STO attached to the token or by the Issuer (Security Token contract owner) - * @param _investors A list of addresses to whom the minted tokens will be delivered - * @param _values A list of the amount of tokens to mint to corresponding addresses from _investor[] list - * @return Success - */ - function mintMulti(address[] _investors, uint256[] _values) external returns (bool success); - - /** - * @notice Function used to attach a module to the security token - * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it - * @dev to control restrictions on transfers. - * @dev You are allowed to add a new moduleType if: - * @dev - there is no existing module of that type yet added - * @dev - the last member of the module list is replacable - * @param _moduleFactory is the address of the module factory to be added - * @param _data is data packed into bytes used to further configure the module (See STO usage) - * @param _maxCost max amount of POLY willing to pay to module. (WIP) - */ - function addModule( - address _moduleFactory, - bytes _data, - uint256 _maxCost, - uint256 _budget - ) external; - - /** - * @notice Archives a module attached to the SecurityToken - * @param _module address of module to archive - */ - function archiveModule(address _module) external; - - /** - * @notice Unarchives a module attached to the SecurityToken - * @param _module address of module to unarchive - */ - function unarchiveModule(address _module) external; - - /** - * @notice Removes a module attached to the SecurityToken - * @param _module address of module to archive - */ - function removeModule(address _module) external; - - /** - * @notice Used by the issuer to set the controller addresses - * @param _controller address of the controller - */ - function setController(address _controller) external; - - /** - * @notice Used by a controller to execute a forced transfer - * @param _from address from which to take tokens - * @param _to address where to send tokens - * @param _value amount of tokens to transfer - * @param _data data to indicate validation - * @param _log data attached to the transfer by controller to emit in event - */ - function forceTransfer(address _from, address _to, uint256 _value, bytes _data, bytes _log) external; - - /** - * @notice Used by a controller to execute a foced burn - * @param _from address from which to take tokens - * @param _value amount of tokens to transfer - * @param _data data to indicate validation - * @param _log data attached to the transfer by controller to emit in event - */ - function forceBurn(address _from, uint256 _value, bytes _data, bytes _log) external; - - /** - * @notice Used by the issuer to permanently disable controller functionality - * @dev enabled via feature switch "disableControllerAllowed" - */ - function disableController() external; - - /** - * @notice Used to get the version of the securityToken - */ - function getVersion() external view returns(uint8[]); - - /** - * @notice Gets the investor count - */ - function getInvestorCount() external view returns(uint256); - - /** - * @notice Overloaded version of the transfer function - * @param _to receiver of transfer - * @param _value value of transfer - * @param _data data to indicate validation - * @return bool success - */ - function transferWithData(address _to, uint256 _value, bytes _data) external returns (bool success); - - /** - * @notice Overloaded version of the transferFrom function - * @param _from sender of transfer - * @param _to receiver of transfer - * @param _value value of transfer - * @param _data data to indicate validation - * @return bool success - */ - function transferFromWithData(address _from, address _to, uint256 _value, bytes _data) external returns(bool); - - /** - * @notice Provides the granularity of the token - * @return uint256 - */ - function granularity() external view returns(uint256); -} - -// File: contracts/interfaces/IModule.sol - -/** - * @title Interface that every module contract should implement - */ -interface IModule { - - /** - * @notice This function returns the signature of configure function - */ - function getInitFunction() external pure returns (bytes4); - - /** - * @notice Return the permission flags that are associated with a module - */ - function getPermissions() external view returns(bytes32[]); - - /** - * @notice Used to withdraw the fee by the factory owner - */ - function takeFee(uint256 _amount) external returns(bool); - -} - -// File: contracts/modules/ModuleStorage.sol - -/** - * @title Storage for Module contract - * @notice Contract is abstract - */ -contract ModuleStorage { - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) public { - securityToken = _securityToken; - factory = msg.sender; - polyToken = IERC20(_polyAddress); - } - - address public factory; - - address public securityToken; - - bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; - - IERC20 public polyToken; - -} - -// File: openzeppelin-solidity/contracts/ownership/Ownable.sol - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable { - address public owner; - - - event OwnershipRenounced(address indexed previousOwner); - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - constructor() public { - owner = msg.sender; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - /** - * @dev Allows the current owner to relinquish control of the contract. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipRenounced(owner); - owner = address(0); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param _newOwner The address to transfer ownership to. - */ - function transferOwnership(address _newOwner) public onlyOwner { - _transferOwnership(_newOwner); - } - - /** - * @dev Transfers control of the contract to a newOwner. - * @param _newOwner The address to transfer ownership to. - */ - function _transferOwnership(address _newOwner) internal { - require(_newOwner != address(0)); - emit OwnershipTransferred(owner, _newOwner); - owner = _newOwner; - } -} - -// File: contracts/modules/Module.sol - -/** - * @title Interface that any module contract should implement - * @notice Contract is abstract - */ -contract Module is IModule, ModuleStorage { - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) public - ModuleStorage(_securityToken, _polyAddress) - { - } - - //Allows owner, factory or permissioned delegate - modifier withPerm(bytes32 _perm) { - bool isOwner = msg.sender == Ownable(securityToken).owner(); - bool isFactory = msg.sender == factory; - require(isOwner||isFactory||ISecurityToken(securityToken).checkPermission(msg.sender, address(this), _perm), "Permission check failed"); - _; - } - - modifier onlyOwner { - require(msg.sender == Ownable(securityToken).owner(), "Sender is not owner"); - _; - } - - modifier onlyFactory { - require(msg.sender == factory, "Sender is not factory"); - _; - } - - modifier onlyFactoryOwner { - require(msg.sender == Ownable(factory).owner(), "Sender is not factory owner"); - _; - } - - modifier onlyFactoryOrOwner { - require((msg.sender == Ownable(securityToken).owner()) || (msg.sender == factory), "Sender is not factory or owner"); - _; - } - - /** - * @notice used to withdraw the fee by the factory owner - */ - function takeFee(uint256 _amount) public withPerm(FEE_ADMIN) returns(bool) { - require(polyToken.transferFrom(securityToken, Ownable(factory).owner(), _amount), "Unable to take fee"); - return true; - } -} - -// File: contracts/modules/Checkpoint/DividendCheckpointStorage.sol - -/** - * DISCLAIMER: Under certain conditions, the function pushDividendPayment - * may fail due to block gas limits. - * If the total number of investors that ever held tokens is greater than ~15,000 then - * the function may fail. If this happens investors can pull their dividends, or the Issuer - * can use pushDividendPaymentToAddresses to provide an explict address list in batches - */ -pragma solidity ^0.4.24; - -/** - * @title Checkpoint module for issuing ether dividends - * @dev abstract contract - */ -contract DividendCheckpointStorage { - - uint256 public EXCLUDED_ADDRESS_LIMIT = 50; - bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; - bytes32 public constant MANAGE = "MANAGE"; - bytes32 public constant CHECKPOINT = "CHECKPOINT"; - - struct Dividend { - uint256 checkpointId; - uint256 created; // Time at which the dividend was created - uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass - uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - - // set to very high value to bypass - uint256 amount; // Dividend amount in WEI - uint256 claimedAmount; // Amount of dividend claimed so far - uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) - bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend - uint256 dividendWithheld; - uint256 dividendWithheldReclaimed; - mapping (address => bool) claimed; // List of addresses which have claimed dividend - mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends - bytes32 name; // Name/title - used for identification - } - - // List of all dividends - Dividend[] public dividends; - - // List of addresses which cannot claim dividends - address[] public excluded; - - // Mapping from address to withholding tax as a percentage * 10**16 - mapping (address => uint256) public withholdingTax; - - // Total amount of ETH withheld per investor - mapping (address => uint256) public investorWithheld; - -} - -// File: contracts/modules/Checkpoint/ICheckpoint.sol - -/** - * @title Interface to be implemented by all checkpoint modules - */ -/*solium-disable-next-line no-empty-blocks*/ -interface ICheckpoint { - -} - -// File: openzeppelin-solidity/contracts/math/Math.sol - -/** - * @title Math - * @dev Assorted math operations - */ -library Math { - function max64(uint64 a, uint64 b) internal pure returns (uint64) { - return a >= b ? a : b; - } - - function min64(uint64 a, uint64 b) internal pure returns (uint64) { - return a < b ? a : b; - } - - function max256(uint256 a, uint256 b) internal pure returns (uint256) { - return a >= b ? a : b; - } - - function min256(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } -} - -// File: openzeppelin-solidity/contracts/math/SafeMath.sol - -/** - * @title SafeMath - * @dev Math operations with safety checks that throw on error - */ -library SafeMath { - - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { - // Gas optimization: this is cheaper than asserting 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - c = a * b; - assert(c / a == b); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // assert(b > 0); // Solidity automatically throws when dividing by 0 - // uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - return a / b; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - assert(b <= a); - return a - b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256 c) { - c = a + b; - assert(c >= a); - return c; - } -} - -// File: contracts/modules/Checkpoint/DividendCheckpoint.sol - -/** - * DISCLAIMER: Under certain conditions, the function pushDividendPayment - * may fail due to block gas limits. - * If the total number of investors that ever held tokens is greater than ~15,000 then - * the function may fail. If this happens investors can pull their dividends, or the Issuer - * can use pushDividendPaymentToAddresses to provide an explict address list in batches - */ -pragma solidity ^0.4.24; - -/** - * @title Checkpoint module for issuing ether dividends - * @dev abstract contract - */ -contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { - using SafeMath for uint256; - - event SetDefaultExcludedAddresses(address[] _excluded, uint256 _timestamp); - event SetWithholding(address[] _investors, uint256[] _withholding, uint256 _timestamp); - event SetWithholdingFixed(address[] _investors, uint256 _withholding, uint256 _timestamp); - - modifier validDividendIndex(uint256 _dividendIndex) { - require(_dividendIndex < dividends.length, "Invalid dividend"); - require(!dividends[_dividendIndex].reclaimed, "Dividend reclaimed"); - /*solium-disable-next-line security/no-block-members*/ - require(now >= dividends[_dividendIndex].maturity, "Dividend maturity in future"); - /*solium-disable-next-line security/no-block-members*/ - require(now < dividends[_dividendIndex].expiry, "Dividend expiry in past"); - _; - } - - /** - * @notice Init function i.e generalise function to maintain the structure of the module contract - * @return bytes4 - */ - function getInitFunction() public pure returns (bytes4) { - return bytes4(0); - } - - /** - * @notice Return the default excluded addresses - * @return List of excluded addresses - */ - function getDefaultExcluded() external view returns (address[]) { - return excluded; - } - - /** - * @notice Creates a checkpoint on the security token - * @return Checkpoint ID - */ - function createCheckpoint() public withPerm(CHECKPOINT) returns (uint256) { - return ISecurityToken(securityToken).createCheckpoint(); - } - - /** - * @notice Function to clear and set list of excluded addresses used for future dividends - * @param _excluded Addresses of investors - */ - function setDefaultExcluded(address[] _excluded) public withPerm(MANAGE) { - require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many excluded addresses"); - for (uint256 j = 0; j < _excluded.length; j++) { - require (_excluded[j] != address(0), "Invalid address"); - for (uint256 i = j + 1; i < _excluded.length; i++) { - require (_excluded[j] != _excluded[i], "Duplicate exclude address"); - } - } - excluded = _excluded; - /*solium-disable-next-line security/no-block-members*/ - emit SetDefaultExcludedAddresses(excluded, now); - } - - /** - * @notice Function to set withholding tax rates for investors - * @param _investors Addresses of investors - * @param _withholding Withholding tax for individual investors (multiplied by 10**16) - */ - function setWithholding(address[] _investors, uint256[] _withholding) public withPerm(MANAGE) { - require(_investors.length == _withholding.length, "Mismatched input lengths"); - /*solium-disable-next-line security/no-block-members*/ - emit SetWithholding(_investors, _withholding, now); - for (uint256 i = 0; i < _investors.length; i++) { - require(_withholding[i] <= 10**18, "Incorrect withholding tax"); - withholdingTax[_investors[i]] = _withholding[i]; - } - } - - /** - * @notice Function to set withholding tax rates for investors - * @param _investors Addresses of investor - * @param _withholding Withholding tax for all investors (multiplied by 10**16) - */ - function setWithholdingFixed(address[] _investors, uint256 _withholding) public withPerm(MANAGE) { - require(_withholding <= 10**18, "Incorrect withholding tax"); - /*solium-disable-next-line security/no-block-members*/ - emit SetWithholdingFixed(_investors, _withholding, now); - for (uint256 i = 0; i < _investors.length; i++) { - withholdingTax[_investors[i]] = _withholding; - } - } - - /** - * @notice Issuer can push dividends to provided addresses - * @param _dividendIndex Dividend to push - * @param _payees Addresses to which to push the dividend - */ - function pushDividendPaymentToAddresses( - uint256 _dividendIndex, - address[] _payees - ) - public - withPerm(DISTRIBUTE) - validDividendIndex(_dividendIndex) - { - Dividend storage dividend = dividends[_dividendIndex]; - for (uint256 i = 0; i < _payees.length; i++) { - if ((!dividend.claimed[_payees[i]]) && (!dividend.dividendExcluded[_payees[i]])) { - _payDividend(_payees[i], dividend, _dividendIndex); - } - } - } - - /** - * @notice Issuer can push dividends using the investor list from the security token - * @param _dividendIndex Dividend to push - * @param _start Index in investor list at which to start pushing dividends - * @param _iterations Number of addresses to push dividends for - */ - function pushDividendPayment( - uint256 _dividendIndex, - uint256 _start, - uint256 _iterations - ) - public - withPerm(DISTRIBUTE) - validDividendIndex(_dividendIndex) - { - Dividend storage dividend = dividends[_dividendIndex]; - address[] memory investors = ISecurityToken(securityToken).getInvestors(); - uint256 numberInvestors = Math.min256(investors.length, _start.add(_iterations)); - for (uint256 i = _start; i < numberInvestors; i++) { - address payee = investors[i]; - if ((!dividend.claimed[payee]) && (!dividend.dividendExcluded[payee])) { - _payDividend(payee, dividend, _dividendIndex); - } - } - } - - /** - * @notice Investors can pull their own dividends - * @param _dividendIndex Dividend to pull - */ - function pullDividendPayment(uint256 _dividendIndex) public validDividendIndex(_dividendIndex) - { - Dividend storage dividend = dividends[_dividendIndex]; - require(!dividend.claimed[msg.sender], "Dividend already claimed"); - require(!dividend.dividendExcluded[msg.sender], "msg.sender excluded from Dividend"); - _payDividend(msg.sender, dividend, _dividendIndex); - } - - /** - * @notice Internal function for paying dividends - * @param _payee Address of investor - * @param _dividend Storage with previously issued dividends - * @param _dividendIndex Dividend to pay - */ - function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal; - - /** - * @notice Issuer can reclaim remaining unclaimed dividend amounts, for expired dividends - * @param _dividendIndex Dividend to reclaim - */ - function reclaimDividend(uint256 _dividendIndex) external; - - /** - * @notice Calculate amount of dividends claimable - * @param _dividendIndex Dividend to calculate - * @param _payee Affected investor address - * @return claim, withheld amounts - */ - function calculateDividend(uint256 _dividendIndex, address _payee) public view returns(uint256, uint256) { - require(_dividendIndex < dividends.length, "Invalid dividend"); - Dividend storage dividend = dividends[_dividendIndex]; - if (dividend.claimed[_payee] || dividend.dividendExcluded[_payee]) { - return (0, 0); - } - uint256 balance = ISecurityToken(securityToken).balanceOfAt(_payee, dividend.checkpointId); - uint256 claim = balance.mul(dividend.amount).div(dividend.totalSupply); - uint256 withheld = claim.mul(withholdingTax[_payee]).div(uint256(10**18)); - return (claim, withheld); - } - - /** - * @notice Get the index according to the checkpoint id - * @param _checkpointId Checkpoint id to query - * @return uint256[] - */ - function getDividendIndex(uint256 _checkpointId) public view returns(uint256[]) { - uint256 counter = 0; - for(uint256 i = 0; i < dividends.length; i++) { - if (dividends[i].checkpointId == _checkpointId) { - counter++; - } - } - - uint256[] memory index = new uint256[](counter); - counter = 0; - for(uint256 j = 0; j < dividends.length; j++) { - if (dividends[j].checkpointId == _checkpointId) { - index[counter] = j; - counter++; - } - } - return index; - } - - /** - * @notice Allows issuer to withdraw withheld tax - * @param _dividendIndex Dividend to withdraw from - */ - function withdrawWithholding(uint256 _dividendIndex) external; - - /** - * @notice Return the permissions flag that are associated with this module - * @return bytes32 array - */ - function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](2); - allPermissions[0] = DISTRIBUTE; - allPermissions[1] = MANAGE; - return allPermissions; - } - -} - -// File: contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol - -/** - * @title Checkpoint module for issuing ERC20 dividends - */ -contract ERC20DividendCheckpointStorage { - - // Mapping to token address for each dividend - mapping (uint256 => address) public dividendTokens; - -} - -// File: contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol - -/** - * @title Checkpoint module for issuing ERC20 dividends - */ -contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendCheckpoint { - using SafeMath for uint256; - - event ERC20DividendDeposited( - address indexed _depositor, - uint256 _checkpointId, - uint256 _created, - uint256 _maturity, - uint256 _expiry, - address indexed _token, - uint256 _amount, - uint256 _totalSupply, - uint256 _dividendIndex, - bytes32 indexed _name - ); - event ERC20DividendClaimed( - address indexed _payee, - uint256 _dividendIndex, - address indexed _token, - uint256 _amount, - uint256 _withheld - ); - event ERC20DividendReclaimed( - address indexed _claimer, - uint256 _dividendIndex, - address indexed _token, - uint256 _claimedAmount - ); - event ERC20DividendWithholdingWithdrawn( - address indexed _claimer, - uint256 _dividendIndex, - address indexed _token, - uint256 _withheldAmount - ); - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) - { - } - - /** - * @notice Creates a dividend and checkpoint for the dividend - * @param _maturity Time from which dividend can be paid - * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer - * @param _token Address of ERC20 token in which dividend is to be denominated - * @param _amount Amount of specified token for dividend - * @param _name Name/Title for identification - */ - function createDividend( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - bytes32 _name - ) - external - withPerm(MANAGE) - { - createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name); - } - - /** - * @notice Creates a dividend with a provided checkpoint - * @param _maturity Time from which dividend can be paid - * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer - * @param _token Address of ERC20 token in which dividend is to be denominated - * @param _amount Amount of specified token for dividend - * @param _checkpointId Checkpoint id from which to create dividends - * @param _name Name/Title for identification - */ - function createDividendWithCheckpoint( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, - bytes32 _name - ) - external - withPerm(MANAGE) - { - _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, excluded, _name); - } - - /** - * @notice Creates a dividend and checkpoint for the dividend - * @param _maturity Time from which dividend can be paid - * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer - * @param _token Address of ERC20 token in which dividend is to be denominated - * @param _amount Amount of specified token for dividend - * @param _excluded List of addresses to exclude - * @param _name Name/Title for identification - */ - function createDividendWithExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - address[] _excluded, - bytes32 _name - ) - public - withPerm(MANAGE) - { - uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); - _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, checkpointId, _excluded, _name); - } - - /** - * @notice Creates a dividend with a provided checkpoint - * @param _maturity Time from which dividend can be paid - * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer - * @param _token Address of ERC20 token in which dividend is to be denominated - * @param _amount Amount of specified token for dividend - * @param _checkpointId Checkpoint id from which to create dividends - * @param _excluded List of addresses to exclude - * @param _name Name/Title for identification - */ - function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, - address[] _excluded, - bytes32 _name - ) - public - withPerm(MANAGE) - { - _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, _excluded, _name); - } - - /** - * @notice Creates a dividend with a provided checkpoint - * @param _maturity Time from which dividend can be paid - * @param _expiry Time until dividend can no longer be paid, and can be reclaimed by issuer - * @param _token Address of ERC20 token in which dividend is to be denominated - * @param _amount Amount of specified token for dividend - * @param _checkpointId Checkpoint id from which to create dividends - * @param _excluded List of addresses to exclude - * @param _name Name/Title for identification - */ - function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, - address[] _excluded, - bytes32 _name - ) - internal - { - ISecurityToken securityTokenInstance = ISecurityToken(securityToken); - require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); - require(_expiry > _maturity, "Expiry before maturity"); - /*solium-disable-next-line security/no-block-members*/ - require(_expiry > now, "Expiry in past"); - require(_amount > 0, "No dividend sent"); - require(_token != address(0), "Invalid token"); - require(_checkpointId <= securityTokenInstance.currentCheckpointId(), "Invalid checkpoint"); - require(IERC20(_token).transferFrom(msg.sender, address(this), _amount), "insufficent allowance"); - require(_name[0] != 0); - uint256 dividendIndex = dividends.length; - uint256 currentSupply = securityTokenInstance.totalSupplyAt(_checkpointId); - uint256 excludedSupply = 0; - dividends.push( - Dividend( - _checkpointId, - now, /*solium-disable-line security/no-block-members*/ - _maturity, - _expiry, - _amount, - 0, - 0, - false, - 0, - 0, - _name - ) - ); - - for (uint256 j = 0; j < _excluded.length; j++) { - require (_excluded[j] != address(0), "Invalid address"); - require(!dividends[dividendIndex].dividendExcluded[_excluded[j]], "duped exclude address"); - excludedSupply = excludedSupply.add(securityTokenInstance.balanceOfAt(_excluded[j], _checkpointId)); - dividends[dividendIndex].dividendExcluded[_excluded[j]] = true; - } - - dividends[dividendIndex].totalSupply = currentSupply.sub(excludedSupply); - dividendTokens[dividendIndex] = _token; - _emitERC20DividendDepositedEvent(_checkpointId, _maturity, _expiry, _token, _amount, currentSupply, dividendIndex, _name); - } - - /** - * @notice Emits the ERC20DividendDeposited event. - * Seperated into a different function as a workaround for stack too deep error - */ - function _emitERC20DividendDepositedEvent( - uint256 _checkpointId, - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 currentSupply, - uint256 dividendIndex, - bytes32 _name - ) - internal - { - /*solium-disable-next-line security/no-block-members*/ - emit ERC20DividendDeposited(msg.sender, _checkpointId, now, _maturity, _expiry, _token, _amount, currentSupply, dividendIndex, _name); - } - - /** - * @notice Internal function for paying dividends - * @param _payee Address of investor - * @param _dividend Storage with previously issued dividends - * @param _dividendIndex Dividend to pay - */ - function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { - (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee); - _dividend.claimed[_payee] = true; - _dividend.claimedAmount = claim.add(_dividend.claimedAmount); - uint256 claimAfterWithheld = claim.sub(withheld); - if (claimAfterWithheld > 0) { - require(IERC20(dividendTokens[_dividendIndex]).transfer(_payee, claimAfterWithheld), "transfer failed"); - _dividend.dividendWithheld = _dividend.dividendWithheld.add(withheld); - investorWithheld[_payee] = investorWithheld[_payee].add(withheld); - emit ERC20DividendClaimed(_payee, _dividendIndex, dividendTokens[_dividendIndex], claim, withheld); - } - } - - /** - * @notice Issuer can reclaim remaining unclaimed dividend amounts, for expired dividends - * @param _dividendIndex Dividend to reclaim - */ - function reclaimDividend(uint256 _dividendIndex) external withPerm(MANAGE) { - require(_dividendIndex < dividends.length, "Invalid dividend"); - /*solium-disable-next-line security/no-block-members*/ - require(now >= dividends[_dividendIndex].expiry, "Dividend expiry in future"); - require(!dividends[_dividendIndex].reclaimed, "already claimed"); - dividends[_dividendIndex].reclaimed = true; - Dividend storage dividend = dividends[_dividendIndex]; - uint256 remainingAmount = dividend.amount.sub(dividend.claimedAmount); - address owner = IOwnable(securityToken).owner(); - require(IERC20(dividendTokens[_dividendIndex]).transfer(owner, remainingAmount), "transfer failed"); - emit ERC20DividendReclaimed(owner, _dividendIndex, dividendTokens[_dividendIndex], remainingAmount); - } - - /** - * @notice Allows issuer to withdraw withheld tax - * @param _dividendIndex Dividend to withdraw from - */ - function withdrawWithholding(uint256 _dividendIndex) external withPerm(MANAGE) { - require(_dividendIndex < dividends.length, "Invalid dividend"); - Dividend storage dividend = dividends[_dividendIndex]; - uint256 remainingWithheld = dividend.dividendWithheld.sub(dividend.dividendWithheldReclaimed); - dividend.dividendWithheldReclaimed = dividend.dividendWithheld; - address owner = IOwnable(securityToken).owner(); - require(IERC20(dividendTokens[_dividendIndex]).transfer(owner, remainingWithheld), "transfer failed"); - emit ERC20DividendWithholdingWithdrawn(owner, _dividendIndex, dividendTokens[_dividendIndex], remainingWithheld); - } - -} diff --git a/scripts/proxy.sol b/scripts/proxy.sol deleted file mode 100644 index ed315955f..000000000 --- a/scripts/proxy.sol +++ /dev/null @@ -1,332 +0,0 @@ -pragma solidity ^0.4.24; - -// File: contracts/Pausable.sol - -/** - * @title Utility contract to allow pausing and unpausing of certain functions - */ -contract Pausable { - - event Pause(uint256 _timestammp); - event Unpause(uint256 _timestamp); - - bool public paused = false; - - /** - * @notice Modifier to make a function callable only when the contract is not paused. - */ - modifier whenNotPaused() { - require(!paused, "Contract is paused"); - _; - } - - /** - * @notice Modifier to make a function callable only when the contract is paused. - */ - modifier whenPaused() { - require(paused, "Contract is not paused"); - _; - } - - /** - * @notice Called by the owner to pause, triggers stopped state - */ - function _pause() internal whenNotPaused { - paused = true; - /*solium-disable-next-line security/no-block-members*/ - emit Pause(now); - } - - /** - * @notice Called by the owner to unpause, returns to normal state - */ - function _unpause() internal whenPaused { - paused = false; - /*solium-disable-next-line security/no-block-members*/ - emit Unpause(now); - } - -} - -// File: contracts/modules/Checkpoint/DividendCheckpointStorage.sol - -/** - * DISCLAIMER: Under certain conditions, the function pushDividendPayment - * may fail due to block gas limits. - * If the total number of investors that ever held tokens is greater than ~15,000 then - * the function may fail. If this happens investors can pull their dividends, or the Issuer - * can use pushDividendPaymentToAddresses to provide an explict address list in batches - */ -pragma solidity ^0.4.24; - -/** - * @title Checkpoint module for issuing ether dividends - * @dev abstract contract - */ -contract DividendCheckpointStorage { - - uint256 public EXCLUDED_ADDRESS_LIMIT = 50; - bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; - bytes32 public constant MANAGE = "MANAGE"; - bytes32 public constant CHECKPOINT = "CHECKPOINT"; - - struct Dividend { - uint256 checkpointId; - uint256 created; // Time at which the dividend was created - uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass - uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - - // set to very high value to bypass - uint256 amount; // Dividend amount in WEI - uint256 claimedAmount; // Amount of dividend claimed so far - uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) - bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend - uint256 dividendWithheld; - uint256 dividendWithheldReclaimed; - mapping (address => bool) claimed; // List of addresses which have claimed dividend - mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends - bytes32 name; // Name/title - used for identification - } - - // List of all dividends - Dividend[] public dividends; - - // List of addresses which cannot claim dividends - address[] public excluded; - - // Mapping from address to withholding tax as a percentage * 10**16 - mapping (address => uint256) public withholdingTax; - - // Total amount of ETH withheld per investor - mapping (address => uint256) public investorWithheld; - -} - -// File: contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol - -/** - * @title Checkpoint module for issuing ERC20 dividends - */ -contract ERC20DividendCheckpointStorage { - - // Mapping to token address for each dividend - mapping (uint256 => address) public dividendTokens; - -} - -// File: contracts/interfaces/IERC20.sol - -/** - * @title ERC20 interface - * @dev see https://github.com/ethereum/EIPs/issues/20 - */ -interface IERC20 { - function decimals() external view returns (uint8); - function totalSupply() external view returns (uint256); - function balanceOf(address _owner) external view returns (uint256); - function allowance(address _owner, address _spender) external view returns (uint256); - function transfer(address _to, uint256 _value) external returns (bool); - function transferFrom(address _from, address _to, uint256 _value) external returns (bool); - function approve(address _spender, uint256 _value) external returns (bool); - function decreaseApproval(address _spender, uint _subtractedValue) external returns (bool); - function increaseApproval(address _spender, uint _addedValue) external returns (bool); - event Transfer(address indexed from, address indexed to, uint256 value); - event Approval(address indexed owner, address indexed spender, uint256 value); -} - -// File: contracts/modules/ModuleStorage.sol - -/** - * @title Storage for Module contract - * @notice Contract is abstract - */ -contract ModuleStorage { - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) public { - securityToken = _securityToken; - factory = msg.sender; - polyToken = IERC20(_polyAddress); - } - - address public factory; - - address public securityToken; - - bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; - - IERC20 public polyToken; - -} - -// File: contracts/proxy/Proxy.sol - -/** - * @title Proxy - * @dev Gives the possibility to delegate any call to a foreign implementation. - */ -contract Proxy { - - /** - * @dev Tells the address of the implementation where every call will be delegated. - * @return address of the implementation to which it will be delegated - */ - function _implementation() internal view returns (address); - - /** - * @dev Fallback function. - * Implemented entirely in `_fallback`. - */ - function _fallback() internal { - _delegate(_implementation()); - } - - /** - * @dev Fallback function allowing to perform a delegatecall to the given implementation. - * This function will return whatever the implementation call returns - */ - function _delegate(address implementation) internal { - /*solium-disable-next-line security/no-inline-assembly*/ - assembly { - // Copy msg.data. We take full control of memory in this inline assembly - // block because it will not return to Solidity code. We overwrite the - // Solidity scratch pad at memory position 0. - calldatacopy(0, 0, calldatasize) - - // Call the implementation. - // out and outsize are 0 because we don't know the size yet. - let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0) - - // Copy the returned data. - returndatacopy(0, 0, returndatasize) - - switch result - // delegatecall returns 0 on error. - case 0 { revert(0, returndatasize) } - default { return(0, returndatasize) } - } - } - - function () public payable { - _fallback(); - } -} - -// File: contracts/proxy/OwnedProxy.sol - -/** - * @title OwnedUpgradeabilityProxy - * @dev This contract combines an upgradeability proxy with basic authorization control functionalities - */ -contract OwnedProxy is Proxy { - - // Owner of the contract - address private __owner; - - // Address of the current implementation - address internal __implementation; - - /** - * @dev Event to show ownership has been transferred - * @param _previousOwner representing the address of the previous owner - * @param _newOwner representing the address of the new owner - */ - event ProxyOwnershipTransferred(address _previousOwner, address _newOwner); - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier ifOwner() { - if (msg.sender == _owner()) { - _; - } else { - _fallback(); - } - } - - /** - * @dev the constructor sets the original owner of the contract to the sender account. - */ - constructor() public { - _setOwner(msg.sender); - } - - /** - * @dev Tells the address of the owner - * @return the address of the owner - */ - function _owner() internal view returns (address) { - return __owner; - } - - /** - * @dev Sets the address of the owner - */ - function _setOwner(address _newOwner) internal { - require(_newOwner != address(0), "Address should not be 0x"); - __owner = _newOwner; - } - - /** - * @notice Internal function to provide the address of the implementation contract - */ - function _implementation() internal view returns (address) { - return __implementation; - } - - /** - * @dev Tells the address of the proxy owner - * @return the address of the proxy owner - */ - function proxyOwner() external ifOwner returns (address) { - return _owner(); - } - - /** - * @dev Tells the address of the current implementation - * @return address of the current implementation - */ - function implementation() external ifOwner returns (address) { - return _implementation(); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param _newOwner The address to transfer ownership to. - */ - function transferProxyOwnership(address _newOwner) external ifOwner { - require(_newOwner != address(0), "Address should not be 0x"); - emit ProxyOwnershipTransferred(_owner(), _newOwner); - _setOwner(_newOwner); - } - -} - -// File: contracts/proxy/ERC20DividendCheckpointProxy.sol - -/** - * @title Transfer Manager module for core transfer validation functionality - */ -contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - * @param _implementation representing the address of the new implementation to be set - */ - constructor (address _securityToken, address _polyAddress, address _implementation) - public - ModuleStorage(_securityToken, _polyAddress) - { - require( - _implementation != address(0), - "Implementation address should not be 0x" - ); - __implementation = _implementation; - } - -} diff --git a/yarn.lock b/yarn.lock index 27308427c..31973936e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,12 +5,10 @@ "@soldoc/markdown@^0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@soldoc/markdown/-/markdown-0.1.0.tgz#9f85be75049af9721b5129f133d52dafbf5f671e" - integrity sha512-V0UnvVVJ1qDzpuKLMuh7oHG94puwi8BI3t99Vrr7dQgIHuJdfZJ4SbGuWuFV/fSthyH++WY4ePO3d6gxfZ2//w== "@soldoc/soldoc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@soldoc/soldoc/-/soldoc-0.4.3.tgz#24ffee9264228e1c3edd61fd3162d63587954933" - integrity sha1-JP/ukmQijhw+3WH9MWLWNYeVSTM= dependencies: "@soldoc/markdown" "^0.1.0" chalk "^2.3.1" @@ -24,31 +22,26 @@ abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= abstract-leveldown@~2.6.0: version "2.6.3" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== dependencies: xtend "~4.0.0" abstract-leveldown@~2.7.1: version "2.7.2" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== dependencies: xtend "~4.0.0" accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= dependencies: mime-types "~2.1.18" negotiator "0.6.1" @@ -56,56 +49,46 @@ accepts@~1.3.5: acorn-dynamic-import@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" - integrity sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ= dependencies: acorn "^4.0.3" acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= dependencies: acorn "^3.0.4" acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= acorn@^5.0.0, acorn@^5.5.0: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= aes-js@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072" - integrity sha512-cEA0gBelItZZV7iBiL8ApCiNgc+gBWJJ4uoORhbu6vOqAJ0UL9wIlxr4RI7ij9SSVzy6AnPwiu37kVYiHCl3nw== ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" - integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= ajv@^5.1.1, ajv@^5.2.2, ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" @@ -115,7 +98,6 @@ ajv@^5.1.1, ajv@^5.2.2, ajv@^5.2.3, ajv@^5.3.0: ajv@^6.1.0: version "6.5.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59" - integrity sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -125,7 +107,6 @@ ajv@^6.1.0: align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= dependencies: kind-of "^3.0.2" longest "^1.0.1" @@ -134,7 +115,6 @@ align-text@^0.1.1, align-text@^0.1.3: ambi@^2.2.0: version "2.5.0" resolved "https://registry.yarnpkg.com/ambi/-/ambi-2.5.0.tgz#7c8e372be48891157e7cea01cb6f9143d1f74220" - integrity sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA= dependencies: editions "^1.1.1" typechecker "^4.3.0" @@ -142,44 +122,36 @@ ambi@^2.2.0: amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= ansi-escapes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" - integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== dependencies: micromatch "^2.1.5" normalize-path "^2.0.0" @@ -187,7 +159,6 @@ anymatch@^1.3.0: anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" normalize-path "^2.1.1" @@ -195,12 +166,10 @@ anymatch@^2.0.0: aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -208,85 +177,56 @@ are-we-there-yet@~1.1.2: argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -arguments-extended@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/arguments-extended/-/arguments-extended-0.0.3.tgz#6107e4917d0eb6f0a4dd66320fc15afc72ef4946" - integrity sha1-YQfkkX0OtvCk3WYyD8Fa/HLvSUY= - dependencies: - extended "~0.0.3" - is-extended "~0.0.8" - arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= dependencies: arr-flatten "^1.0.1" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-extended@~0.0.3, array-extended@~0.0.4, array-extended@~0.0.5: - version "0.0.11" - resolved "https://registry.yarnpkg.com/array-extended/-/array-extended-0.0.11.tgz#d7144ae748de93ca726f121009dbff1626d164bd" - integrity sha1-1xRK50jek8pybxIQCdv/FibRZL0= - dependencies: - arguments-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= dependencies: array-uniq "^1.0.1" array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -295,36 +235,30 @@ asn1.js@^4.0.0: asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assert@^1.1.1: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= dependencies: util "0.10.3" assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-eventemitter@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== dependencies: async "^2.4.0" @@ -337,49 +271,44 @@ async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== async@1.x, async@^1.4.2, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.4.1, async@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== dependencies: lodash "^4.17.10" +async@~0.9.0: + version "0.9.2" + resolved "http://registry.npmjs.org/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + async@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" - integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -388,7 +317,6 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: babel-core@^6.0.14, babel-core@^6.26.0: version "6.26.3" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== dependencies: babel-code-frame "^6.26.0" babel-generator "^6.26.0" @@ -413,7 +341,6 @@ babel-core@^6.0.14, babel-core@^6.26.0: babel-generator@^6.26.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" @@ -427,7 +354,6 @@ babel-generator@^6.26.0: babel-helper-bindify-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" - integrity sha1-FMGeXxQte0fxmlJDHlKxzLxAozA= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -436,7 +362,6 @@ babel-helper-bindify-decorators@^6.24.1: babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= dependencies: babel-helper-explode-assignable-expression "^6.24.1" babel-runtime "^6.22.0" @@ -445,7 +370,6 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -455,7 +379,6 @@ babel-helper-call-delegate@^6.24.1: babel-helper-define-map@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.26.0" @@ -465,7 +388,6 @@ babel-helper-define-map@^6.24.1: babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -474,7 +396,6 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-helper-explode-class@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" - integrity sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes= dependencies: babel-helper-bindify-decorators "^6.24.1" babel-runtime "^6.22.0" @@ -484,7 +405,6 @@ babel-helper-explode-class@^6.24.1: babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= dependencies: babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" @@ -495,7 +415,6 @@ babel-helper-function-name@^6.24.1: babel-helper-get-function-arity@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -503,7 +422,6 @@ babel-helper-get-function-arity@^6.24.1: babel-helper-hoist-variables@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -511,7 +429,6 @@ babel-helper-hoist-variables@^6.24.1: babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -519,7 +436,6 @@ babel-helper-optimise-call-expression@^6.24.1: babel-helper-regex@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= dependencies: babel-runtime "^6.26.0" babel-types "^6.26.0" @@ -528,7 +444,6 @@ babel-helper-regex@^6.24.1: babel-helper-remap-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -539,7 +454,6 @@ babel-helper-remap-async-to-generator@^6.24.1: babel-helper-replace-supers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= dependencies: babel-helper-optimise-call-expression "^6.24.1" babel-messages "^6.23.0" @@ -551,7 +465,6 @@ babel-helper-replace-supers@^6.24.1: babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -559,61 +472,50 @@ babel-helpers@^6.24.1: babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= dependencies: babel-runtime "^6.22.0" babel-plugin-check-es2015-constants@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= dependencies: babel-runtime "^6.22.0" babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= babel-plugin-syntax-async-generators@^6.5.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - integrity sha1-a8lj67FuzLrmuStZbrfzXDQqi5o= babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= babel-plugin-syntax-decorators@^6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" - integrity sha1-MSVjtNvePMgGzuPkFszurd0RrAs= babel-plugin-syntax-dynamic-import@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" - integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= babel-plugin-transform-async-generator-functions@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" - integrity sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-generators "^6.5.0" @@ -622,7 +524,6 @@ babel-plugin-transform-async-generator-functions@^6.24.1: babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-functions "^6.8.0" @@ -631,7 +532,6 @@ babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async- babel-plugin-transform-class-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= dependencies: babel-helper-function-name "^6.24.1" babel-plugin-syntax-class-properties "^6.8.0" @@ -641,7 +541,6 @@ babel-plugin-transform-class-properties@^6.24.1: babel-plugin-transform-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" - integrity sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0= dependencies: babel-helper-explode-class "^6.24.1" babel-plugin-syntax-decorators "^6.13.0" @@ -652,21 +551,18 @@ babel-plugin-transform-decorators@^6.24.1: babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= dependencies: babel-runtime "^6.26.0" babel-template "^6.26.0" @@ -677,7 +573,6 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= dependencies: babel-helper-define-map "^6.24.1" babel-helper-function-name "^6.24.1" @@ -692,7 +587,6 @@ babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-cla babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -700,14 +594,12 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transfor babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -715,14 +607,12 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2 babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -731,14 +621,12 @@ babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= dependencies: babel-plugin-transform-es2015-modules-commonjs "^6.24.1" babel-runtime "^6.22.0" @@ -747,7 +635,6 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.26.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== dependencies: babel-plugin-transform-strict-mode "^6.24.1" babel-runtime "^6.26.0" @@ -757,7 +644,6 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -766,7 +652,6 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= dependencies: babel-plugin-transform-es2015-modules-amd "^6.24.1" babel-runtime "^6.22.0" @@ -775,7 +660,6 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= dependencies: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" @@ -783,7 +667,6 @@ babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= dependencies: babel-helper-call-delegate "^6.24.1" babel-helper-get-function-arity "^6.24.1" @@ -795,7 +678,6 @@ babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015- babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -803,14 +685,12 @@ babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transfo babel-plugin-transform-es2015-spread@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -819,21 +699,18 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -842,7 +719,6 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= dependencies: babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" babel-plugin-syntax-exponentiation-operator "^6.8.0" @@ -851,7 +727,6 @@ babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-e babel-plugin-transform-object-rest-spread@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" @@ -859,14 +734,12 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= dependencies: regenerator-transform "^0.10.0" babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -874,7 +747,6 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-polyfill@6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= dependencies: babel-runtime "^6.26.0" core-js "^2.5.0" @@ -883,7 +755,6 @@ babel-polyfill@6.26.0: babel-preset-env@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -919,7 +790,6 @@ babel-preset-env@^1.7.0: babel-preset-es2015@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - integrity sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk= dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-transform-es2015-arrow-functions "^6.22.0" @@ -949,7 +819,6 @@ babel-preset-es2015@6.24.1: babel-preset-stage-2@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" - integrity sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE= dependencies: babel-plugin-syntax-dynamic-import "^6.18.0" babel-plugin-transform-class-properties "^6.24.1" @@ -959,7 +828,6 @@ babel-preset-stage-2@6.24.1: babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" - integrity sha1-g2raCp56f6N8sTj7kyb4eTSkg5U= dependencies: babel-plugin-syntax-trailing-function-commas "^6.22.0" babel-plugin-transform-async-generator-functions "^6.24.1" @@ -970,7 +838,6 @@ babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: babel-register@6.26.0, babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= dependencies: babel-core "^6.26.0" babel-runtime "^6.26.0" @@ -983,7 +850,6 @@ babel-register@6.26.0, babel-register@^6.26.0: babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" @@ -991,7 +857,6 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= dependencies: babel-runtime "^6.26.0" babel-traverse "^6.26.0" @@ -1002,7 +867,6 @@ babel-template@^6.24.1, babel-template@^6.26.0: babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= dependencies: babel-code-frame "^6.26.0" babel-messages "^6.23.0" @@ -1017,7 +881,6 @@ babel-traverse@^6.24.1, babel-traverse@^6.26.0: babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= dependencies: babel-runtime "^6.26.0" esutils "^2.0.2" @@ -1027,7 +890,6 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: babelify@^7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= dependencies: babel-core "^6.0.14" object-assign "^4.0.0" @@ -1035,34 +897,28 @@ babelify@^7.3.0: babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base-x@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" - integrity sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA== dependencies: safe-buffer "^5.0.1" base64-js@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" - integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg= base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -1075,29 +931,24 @@ base@^0.11.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== bignumber.js@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" - integrity sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA== bignumber.js@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" - integrity sha512-KWTu6ZMVk9sxlDJQh2YH1UOnfDP8O8TpxUxgQG/vKASoSnEjK9aVuOueFaPcQEYQ5fyNXNTOYwYw3099RYebWg== bignumber.js@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-6.0.0.tgz#bbfa047644609a5af093e9cbd83b0461fa3f6002" - integrity sha512-x247jIuy60/+FtMRvscqfxtVHQf8AGx2hm9c6btkgC0x/hp9yt+teISNhvF8WlwRkCc5yF2fDECH8SIMe8j+GA== "bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" @@ -1114,24 +965,20 @@ bignumber.js@^6.0.0: binary-extensions@^1.0.0: version "1.12.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" - integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== bindings@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" - integrity sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw== bip66@^1.1.3: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" - integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= dependencies: safe-buffer "^5.0.1" bitcore-lib@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.15.0.tgz#f924be13869f2aab7e04aeec5642ad3359b6cec2" - integrity sha512-AeXLWhiivF6CDFzrABZHT4jJrflyylDWTi32o30rF92HW9msfuKpjzrHtFKYGa9w0kNVv5HABQjCB3OEav4PhQ== dependencies: bn.js "=4.11.8" bs58 "=4.0.1" @@ -1143,7 +990,6 @@ bitcore-lib@^0.15.0: bitcore-mnemonic@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-1.5.0.tgz#c7e785beb6bf0616ed4992785dc3658670425a39" - integrity sha512-sbeP4xwkindLMfIQhVxj6rZSDMwtiKmfc1DqvwpR6Yg+Qo4I4WHO5pvzb12Y04uDh1N3zgD45esHhfH0HHmE4g== dependencies: bitcore-lib "^0.15.0" unorm "^1.3.3" @@ -1151,7 +997,6 @@ bitcore-mnemonic@^1.5.0: bl@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== dependencies: readable-stream "^2.3.5" safe-buffer "^5.1.1" @@ -1159,39 +1004,32 @@ bl@^1.0.0: block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= dependencies: inherits "~2.0.0" bluebird@^2.9.34: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= bluebird@^3.4.6, bluebird@^3.5.0: version "3.5.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" - integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg== bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= bn.js@=4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== bn.js@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625" - integrity sha1-EhYrwq5x/EClYmwzQ486h1zTdiU= body-parser@1.18.3, body-parser@^1.16.0: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" - integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= dependencies: bytes "3.0.0" content-type "~1.0.4" @@ -1207,7 +1045,6 @@ body-parser@1.18.3, body-parser@^1.16.0: borc@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/borc/-/borc-2.0.3.tgz#08845ea73a6d3211120928ee3929f8dc2de9f52e" - integrity sha512-2mfipKUXn7yLgwn8D5jZkJqd2ZyzqmYZQX/9d4On33oGNDLwxj5qQMst+nkKyEdaujQRFfrZCId+k8wehQVANg== dependencies: bignumber.js "^6.0.0" commander "^2.15.0" @@ -1217,7 +1054,6 @@ borc@^2.0.2: brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1225,7 +1061,6 @@ brace-expansion@^1.1.7: braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= dependencies: expand-range "^1.8.1" preserve "^0.2.0" @@ -1234,7 +1069,6 @@ braces@^1.8.2: braces@^2.3.0, braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -1250,22 +1084,18 @@ braces@^2.3.0, braces@^2.3.1: brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1277,7 +1107,6 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: browserify-cipher@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -1286,7 +1115,6 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -1296,7 +1124,6 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= dependencies: bn.js "^4.1.0" randombytes "^2.0.1" @@ -1304,14 +1131,12 @@ browserify-rsa@^4.0.0: browserify-sha3@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" - integrity sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE= dependencies: js-sha3 "^0.3.1" browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= dependencies: bn.js "^4.1.1" browserify-rsa "^4.0.0" @@ -1324,14 +1149,12 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" browserslist@^3.2.6: version "3.2.8" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== dependencies: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" @@ -1339,19 +1162,16 @@ browserslist@^3.2.6: bs58@=4.0.1, bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= dependencies: base-x "^3.0.2" bs58@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" - integrity sha1-VZCNWPGYKrogCPob7Y+RmYopv40= bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== dependencies: bs58 "^4.0.0" create-hash "^1.1.0" @@ -1360,17 +1180,14 @@ bs58check@^2.1.2: bson@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.0.tgz#bee57d1fb6a87713471af4e32bcae36de814b5b0" - integrity sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA== buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== buffer-alloc@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== dependencies: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" @@ -1378,37 +1195,30 @@ buffer-alloc@^1.2.0: buffer-compare@=1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.1.1.tgz#5be7be853af89198d1f4ddc090d1d66a48aef596" - integrity sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY= buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-to-arraybuffer@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^3.0.1: version "3.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" - integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs= dependencies: base64-js "0.0.8" ieee754 "^1.1.4" @@ -1417,7 +1227,6 @@ buffer@^3.0.1: buffer@^4.3.0, buffer@^4.9.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1426,7 +1235,6 @@ buffer@^4.3.0, buffer@^4.9.0: buffer@^5.0.5: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" - integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1434,22 +1242,18 @@ buffer@^5.0.5: builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -1464,34 +1268,28 @@ cache-base@^1.0.1: caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= dependencies: callsites "^0.2.0" callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= caminte@0.3.7: version "0.3.7" resolved "https://registry.yarnpkg.com/caminte/-/caminte-0.3.7.tgz#ec1ec0457664a0f092643b7c646c457d5cd6f693" - integrity sha1-7B7ARXZkoPCSZDt8ZGxFfVzW9pM= dependencies: bluebird "^3.4.6" uuid "^3.0.1" @@ -1499,17 +1297,14 @@ caminte@0.3.7: caniuse-lite@^1.0.30000844: version "1.0.30000890" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000890.tgz#86a18ffcc65d79ec6a437e985761b8bf1c4efeaf" - integrity sha512-4NI3s4Y6ROm+SgZN5sLUG4k7nVWQnedis3c/RWkynV5G6cHSY7+a8fwFyn2yoBDE3E6VswhTNNwR3PvzGqlTkg== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= center-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= dependencies: align-text "^0.1.3" lazy-cache "^1.0.3" @@ -1517,7 +1312,6 @@ center-align@^0.1.1: chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -1528,7 +1322,6 @@ chalk@^1.1.3: chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1537,19 +1330,16 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= checkpoint-store@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= dependencies: functional-red-black-tree "^1.0.1" chokidar@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= dependencies: anymatch "^1.3.0" async-each "^1.0.0" @@ -1565,7 +1355,6 @@ chokidar@^1.6.0: chokidar@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" - integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== dependencies: anymatch "^2.0.0" async-each "^1.0.0" @@ -1585,12 +1374,10 @@ chokidar@^2.0.2: chownr@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -1598,12 +1385,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" @@ -1613,7 +1398,6 @@ class-utils@^0.3.5: cli-color@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.3.0.tgz#cd2ec212efbd1a0eeb5b017f17d4e2d15e91420f" - integrity sha512-XmbLr8MzgOup/sPHF4nOZerCOcL7rD7vKWpEl0axUsMAY+AEimOhYva1ksskWqkLGY/bjR9h7Cfbr+RrJRfmTQ== dependencies: ansi-regex "^2.1.1" d "1" @@ -1625,19 +1409,16 @@ cli-color@^1.2.0: cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= dependencies: center-align "^0.1.1" right-align "^0.1.1" @@ -1646,7 +1427,6 @@ cliui@^2.1.0: cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -1655,7 +1435,6 @@ cliui@^3.2.0: cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" @@ -1664,22 +1443,18 @@ cliui@^4.0.0: clone@2.x, clone@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= coinstring@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - integrity sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q= dependencies: bs58 "^2.0.1" create-hash "^1.1.1" @@ -1687,7 +1462,6 @@ coinstring@^2.0.0: collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -1695,85 +1469,70 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= colors@^1.1.2: version "1.3.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" - integrity sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ== combined-stream@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= dependencies: delayed-stream "~1.0.0" combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" - integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== dependencies: delayed-stream "~1.0.0" commander@2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== commander@2.15.1: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== commander@^2.11.0, commander@^2.14.1, commander@^2.15.0, commander@^2.8.1, commander@^2.9.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== commander@~2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= dependencies: graceful-readlink ">= 1.0.0" compare-versions@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" - integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg== component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" @@ -1783,76 +1542,62 @@ concat-stream@^1.6.0: console-browserify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= dependencies: date-now "^0.1.4" console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== dependencies: safe-buffer "~5.1.1" cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= cookiejar@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0, core-js@^2.5.0: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cors@^2.8.1: version "2.8.4" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" - integrity sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY= dependencies: object-assign "^4" vary "^1" @@ -1860,7 +1605,6 @@ cors@^2.8.1: coveralls@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" - integrity sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw== dependencies: growl "~> 1.10.0" js-yaml "^3.11.0" @@ -1872,7 +1616,6 @@ coveralls@^3.0.1: create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== dependencies: bn.js "^4.1.0" elliptic "^6.0.0" @@ -1880,7 +1623,6 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -1891,7 +1633,6 @@ create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -1903,7 +1644,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: cron-parser@^2.4.0: version "2.6.0" resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.6.0.tgz#ae2514ceda9ccb540256e201bdd23ae814e03674" - integrity sha512-KGfDDTjBIx85MnVYcdhLccoJH/7jcYW+5Z/t3Wsg2QlJhmmjf+97z+9sQftS71lopOYYapjEKEvmWaCsym5Z4g== dependencies: is-nan "^1.2.1" moment-timezone "^0.5.0" @@ -1911,7 +1651,6 @@ cron-parser@^2.4.0: cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" @@ -1920,7 +1659,6 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: crypto-browserify@3.12.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -1937,115 +1675,84 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0: crypto-js@^3.1.4, crypto-js@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" - integrity sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU= crypto-js@^3.1.9-1: version "3.1.9-1" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8" - integrity sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg= crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= csextends@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/csextends/-/csextends-1.2.0.tgz#6374b210984b54d4495f29c99d3dd069b80543e5" - integrity sha512-S/8k1bDTJIwuGgQYmsRoE+8P+ohV32WhQ0l4zqrc0XDdxOhjQQD7/wTZwCzoZX53jSX3V/qwjT+OkPTxWQcmjg== cycle@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= dependencies: es5-ext "^0.10.9" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" -date-extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/date-extended/-/date-extended-0.0.6.tgz#23802d57dd1bf7818813fe0c32e851a86da267c9" - integrity sha1-I4AtV90b94GIE/4MMuhRqG2iZ8k= - dependencies: - array-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" - date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= death@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" - integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= debug@*: version "4.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" - integrity sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg== dependencies: ms "^2.1.1" debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" debug@^3.0.1, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -declare.js@~0.0.4: - version "0.0.8" - resolved "https://registry.yarnpkg.com/declare.js/-/declare.js-0.0.8.tgz#0478adff9564c004f51df73d8bc134019d28dcde" - integrity sha1-BHit/5VkwAT1Hfc9i8E0AZ0o3N4= decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: mimic-response "^1.0.0" decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== dependencies: file-type "^5.2.0" is-stream "^1.1.0" @@ -2054,7 +1761,6 @@ decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: decompress-tarbz2@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== dependencies: decompress-tar "^4.1.0" file-type "^6.1.0" @@ -2065,7 +1771,6 @@ decompress-tarbz2@^4.0.0: decompress-targz@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== dependencies: decompress-tar "^4.1.1" file-type "^5.2.0" @@ -2074,7 +1779,6 @@ decompress-targz@^4.0.0: decompress-unzip@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= dependencies: file-type "^3.8.0" get-stream "^2.2.0" @@ -2084,7 +1788,6 @@ decompress-unzip@^4.0.1: decompress@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= dependencies: decompress-tar "^4.0.0" decompress-tarbz2 "^4.0.0" @@ -2098,57 +1801,52 @@ decompress@^4.0.0: deep-assign@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-2.0.0.tgz#ebe06b1f07f08dae597620e3dd1622f371a1c572" - integrity sha1-6+BrHwfwja5ZdiDj3RYi83GhxXI= dependencies: is-obj "^1.0.0" +deep-equal@~0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" + deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= deferred-leveldown@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== dependencies: abstract-leveldown "~2.6.0" define-properties@^1.1.1, define-properties@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" @@ -2156,12 +1854,10 @@ define-property@^2.0.2: defined@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag= dependencies: globby "^5.0.0" is-path-cwd "^1.0.0" @@ -2174,27 +1870,22 @@ del@^2.0.2: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= delimit-stream@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" - integrity sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs= depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -2202,34 +1893,28 @@ des.js@^1.0.0: destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= dependencies: repeating "^2.0.0" detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= diff@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" @@ -2238,7 +1923,6 @@ diffie-hellman@^5.0.0: doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= dependencies: esutils "^2.0.2" isarray "^1.0.0" @@ -2246,24 +1930,20 @@ doctrine@1.5.0: doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== drbg.js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= dependencies: browserify-aes "^1.0.6" create-hash "^1.1.2" @@ -2272,19 +1952,16 @@ drbg.js@^1.0.1: duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= eachr@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/eachr/-/eachr-2.0.4.tgz#466f7caa10708f610509e32c807aafe57fc122bf" - integrity sha1-Rm98qhBwj2EFCeMsgHqv5X/BIr8= dependencies: typechecker "^2.0.8" ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" @@ -2292,12 +1969,10 @@ ecc-jsbn@~0.1.1: editions@^1.1.1, editions@^1.3.3, editions@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" - integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== editions@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/editions/-/editions-2.0.2.tgz#54fdac6fb24b0a1a72ffc1ba0126c10602c3e0bd" - integrity sha512-0B8aSTWUu9+JW99zHoeogavCi+lkE5l35FK0OKe0pCobixJYoeof3ZujtqYzSsU2MskhRadY5V9oWUuyG4aJ3A== dependencies: errlop "^1.0.2" semver "^5.5.0" @@ -2305,17 +1980,14 @@ editions@^2.0.2: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.47: version "1.3.78" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.78.tgz#ecb72b5b166ba6598efb384461d63cad74678ebf" - integrity sha512-p4D/5iX08c3LNep5bWn/X3dFmec1K9le6O43lgRsO/vYKBTH2smWDMDfkGlPtERFcLVkI8xdKW5EokBZODh1xg== elliptic@6.3.3: version "6.3.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2325,7 +1997,6 @@ elliptic@6.3.3: elliptic@=6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" - integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2338,7 +2009,6 @@ elliptic@=6.4.0: elliptic@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-3.1.0.tgz#c21682ef762769b56a74201609105da11d5f60cc" - integrity sha1-whaC73YnabVqdCAWCRBdoR1fYMw= dependencies: bn.js "^2.0.3" brorand "^1.0.1" @@ -2348,7 +2018,6 @@ elliptic@^3.1.0: elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: version "6.4.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2361,31 +2030,26 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= dependencies: iconv-lite "~0.4.13" end-of-stream@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: once "^1.4.0" enhanced-resolve@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" - integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24= dependencies: graceful-fs "^4.1.2" memory-fs "^0.4.0" @@ -2395,33 +2059,28 @@ enhanced-resolve@^3.4.0: eol@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" - integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== errlop@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/errlop/-/errlop-1.0.3.tgz#dba29c90cf832c3d2ce469fe515d7e5eef2c6676" - integrity sha512-5VTnt0yikY4LlQEfCXVSqfE6oLj1HVM4zVSvAKMnoYjL/zrb6nqiLowZS4XlG7xENfyj7lpYWvT+wfSCr6dtlA== dependencies: editions "^1.3.4" errno@^0.1.3, errno@~0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== dependencies: prr "~1.0.1" error-ex@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" es-abstract@^1.5.0: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" @@ -2432,7 +2091,6 @@ es-abstract@^1.5.0: es-to-primitive@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -2441,7 +2099,6 @@ es-to-primitive@^1.1.1: es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: version "0.10.46" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572" - integrity sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw== dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" @@ -2450,7 +2107,6 @@ es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= dependencies: d "1" es5-ext "^0.10.35" @@ -2459,7 +2115,6 @@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0 es6-map@^0.1.3: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= dependencies: d "1" es5-ext "~0.10.14" @@ -2471,7 +2126,6 @@ es6-map@^0.1.3: es6-set@~0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= dependencies: d "1" es5-ext "~0.10.14" @@ -2482,7 +2136,6 @@ es6-set@~0.1.5: es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= dependencies: d "1" es5-ext "~0.10.14" @@ -2490,7 +2143,6 @@ es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8= dependencies: d "1" es5-ext "^0.10.14" @@ -2500,17 +2152,14 @@ es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= dependencies: esprima "^2.7.1" estraverse "^1.9.1" @@ -2522,7 +2171,6 @@ escodegen@1.8.x: escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= dependencies: es6-map "^0.1.3" es6-weak-map "^2.0.1" @@ -2532,12 +2180,10 @@ escope@^3.6.0: eslint-config-standard@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz#87ee0d3c9d95382dc761958cbb23da9eea31e0ba" - integrity sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw== eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" - integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== dependencies: debug "^2.6.9" resolve "^1.5.0" @@ -2545,7 +2191,6 @@ eslint-import-resolver-node@^0.3.1: eslint-module-utils@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" - integrity sha1-snA2LNiLGkitMIl2zn+lTphBF0Y= dependencies: debug "^2.6.8" pkg-dir "^1.0.0" @@ -2553,7 +2198,6 @@ eslint-module-utils@^2.2.0: eslint-plugin-import@^2.10.0: version "2.14.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" - integrity sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g== dependencies: contains-path "^0.1.0" debug "^2.6.8" @@ -2569,7 +2213,6 @@ eslint-plugin-import@^2.10.0: eslint-plugin-node@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz#bf19642298064379315d7a4b2a75937376fa05e4" - integrity sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw== dependencies: ignore "^3.3.6" minimatch "^3.0.4" @@ -2579,17 +2222,14 @@ eslint-plugin-node@^6.0.1: eslint-plugin-promise@^3.7.0: version "3.8.0" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" - integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ== eslint-plugin-standard@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz#2a9e21259ba4c47c02d53b2d0c9135d4b1022d47" - integrity sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w== eslint-scope@^3.7.1: version "3.7.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" - integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2597,12 +2237,10 @@ eslint-scope@^3.7.1: eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== eslint@^4.19.1: version "4.19.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" - integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" @@ -2646,7 +2284,6 @@ eslint@^4.19.1: espree@^3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== dependencies: acorn "^5.5.0" acorn-jsx "^3.0.0" @@ -2654,51 +2291,42 @@ espree@^3.5.4: esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== dependencies: estraverse "^4.1.0" estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eth-block-tracker@^2.2.2: version "2.3.1" resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz#ab6d177e5b50128fa06d7ae9e0489c7484bac95e" - integrity sha512-NamWuMBIl8kmkJFVj8WzGatySTzQPQag4Xr677yFxdVtIxACFbL/dQowk0MzEqIKk93U1TwY3MjVU6mOcwZnKA== dependencies: async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c eth-query "^2.1.0" @@ -2712,7 +2340,6 @@ eth-block-tracker@^2.2.2: eth-lib@0.1.27, eth-lib@^0.1.26: version "0.1.27" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" - integrity sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA== dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2725,7 +2352,6 @@ eth-lib@0.1.27, eth-lib@^0.1.26: eth-lib@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" - integrity sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco= dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2734,7 +2360,6 @@ eth-lib@0.2.7: eth-lightwallet@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eth-lightwallet/-/eth-lightwallet-3.0.1.tgz#297022932aa568f4e4eb0873bff257f5e5b78709" - integrity sha512-79vVCETy+4l1b6wuOWwjqPW3Bom5ZK46BgkUNwaXhiMG1rrMRHjpjYEWMqH0JHeCzOzB4HBIFz7eK1/4s6w5nA== dependencies: bitcore-lib "^0.15.0" bitcore-mnemonic "^1.5.0" @@ -2751,7 +2376,6 @@ eth-lightwallet@^3.0.1: eth-query@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= dependencies: json-rpc-random-id "^1.0.0" xtend "^4.0.1" @@ -2759,7 +2383,6 @@ eth-query@^2.1.0: eth-sig-util@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= dependencies: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" @@ -2767,7 +2390,6 @@ eth-sig-util@^1.4.2: ethereum-bridge@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/ethereum-bridge/-/ethereum-bridge-0.6.1.tgz#53c93ed7c0e21752a91e5f089a5997e1d6fea228" - integrity sha512-yDTivI85618BoLI71yNRzW6iVcVN2rjnviCIzs0QOCOENj4XpYQhMDGhdqDi8XWDdzTd0Ja/Canuuh3vfE2IcA== dependencies: async "^2.4.1" borc "^2.0.2" @@ -2798,17 +2420,14 @@ ethereum-bridge@^0.6.1: ethereum-common@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= ethereumjs-abi@0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.4.tgz#9ba1bb056492d00c27279f6eccd4d58275912c1a" - integrity sha1-m6G7BWSS0AwnJ59uzNTVgnWRLBo= dependencies: bn.js "^4.10.0" ethereumjs-util "^4.3.0" @@ -2823,7 +2442,6 @@ ethereumjs-abi@^0.6.5, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereu ethereumjs-account@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== dependencies: ethereumjs-util "^5.0.0" rlp "^2.0.0" @@ -2832,7 +2450,6 @@ ethereumjs-account@^2.0.3: ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: version "1.7.1" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== dependencies: async "^2.0.1" ethereum-common "0.2.0" @@ -2843,26 +2460,22 @@ ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: ethereumjs-common@~0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-0.4.1.tgz#27690a24a817b058cc3a2aedef9392e8d7d63984" - integrity sha512-ywYGsOeGCsMNWso5Y4GhjWI24FJv9FK7+VyVKiQgXg8ZRDPXJ7F/kJ1CnjtkjTvDF4e0yqU+FWswlqR3bmZQ9Q== ethereumjs-testrpc-sc@6.1.6: version "6.1.6" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.6.tgz#290595380b5182814564d4aa38f35b7788aab070" - integrity sha512-iv2qiGBFgk9mn5Nq2enX8dG5WQ7Lk+FCqpnxfPfH4Ns8KLPwttmNOy264nh3SXDJJvcQwz/XnlLteDQVILotbg== dependencies: source-map-support "^0.5.3" ethereumjs-testrpc@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc/-/ethereumjs-testrpc-6.0.3.tgz#7a0b87bf3670f92f607f98fa6a78801d9741b124" - integrity sha512-lAxxsxDKK69Wuwqym2K49VpXtBvLEsXr1sryNG4AkvL5DomMdeCBbu3D87UEevKenLHBiT8GTjARwN6Yj039gA== dependencies: webpack "^3.0.0" ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@^1.3.3: version "1.3.7" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== dependencies: ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" @@ -2870,7 +2483,6 @@ ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@ ethereumjs-util@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" - integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= dependencies: bn.js "^4.8.0" create-hash "^1.1.2" @@ -2881,7 +2493,6 @@ ethereumjs-util@^4.3.0: ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.3, ethereumjs-util@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" - integrity sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA== dependencies: bn.js "^4.11.0" create-hash "^1.1.2" @@ -2894,7 +2505,6 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum ethereumjs-vm@^2.0.2: version "2.4.0" resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.4.0.tgz#244f1e35f2755e537a13546111d1a4c159d34b13" - integrity sha512-MJ4lCWa5c6LhahhhvoDKW+YGjK00ZQn0RHHLh4L+WaH1k6Qv7/q3uTluew6sJGNCZdlO0yYMDXYW9qyxLHKlgQ== dependencies: async "^2.1.2" async-eventemitter "^0.2.2" @@ -2911,7 +2521,6 @@ ethereumjs-vm@^2.0.2: ethereumjs-wallet@^0.6.0: version "0.6.2" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz#67244b6af3e8113b53d709124b25477b64aeccda" - integrity sha512-DHEKPV9lYORM7dL8602dkb+AgdfzCYz2lxpdYQoD3OwG355LLDuivW9rGuLpDMCry/ORyBYV6n+QCo/71SwACg== dependencies: aes-js "^3.1.1" bs58check "^2.1.2" @@ -2925,7 +2534,6 @@ ethereumjs-wallet@^0.6.0: ethers@^3.0.15: version "3.0.29" resolved "https://registry.yarnpkg.com/ethers/-/ethers-3.0.29.tgz#ce8139955b4ed44456eb6764b089bb117c86775d" - integrity sha512-OGyA5pW5xFC5o/ZV5MfIoVp/EdA1QMg2bMJFf7Kznsz8m7IzzbgsPHTCjzSfKQDs/XDphGyRcA7A6bkIeJL4gw== dependencies: aes-js "3.0.0" bn.js "^4.4.0" @@ -2941,7 +2549,6 @@ ethers@^3.0.15: ethjs-abi@0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.1.8.tgz#cd288583ed628cdfadaf8adefa3ba1dbcbca6c18" - integrity sha1-zSiFg+1ijN+tr4re+juh28vKbBg= dependencies: bn.js "4.11.6" js-sha3 "0.5.5" @@ -2950,7 +2557,6 @@ ethjs-abi@0.1.8: ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= dependencies: bn.js "4.11.6" number-to-bn "1.7.0" @@ -2958,7 +2564,6 @@ ethjs-unit@0.1.6: ethjs-util@^0.1.3: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== dependencies: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" @@ -2966,7 +2571,6 @@ ethjs-util@^0.1.3: event-emitter@^0.3.5, event-emitter@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= dependencies: d "1" es5-ext "~0.10.14" @@ -2974,22 +2578,18 @@ event-emitter@^0.3.5, event-emitter@~0.3.5: eventemitter3@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" - integrity sha1-R3hr2qCHyvext15zq8XH1UAVjNA= events@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" @@ -2997,7 +2597,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -3010,14 +2609,12 @@ execa@^0.7.0: expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= dependencies: is-posix-bracket "^0.1.0" expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -3030,14 +2627,12 @@ expand-brackets@^2.1.4: expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= dependencies: fill-range "^2.1.0" express@^4.14.0: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" - integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== dependencies: accepts "~1.3.5" array-flatten "1.1.1" @@ -3073,14 +2668,12 @@ express@^4.14.0: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -3088,33 +2681,16 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extended@0.0.6, extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/extended/-/extended-0.0.6.tgz#7fb8bf7b9dae397586e48570acfd642c78e50669" - integrity sha1-f7i/e52uOXWG5IVwrP1kLHjlBmk= - dependencies: - extender "~0.0.5" - -extender@~0.0.5: - version "0.0.10" - resolved "https://registry.yarnpkg.com/extender/-/extender-0.0.10.tgz#589c07482be61a1460b6d81f9c24aa67e8f324cd" - integrity sha1-WJwHSCvmGhRgttgfnCSqZ+jzJM0= - dependencies: - declare.js "~0.0.4" extendr@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/extendr/-/extendr-2.1.0.tgz#301aa0bbea565f4d2dc8f570f2a22611a8527b56" - integrity sha1-MBqgu+pWX00tyPVw8qImEahSe1Y= dependencies: typechecker "~2.0.1" external-editor@^2.0.4: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== dependencies: chardet "^0.4.0" iconv-lite "^0.4.17" @@ -3123,14 +2699,12 @@ external-editor@^2.0.4: extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= dependencies: is-extglob "^1.0.0" extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -3144,87 +2718,64 @@ extglob@^2.0.4: extract-opts@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d" - integrity sha1-H6KOunNSxttID4hc63GkaBC+bX0= dependencies: typechecker "~2.0.1" extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= eyes@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= fake-merkle-patricia-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= dependencies: checkpoint-store "^1.1.0" -fast-csv@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-2.4.1.tgz#bd7dd268391f729367b59445b8dd0ad026881b26" - integrity sha1-vX3SaDkfcpNntZRFuN0K0CaIGyY= - dependencies: - extended "0.0.6" - is-extended "0.0.10" - object-extended "0.0.7" - string-extended "0.0.8" - fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= dependencies: pend "~1.2.0" fetch-ponyfill@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" - integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= dependencies: node-fetch "~1.7.1" figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" @@ -3232,27 +2783,22 @@ file-entry-cache@^2.0.0: file-type@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= file-type@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha1-LdvqfHP/42No365J3DOMBYwritY= file-type@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= fill-range@^2.1.0: version "2.2.4" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== dependencies: is-number "^2.1.0" isobject "^2.0.0" @@ -3263,7 +2809,6 @@ fill-range@^2.1.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -3273,7 +2818,6 @@ fill-range@^4.0.0: finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" - integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== dependencies: debug "2.6.9" encodeurl "~1.0.2" @@ -3286,7 +2830,6 @@ finalhandler@1.1.1: find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" @@ -3294,14 +2837,12 @@ find-up@^1.0.0: find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" - integrity sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE= dependencies: circular-json "^0.3.1" del "^2.0.2" @@ -3311,31 +2852,26 @@ flat-cache@^1.2.1: for-each@^0.3.2, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= dependencies: for-in "^1.0.1" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= dependencies: asynckit "^0.4.0" combined-stream "1.0.6" @@ -3344,29 +2880,24 @@ form-data@~2.3.2: forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3377,7 +2908,6 @@ fs-extra@^0.30.0: fs-extra@^2.0.0, fs-extra@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" - integrity sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3385,7 +2915,6 @@ fs-extra@^2.0.0, fs-extra@^2.1.2: fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3394,7 +2923,6 @@ fs-extra@^4.0.2: fs-extra@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3403,14 +2931,12 @@ fs-extra@^5.0.0: fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== dependencies: minipass "^2.2.1" fs-promise@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" - integrity sha1-9k5PhUvPaJqovdy6JokW2z20aFQ= dependencies: any-promise "^1.3.0" fs-extra "^2.0.0" @@ -3420,17 +2946,14 @@ fs-promise@^2.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fs@0.0.1-security: version "0.0.1-security" resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" - integrity sha1-invTcYa23d84E/I4WLV+yq9eQdQ= fsevents@^1.0.0, fsevents@^1.2.2: version "1.2.4" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -3438,7 +2961,6 @@ fsevents@^1.0.0, fsevents@^1.2.2: fstream@^1.0.2, fstream@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -3448,24 +2970,20 @@ fstream@^1.0.2, fstream@^1.0.8: function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= ganache-cli@^6.1.8: version "6.1.8" resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.8.tgz#49a8a331683a9652183f82ef1378d17e1814fcd3" - integrity sha512-yXzteu4SIgUL31mnpm9j+x6dpHUw0p/nsRVkcySKq0w+1vDxH9jMErP1QhZAJuTVE6ni4nfvGSNkaQx5cD3jfg== dependencies: source-map-support "^0.5.3" gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -3479,12 +2997,10 @@ gauge@~2.7.3: get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= dependencies: object-assign "^4.0.1" pinkie-promise "^2.0.0" @@ -3492,24 +3008,20 @@ get-stream@^2.2.0: get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= dependencies: glob-parent "^2.0.0" is-glob "^2.0.0" @@ -3517,14 +3029,12 @@ glob-base@^0.3.0: glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= dependencies: is-glob "^2.0.0" glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -3532,7 +3042,6 @@ glob-parent@^3.1.0: glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3544,7 +3053,6 @@ glob@7.1.2: glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= dependencies: inflight "^1.0.4" inherits "2" @@ -3555,7 +3063,6 @@ glob@^5.0.15: glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3567,7 +3074,6 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: glob@~6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= dependencies: inflight "^1.0.4" inherits "2" @@ -3578,7 +3084,6 @@ glob@~6.0.4: global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" - integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= dependencies: min-document "^2.19.0" process "~0.5.1" @@ -3586,17 +3091,14 @@ global@~4.3.0: globals@^11.0.1: version "11.8.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" - integrity sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA== globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0= dependencies: array-union "^1.0.1" arrify "^1.0.0" @@ -3608,7 +3110,6 @@ globby@^5.0.0: got@7.1.0, got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== dependencies: decompress-response "^3.2.0" duplexer3 "^0.1.4" @@ -3628,27 +3129,22 @@ got@7.1.0, got@^7.1.0: graceful-fs@*, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= growl@1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== growl@1.10.5, "growl@~> 1.10.0": version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: version "4.0.12" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" - integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA== dependencies: async "^2.5.0" optimist "^0.6.1" @@ -3659,12 +3155,10 @@ handlebars@^4.0.1: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" - integrity sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA== dependencies: ajv "^5.3.0" har-schema "^2.0.0" @@ -3672,51 +3166,42 @@ har-validator@~5.1.0: has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= has-to-string-tag-x@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== dependencies: has-symbol-support-x "^1.4.1" has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -3725,7 +3210,6 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -3734,12 +3218,10 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -3747,14 +3229,12 @@ has-values@^1.0.0: has@^1.0.1, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -3762,7 +3242,6 @@ hash-base@^3.0.0: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.5" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" - integrity sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" @@ -3770,7 +3249,6 @@ hash.js@^1.0.0, hash.js@^1.0.3: hdkey@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.0.tgz#e74e7b01d2c47f797fa65d1d839adb7a44639f29" - integrity sha512-E7aU8pNlWUJbXGjTz/+lKf1LkMcA3hUrC5ZleeizrmLSd++kvf8mSOe3q8CmBDA9j4hdfXO5iY6hGiTUCOV2jQ== dependencies: coinstring "^2.0.0" safe-buffer "^5.1.1" @@ -3779,12 +3257,10 @@ hdkey@^1.0.0: he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -3793,7 +3269,6 @@ hmac-drbg@^1.0.0: home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.1" @@ -3801,12 +3276,10 @@ home-or-tmp@^2.0.0: hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" @@ -3816,12 +3289,10 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: http-https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" @@ -3830,12 +3301,10 @@ http-signature@~1.2.0: https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= i18n@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/i18n/-/i18n-0.8.3.tgz#2d8cf1c24722602c2041d01ba6ae5eaa51388f0e" - integrity sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4= dependencies: debug "*" make-plural "^3.0.3" @@ -3844,41 +3313,39 @@ i18n@^0.8.3: mustache "*" sprintf-js ">=1.0.3" +i@0.3.x: + version "0.3.6" + resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d" + iconv-lite@0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" ieee754@^1.1.4, ieee754@^1.1.8: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== dependencies: minimatch "^3.0.4" ignore@^3.3.3, ignore@^3.3.6: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== ignorefs@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ignorefs/-/ignorefs-1.2.0.tgz#da59fb858976e4a5e43702ccd1f282fdbc9e5756" - integrity sha1-2ln7hYl25KXkNwLM0fKC/byeV1Y= dependencies: editions "^1.3.3" ignorepatterns "^1.1.0" @@ -3886,27 +3353,22 @@ ignorefs@^1.0.0: ignorepatterns@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ignorepatterns/-/ignorepatterns-1.1.0.tgz#ac8f436f2239b5dfb66d5f0d3a904a87ac67cc5e" - integrity sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4= immediate@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" @@ -3914,22 +3376,18 @@ inflight@^1.0.4: inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= inherits@2.0.1, inherits@=2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" - integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -3949,91 +3407,76 @@ inquirer@^3.0.6: interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" - integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= dependencies: builtin-modules "^1.0.0" is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -4042,7 +3485,6 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -4051,261 +3493,210 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= dependencies: is-primitive "^2.0.0" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" -is-extended@0.0.10, is-extended@~0.0.3, is-extended@~0.0.8: - version "0.0.10" - resolved "https://registry.yarnpkg.com/is-extended/-/is-extended-0.0.10.tgz#244e140df75bb1c9a3106f412ff182fb534a6d62" - integrity sha1-JE4UDfdbscmjEG9BL/GC+1NKbWI= - dependencies: - extended "~0.0.3" - is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= dependencies: number-is-nan "^1.0.0" is-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= dependencies: is-extglob "^1.0.0" is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= dependencies: is-extglob "^2.1.1" is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= is-nan@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" - integrity sha1-n69ltvttskt/XAYoR16nH5iEAeI= dependencies: define-properties "^1.1.1" is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= dependencies: kind-of "^3.0.2" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= is-path-in-cwd@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== dependencies: is-path-inside "^1.0.0" is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= dependencies: path-is-inside "^1.0.1" is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= is-promise@^2.1, is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= dependencies: has "^1.0.1" is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== dependencies: has-symbols "^1.0.0" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= dependencies: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" @@ -4313,12 +3704,10 @@ isomorphic-fetch@^2.2.0: isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= dependencies: abbrev "1.0.x" async "1.x" @@ -4338,7 +3727,6 @@ istanbul@^0.4.5: isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== dependencies: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" @@ -4346,37 +3734,30 @@ isurl@^1.0.0-alpha5: js-sha3@0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a" - integrity sha1-uvDA6MVK1ZA0R9+Wreekobynmko= js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= js-sha3@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" - integrity sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM= js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.9.1: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4384,27 +3765,22 @@ js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.9.1: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-loader@^0.5.4: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" - integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== json-rpc-engine@^3.6.0: version "3.8.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" - integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== dependencies: async "^2.0.1" babel-preset-env "^1.7.0" @@ -4416,82 +3792,68 @@ json-rpc-engine@^3.6.0: json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= dependencies: inherits "^2.0.1" json-rpc-random-id@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= dependencies: jsonify "~0.0.0" json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json-text-sequence@^0.1: version "0.1.1" resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" - integrity sha1-py8hfcSvxGKf/1/rME3BvVGi89I= dependencies: delimit-stream "0.1.0" json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= optionalDependencies: graceful-fs "^4.1.6" jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= optionalDependencies: graceful-fs "^4.1.6" jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" extsprintf "1.3.0" @@ -4501,7 +3863,6 @@ jsprim@^1.2.2: keccak@^1.0.2: version "1.4.0" resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" - integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== dependencies: bindings "^1.2.1" inherits "^2.0.3" @@ -4511,7 +3872,6 @@ keccak@^1.0.2: keccakjs@^0.2.0, keccakjs@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" - integrity sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0= dependencies: browserify-sha3 "^0.0.1" sha3 "^1.1.0" @@ -4519,74 +3879,62 @@ keccakjs@^0.2.0, keccakjs@^0.2.1: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= optionalDependencies: graceful-fs "^4.1.9" lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM= level-codec@~7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== level-errors@^1.0.3: version "1.1.2" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== dependencies: errno "~0.1.1" level-errors@~1.0.3: version "1.0.5" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== dependencies: errno "~0.1.1" level-iterator-stream@~1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= dependencies: inherits "^2.0.1" level-errors "^1.0.3" @@ -4596,7 +3944,6 @@ level-iterator-stream@~1.3.0: level-ws@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= dependencies: readable-stream "~1.0.15" xtend "~2.1.1" @@ -4604,7 +3951,6 @@ level-ws@0.0.0: levelup@^1.2.1: version "1.3.9" resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== dependencies: deferred-leveldown "~1.2.1" level-codec "~7.0.0" @@ -4617,7 +3963,6 @@ levelup@^1.2.1: levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -4625,7 +3970,6 @@ levn@^0.3.0, levn@~0.3.0: load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4636,7 +3980,6 @@ load-json-file@^1.0.0: load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4646,12 +3989,10 @@ load-json-file@^2.0.0: loader-runner@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.1.tgz#026f12fe7c3115992896ac02ba022ba92971b979" - integrity sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw== loader-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" - integrity sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0= dependencies: big.js "^3.1.3" emojis-list "^2.0.0" @@ -4660,7 +4001,6 @@ loader-utils@^1.1.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -4668,54 +4008,44 @@ locate-path@^2.0.0: lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash@4.x, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== lodash@=4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= log-driver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" - integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== long-timeout@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" - integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ= longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lru-cache@^4.0.1: version "4.1.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" - integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -4723,57 +4053,48 @@ lru-cache@^4.0.1: lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" - integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= dependencies: es5-ext "~0.10.2" ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== dependencies: pify "^3.0.0" make-plural@^3.0.3, make-plural@~3.0.3: version "3.0.6" resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-3.0.6.tgz#2033a03bac290b8f3bb91258f65b9df7e8b01ca7" - integrity sha1-IDOgO6wpC487uRJY9lud9+iwHKc= optionalDependencies: minimist "^1.2.0" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" math-interval-parser@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-interval-parser/-/math-interval-parser-1.1.0.tgz#dbeda5b06b3249973c6df6170fde2386f0afd893" - integrity sha1-2+2lsGsySZc8bfYXD94jhvCv2JM= dependencies: xregexp "^2.0.0" math-random@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" - integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -4782,19 +4103,16 @@ md5.js@^1.3.4: media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= dependencies: mimic-fn "^1.0.0" memdown@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= dependencies: abstract-leveldown "~2.7.1" functional-red-black-tree "^1.0.1" @@ -4806,7 +4124,6 @@ memdown@^1.0.0: memoizee@^0.4.14: version "0.4.14" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" - integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== dependencies: d "1" es5-ext "^0.10.45" @@ -4820,7 +4137,6 @@ memoizee@^0.4.14: memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= dependencies: errno "^0.1.3" readable-stream "^2.0.1" @@ -4828,17 +4144,14 @@ memory-fs@^0.4.0, memory-fs@~0.4.1: memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= merkle-patricia-tree@^2.1.2: version "2.3.2" resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== dependencies: async "^1.4.2" ethereumjs-util "^5.0.0" @@ -4852,7 +4165,6 @@ merkle-patricia-tree@^2.1.2: messageformat@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/messageformat/-/messageformat-0.3.1.tgz#e58fff8245e9b3971799e5b43db58b3e9417f5a2" - integrity sha1-5Y//gkXps5cXmeW0PbWLPpQX9aI= dependencies: async "~1.5.2" glob "~6.0.4" @@ -4863,12 +4175,10 @@ messageformat@^0.3.1: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@^2.1.5: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= dependencies: arr-diff "^2.0.0" array-unique "^0.2.1" @@ -4887,7 +4197,6 @@ micromatch@^2.1.5: micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4906,7 +4215,6 @@ micromatch@^3.1.10, micromatch@^3.1.4: miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" @@ -4914,73 +4222,60 @@ miller-rabin@^4.0.0: mime-db@~1.36.0: version "1.36.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" - integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw== mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.20" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" - integrity sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A== dependencies: mime-db "~1.36.0" mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= dependencies: dom-walk "^0.1.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@^1.2.0, minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= minipass@^2.2.1, minipass@^2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957" - integrity sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" @@ -4988,14 +4283,12 @@ minipass@^2.2.1, minipass@^2.3.3: minizlib@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" - integrity sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg== dependencies: minipass "^2.2.1" mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -5003,21 +4296,18 @@ mixin-deep@^1.2.0: mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" mocha@^4.0.1, mocha@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" - integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== dependencies: browser-stdout "1.3.0" commander "2.11.0" @@ -5033,7 +4323,6 @@ mocha@^4.0.1, mocha@^4.1.0: mocha@^5.0.1: version "5.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== dependencies: browser-stdout "1.3.1" commander "2.15.1" @@ -5050,39 +4339,32 @@ mocha@^5.0.1: mock-fs@^4.1.0: version "4.7.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" - integrity sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA== moment-timezone@^0.5.0: version "0.5.21" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.21.tgz#3cba247d84492174dbf71de2a9848fa13207b845" - integrity sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A== dependencies: moment ">= 2.9.0" "moment@>= 2.9.0", moment@^2.22.2: version "2.22.2" resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" - integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y= mout@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" - integrity sha1-ujYR318OWx/7/QEWa48C0fX6K5k= ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== multihashes@^0.4.5: version "0.4.14" resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.14.tgz#774db9a161f81a8a27dc60788f91248e020f5244" - integrity sha512-V/g/EIN6nALXfS/xHUAgtfPP3mn3sPIF/i9beuGKf25QXS2QZYCpeVJbDPEannkz32B2fihzCe2D/KMrbcmefg== dependencies: bs58 "^4.0.1" varint "^5.0.0" @@ -5090,22 +4372,18 @@ multihashes@^0.4.5: mustache@*: version "3.0.0" resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.0.tgz#3de22dd9ba38152f7355399a953dd4528c403338" - integrity sha512-bhBDkK/PioIbtQzRIbGUGypvc3MC4c389QnJt8KDIEJ666OidRPoXAQAHPivikfS3JkMEaWoPvcDL7YrQxtSwg== mustache@^2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" - integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== -mute-stream@0.0.7: +mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" object-assign "^4.0.1" @@ -5114,22 +4392,18 @@ mz@^2.6.0: nan@2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== nan@^2.0.8, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" - integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -5146,12 +4420,14 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +ncp@1.0.x: + version "1.0.1" + resolved "http://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== dependencies: debug "^2.1.2" iconv-lite "^0.4.4" @@ -5160,27 +4436,22 @@ needle@^2.2.1: negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= neo-async@^2.5.0: version "2.5.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc" - integrity sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw== next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= node-async-loop@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/node-async-loop/-/node-async-loop-1.2.2.tgz#c5870299bf6477b780c88b431aa5b37733f55a3d" - integrity sha1-xYcCmb9kd7eAyItDGqWzdzP1Wj0= node-cache@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.0.tgz#48ac796a874e762582692004a376d26dfa875811" - integrity sha512-obRu6/f7S024ysheAjoYFEEBqqDWv4LOMNJEuO8vMeEw2AT4z+NCzO4hlc2lhI4vATzbCQv6kke9FVdx0RbCOw== dependencies: clone "2.x" lodash "4.x" @@ -5188,7 +4459,6 @@ node-cache@^4.1.1: node-fetch@^1.0.1, node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== dependencies: encoding "^0.1.11" is-stream "^1.0.1" @@ -5196,7 +4466,6 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: node-libs-browser@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" - integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -5225,7 +4494,6 @@ node-libs-browser@^2.0.0: node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -5241,7 +4509,6 @@ node-pre-gyp@^0.10.0: node-schedule@^1.2.3: version "1.3.0" resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-1.3.0.tgz#e7a7e816a7f2550d5b170bd106e765db28bdf030" - integrity sha512-NNwO9SUPjBwFmPh3vXiPVEhJLn4uqYmZYvJV358SRGM06BR4UoIqxJpeJwDDXB6atULsgQA97MfD1zMd5xsu+A== dependencies: cron-parser "^2.4.0" long-timeout "0.1.1" @@ -5250,14 +4517,12 @@ node-schedule@^1.2.3: nopt@3.x, nopt@~3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" osenv "^0.1.4" @@ -5265,7 +4530,6 @@ nopt@^4.0.1: normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" @@ -5275,19 +4539,16 @@ normalize-package-data@^2.3.2: normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" - integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" - integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -5295,14 +4556,12 @@ npm-packlist@^1.1.6: npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" @@ -5312,12 +4571,10 @@ npmlog@^4.0.2: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -5325,57 +4582,40 @@ number-to-bn@1.7.0: oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" -object-extended@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/object-extended/-/object-extended-0.0.7.tgz#84fd23f56b15582aeb3e88b05cb55d2432d68a33" - integrity sha1-hP0j9WsVWCrrPoiwXLVdJDLWijM= - dependencies: - array-extended "~0.0.4" - extended "~0.0.3" - is-extended "~0.0.3" - object-inspect@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= dependencies: for-own "^0.1.4" is-extendable "^0.1.1" @@ -5383,47 +4623,40 @@ object.omit@^2.0.0: object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" oboe@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" - integrity sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8= dependencies: http-https "^1.0.0" on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" openzeppelin-solidity@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-1.10.0.tgz#d77eee6653f5958d051318a61ba0b436f92216c0" - integrity sha512-igkrumQQ2lrN2zjeQV4Dnb0GpTBj1fzMcd8HPyBUqwI0hhuscX/HzXiqKT6gFQl1j9Wy/ppVVs9fqL/foF7Gmg== optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= dependencies: minimist "~0.0.1" wordwrap "~0.0.2" @@ -5431,7 +4664,6 @@ optimist@^0.6.1: optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" @@ -5443,29 +4675,24 @@ optionator@^0.8.1, optionator@^0.8.2: original-require@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" - integrity sha1-DxMEcVhM0zURxew4yNWSE/msXiA= os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== dependencies: execa "^0.7.0" lcid "^1.0.0" @@ -5474,12 +4701,10 @@ os-locale@^2.0.0: os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -5487,48 +4712,40 @@ osenv@^0.1.4: p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= dependencies: p-limit "^1.1.0" p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= dependencies: p-finally "^1.0.0" p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" - integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== parse-asn1@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" - integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -5539,7 +4756,6 @@ parse-asn1@^5.0.0: parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= dependencies: glob-base "^0.3.0" is-dotfile "^1.0.0" @@ -5549,7 +4765,6 @@ parse-glob@^3.0.4: parse-headers@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" - integrity sha1-aug6eqJanZtwCswoaYzR8e1+lTY= dependencies: for-each "^0.3.2" trim "0.0.1" @@ -5557,71 +4772,58 @@ parse-headers@^2.0.0: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-parse@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -5630,14 +4832,12 @@ path-type@^1.0.0: path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= dependencies: pify "^2.0.0" pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -5648,119 +4848,116 @@ pbkdf2@^3.0.3: pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" - integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= dependencies: find-up "^1.0.0" +pkginfo@0.3.x: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" + +pkginfo@0.x.x: + version "0.4.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" + pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= pragma-singleton@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pragma-singleton/-/pragma-singleton-1.0.3.tgz#6894317bb8d47157e59de2a4a009db7e6f63e30e" - integrity sha1-aJQxe7jUcVflneKkoAnbfm9j4w4= prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= prettier@^1.14.3: version "1.14.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" - integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg== private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= process@~0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= progress@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= promise-to-callback@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= dependencies: is-fn "^1.0.0" set-immediate-shim "^1.0.1" +prompt@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe" + dependencies: + colors "^1.1.2" + pkginfo "0.x.x" + read "1.0.x" + revalidator "0.1.x" + utile "0.3.x" + winston "2.1.x" + prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" - integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== dependencies: loose-envify "^1.3.1" object-assign "^4.1.1" @@ -5768,7 +4965,6 @@ prop-types@^15.6.2: proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" - integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== dependencies: forwarded "~0.1.2" ipaddr.js "1.8.0" @@ -5776,22 +4972,18 @@ proxy-addr@~2.0.4: prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24: version "1.1.29" resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" - integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -5803,27 +4995,22 @@ public-encrypt@^4.0.0: punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== dependencies: decode-uri-component "^0.2.0" object-assign "^4.1.0" @@ -5832,17 +5019,14 @@ query-string@^5.0.1: querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= randomatic@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116" - integrity sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ== dependencies: is-number "^4.0.0" kind-of "^6.0.0" @@ -5851,14 +5035,12 @@ randomatic@^3.0.0: randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -5866,17 +5048,14 @@ randomfill@^1.0.3: randomhex@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" - integrity sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU= range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== dependencies: bytes "3.0.0" http-errors "1.6.3" @@ -5886,7 +5065,6 @@ raw-body@2.3.3: rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" ini "~1.3.0" @@ -5896,7 +5074,6 @@ rc@^1.2.7: react-dom@^16.2.0: version "16.5.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.5.2.tgz#b69ee47aa20bab5327b2b9d7c1fe2a30f2cfa9d7" - integrity sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5906,7 +5083,6 @@ react-dom@^16.2.0: react@^16.2.0: version "16.5.2" resolved "https://registry.yarnpkg.com/react/-/react-16.5.2.tgz#19f6b444ed139baa45609eee6dc3d318b3895d42" - integrity sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5916,7 +5092,6 @@ react@^16.2.0: read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -5924,7 +5099,6 @@ read-pkg-up@^1.0.1: read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= dependencies: find-up "^2.0.0" read-pkg "^2.0.0" @@ -5932,7 +5106,6 @@ read-pkg-up@^2.0.0: read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" @@ -5941,16 +5114,20 @@ read-pkg@^1.0.0: read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" path-type "^2.0.0" +read@1.0.x: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + dependencies: + mute-stream "~0.0.4" + readable-stream@^1.0.33: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5960,7 +5137,6 @@ readable-stream@^1.0.33: readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -5973,7 +5149,6 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5983,7 +5158,6 @@ readable-stream@~1.0.15: readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" @@ -5992,34 +5166,28 @@ readdirp@^2.0.0: readline-sync@^1.4.9: version "1.4.9" resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.9.tgz#3eda8e65f23cd2a17e61301b1f0003396af5ecda" - integrity sha1-PtqOZfI80qF+YTAbHwADOWr17No= rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" regenerate@^1.2.1: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" @@ -6028,14 +5196,12 @@ regenerator-transform@^0.10.0: regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== dependencies: is-equal-shallow "^0.1.3" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" @@ -6043,12 +5209,10 @@ regex-not@^1.0.0, regex-not@^1.0.2: regexpp@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" - integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= dependencies: regenerate "^1.2.1" regjsgen "^0.2.0" @@ -6057,62 +5221,52 @@ regexpu-core@^2.0.0: regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= regjsparser@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= dependencies: is-finite "^1.0.0" req-cwd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-1.0.1.tgz#0d73aeae9266e697a78f7976019677e76acf0fff" - integrity sha1-DXOurpJm5penj3l2AZZ352rPD/8= dependencies: req-from "^1.0.1" req-from@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-from/-/req-from-1.0.1.tgz#bf81da5147947d32d13b947dc12a58ad4587350e" - integrity sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4= dependencies: resolve-from "^2.0.0" request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" - integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= dependencies: lodash "^4.13.1" request-promise@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" - integrity sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ= dependencies: bluebird "^3.5.0" request-promise-core "1.1.1" @@ -6122,7 +5276,6 @@ request-promise@^4.2.2: request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -6148,22 +5301,18 @@ request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.8 require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" - integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" @@ -6171,41 +5320,34 @@ require-uncached@^1.0.3: resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.1.6, resolve@^1.3.3, resolve@^1.5.0, resolve@^1.6.0: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== dependencies: path-parse "^1.0.5" resolve@~1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" - integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw== dependencies: path-parse "^1.0.5" restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" signal-exit "^3.0.2" @@ -6213,33 +5355,32 @@ restore-cursor@^2.0.0: resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= dependencies: through "~2.3.4" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +revalidator@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1: +rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== dependencies: glob "^7.0.5" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -6247,79 +5388,66 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: rlp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9" - integrity sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA== dependencies: safe-buffer "^5.1.1" run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= dependencies: is-promise "^2.1.0" rustbn.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" - integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== rx-lite-aggregates@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= dependencies: rx-lite "*" rx-lite@*, rx-lite@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-event-emitter@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" - integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== dependencies: events "^3.0.0" safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" safe@^0.4.5: version "0.4.6" resolved "https://registry.yarnpkg.com/safe/-/safe-0.4.6.tgz#1d5580cf2635c5cb940ea48fb5081ae3c25b1be1" - integrity sha1-HVWAzyY1xcuUDqSPtQga48JbG+E= safefs@^3.1.2: version "3.2.2" resolved "https://registry.yarnpkg.com/safefs/-/safefs-3.2.2.tgz#8170c1444d7038e08caea05a374fae2fa349e15c" - integrity sha1-gXDBRE1wOOCMrqBaN0+uL6NJ4Vw= dependencies: graceful-fs "*" "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== scandirectory@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/scandirectory/-/scandirectory-2.5.0.tgz#6ce03f54a090b668e3cbedbf20edf9e310593e72" - integrity sha1-bOA/VKCQtmjjy+2/IO354xBZPnI= dependencies: ignorefs "^1.0.0" safefs "^3.1.2" @@ -6328,24 +5456,20 @@ scandirectory@^2.5.0: schedule@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.5.0.tgz#c128fffa0b402488b08b55ae74bb9df55cc29cc8" - integrity sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw== dependencies: object-assign "^4.1.1" scrypt-async@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-1.3.1.tgz#a11fd6fac981b4b823ee01dee0221169500ddae9" - integrity sha1-oR/W+smBtLgj7gHe4CIRaVAN2uk= scrypt-js@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" - integrity sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q= scrypt.js@0.2.0, scrypt.js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" - integrity sha1-r40UZbcemZARC+38WTuUeeA6ito= dependencies: scrypt "^6.0.2" scryptsy "^1.2.1" @@ -6353,21 +5477,18 @@ scrypt.js@0.2.0, scrypt.js@^0.2.0: scrypt@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" - integrity sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0= dependencies: nan "^2.0.8" scryptsy@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= dependencies: pbkdf2 "^3.0.3" secp256k1@^3.0.1: version "3.5.2" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.2.tgz#f95f952057310722184fe9c914e6b71281f2f2ae" - integrity sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ== dependencies: bindings "^1.2.1" bip66 "^1.1.3" @@ -6381,29 +5502,24 @@ secp256k1@^3.0.1: seek-bzip@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= dependencies: commander "~2.8.1" semaphore@>=1.0.1, semaphore@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== semver@~5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== dependencies: debug "2.6.9" depd "~1.1.2" @@ -6422,7 +5538,6 @@ send@0.16.2: serve-static@1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" @@ -6432,7 +5547,6 @@ serve-static@1.13.2: servify@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== dependencies: body-parser "^1.16.0" cors "^2.8.1" @@ -6443,17 +5557,14 @@ servify@^0.1.12: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6463,7 +5574,6 @@ set-value@^0.4.3: set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6473,22 +5583,18 @@ set-value@^2.0.0: setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -6496,35 +5602,30 @@ sha.js@^2.4.0, sha.js@^2.4.8: sha3@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" - integrity sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k= dependencies: nan "2.10.0" shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shelljs@^0.7.4: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= dependencies: glob "^7.0.0" interpret "^1.0.0" rechoir "^0.6.2" -shelljs@^0.8.1, shelljs@^0.8.2: +shelljs@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" - integrity sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ== dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -6533,17 +5634,14 @@ shelljs@^0.8.1, shelljs@^0.8.2: signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= simple-get@^2.7.0: version "2.8.1" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== dependencies: decompress-response "^3.3.0" once "^1.3.1" @@ -6552,19 +5650,16 @@ simple-get@^2.7.0: slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== dependencies: is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -6573,14 +5668,12 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -6594,22 +5687,18 @@ snapdragon@^0.8.1: sol-digger@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" - integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= sol-explore@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" - integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= sol-explore@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.2.tgz#43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2" - integrity sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI= sol-merger@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-0.1.2.tgz#1f12500f42d427dc0ec8e4c113392acd8a6f62d9" - integrity sha512-12Z84jxeb5VFlQOGS38HOiTrHYohU07oQ5wHOcFJmcRRbaL5kWN7IcldMO1QdW8kONyKdj0xhukzLlN5m5ix4w== dependencies: bluebird "^3.5.0" cli-color "^1.2.0" @@ -6621,7 +5710,6 @@ sol-merger@^0.1.2: solc@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.24.tgz#354f14b269b38cbaa82a47d1ff151723502b954e" - integrity sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -6632,7 +5720,6 @@ solc@0.4.24: solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: version "0.4.25" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.25.tgz#06b8321f7112d95b4b903639b1138a4d292f5faa" - integrity sha512-jU1YygRVy6zatgXrLY2rRm7HW1d7a8CkkEgNJwvH2VLpWhMFsMdWcJn6kUqZwcSz/Vm+w89dy7Z/aB5p6AFTrg== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -6643,7 +5730,6 @@ solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: solidity-coverage@^0.5.11: version "0.5.11" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" - integrity sha512-qikdsSi6+9XbfvwA0aI7HUVpF9fIFNqRWTw23M89GMDY+b6Gj0wWU9IngJS0fimoZIAdEp3bfChxvpfVcrUesg== dependencies: death "^1.1.0" ethereumjs-testrpc-sc "6.1.6" @@ -6659,7 +5745,6 @@ solidity-coverage@^0.5.11: solidity-docgen@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/solidity-docgen/-/solidity-docgen-0.1.0.tgz#f3a56ff074e8c7d832af3a3d462c3b5abf0f64cb" - integrity sha512-F7ufNWmlP5c5hIi66Ijv9tc+HNosyO7ijWq6pRtyBR1WqyJBH/0DJkD6QZI8HkE8p6LEXiPKxGBWbAeVT9Nu9g== dependencies: commander "^2.14.1" lodash "^4.17.5" @@ -6672,7 +5757,6 @@ solidity-docgen@^0.1.0: solidity-parser-sc@0.4.11: version "0.4.11" resolved "https://registry.yarnpkg.com/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz#86734c9205537007f4d6201b57176e41696ee607" - integrity sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw== dependencies: mocha "^4.1.0" pegjs "^0.10.0" @@ -6681,12 +5765,10 @@ solidity-parser-sc@0.4.11: solium-plugin-security@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" - integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== solium@^1.1.6: version "1.1.8" resolved "https://registry.yarnpkg.com/solium/-/solium-1.1.8.tgz#35d30a15c572a233ce8a90226d6cfccb762fadb7" - integrity sha512-fn0lusM6of14CytIDDHK73SGjn6NsVTaCVJjaKCKJyqKhT00rH/hDtvnIeZ2ZTD9z/xaXd4Js2brW3az6AV9RA== dependencies: ajv "^5.2.2" chokidar "^1.6.0" @@ -6704,7 +5786,6 @@ solium@^1.1.6: solparse@2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.5.tgz#72709c867cd6bfc50ec2325f4b81d2b3ea365d99" - integrity sha512-t7tvtR6KU6QfPYLMv1nlCh9DA8HYIu5tbjHpKu0fhGFZ1NuSp0KKDHfFHv07g6v1xgcuUY3rVqNFjZt5b9+5qA== dependencies: mocha "^4.0.1" pegjs "^0.10.0" @@ -6713,17 +5794,14 @@ solparse@2.2.5: sorted-array-functions@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.2.0.tgz#43265b21d6e985b7df31621b1c11cc68d8efc7c3" - integrity sha512-sWpjPhIZJtqO77GN+LD8dDsDKcWZ9GCOJNqKzi1tvtjGIzwfoyuRH8S0psunmc6Z5P+qfDqztSbwYR5X/e1UTg== source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== dependencies: atob "^2.1.1" decode-uri-component "^0.2.0" @@ -6734,14 +5812,12 @@ source-map-resolve@^0.5.0: source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== dependencies: source-map "^0.5.6" source-map-support@^0.5.3: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -6749,29 +5825,24 @@ source-map-support@^0.5.3: source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= dependencies: amdefine ">=0.0.4" spdx-correct@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" - integrity sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -6779,12 +5850,10 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" @@ -6792,29 +5861,24 @@ spdx-expression-parse@^3.0.0: spdx-license-ids@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f" - integrity sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@>=1.0.3: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" - integrity sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw= sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: version "1.15.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2" - integrity sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -6829,12 +5893,10 @@ sshpk@^1.7.0: stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -6842,27 +5904,22 @@ static-extend@^0.1.1: "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== stdio@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/stdio/-/stdio-0.2.7.tgz#a1c57da10fe1cfaa0c3bf683c9d0743d1b660839" - integrity sha1-ocV9oQ/hz6oMO/aDydB0PRtmCDk= stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds= dependencies: inherits "~2.0.1" readable-stream "^2.0.2" @@ -6870,7 +5927,6 @@ stream-browserify@^2.0.1: stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" @@ -6881,22 +5937,10 @@ stream-http@^2.7.2: strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - -string-extended@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/string-extended/-/string-extended-0.0.8.tgz#741957dff487b0272a79eec5a44f239ee6f17ccd" - integrity sha1-dBlX3/SHsCcqee7FpE8jnubxfM0= - dependencies: - array-extended "~0.0.5" - date-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -6905,7 +5949,6 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" @@ -6913,7 +5956,6 @@ string-width@^1.0.1: string.prototype.trim@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" - integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= dependencies: define-properties "^1.1.2" es-abstract "^1.5.0" @@ -6922,109 +5964,92 @@ string.prototype.trim@~1.1.2: string_decoder@^1.0.0, string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== dependencies: is-natural-number "^4.0.1" strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= dependencies: is-hex-prefixed "1.0.0" strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= supports-color@4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== dependencies: has-flag "^2.0.0" supports-color@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== dependencies: has-flag "^3.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" supports-color@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= dependencies: has-flag "^2.0.0" supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" swarm-js@0.1.37: version "0.1.37" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" - integrity sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ== dependencies: bluebird "^3.5.0" buffer "^5.0.5" @@ -7043,7 +6068,6 @@ swarm-js@0.1.37: table@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" - integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== dependencies: ajv "^5.2.3" ajv-keywords "^2.1.0" @@ -7055,12 +6079,10 @@ table@4.0.2: tapable@^0.2.7: version "0.2.8" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" - integrity sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI= tape@^4.4.0, tape@^4.6.3: version "4.9.1" resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9" - integrity sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw== dependencies: deep-equal "~1.0.1" defined "~1.0.0" @@ -7079,7 +6101,6 @@ tape@^4.4.0, tape@^4.6.3: tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== dependencies: bl "^1.0.0" buffer-alloc "^1.2.0" @@ -7092,7 +6113,6 @@ tar-stream@^1.5.2: tar.gz@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" - integrity sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg== dependencies: bluebird "^2.9.34" commander "^2.8.1" @@ -7103,7 +6123,6 @@ tar.gz@^1.0.5: tar@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= dependencies: block-stream "*" fstream "^1.0.2" @@ -7112,7 +6131,6 @@ tar@^2.1.1: tar@^4: version "4.4.6" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" - integrity sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg== dependencies: chownr "^1.0.1" fs-minipass "^1.2.5" @@ -7125,7 +6143,6 @@ tar@^4: taskgroup@^4.0.5, taskgroup@^4.2.0: version "4.3.1" resolved "https://registry.yarnpkg.com/taskgroup/-/taskgroup-4.3.1.tgz#7de193febd768273c457730497024d512c27915a" - integrity sha1-feGT/r12gnPEV3MElwJNUSwnkVo= dependencies: ambi "^2.2.0" csextends "^1.0.3" @@ -7133,43 +6150,36 @@ taskgroup@^4.0.5, taskgroup@^4.2.0: text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= thenify-all@^1.0.0, thenify-all@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.0" resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" - integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= dependencies: any-promise "^1.0.0" through@^2.3.6, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-browserify@^2.0.4: version "2.0.10" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== dependencies: setimmediate "^1.0.4" timers-ext@^0.1.5: version "0.1.7" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" - integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== dependencies: es5-ext "~0.10.46" next-tick "1" @@ -7177,7 +6187,6 @@ timers-ext@^0.1.5: tingodb@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/tingodb/-/tingodb-0.6.1.tgz#f63336259af7dfa6c90dfe2556a0dfb0d4eede59" - integrity sha1-9jM2JZr336bJDf4lVqDfsNTu3lk= dependencies: lodash "^4.17.5" safe "^0.4.5" @@ -7188,36 +6197,30 @@ tingodb@^0.6.1: tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= to-buffer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -7225,7 +6228,6 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" @@ -7235,7 +6237,6 @@ to-regex@^3.0.1, to-regex@^3.0.2: tough-cookie@>=2.3.3, tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: psl "^1.1.24" punycode "^1.4.1" @@ -7243,27 +6244,22 @@ tough-cookie@>=2.3.3, tough-cookie@~2.4.3: tree-kill@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" - integrity sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg== trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= truffle-blockchain-utils@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-blockchain-utils/-/truffle-blockchain-utils-0.0.5.tgz#a4e5c064dadd69f782a137f3d276d21095da7a47" - integrity sha1-pOXAZNrdafeCoTfz0nbSEJXaekc= truffle-contract-schema@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/truffle-contract-schema/-/truffle-contract-schema-2.0.1.tgz#9bf821d32e26e674ba15eb5d40f96b10b1c9d568" - integrity sha1-m/gh0y4m5nS6FetdQPlrELHJ1Wg= dependencies: ajv "^5.1.1" crypto-js "^3.1.9-1" @@ -7272,7 +6268,6 @@ truffle-contract-schema@^2.0.1: truffle-contract@^3.0.4: version "3.0.6" resolved "https://registry.yarnpkg.com/truffle-contract/-/truffle-contract-3.0.6.tgz#2ef6fc32d7faafa9f4aed8e50001a9fdea342192" - integrity sha1-Lvb8Mtf6r6n0rtjlAAGp/eo0IZI= dependencies: ethjs-abi "0.1.8" truffle-blockchain-utils "^0.0.5" @@ -7283,12 +6278,10 @@ truffle-contract@^3.0.4: truffle-error@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/truffle-error/-/truffle-error-0.0.3.tgz#4bf55242e14deee1c7194932709182deff2c97ca" - integrity sha1-S/VSQuFN7uHHGUkycJGC3v8sl8o= truffle-hdwallet-provider-privkey@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider-privkey/-/truffle-hdwallet-provider-privkey-0.1.0.tgz#9417047a74ad37d923df926154b6486ffb57f6c9" - integrity sha512-Vj04yr2d9qLRZspoHztbE/YQnVaoFb90JNZHtggRUm+JFm/NOiSJHLVI63+3mtUIuQ04EuKZ7Df8JQw0Ni7IeA== dependencies: ethereumjs-tx "^1.3.3" ethereumjs-wallet "^0.6.0" @@ -7298,7 +6291,6 @@ truffle-hdwallet-provider-privkey@^0.1.0: truffle-wallet-provider@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-wallet-provider/-/truffle-wallet-provider-0.0.5.tgz#db59ce6fa1c558766011137509a94dfca8d1408e" - integrity sha1-21nOb6HFWHZgERN1CalN/KjRQI4= dependencies: ethereumjs-wallet "^0.6.0" web3 "^0.18.2" @@ -7307,7 +6299,6 @@ truffle-wallet-provider@0.0.5: truffle@^4.1.13: version "4.1.14" resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.14.tgz#8d2c298e29abf9b1e486e44ff9faca6d34bb9030" - integrity sha512-e7tTLvKP3bN9dE7MagfWyFjy4ZgoEGbeujECy1me1ENBzbj/aO/+45gs72qsL3+3IkCNNcWNOJjjrm8BYZZNNg== dependencies: mocha "^4.1.0" original-require "1.0.1" @@ -7316,36 +6307,30 @@ truffle@^4.1.13: tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.13.2.tgz#453161770469d45cd266c36404e2bc99a8fa9944" - integrity sha1-RTFhdwRp1FzSZsNkBOK8maj6mUQ= tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" - integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== dependencies: media-typer "0.3.0" mime-types "~2.1.18" @@ -7353,36 +6338,30 @@ type-is@~1.6.16: typechecker@^2.0.8: version "2.1.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.1.0.tgz#d1c2093a54ff8a19f58cff877eeaa54f2242d383" - integrity sha1-0cIJOlT/ihn1jP+HfuqlTyJC04M= typechecker@^4.3.0: version "4.6.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.6.0.tgz#d245d9c2df21147d5e2a942fff170b68ece73c87" - integrity sha512-83OrXpyP3LNr7aRbLkt2nkjE/d7q8su8/uRvrKxCpswqVCVGOgyaKpaz8/MTjQqBYe4eLNuJ44pNakFZKqyPMA== dependencies: editions "^2.0.2" typechecker@~2.0.1: version "2.0.8" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.0.8.tgz#e83da84bb64c584ccb345838576c40b0337db82e" - integrity sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4= typedarray-to-buffer@^3.1.2: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -7392,7 +6371,6 @@ uglify-js@^2.8.29: uglify-js@^3.1.4: version "3.4.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" - integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== dependencies: commander "~2.17.1" source-map "~0.6.1" @@ -7400,12 +6378,10 @@ uglify-js@^3.1.4: uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= uglifyjs-webpack-plugin@^0.4.6: version "0.4.6" resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" - integrity sha1-uVH0q7a9YX5m9j64kUmOORdj4wk= dependencies: source-map "^0.5.6" uglify-js "^2.8.29" @@ -7414,12 +6390,10 @@ uglifyjs-webpack-plugin@^0.4.6: ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== unbzip2-stream@^1.0.9: version "1.3.1" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" - integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw== dependencies: buffer "^3.0.1" through "^2.3.6" @@ -7427,17 +6401,14 @@ unbzip2-stream@^1.0.9: underscore@1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= underscore@^1.8.3: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -7447,22 +6418,18 @@ union-value@^1.0.0: universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== unorm@^1.3.3: version "1.4.1" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300" - integrity sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA= unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -7470,41 +6437,34 @@ unset-value@^1.0.0: upath@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= dependencies: prepend-http "^1.0.1" url-set-query@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= dependencies: punycode "1.3.2" querystring "0.2.0" @@ -7512,66 +6472,65 @@ url@^0.11.0: use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== utf8@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" - integrity sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g= utf8@^2.1.1, utf8@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" - integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY= utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= dependencies: inherits "2.0.1" util@^0.10.3: version "0.10.4" resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== dependencies: inherits "2.0.3" +utile@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a" + dependencies: + async "~0.9.0" + deep-equal "~0.2.1" + i "0.3.x" + mkdirp "0.x.x" + ncp "1.0.x" + rimraf "2.x.x" + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== valid-url@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" @@ -7579,17 +6538,14 @@ validate-npm-package-license@^3.0.1: varint@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf" - integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8= vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -7598,14 +6554,12 @@ verror@1.10.0: vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= dependencies: indexof "0.0.1" watchpack@^1.4.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== dependencies: chokidar "^2.0.2" graceful-fs "^4.1.2" @@ -7614,7 +6568,6 @@ watchpack@^1.4.0: watchr@~2.4.13: version "2.4.13" resolved "https://registry.yarnpkg.com/watchr/-/watchr-2.4.13.tgz#d74847bb4d6f90f61fe2c74f9f68662aa0e07601" - integrity sha1-10hHu01vkPYf4sdPn2hmKqDgdgE= dependencies: eachr "^2.0.2" extendr "^2.1.0" @@ -7628,7 +6581,6 @@ watchr@~2.4.13: web3-bzz@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.34.tgz#068d37777ab65e5c60f8ec8b9a50cfe45277929c" - integrity sha1-Bo03d3q2Xlxg+OyLmlDP5FJ3kpw= dependencies: got "7.1.0" swarm-js "0.1.37" @@ -7637,7 +6589,6 @@ web3-bzz@1.0.0-beta.34: web3-core-helpers@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz#b168da00d3e19e156bc15ae203203dd4dfee2d03" - integrity sha1-sWjaANPhnhVrwVriAyA91N/uLQM= dependencies: underscore "1.8.3" web3-eth-iban "1.0.0-beta.34" @@ -7646,7 +6597,6 @@ web3-core-helpers@1.0.0-beta.34: web3-core-method@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz#ec163c8a2c490fa02a7ec15559fa7307fc7cc6dd" - integrity sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7657,7 +6607,6 @@ web3-core-method@1.0.0-beta.34: web3-core-promievent@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz#a4f4fa6784bb293e82c60960ae5b56a94cd03edc" - integrity sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw= dependencies: any-promise "1.3.0" eventemitter3 "1.1.1" @@ -7665,7 +6614,6 @@ web3-core-promievent@1.0.0-beta.34: web3-core-requestmanager@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz#01f8f6cf2ae6b6f0b70c38bae1ef741b5bab215c" - integrity sha1-Afj2zyrmtvC3DDi64e90G1urIVw= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7676,7 +6624,6 @@ web3-core-requestmanager@1.0.0-beta.34: web3-core-subscriptions@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz#9fed144033f221c3cf21060302ffdaf5ef2de2de" - integrity sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4= dependencies: eventemitter3 "1.1.1" underscore "1.8.3" @@ -7685,7 +6632,6 @@ web3-core-subscriptions@1.0.0-beta.34: web3-core@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.34.tgz#121be8555e9fb00d2c5d05ddd3381d0c9e46987e" - integrity sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4= dependencies: web3-core-helpers "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7695,7 +6641,6 @@ web3-core@1.0.0-beta.34: web3-eth-abi@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz#034533e3aa2f7e59ff31793eaea685c0ed5af67a" - integrity sha1-A0Uz46ovfln/MXk+rqaFwO1a9no= dependencies: bn.js "4.11.6" underscore "1.8.3" @@ -7705,7 +6650,6 @@ web3-eth-abi@1.0.0-beta.34: web3-eth-accounts@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz#e09142eeecc797ac3459b75e9b23946d3695f333" - integrity sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM= dependencies: any-promise "1.3.0" crypto-browserify "3.12.0" @@ -7721,7 +6665,6 @@ web3-eth-accounts@1.0.0-beta.34: web3-eth-contract@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz#9dbb38fae7643a808427a20180470ec7415c91e6" - integrity sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -7735,7 +6678,6 @@ web3-eth-contract@1.0.0-beta.34: web3-eth-iban@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz#9af458605867ccf74ea979aaf326b38ba6a5ba0c" - integrity sha1-mvRYYFhnzPdOqXmq8yazi6alugw= dependencies: bn.js "4.11.6" web3-utils "1.0.0-beta.34" @@ -7743,7 +6685,6 @@ web3-eth-iban@1.0.0-beta.34: web3-eth-personal@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz#9afba167342ebde5420bcd5895c3f6c34388f205" - integrity sha1-mvuhZzQuveVCC81YlcP2w0OI8gU= dependencies: web3-core "1.0.0-beta.34" web3-core-helpers "1.0.0-beta.34" @@ -7754,7 +6695,6 @@ web3-eth-personal@1.0.0-beta.34: web3-eth@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.34.tgz#74086000850c6fe6f535ef49837d6d4bb6113268" - integrity sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -7772,7 +6712,6 @@ web3-eth@1.0.0-beta.34: web3-net@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.34.tgz#427cea2f431881449c8e38d523290f173f9ff63d" - integrity sha1-QnzqL0MYgUScjjjVIykPFz+f9j0= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7781,7 +6720,6 @@ web3-net@1.0.0-beta.34: web3-provider-engine@^13.6.4: version "13.8.0" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz#4c7c1ad2af5f1fe10343b8a65495879a2f9c00df" - integrity sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ== dependencies: async "^2.5.0" clone "^2.0.0" @@ -7806,7 +6744,6 @@ web3-provider-engine@^13.6.4: web3-provider-engine@^8.4.0: version "8.6.1" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz#4d86e19e30caaf97df351511ec0f60136e5b30eb" - integrity sha1-TYbhnjDKr5ffNRUR7A9gE25bMOs= dependencies: async "^2.1.2" clone "^2.0.0" @@ -7826,7 +6763,6 @@ web3-provider-engine@^8.4.0: web3-providers-http@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz#e561b52bbb43766282007d40285bfe3550c27e7a" - integrity sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno= dependencies: web3-core-helpers "1.0.0-beta.34" xhr2 "0.1.4" @@ -7834,7 +6770,6 @@ web3-providers-http@1.0.0-beta.34: web3-providers-ipc@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz#a1b77f1a306d73649a9c039052e40cb71328d00a" - integrity sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao= dependencies: oboe "2.1.3" underscore "1.8.3" @@ -7843,7 +6778,6 @@ web3-providers-ipc@1.0.0-beta.34: web3-providers-ws@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz#7de70f1b83f2de36476772156becfef6e3516eb3" - integrity sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7852,7 +6786,6 @@ web3-providers-ws@1.0.0-beta.34: web3-shh@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.34.tgz#975061d71eaec42ccee576f7bd8f70f03844afe0" - integrity sha1-l1Bh1x6uxCzO5Xb3vY9w8DhEr+A= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7862,7 +6795,6 @@ web3-shh@1.0.0-beta.34: web3-utils@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.34.tgz#9411fc39aaef39ca4e06169f762297d9ff020970" - integrity sha1-lBH8OarvOcpOBhafdiKX2f8CCXA= dependencies: bn.js "4.11.6" eth-lib "0.1.27" @@ -7875,7 +6807,6 @@ web3-utils@1.0.0-beta.34: web3@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/web3/-/web3-0.19.1.tgz#e763d5b1107c4bc24abd4f8cbee1ba3659e6eb31" - integrity sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE= dependencies: bignumber.js "^4.0.2" crypto-js "^3.1.4" @@ -7886,7 +6817,6 @@ web3@0.19.1: web3@0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.2.tgz#c54dac5fc0e377399c04c1a6ecbb12e4513278d6" - integrity sha1-xU2sX8DjdzmcBMGm7LsS5FEyeNY= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7897,7 +6827,6 @@ web3@0.20.2: web3@0.20.6: version "0.20.6" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.6.tgz#3e97306ae024fb24e10a3d75c884302562215120" - integrity sha1-PpcwauAk+yThCj11yIQwJWIhUSA= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7908,7 +6837,6 @@ web3@0.20.6: web3@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.34.tgz#347e561b784098cb5563315f490479a1d91f2ab1" - integrity sha1-NH5WG3hAmMtVYzFfSQR5odkfKrE= dependencies: web3-bzz "1.0.0-beta.34" web3-core "1.0.0-beta.34" @@ -7921,7 +6849,6 @@ web3@1.0.0-beta.34: web3@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" - integrity sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js#master" crypto-js "^3.1.4" @@ -7931,7 +6858,6 @@ web3@^0.16.0: web3@^0.18.2, web3@^0.18.4: version "0.18.4" resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" - integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" crypto-js "^3.1.4" @@ -7942,7 +6868,6 @@ web3@^0.18.2, web3@^0.18.4: web3@^0.20.5: version "0.20.7" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.7.tgz#1605e6d81399ed6f85a471a4f3da0c8be57df2f7" - integrity sha512-VU6/DSUX93d1fCzBz7WP/SGCQizO1rKZi4Px9j/3yRyfssHyFcZamMw2/sj4E8TlfMXONvZLoforR8B4bRoyTQ== dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7953,7 +6878,6 @@ web3@^0.20.5: webpack-sources@^1.0.1: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" - integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== dependencies: source-list-map "^2.0.0" source-map "~0.6.1" @@ -7961,7 +6885,6 @@ webpack-sources@^1.0.1: webpack@^3.0.0: version "3.12.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.12.0.tgz#3f9e34360370602fcf639e97939db486f4ec0d74" - integrity sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ== dependencies: acorn "^5.0.0" acorn-dynamic-import "^2.0.0" @@ -7998,46 +6921,50 @@ webpack@^3.0.0: whatwg-fetch@>=0.10.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@^1.1.1, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= + +winston@2.1.x: + version "2.1.1" + resolved "http://registry.npmjs.org/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" + dependencies: + async "~1.0.0" + colors "1.0.x" + cycle "1.0.x" + eyes "0.1.x" + isstream "0.1.x" + pkginfo "0.3.x" + stack-trace "0.0.x" winston@^2.3.1: version "2.4.4" resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.4.tgz#a01e4d1d0a103cf4eada6fc1f886b3110d71c34b" - integrity sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q== dependencies: async "~1.0.0" colors "1.0.x" @@ -8049,22 +6976,18 @@ winston@^2.3.1: wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= wordwrap@^1.0.0, wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -8072,19 +6995,16 @@ wrap-ansi@^2.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= dependencies: mkdirp "^0.5.1" ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" @@ -8093,14 +7013,12 @@ ws@^3.0.0: xhr-request-promise@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" - integrity sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0= dependencies: xhr-request "^1.0.1" xhr-request@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== dependencies: buffer-to-arraybuffer "^0.0.5" object-assign "^4.1.1" @@ -8113,19 +7031,16 @@ xhr-request@^1.0.1: xhr2-cookies@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= dependencies: cookiejar "^2.1.1" xhr2@*, xhr2@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" - integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8= xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: version "2.5.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" - integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== dependencies: global "~4.3.0" is-function "^1.0.1" @@ -8135,49 +7050,40 @@ xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: xmlhttprequest@*, xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= xregexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" - integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= dependencies: object-keys "~0.4.0" y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= dependencies: camelcase "^3.0.0" lodash.assign "^4.0.6" @@ -8185,28 +7091,24 @@ yargs-parser@^2.4.1: yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k= dependencies: camelcase "^4.1.0" yargs-parser@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== dependencies: camelcase "^4.1.0" yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= dependencies: camelcase "^4.1.0" yargs@^10.0.3: version "10.1.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" - integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -8224,7 +7126,6 @@ yargs@^10.0.3: yargs@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -8242,7 +7143,6 @@ yargs@^11.0.0: yargs@^4.6.0, yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= dependencies: cliui "^3.2.0" decamelize "^1.1.1" @@ -8262,7 +7162,6 @@ yargs@^4.6.0, yargs@^4.7.1: yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - integrity sha1-YpmpBVsc78lp/355wdkY3Osiw2A= dependencies: camelcase "^4.1.0" cliui "^3.2.0" @@ -8281,7 +7180,6 @@ yargs@^8.0.2: yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= dependencies: camelcase "^1.0.2" cliui "^2.1.0" @@ -8291,7 +7189,6 @@ yargs@~3.10.0: yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" From 42e4a789931d47984429d84b78e40bb3c3320f6a Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 27 Nov 2018 09:20:35 +0000 Subject: [PATCH 208/582] Optimise GTM (#433) - Add an Offset that can be used to move all from & to dates forwards or backwards by a fixed offset. - Add address[] public investors to record a list of all addresses that have been added to the whitelist - Fix for when allowAllWhitelistIssuances is FALSE - Clearer logic around toTime, fromTime & expiryTime - Make GTM a Proxy based implementation to reduce deployment gas costs --- CHANGELOG.md | 6 + .../modules/Checkpoint/DividendCheckpoint.sol | 37 +- .../Checkpoint/DividendCheckpointStorage.sol | 43 + .../Checkpoint/ERC20DividendCheckpoint.sol | 39 +- .../ERC20DividendCheckpointFactory.sol | 9 +- .../ERC20DividendCheckpointStorage.sol | 11 + .../Checkpoint/EtherDividendCheckpoint.sol | 25 +- .../EtherDividendCheckpointFactory.sol | 9 +- contracts/modules/Module.sol | 20 +- contracts/modules/ModuleStorage.sol | 30 + .../GeneralTransferManager.sol | 156 ++- .../GeneralTransferManagerFactory.sol | 10 +- .../GeneralTransferManagerStorage.sol | 53 + .../proxy/ERC20DividendCheckpointProxy.sol | 31 + .../proxy/EtherDividendCheckpointProxy.sol | 30 + .../proxy/GeneralTransferManagerProxy.sol | 30 + contracts/proxy/OwnedProxy.sol | 91 ++ migrations/2_deploy_contracts.js | 24 +- package.json | 1 + scripts/compareStorageLayout.js | 139 ++ test/b_capped_sto.js | 14 +- test/c_checkpoints.js | 6 +- test/d_count_transfer_manager.js | 8 +- test/e_erc20_dividends.js | 12 +- test/f_ether_dividends.js | 12 +- test/h_general_transfer_manager.js | 168 ++- test/helpers/createInstances.js | 32 +- test/helpers/signData.js | 2 +- test/i_Issuance.js | 4 +- test/j_manual_approval_transfer_manager.js | 6 +- test/l_percentage_transfer_manager.js | 8 +- test/m_presale_sto.js | 6 +- test/o_security_token.js | 20 +- test/p_usd_tiered_sto.js | 18 +- test/q_usd_tiered_sto_sim.js | 6 +- test/r_concurrent_STO.js | 6 +- test/u_module_registry_proxy.js | 5 +- test/v_tracked_redemptions.js | 6 +- ...kup_volume_restriction_transfer_manager.js | 14 +- test/x_single_trade_volume_restriction.js | 24 +- test/y_scheduled_checkpoints.js | 6 +- yarn.lock | 1247 +---------------- 42 files changed, 975 insertions(+), 1449 deletions(-) create mode 100644 contracts/modules/Checkpoint/DividendCheckpointStorage.sol create mode 100644 contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol create mode 100644 contracts/modules/ModuleStorage.sol create mode 100644 contracts/modules/TransferManager/GeneralTransferManagerStorage.sol create mode 100644 contracts/proxy/ERC20DividendCheckpointProxy.sol create mode 100644 contracts/proxy/EtherDividendCheckpointProxy.sol create mode 100644 contracts/proxy/GeneralTransferManagerProxy.sol create mode 100644 contracts/proxy/OwnedProxy.sol create mode 100644 scripts/compareStorageLayout.js diff --git a/CHANGELOG.md b/CHANGELOG.md index db3d8dcde..0e19e93ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,12 @@ All notable changes to this project will be documented in this file. * Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. * Removed individual mappings for tier data removed in UDSTSTO. +# GeneralTransferManager +* Add an Offset that can be used to move all from & to dates forwards or backwards by a fixed offset. +* Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`) +* Fix for when `allowAllWhitelistIssuances` is FALSE +* Make GTM a Proxy based implementation to reduce deployment gas costs + ##Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 452a48b13..3a345af25 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -8,6 +8,7 @@ pragma solidity ^0.4.24; import "./ICheckpoint.sol"; +import "./DividendCheckpointStorage.sol"; import "../Module.sol"; import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -17,43 +18,9 @@ import "openzeppelin-solidity/contracts/math/Math.sol"; * @title Checkpoint module for issuing ether dividends * @dev abstract contract */ -contract DividendCheckpoint is ICheckpoint, Module { +contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { using SafeMath for uint256; - uint256 public EXCLUDED_ADDRESS_LIMIT = 50; - bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; - bytes32 public constant MANAGE = "MANAGE"; - bytes32 public constant CHECKPOINT = "CHECKPOINT"; - - struct Dividend { - uint256 checkpointId; - uint256 created; // Time at which the dividend was created - uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass - uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - - // set to very high value to bypass - uint256 amount; // Dividend amount in WEI - uint256 claimedAmount; // Amount of dividend claimed so far - uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) - bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend - uint256 dividendWithheld; - uint256 dividendWithheldReclaimed; - mapping (address => bool) claimed; // List of addresses which have claimed dividend - mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends - bytes32 name; // Name/title - used for identification - } - - // List of all dividends - Dividend[] public dividends; - - // List of addresses which cannot claim dividends - address[] public excluded; - - // Mapping from address to withholding tax as a percentage * 10**16 - mapping (address => uint256) public withholdingTax; - - // Total amount of ETH withheld per investor - mapping (address => uint256) public investorWithheld; - event SetDefaultExcludedAddresses(address[] _excluded, uint256 _timestamp); event SetWithholding(address[] _investors, uint256[] _withholding, uint256 _timestamp); event SetWithholdingFixed(address[] _investors, uint256 _withholding, uint256 _timestamp); diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol new file mode 100644 index 000000000..4cf1f2838 --- /dev/null +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -0,0 +1,43 @@ +pragma solidity ^0.4.24; + +/** + * @title Holds the storage variable for the DividendCheckpoint modules (i.e ERC20, Ether) + * @dev abstract contract + */ +contract DividendCheckpointStorage { + + uint256 public EXCLUDED_ADDRESS_LIMIT = 50; + bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; + bytes32 public constant MANAGE = "MANAGE"; + bytes32 public constant CHECKPOINT = "CHECKPOINT"; + + struct Dividend { + uint256 checkpointId; + uint256 created; // Time at which the dividend was created + uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass + uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - + // set to very high value to bypass + uint256 amount; // Dividend amount in WEI + uint256 claimedAmount; // Amount of dividend claimed so far + uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) + bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend + uint256 dividendWithheld; + uint256 dividendWithheldReclaimed; + mapping (address => bool) claimed; // List of addresses which have claimed dividend + mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends + bytes32 name; // Name/title - used for identification + } + + // List of all dividends + Dividend[] public dividends; + + // List of addresses which cannot claim dividends + address[] public excluded; + + // Mapping from address to withholding tax as a percentage * 10**16 + mapping (address => uint256) public withholdingTax; + + // Total amount of ETH withheld per investor + mapping (address => uint256) public investorWithheld; + +} diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 1f7f25cd5..b779088f7 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -1,17 +1,16 @@ pragma solidity ^0.4.24; import "./DividendCheckpoint.sol"; +import "./ERC20DividendCheckpointStorage.sol"; import "../../interfaces/IOwnable.sol"; import "../../interfaces/IERC20.sol"; /** * @title Checkpoint module for issuing ERC20 dividends */ -contract ERC20DividendCheckpoint is DividendCheckpoint { +contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendCheckpoint { using SafeMath for uint256; - // Mapping to token address for each dividend - mapping (uint256 => address) public dividendTokens; event ERC20DividendDeposited( address indexed _depositor, uint256 _checkpointId, @@ -68,8 +67,8 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { address _token, uint256 _amount, bytes32 _name - ) - external + ) + external withPerm(MANAGE) { createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name); @@ -133,16 +132,16 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _name Name/Title for identification */ function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, address[] _excluded, bytes32 _name - ) + ) public - withPerm(MANAGE) + withPerm(MANAGE) { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, _excluded, _name); } @@ -158,15 +157,15 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _name Name/Title for identification */ function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, address[] _excluded, bytes32 _name - ) - internal + ) + internal { ISecurityToken securityTokenInstance = ISecurityToken(securityToken); require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); @@ -210,7 +209,7 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { } /** - * @notice Emits the ERC20DividendDeposited event. + * @notice Emits the ERC20DividendDeposited event. * Seperated into a different function as a workaround for stack too deep error */ function _emitERC20DividendDepositedEvent( diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 5fd158c26..a684e553b 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./ERC20DividendCheckpoint.sol"; +import "../../proxy/ERC20DividendCheckpointProxy.sol"; import "../ModuleFactory.sol"; /** @@ -8,6 +8,8 @@ import "../ModuleFactory.sol"; */ contract ERC20DividendCheckpointFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken @@ -15,7 +17,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; @@ -24,6 +26,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { description = "Create ERC20 dividends for token holders at a specific checkpoint"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,7 +36,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "insufficent allowance"); - address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender, address(polyToken)); + address erc20DividendCheckpoint = new ERC20DividendCheckpointProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return erc20DividendCheckpoint; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol new file mode 100644 index 000000000..29401f8d9 --- /dev/null +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.24; + +/** + * @title It holds the storage variables related to ERC20DividendCheckpoint module + */ +contract ERC20DividendCheckpointStorage { + + // Mapping to token address for each dividend + mapping (uint256 => address) public dividendTokens; + +} diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index 4def51468..f5a916818 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -8,6 +8,7 @@ import "../../interfaces/IOwnable.sol"; */ contract EtherDividendCheckpoint is DividendCheckpoint { using SafeMath for uint256; + event EtherDividendDeposited( address indexed _depositor, uint256 _checkpointId, @@ -56,7 +57,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, uint256 _checkpointId, bytes32 _name - ) + ) external payable withPerm(MANAGE) @@ -76,7 +77,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, address[] _excluded, bytes32 _name - ) + ) public payable withPerm(MANAGE) @@ -94,10 +95,10 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _name Name/title for identification */ function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] _excluded, + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] _excluded, bytes32 _name ) public @@ -116,12 +117,12 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _name Name/title for identification */ function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] _excluded, + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] _excluded, bytes32 _name - ) + ) internal { require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); @@ -169,7 +170,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { */ function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee); - _dividend.claimed[_payee] = true; + _dividend.claimed[_payee] = true; uint256 claimAfterWithheld = claim.sub(withheld); if (claimAfterWithheld > 0) { /*solium-disable-next-line security/no-send*/ diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 315760be1..3129fba42 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./EtherDividendCheckpoint.sol"; +import "../../proxy/EtherDividendCheckpointProxy.sol"; import "../ModuleFactory.sol"; /** @@ -8,6 +8,8 @@ import "../ModuleFactory.sol"; */ contract EtherDividendCheckpointFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken @@ -15,7 +17,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; @@ -24,6 +26,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { description = "Create ETH dividends for token holders at a specific checkpoint"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,7 +36,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent allowance or balance"); - address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender, address(polyToken)); + address ethDividendCheckpoint = new EtherDividendCheckpointProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return ethDividendCheckpoint; diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index 1e27d424e..1566a3428 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -2,33 +2,23 @@ pragma solidity ^0.4.24; import "../interfaces/IModule.sol"; import "../interfaces/ISecurityToken.sol"; -import "../interfaces/IERC20.sol"; +import "./ModuleStorage.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; /** * @title Interface that any module contract should implement * @notice Contract is abstract */ -contract Module is IModule { - - address public factory; - - address public securityToken; - - bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; - - IERC20 public polyToken; +contract Module is IModule, ModuleStorage { /** * @notice Constructor * @param _securityToken Address of the security token * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public { - require(_securityToken != address(0) && _polyAddress != address(0), "Invalid address"); - securityToken = _securityToken; - factory = msg.sender; - polyToken = IERC20(_polyAddress); + constructor (address _securityToken, address _polyAddress) public + ModuleStorage(_securityToken, _polyAddress) + { } //Allows owner, factory or permissioned delegate diff --git a/contracts/modules/ModuleStorage.sol b/contracts/modules/ModuleStorage.sol new file mode 100644 index 000000000..cd52c9de2 --- /dev/null +++ b/contracts/modules/ModuleStorage.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../interfaces/IERC20.sol"; + +/** + * @title Storage for Module contract + * @notice Contract is abstract + */ +contract ModuleStorage { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) public { + securityToken = _securityToken; + factory = msg.sender; + polyToken = IERC20(_polyAddress); + } + + address public factory; + + address public securityToken; + + bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; + + IERC20 public polyToken; + +} diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 814d54d7b..04028fead 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -1,47 +1,16 @@ pragma solidity ^0.4.24; import "./ITransferManager.sol"; +import "./GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Transfer Manager module for core transfer validation functionality */ -contract GeneralTransferManager is ITransferManager { +contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManager { using SafeMath for uint256; - //Address from which issuances come - address public issuanceAddress = address(0); - - //Address which can sign whitelist changes - address public signingAddress = address(0); - - bytes32 public constant WHITELIST = "WHITELIST"; - bytes32 public constant FLAGS = "FLAGS"; - - //from and to timestamps that an investor can send / receive tokens respectively - struct TimeRestriction { - uint256 fromTime; - uint256 toTime; - uint256 expiryTime; - bool canBuyFromSTO; - } - - // An address can only send / receive tokens once their corresponding uint256 > block.number - // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) - mapping (address => TimeRestriction) public whitelist; - // Map of used nonces by customer - mapping(address => mapping(uint256 => bool)) public nonceMap; - - //If true, there are no transfer restrictions, for any addresses - bool public allowAllTransfers = false; - //If true, time lock is ignored for transfers (address must still be on whitelist) - bool public allowAllWhitelistTransfers = false; - //If true, time lock is ignored for issuances (address must still be on whitelist) - bool public allowAllWhitelistIssuances = true; - //If true, time lock is ignored for burn transactions - bool public allowAllBurnTransfers = false; - // Emit when Issuance address get changed event ChangeIssuanceAddress(address _issuanceAddress); // Emit when there is change in the flag variable called allowAllTransfers @@ -55,14 +24,21 @@ contract GeneralTransferManager is ITransferManager { // Emit when there is change in the flag variable called signingAddress event ChangeSigningAddress(address _signingAddress); // Emit when investor details get modified related to their whitelisting + event OffsetModified(uint64 _time, uint8 _isForward); + + // _fromTime is the time from which the _investor can send tokens + // _toTime is the time from which the _investor can receive tokens + // if allowAllWhitelistIssuances is TRUE, then _toTime is ignored when receiving tokens from the issuance address + // if allowAllWhitelistTransfers is TRUE, then _toTime and _fromTime is ignored when sending or receiving tokens + // in any case, any investor sending or receiving tokens, must have a _expiryTime in the future event ModifyWhitelist( address _investor, uint256 _dateAdded, address _addedBy, - uint256 _fromTime, - uint256 _toTime, - uint256 _expiryTime, - bool _canBuyFromSTO + uint64 _fromTime, + uint64 _toTime, + uint64 _expiryTime, + uint8 _canBuyFromSTO ); /** @@ -76,6 +52,12 @@ contract GeneralTransferManager is ITransferManager { { } + function modifyOffset(uint64 _time, uint8 _isForward) public withPerm(FLAGS) { + offset.time = _time; + offset.isForward = _isForward; + emit OffsetModified(_time, _isForward); + } + /** * @notice This function returns the signature of configure function */ @@ -168,16 +150,19 @@ contract GeneralTransferManager is ITransferManager { //Anyone on the whitelist can transfer, regardless of time return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA; } + if (_from == issuanceAddress && (whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { + return Result.NA; + } if (allowAllWhitelistIssuances && _from == issuanceAddress) { - if (!whitelist[_to].canBuyFromSTO && _isSTOAttached()) { - return Result.NA; - } return _onWhitelist(_to) ? Result.VALID : Result.NA; } + if (_from == issuanceAddress) { + return (_onWhitelist(_to) && _adjustTimes(whitelist[_to].toTime) <= uint64(now)) ? Result.VALID : Result.NA; + } //Anyone on the whitelist can transfer provided the blocknumber is large enough /*solium-disable-next-line security/no-block-members*/ - return ((_onWhitelist(_from) && whitelist[_from].fromTime <= now) && - (_onWhitelist(_to) && whitelist[_to].toTime <= now)) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return ((_onWhitelist(_from) && _adjustTimes(whitelist[_from].fromTime) <= uint64(now)) && + (_onWhitelist(_to) && _adjustTimes(whitelist[_to].toTime) <= uint64(now))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -192,16 +177,39 @@ contract GeneralTransferManager is ITransferManager { */ function modifyWhitelist( address _investor, - uint256 _fromTime, - uint256 _toTime, - uint256 _expiryTime, - bool _canBuyFromSTO + uint64 _fromTime, + uint64 _toTime, + uint64 _expiryTime, + uint8 _canBuyFromSTO ) public withPerm(WHITELIST) { - //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); + _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + } + + /** + * @notice Adds or removes addresses from the whitelist. + * @param _investor is the address to whitelist + * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens + * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others + * @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC + * @param _canBuyFromSTO is used to know whether the investor is restricted investor or not. + */ + function _modifyWhitelist( + address _investor, + uint64 _fromTime, + uint64 _toTime, + uint64 _expiryTime, + uint8 _canBuyFromSTO + ) + internal + { + require(_investor != address(0), "Invalid investor"); + if (whitelist[_investor].added == uint8(0)) { + investors.push(_investor); + } + whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO, uint8(1)); /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -216,17 +224,17 @@ contract GeneralTransferManager is ITransferManager { */ function modifyWhitelistMulti( address[] _investors, - uint256[] _fromTimes, - uint256[] _toTimes, - uint256[] _expiryTimes, - bool[] _canBuyFromSTO + uint64[] _fromTimes, + uint64[] _toTimes, + uint64[] _expiryTimes, + uint8[] _canBuyFromSTO ) public withPerm(WHITELIST) { require(_investors.length == _fromTimes.length, "Mismatched input lengths"); require(_fromTimes.length == _toTimes.length, "Mismatched input lengths"); require(_toTimes.length == _expiryTimes.length, "Mismatched input lengths"); require(_canBuyFromSTO.length == _toTimes.length, "Mismatched input length"); for (uint256 i = 0; i < _investors.length; i++) { - modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); + _modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); } } @@ -246,29 +254,31 @@ contract GeneralTransferManager is ITransferManager { */ function modifyWhitelistSigned( address _investor, - uint256 _fromTime, - uint256 _toTime, - uint256 _expiryTime, - bool _canBuyFromSTO, - uint256 _validFrom, - uint256 _validTo, + uint64 _fromTime, + uint64 _toTime, + uint64 _expiryTime, + uint8 _canBuyFromSTO, + uint64 _validFrom, + uint64 _validTo, uint256 _nonce, uint8 _v, bytes32 _r, bytes32 _s ) public { /*solium-disable-next-line security/no-block-members*/ - require(_validFrom <= now, "ValidFrom is too early"); + require(_validFrom <= uint64(now), "ValidFrom is too early"); /*solium-disable-next-line security/no-block-members*/ - require(_validTo >= now, "ValidTo is too late"); + require(_validTo >= uint64(now), "ValidTo is too late"); require(!nonceMap[_investor][_nonce], "Already used signature"); nonceMap[_investor][_nonce] = true; bytes32 hash = keccak256( abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) ); _checkSig(hash, _v, _r, _s); - //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); + if (whitelist[_investor].added == uint8(0)) { + investors.push(_investor); + } + whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO, uint8(1)); /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -289,8 +299,7 @@ contract GeneralTransferManager is ITransferManager { * @param _investor Address of the investor */ function _onWhitelist(address _investor) internal view returns(bool) { - return (((whitelist[_investor].fromTime != 0) || (whitelist[_investor].toTime != 0)) && - (whitelist[_investor].expiryTime >= now)); /*solium-disable-line security/no-block-members*/ + return (whitelist[_investor].expiryTime >= uint64(now)); /*solium-disable-line security/no-block-members*/ } /** @@ -301,6 +310,23 @@ contract GeneralTransferManager is ITransferManager { return attached; } + function _adjustTimes(uint64 _time) internal view returns(uint64) { + if (offset.isForward != 0) { + require(_time + offset.time > _time); + return _time + offset.time; + } else { + require(_time >= offset.time); + return _time - offset.time; + } + } + + /** + * @dev Returns list of all investors + */ + function getInvestors() external view returns(address[]) { + return investors; + } + /** * @notice Return the permissions flag that are associated with general trnasfer manager */ diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index c15eb52aa..4c81be20a 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./GeneralTransferManager.sol"; +import "../../proxy/GeneralTransferManagerProxy.sol"; import "../ModuleFactory.sol"; /** @@ -8,19 +8,23 @@ import "../ModuleFactory.sol"; */ contract GeneralTransferManagerFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid logic contract"); version = "1.0.0"; name = "GeneralTransferManager"; title = "General Transfer Manager"; description = "Manage transfers using a time based whitelist"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } @@ -31,7 +35,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - address generalTransferManager = new GeneralTransferManager(msg.sender, address(polyToken)); + address generalTransferManager = new GeneralTransferManagerProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(generalTransferManager); diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol new file mode 100644 index 000000000..f5c162080 --- /dev/null +++ b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol @@ -0,0 +1,53 @@ +pragma solidity ^0.4.24; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract GeneralTransferManagerStorage { + + //Address from which issuances come + address public issuanceAddress = address(0); + + //Address which can sign whitelist changes + address public signingAddress = address(0); + + bytes32 public constant WHITELIST = "WHITELIST"; + bytes32 public constant FLAGS = "FLAGS"; + + //from and to timestamps that an investor can send / receive tokens respectively + struct TimeRestriction { + uint64 fromTime; + uint64 toTime; + uint64 expiryTime; + uint8 canBuyFromSTO; + uint8 added; + } + + // Allows all TimeRestrictions to be offset + struct Offset { + uint64 time; + uint8 isForward; + } + + // Offset to be applied to all timings (except KYC expiry) + Offset public offset; + + // List of all addresses that have been added to the GTM at some point + address[] public investors; + + // An address can only send / receive tokens once their corresponding uint256 > block.number + // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) + mapping (address => TimeRestriction) public whitelist; + // Map of used nonces by customer + mapping(address => mapping(uint256 => bool)) public nonceMap; + + //If true, there are no transfer restrictions, for any addresses + bool public allowAllTransfers = false; + //If true, time lock is ignored for transfers (address must still be on whitelist) + bool public allowAllWhitelistTransfers = false; + //If true, time lock is ignored for issuances (address must still be on whitelist) + bool public allowAllWhitelistIssuances = true; + //If true, time lock is ignored for burn transactions + bool public allowAllBurnTransfers = false; + +} diff --git a/contracts/proxy/ERC20DividendCheckpointProxy.sol b/contracts/proxy/ERC20DividendCheckpointProxy.sol new file mode 100644 index 000000000..8839d30e1 --- /dev/null +++ b/contracts/proxy/ERC20DividendCheckpointProxy.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.4.24; + +import "../modules/Checkpoint/ERC20DividendCheckpointStorage.sol"; +import "../modules/Checkpoint/DividendCheckpointStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + +} diff --git a/contracts/proxy/EtherDividendCheckpointProxy.sol b/contracts/proxy/EtherDividendCheckpointProxy.sol new file mode 100644 index 000000000..40b1c1332 --- /dev/null +++ b/contracts/proxy/EtherDividendCheckpointProxy.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../modules/Checkpoint/DividendCheckpointStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract EtherDividendCheckpointProxy is DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + +} diff --git a/contracts/proxy/GeneralTransferManagerProxy.sol b/contracts/proxy/GeneralTransferManagerProxy.sol new file mode 100644 index 000000000..cb9b69070 --- /dev/null +++ b/contracts/proxy/GeneralTransferManagerProxy.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../modules/TransferManager/GeneralTransferManagerStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract GeneralTransferManagerProxy is GeneralTransferManagerStorage, ModuleStorage, Pausable, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + +} diff --git a/contracts/proxy/OwnedProxy.sol b/contracts/proxy/OwnedProxy.sol new file mode 100644 index 000000000..b75142fbe --- /dev/null +++ b/contracts/proxy/OwnedProxy.sol @@ -0,0 +1,91 @@ +pragma solidity ^0.4.18; + +import "./Proxy.sol"; + +/** + * @title OwnedProxy + * @dev This contract combines an upgradeability proxy with basic authorization control functionalities + */ +contract OwnedProxy is Proxy { + + // Owner of the contract + address private __owner; + + // Address of the current implementation + address internal __implementation; + + /** + * @dev Event to show ownership has been transferred + * @param _previousOwner representing the address of the previous owner + * @param _newOwner representing the address of the new owner + */ + event ProxyOwnershipTransferred(address _previousOwner, address _newOwner); + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier ifOwner() { + if (msg.sender == _owner()) { + _; + } else { + _fallback(); + } + } + + /** + * @dev the constructor sets the original owner of the contract to the sender account. + */ + constructor() public { + _setOwner(msg.sender); + } + + /** + * @dev Tells the address of the owner + * @return the address of the owner + */ + function _owner() internal view returns (address) { + return __owner; + } + + /** + * @dev Sets the address of the owner + */ + function _setOwner(address _newOwner) internal { + require(_newOwner != address(0), "Address should not be 0x"); + __owner = _newOwner; + } + + /** + * @notice Internal function to provide the address of the implementation contract + */ + function _implementation() internal view returns (address) { + return __implementation; + } + + /** + * @dev Tells the address of the proxy owner + * @return the address of the proxy owner + */ + function proxyOwner() external ifOwner returns (address) { + return _owner(); + } + + /** + * @dev Tells the address of the current implementation + * @return address of the current implementation + */ + function implementation() external ifOwner returns (address) { + return _implementation(); + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param _newOwner The address to transfer ownership to. + */ + function transferProxyOwnership(address _newOwner) external ifOwner { + require(_newOwner != address(0), "Address should not be 0x"); + emit ProxyOwnershipTransferred(_owner(), _newOwner); + _setOwner(_newOwner); + } + +} diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 694fdf03e..f25cfab35 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,9 +1,12 @@ const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') +const GeneralTransferManagerLogic = artifacts.require('./GeneralTransferManager.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') +const EtherDividendCheckpointLogic = artifacts.require('./EtherDividendCheckpoint.sol') +const ERC20DividendCheckpointLogic = artifacts.require('./ERC20DividendCheckpoint.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); @@ -145,10 +148,22 @@ module.exports = function (deployer, network, accounts) { moduleRegistry = ModuleRegistry.at(ModuleRegistryProxy.address); // Add module registry to polymath registry return polymathRegistry.changeAddress("ModuleRegistry", ModuleRegistryProxy.address, {from: PolymathAccount}); + }).then(() => { + // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(GeneralTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(ERC20DividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(EtherDividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); }).then(() => { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, GeneralTransferManagerLogic.address, {from: PolymathAccount}); }).then(() => { // C) Deploy the GeneralPermissionManagerFactory Contract (Factory used to generate the GeneralPermissionManager contract and // this manager attach with the securityToken contract at the time of deployment) @@ -164,11 +179,11 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // D) Deploy the EtherDividendCheckpointFactory Contract (Factory used to generate the EtherDividendCheckpoint contract use // to provide the functionality of the dividend in terms of ETH) - return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, EtherDividendCheckpointLogic.address, {from: PolymathAccount}); }).then(() => { // D) Deploy the ERC20DividendCheckpointFactory Contract (Factory used to generate the ERC20DividendCheckpoint contract use // to provide the functionality of the dividend in terms of ERC20 token) - return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, ERC20DividendCheckpointLogic.address, {from: PolymathAccount}); }).then(() => { // D) Deploy the ManualApprovalTransferManagerFactory Contract (Factory used to generate the ManualApprovalTransferManager contract use // to manual approve the transfer that will overcome the other transfer restrictions) @@ -303,6 +318,7 @@ module.exports = function (deployer, network, accounts) { POLYOracle: ${POLYOracle} STFactory: ${STFactory.address} + GeneralTransferManagerLogic: ${GeneralTransferManagerLogic.address} GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} @@ -313,6 +329,8 @@ module.exports = function (deployer, network, accounts) { CountTransferManagerFactory: ${CountTransferManagerFactory.address} PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} + EtherDividendCheckpointLogic: ${EtherDividendCheckpointLogic.address} + ERC20DividendCheckpointLogic: ${ERC20DividendCheckpointLogic.address} EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} --------------------------------------------------------------------------------- diff --git a/package.json b/package.json index ef2d76c38..58104d99b 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "ethers": "^3.0.15", "fs": "0.0.1-security", "openzeppelin-solidity": "1.10.0", + "prompt": "^1.0.0", "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", diff --git a/scripts/compareStorageLayout.js b/scripts/compareStorageLayout.js new file mode 100644 index 000000000..c339bf095 --- /dev/null +++ b/scripts/compareStorageLayout.js @@ -0,0 +1,139 @@ +const fs = require('fs'); +const _ = require('underscore'); +const solc = require('solc'); +const prompt = require('prompt'); +const path = require('path'); +const util = require('util'); +const exec = util.promisify(require('child_process').exec); + +prompt.start(); + +prompt.get(['LogicContract', 'ProxyContract'], async(err, result) => { + + let logicContract; + let proxyContract; + + const fileList = walkSync('./contracts', []); + + let paths = findPath(result.LogicContract, result.ProxyContract, fileList); + + if (paths.length == 2) { + + console.log("Contracts exists \n"); + + await flatContracts(paths); + + if (path.basename(paths[0]) === result.LogicContract) { + logicContract = fs.readFileSync(`./flat/${path.basename(paths[0])}`, 'utf8'); + } else { + logicContract = fs.readFileSync(`./flat/${path.basename(paths[1])}`, 'utf8'); + } + if (path.basename(paths[0]) === result.ProxyContract) { + proxyContract = fs.readFileSync(`./flat/${path.basename(paths[0])}`, 'utf8'); + } else { + proxyContract = fs.readFileSync(`./flat/${path.basename(paths[1])}`, 'utf8'); + } + + let logicInput = { + 'contracts': logicContract + } + let proxyInput = { + 'contracts': proxyContract + } + + console.log(compareStorageLayouts(parseContract(logicInput), parseContract(proxyInput))); + + } else { + console.log("Contracts doesn't exists"); + } +}); + +function traverseAST(_input, _elements) { + if(_input.children) { + for(var i=0;i<_input.children.length;i++) { + traverseAST(_input.children[i], _elements); + } + } + _elements.push(_input); +} + +function compareStorageLayouts(logicLayout, proxyLayout) { + function makeComp(x) { + return [x.constant, x.name, x.stateVariable, x.storageLocation, x.type, x.value, x.visibility].join(':'); + } + // if(newLayout.length < oldLayout.length) return false; + for(var i=0; i < logicLayout.length; i++) { + const a = logicLayout[i].attributes; + const comp1 = makeComp(a) + console.log(comp1); + const b = proxyLayout[i].attributes; + const comp2 = makeComp(b); + console.log(comp2); + if(comp1 != comp2) { + return false; + } + } + return true; +} + +function parseContract(input) { + + var output = solc.compile({ sources: input }, 1, _.noop); + const elements = []; + const AST = output.sources.contracts.AST; + // console.log(AST); + traverseAST(AST, elements); + // console.log(elements); + + // filter out all Contract Definitions + const contractDefinitions = _.filter(elements, (e,i) => e.name == 'ContractDefinition'); + + // filter out all linearizedBaseContracts + // pick the last one as the last contract always has the full inheritance + const linearizedBaseContracts = _.last(_.map(contractDefinitions, e => e.attributes.linearizedBaseContracts)); + + // get all stateVariables + const stateVariables = _.filter(elements, e => e.attributes && e.attributes.stateVariable ) + + // group them by scope + const stateVariableMap = _.groupBy(stateVariables, e => e.attributes.scope); + + orderedStateVariables = _.reduceRight(linearizedBaseContracts, (a, b) => { + return a.concat(stateVariableMap[b] || []) + }, []); + return orderedStateVariables; +} + +var walkSync = function(dir, filelist) { + files = fs.readdirSync(dir); + filelist = filelist || []; + files.forEach(function(file) { + if (fs.statSync(path.join(dir, file)).isDirectory()) { + filelist = walkSync(path.join(dir, file), filelist); + } + else { + filelist.push(path.join(dir, file)); + } + }); + return filelist; +}; + +var findPath = function(logicContractName, proxyContractName, fileList) { + let paths = new Array(); + for (let i =0; i < fileList.length; i++) { + if ((logicContractName === path.basename(fileList[i]) || logicContractName === (path.basename(fileList[i])).split(".")[0]) || + (proxyContractName === path.basename(fileList[i]) || proxyContractName === (path.basename(fileList[i])).split(".")[0])) { + paths.push(fileList[i]); + } + } + return paths; +} + +async function flatContracts(_paths, _logic) { + let promises = new Array(); + for (let i = 0; i< _paths.length; i++) { + promises.push(await exec(`./node_modules/.bin/sol-merger ${_paths[i]} ./flat`)); + } + await Promise.all(promises); +} + diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index fce1ee5e5..b1365ad3b 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -130,7 +130,7 @@ contract("CappedSTO", accounts => { // STEP 5: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - + // STEP 6: Deploy the CappedSTOFactory I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); @@ -360,7 +360,7 @@ contract("CappedSTO", accounts => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { from: account_issuer }); @@ -443,7 +443,7 @@ contract("CappedSTO", accounts => { fromTime, toTime + duration.days(20), expiryTime, - true, + 1, { from: account_issuer } @@ -565,7 +565,7 @@ contract("CappedSTO", accounts => { it("Should successfully whitelist investor 3", async () => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { from: account_issuer, gas: 500000 }); @@ -733,7 +733,7 @@ contract("CappedSTO", accounts => { "Tokens are not transfered properly" ); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, P_fromTime, P_toTime, P_expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, P_fromTime, P_toTime, P_expiryTime, 1, { from: account_issuer, gas: 500000 }); @@ -800,7 +800,7 @@ contract("CappedSTO", accounts => { P_fromTime, P_toTime + duration.days(20), P_expiryTime, - true, + 1, { from: account_issuer, gas: 500000 @@ -997,7 +997,7 @@ contract("CappedSTO", accounts => { await I_PolyToken.getTokens(polyToInvest * Math.pow(10, 18), account_investor3); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, 1, { from: account_issuer, gas: 500000 }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 6a08b6dea..2ba198f83 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -149,7 +149,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - false, + 0, { from: account_issuer, gas: 6000000 @@ -176,7 +176,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - false, + 0, { from: account_issuer, gas: 6000000 @@ -201,7 +201,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - false, + 0, { from: account_issuer, gas: 6000000 diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 1a1e7717a..4e86bdbb6 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -200,7 +200,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -230,7 +230,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -257,7 +257,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -282,7 +282,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index b832bcee2..6a4baeab6 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -89,7 +89,7 @@ contract("ERC20DividendCheckpoint", accounts => { account_investor4 = accounts[9]; account_temp = accounts[2]; account_manager = accounts[5]; - + // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -202,7 +202,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -232,7 +232,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -372,7 +372,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(20), - true, + 1, { from: account_issuer, gas: 500000 @@ -434,7 +434,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -970,7 +970,7 @@ contract("ERC20DividendCheckpoint", accounts => { let expiry = latestTime() + duration.days(10); let exclusions = [1]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); - await I_SecurityToken.createCheckpoint({ from: token_owner }); + await I_SecurityToken.createCheckpoint({ from: token_owner }); await catchRevert(I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index b4e5bbf2b..68c11f72f 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -200,7 +200,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -230,7 +230,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -364,7 +364,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(20), - true, + 1, { from: account_issuer, gas: 500000 @@ -415,7 +415,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -719,7 +719,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 500000 @@ -851,7 +851,7 @@ contract("EtherDividendCheckpoint", accounts => { let expiry = latestTime() + duration.days(10); let exclusions = [1]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); - await I_SecurityToken.createCheckpoint({ from: token_owner }); + await I_SecurityToken.createCheckpoint({ from: token_owner }); await catchRevert(I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 3e060c288..5dbcf5a6c 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -92,6 +92,7 @@ contract("GeneralTransferManager", accounts => { account_investor1 = accounts[8]; account_investor2 = accounts[9]; account_delegate = accounts[7]; + account_investor3 = accounts[5]; account_investor4 = accounts[6]; account_affiliates1 = accounts[3]; @@ -172,14 +173,14 @@ contract("GeneralTransferManager", accounts => { await catchRevert( I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}) ); - }) + }); it("Should attach the paid GTM", async() => { let snap_id = await takeSnapshot(); await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); await I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}); await revertToSnapshot(snap_id); - }) + }); it("Should whitelist the affiliates before the STO attached", async () => { let tx = await I_GeneralTransferManager.modifyWhitelistMulti( @@ -187,7 +188,7 @@ contract("GeneralTransferManager", accounts => { [latestTime() + duration.days(30), latestTime() + duration.days(30)], [latestTime() + duration.days(90), latestTime() + duration.days(90)], [latestTime() + duration.years(1), latestTime() + duration.years(1)], - [false, false], + [0, 0], { from: account_issuer, gas: 6000000 @@ -195,6 +196,30 @@ contract("GeneralTransferManager", accounts => { ); assert.equal(tx.logs[0].args._investor, account_affiliates1); assert.equal(tx.logs[1].args._investor, account_affiliates2); + assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2]); + }); + + it("Should whitelist lots of addresses and check gas", async () => { + let mockInvestors = []; + for (let i = 0; i < 50; i++) { + mockInvestors.push("0x1000000000000000000000000000000000000000".substring(0,42-i.toString().length) + i.toString()); + } + + let times = range1(50); + let bools = rangeB(50); + let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + mockInvestors, + times, + times, + times, + bools, + { + from: account_issuer, + gas: 7900000 + } + ); + console.log("Multi Whitelist x 50: " + tx.receipt.gasUsed); + assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2].concat(mockInvestors)); }); it("Should mint the tokens to the affiliates", async () => { @@ -291,7 +316,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -320,7 +345,7 @@ contract("GeneralTransferManager", accounts => { it("Should fail in buying the tokens from the STO -- because amount is 0", async() => { await catchRevert( I_DummySTO.generateTokens(account_investor1, 0, { from: token_owner }) - ); + ); }); it("Should fail in buying the tokens from the STO -- because STO is paused", async() => { @@ -342,6 +367,106 @@ contract("GeneralTransferManager", accounts => { }); }); + describe("Buy tokens using on-chain whitelist and negative offset", async () => { + // let snap_id; + + it("Should Buy the tokens", async () => { + // Add the Investor in to the whitelist + // snap_id = await takeSnapshot(); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime() + duration.days(10), + latestTime() + duration.days(10), + latestTime() + duration.days(20), + 1, + { + from: account_issuer, + gas: 6000000 + } + ); + + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor1.toLowerCase(), + "Failed in adding the investor in whitelist" + ); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + + await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("3", "ether")); + }); + + it("Add an offset and check transfers are disabled", async () => { + let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 0, {from: token_owner}); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("3", "ether")); + tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); + // await revertToSnapshot(snap_id); + }); + + }); + + + describe("Buy tokens using on-chain whitelist and positive offset", async () => { + // let snap_id; + + it("Should Buy the tokens", async () => { + + // Add the Investor in to the whitelist + // snap_id = await takeSnapshot(); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(20), + 1, + { + from: account_issuer, + gas: 6000000 + } + ); + + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor1.toLowerCase(), + "Failed in adding the investor in whitelist" + ); + + // Jump time + await increaseTime(5000); + // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); + // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); + + // Mint some tokens + console.log(await I_GeneralTransferManager.offset.call()); + await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + }); + + it("Add an offset and check transfers are disabled", async () => { + let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 1, {from: token_owner}); + // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); + // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); + + await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); + await increaseTime(duration.days(10)); + // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); + // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); + + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); + // await revertToSnapshot(snap_id); + }); + + }); + describe("Buy tokens using off-chain whitelist", async () => { it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { await catchRevert(I_DummySTO.generateTokens(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner })); @@ -359,7 +484,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -376,7 +501,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -403,7 +528,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -420,7 +545,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -447,7 +572,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -464,7 +589,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - true, + 1, validFrom, validTo, nonce, @@ -491,7 +616,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - true, + 1, validFrom, validTo, nonce, @@ -507,7 +632,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - true, + 1, validFrom, validTo, nonce, @@ -547,7 +672,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - true, + 1, validFrom, validTo, nonce, @@ -563,7 +688,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - true, + 1, validFrom, validTo, nonce, @@ -670,7 +795,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [true, true], + [1, 1], { from: account_delegate, gas: 6000000 @@ -690,7 +815,7 @@ contract("GeneralTransferManager", accounts => { [fromTime], [toTime, toTime], [expiryTime, expiryTime], - [true, true], + [1, 1], { from: account_delegate, gas: 6000000 @@ -710,7 +835,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime], [expiryTime, expiryTime], - [true, true], + [1, 1], { from: account_delegate, gas: 6000000 @@ -730,7 +855,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime], - [true, true], + [1, 1], { from: account_delegate, gas: 6000000 @@ -749,7 +874,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [true, true], + [1, 1], { from: token_owner, gas: 6000000 @@ -836,3 +961,6 @@ contract("GeneralTransferManager", accounts => { }) }); }); + +function range1(i) {return i?range1(i-1).concat(i):[]} +function rangeB(i) {return i?rangeB(i-1).concat(0):[]} diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 2021d350e..a6118741f 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -8,6 +8,8 @@ const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); +const ERC20DividendCheckpoint = artifacts.require("./ERC20DividendCheckpoint.sol"); +const EtherDividendCheckpoint = artifacts.require("./EtherDividendCheckpoint.sol"); const ERC20DividendCheckpointFactory = artifacts.require("./ERC20DividendCheckpointFactory.sol"); const EtherDividendCheckpointFactory = artifacts.require("./EtherDividendCheckpointFactory.sol"); const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); @@ -20,6 +22,7 @@ const USDTieredSTOProxyFactory = artifacts.require("./USDTieredSTOProxyFactory") const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); const FeatureRegistry = artifacts.require("./FeatureRegistry.sol"); const STFactory = artifacts.require("./STFactory.sol"); +const GeneralTransferManager = artifacts.require("./GeneralTransferManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); @@ -45,10 +48,13 @@ let I_SingleTradeVolumeRestrictionManagerFactory; let I_ManualApprovalTransferManagerFactory; let I_VolumeRestrictionTransferManagerFactory; let I_PercentageTransferManagerFactory; +let I_EtherDividendCheckpointLogic; let I_EtherDividendCheckpointFactory; let I_CountTransferManagerFactory; +let I_ERC20DividendCheckpointLogic; let I_ERC20DividendCheckpointFactory; let I_GeneralPermissionManagerFactory; +let I_GeneralTransferManagerLogic; let I_GeneralTransferManagerFactory; let I_GeneralTransferManager; let I_ModuleRegistryProxy; @@ -82,7 +88,9 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { let b = await deployFeatureRegistry(account_polymath); // STEP 3: Deploy the ModuleRegistry let c = await deployModuleRegistry(account_polymath); - // STEP 4: Deploy the GeneralTransferManagerFactory + // STEP 4a: Deploy the GeneralTransferManagerFactory + let logic = await deployGTMLogic(account_polymath); + // STEP 4b: Deploy the GeneralTransferManagerFactory let d = await deployGTM(account_polymath); // Step 6: Deploy the STversionProxy contract let e = await deploySTFactory(account_polymath); @@ -127,8 +135,20 @@ async function deployModuleRegistry(account_polymath) { return new Array(I_ModuleRegistry, I_ModuleRegistryProxy, I_MRProxied); } +async function deployGTMLogic(account_polymath) { + I_GeneralTransferManagerLogic = await GeneralTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + + assert.notEqual( + I_GeneralTransferManagerLogic.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerLogic contract was not deployed" + ); + + return new Array(I_GeneralTransferManagerLogic); +} + async function deployGTM(account_polymath) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); assert.notEqual( I_GeneralTransferManagerFactory.address.valueOf(), @@ -193,7 +213,7 @@ async function registerAndVerifyByMR(factoryAdrress, owner, mr) { /// Deploy the TransferManagers export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(polyToken, setupCost, 0, 0, I_GeneralTransferManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), @@ -355,7 +375,8 @@ export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInst /// Deploy the Dividend Modules export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_ERC20DividendCheckpointLogic = await ERC20DividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(polyToken, setupCost, 0, 0, I_ERC20DividendCheckpointLogic.address, { from: accountPolymath }); assert.notEqual( I_ERC20DividendCheckpointFactory.address.valueOf(), @@ -367,7 +388,8 @@ export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyIns } export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_EtherDividendCheckpointLogic = await EtherDividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(polyToken, setupCost, 0, 0, I_EtherDividendCheckpointLogic.address, { from: accountPolymath }); assert.notEqual( I_EtherDividendCheckpointFactory.address.valueOf(), diff --git a/test/helpers/signData.js b/test/helpers/signData.js index ea7476cc3..2e5c1ad61 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -6,7 +6,7 @@ const ethUtil = require("ethereumjs-util"); function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce, pk) { let packedData = utils .solidityKeccak256( - ["address", "address", "uint256", "uint256", "uint256", "bool", "uint256", "uint256", "uint256"], + ["address", "address", "uint64", "uint64", "uint64", "uint8", "uint64", "uint64", "uint256"], [tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce] ) .slice(2); diff --git a/test/i_Issuance.js b/test/i_Issuance.js index ac1fcdd37..efcf0db96 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -215,7 +215,7 @@ contract("Issuance", accounts => { fromTime + duration.days(70), toTime + duration.days(90), expiryTime + duration.days(50), - true, + 1, { from: account_polymath } @@ -271,7 +271,7 @@ contract("Issuance", accounts => { }); it("should add the investor into the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { from: account_delegate, gas: 7000000 }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 0461f287a..c817f5c44 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -171,7 +171,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -201,7 +201,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -290,7 +290,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index b15ee41a0..530b202c8 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -120,7 +120,7 @@ contract("PercentageTransferManager", accounts => { // STEP 4(b): Deploy the PercentageTransferManager [P_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); - + // Printing all the contract addresses console.log(` --------------------- Polymath Network Smart Contracts: --------------------- @@ -192,7 +192,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -222,7 +222,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -287,7 +287,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index a89932dc4..35a348c30 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -236,7 +236,7 @@ contract("PreSaleSTO", accounts => { expiryTime = toTime + duration.days(100); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { from: account_issuer, gas: 6000000 }); @@ -277,7 +277,7 @@ contract("PreSaleSTO", accounts => { expiryTime = toTime + duration.days(100); // Add the Investor in to the whitelist - let tx1 = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { + let tx1 = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { from: account_issuer, gas: 6000000 }); @@ -285,7 +285,7 @@ contract("PreSaleSTO", accounts => { assert.equal(tx1.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); // Add the Investor in to the whitelist - let tx2 = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { + let tx2 = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { from: account_issuer, gas: 6000000 }); diff --git a/test/o_security_token.js b/test/o_security_token.js index 52521181e..7d2722a20 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -193,7 +193,7 @@ contract("SecurityToken", accounts => { let toTime = fromTime + duration.days(100); let expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 6000000 }); @@ -212,7 +212,7 @@ contract("SecurityToken", accounts => { let toTime = fromTime + duration.days(100); let expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 6000000 }); @@ -517,7 +517,7 @@ contract("SecurityToken", accounts => { toTime = fromTime + duration.days(100); expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 6000000 }); @@ -614,7 +614,7 @@ contract("SecurityToken", accounts => { }); it("Should transfer from whitelist investor1 to whitelist investor 2", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 500000 }); @@ -636,7 +636,7 @@ contract("SecurityToken", accounts => { it("Should transferFrom from one investor to other", async () => { await I_SecurityToken.approve(account_investor1, 2 * Math.pow(10, 18), { from: account_investor2 }); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { from: token_owner, gas: 500000 }); @@ -682,7 +682,7 @@ contract("SecurityToken", accounts => { }); it("Should add the investor in the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, 1, { from: account_delegate, gas: 6000000 }); @@ -722,7 +722,7 @@ contract("SecurityToken", accounts => { }); it("Should remove investor from the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, 0, 0, 0, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, 0, 0, 0, 1, { from: account_delegate, gas: 6000000 }); @@ -751,7 +751,7 @@ contract("SecurityToken", accounts => { }); it("Should fail in buying to tokens", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, 1, { from: account_delegate, gas: 6000000 }); @@ -939,7 +939,7 @@ contract("SecurityToken", accounts => { latestTime(), latestTime() + duration.seconds(2), latestTime() + duration.days(50), - true, + 1, { from: account_delegate, gas: 6000000 @@ -982,7 +982,7 @@ contract("SecurityToken", accounts => { latestTime(), latestTime() + duration.seconds(2), latestTime() + duration.days(50), - true, + 1, { from: account_delegate, gas: 6000000 diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 604eb1aaf..8a274942a 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -222,7 +222,7 @@ contract("USDTieredSTO", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 4: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, I_PolyToken.address, 0); @@ -1005,7 +1005,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1105,7 +1105,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1160,7 +1160,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1230,7 +1230,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1285,7 +1285,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime(); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1353,7 +1353,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = true; + let whitelisted = 1; const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER @@ -4482,7 +4482,7 @@ contract("USDTieredSTO", accounts => { "fundsRaisedUSD not changed as expected" ); }); - + it("should return minted tokens in a tier", async () => { let totalMinted = (await I_USDTieredSTO_Array[0].getTokensSoldByTier.call(0)).toNumber(); let individualMinted = await I_USDTieredSTO_Array[0].getTokensMintedByTier.call(0); @@ -4564,7 +4564,7 @@ contract("USDTieredSTO", accounts => { assert.equal((await I_USDTieredSTOFactory.getSetupCost.call()).toNumber(), STOSetupCost); assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0], 3); assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), "USDTieredSTO", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.description.call(), + assert.equal(await I_USDTieredSTOFactory.description.call(), "It allows both accredited and non-accredited investors to contribute into the STO. Non-accredited investors will be capped at a maximum investment limit (as a default or specific to their jurisdiction). Tokens will be sold according to tiers sequentially & each tier has its own price and volume of tokens to sell. Upon receipt of funds (ETH, POLY or DAI), security tokens will automatically transfer to investor’s wallet address", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.title.call(), "USD Tiered STO", "Wrong Module added"); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 55f84f2b3..31929ade5 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -195,7 +195,7 @@ contract("USDTieredSTO Sim", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 5: Deploy the USDTieredSTOFactory @@ -353,13 +353,13 @@ contract("USDTieredSTO Sim", accounts => { let fromTime = latestTime() + duration.days(15); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = true; + let canBuyFromSTO = 1; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, 0, { from: ISSUER }); await increaseTime(duration.days(3)); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 7912658a4..36761308e 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -2,7 +2,7 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import { takeSnapshot, increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; -import { +import { setUpPolymathNetwork, deployDummySTOAndVerifyed, deployCappedSTOAndVerifyed, @@ -94,7 +94,7 @@ contract("Concurrent STO", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + // STEP 2: Deploy the STO Factories [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, STOSetupCost); @@ -159,7 +159,7 @@ contract("Concurrent STO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = true; + let canBuyFromSTO = 1; let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: account_issuer, diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 6d00b8fe2..877d173d4 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -9,6 +9,7 @@ const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); const ModuleRegistry = artifacts.require("./ModuleRegistry.sol"); const STFactory = artifacts.require("./STFactory.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); +const GeneralTransferManagerLogic = artifacts.require("./GeneralTransferManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); @@ -122,7 +123,9 @@ contract("ModuleRegistryProxy", accounts => { await I_MRProxied.updateFromRegistry({ from: account_polymath }); // STEP 4: Deploy the GeneralTransferManagerFactory - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { + let I_GeneralTransferManagerLogic = await GeneralTransferManagerLogic.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 159564651..eacddd87e 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -102,7 +102,7 @@ contract("TrackedRedemption", accounts => { I_STRProxied ] = instances; - + // STEP 4: Deploy the TrackedRedemption [I_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); [P_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); @@ -190,7 +190,7 @@ contract("TrackedRedemption", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 @@ -220,7 +220,7 @@ contract("TrackedRedemption", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - true, + 1, { from: account_issuer, gas: 500000 diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index fe06f3f5c..7646fb031 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -112,7 +112,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { STFactory: ${I_STFactory.address} GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} - LockupVolumeRestrictionTransferManagerFactory: + LockupVolumeRestrictionTransferManagerFactory: ${I_VolumeRestrictionTransferManagerFactory.address} ----------------------------------------------------------------------------- `); @@ -165,7 +165,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer }); @@ -192,7 +192,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer }); @@ -249,7 +249,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer }); @@ -346,14 +346,14 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // balance should be 9000000000000000000 here (9 eth) let balance = await I_SecurityToken.balanceOf(account_investor2) - + // create a lockup for their entire balance // over 16 seconds total, with 4 periods of 4 seconds each. // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 await catchRevert( I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }) ); - + }); it("Should prevent the transfer of tokens in a lockup", async() => { @@ -572,7 +572,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); it("Should revert if the parameters are bad when creating multiple lockups", async() => { - + await catchRevert( // pass in the wrong number of params. txn should revert I_VolumeRestrictionTransferManager.addLockUpMulti( diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index 15c01e68c..25243a638 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -107,7 +107,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); - + }); describe("Generate the SecurityToken", async () => { @@ -165,7 +165,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer }); @@ -193,7 +193,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer }); @@ -212,7 +212,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { // it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { let managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); await catchRevert( I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { from: token_owner}) @@ -222,7 +222,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); - + let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); @@ -291,7 +291,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]) ); - await catchRevert( + await catchRevert( I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { from: token_owner }) ); @@ -342,7 +342,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { await catchRevert ( I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { from: token_owner }) ); - // Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage + // Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage await catchRevert ( I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { from: token_owner }) ); @@ -393,7 +393,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { from: token_owner }); assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - + //Global limit can be set by non-admins await catchRevert( I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89) @@ -542,7 +542,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer } ); @@ -552,7 +552,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer } ); @@ -562,7 +562,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, { + 1, { from: account_issuer } ); @@ -667,7 +667,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { }); it('should change transfer limits to tokens', async () => { - // Should not change to percentage again + // Should not change to percentage again await catchRevert( I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { from: token_owner }) ); diff --git a/test/y_scheduled_checkpoints.js b/test/y_scheduled_checkpoints.js index 5fcc03a74..864c6b9a1 100644 --- a/test/y_scheduled_checkpoints.js +++ b/test/y_scheduled_checkpoints.js @@ -192,7 +192,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -235,7 +235,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 @@ -270,7 +270,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - true, + 1, { from: account_issuer, gas: 6000000 diff --git a/yarn.lock b/yarn.lock index 27308427c..31973936e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,12 +5,10 @@ "@soldoc/markdown@^0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@soldoc/markdown/-/markdown-0.1.0.tgz#9f85be75049af9721b5129f133d52dafbf5f671e" - integrity sha512-V0UnvVVJ1qDzpuKLMuh7oHG94puwi8BI3t99Vrr7dQgIHuJdfZJ4SbGuWuFV/fSthyH++WY4ePO3d6gxfZ2//w== "@soldoc/soldoc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@soldoc/soldoc/-/soldoc-0.4.3.tgz#24ffee9264228e1c3edd61fd3162d63587954933" - integrity sha1-JP/ukmQijhw+3WH9MWLWNYeVSTM= dependencies: "@soldoc/markdown" "^0.1.0" chalk "^2.3.1" @@ -24,31 +22,26 @@ abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= abstract-leveldown@~2.6.0: version "2.6.3" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== dependencies: xtend "~4.0.0" abstract-leveldown@~2.7.1: version "2.7.2" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== dependencies: xtend "~4.0.0" accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= dependencies: mime-types "~2.1.18" negotiator "0.6.1" @@ -56,56 +49,46 @@ accepts@~1.3.5: acorn-dynamic-import@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" - integrity sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ= dependencies: acorn "^4.0.3" acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= dependencies: acorn "^3.0.4" acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= acorn@^5.0.0, acorn@^5.5.0: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= aes-js@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072" - integrity sha512-cEA0gBelItZZV7iBiL8ApCiNgc+gBWJJ4uoORhbu6vOqAJ0UL9wIlxr4RI7ij9SSVzy6AnPwiu37kVYiHCl3nw== ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" - integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= ajv@^5.1.1, ajv@^5.2.2, ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" @@ -115,7 +98,6 @@ ajv@^5.1.1, ajv@^5.2.2, ajv@^5.2.3, ajv@^5.3.0: ajv@^6.1.0: version "6.5.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59" - integrity sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -125,7 +107,6 @@ ajv@^6.1.0: align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= dependencies: kind-of "^3.0.2" longest "^1.0.1" @@ -134,7 +115,6 @@ align-text@^0.1.1, align-text@^0.1.3: ambi@^2.2.0: version "2.5.0" resolved "https://registry.yarnpkg.com/ambi/-/ambi-2.5.0.tgz#7c8e372be48891157e7cea01cb6f9143d1f74220" - integrity sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA= dependencies: editions "^1.1.1" typechecker "^4.3.0" @@ -142,44 +122,36 @@ ambi@^2.2.0: amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= ansi-escapes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" - integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== dependencies: micromatch "^2.1.5" normalize-path "^2.0.0" @@ -187,7 +159,6 @@ anymatch@^1.3.0: anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" normalize-path "^2.1.1" @@ -195,12 +166,10 @@ anymatch@^2.0.0: aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -208,85 +177,56 @@ are-we-there-yet@~1.1.2: argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -arguments-extended@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/arguments-extended/-/arguments-extended-0.0.3.tgz#6107e4917d0eb6f0a4dd66320fc15afc72ef4946" - integrity sha1-YQfkkX0OtvCk3WYyD8Fa/HLvSUY= - dependencies: - extended "~0.0.3" - is-extended "~0.0.8" - arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= dependencies: arr-flatten "^1.0.1" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-extended@~0.0.3, array-extended@~0.0.4, array-extended@~0.0.5: - version "0.0.11" - resolved "https://registry.yarnpkg.com/array-extended/-/array-extended-0.0.11.tgz#d7144ae748de93ca726f121009dbff1626d164bd" - integrity sha1-1xRK50jek8pybxIQCdv/FibRZL0= - dependencies: - arguments-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= dependencies: array-uniq "^1.0.1" array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -295,36 +235,30 @@ asn1.js@^4.0.0: asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assert@^1.1.1: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= dependencies: util "0.10.3" assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-eventemitter@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== dependencies: async "^2.4.0" @@ -337,49 +271,44 @@ async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== async@1.x, async@^1.4.2, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.4.1, async@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== dependencies: lodash "^4.17.10" +async@~0.9.0: + version "0.9.2" + resolved "http://registry.npmjs.org/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + async@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" - integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -388,7 +317,6 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: babel-core@^6.0.14, babel-core@^6.26.0: version "6.26.3" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== dependencies: babel-code-frame "^6.26.0" babel-generator "^6.26.0" @@ -413,7 +341,6 @@ babel-core@^6.0.14, babel-core@^6.26.0: babel-generator@^6.26.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" @@ -427,7 +354,6 @@ babel-generator@^6.26.0: babel-helper-bindify-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" - integrity sha1-FMGeXxQte0fxmlJDHlKxzLxAozA= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -436,7 +362,6 @@ babel-helper-bindify-decorators@^6.24.1: babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= dependencies: babel-helper-explode-assignable-expression "^6.24.1" babel-runtime "^6.22.0" @@ -445,7 +370,6 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -455,7 +379,6 @@ babel-helper-call-delegate@^6.24.1: babel-helper-define-map@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.26.0" @@ -465,7 +388,6 @@ babel-helper-define-map@^6.24.1: babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -474,7 +396,6 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-helper-explode-class@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" - integrity sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes= dependencies: babel-helper-bindify-decorators "^6.24.1" babel-runtime "^6.22.0" @@ -484,7 +405,6 @@ babel-helper-explode-class@^6.24.1: babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= dependencies: babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" @@ -495,7 +415,6 @@ babel-helper-function-name@^6.24.1: babel-helper-get-function-arity@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -503,7 +422,6 @@ babel-helper-get-function-arity@^6.24.1: babel-helper-hoist-variables@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -511,7 +429,6 @@ babel-helper-hoist-variables@^6.24.1: babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -519,7 +436,6 @@ babel-helper-optimise-call-expression@^6.24.1: babel-helper-regex@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= dependencies: babel-runtime "^6.26.0" babel-types "^6.26.0" @@ -528,7 +444,6 @@ babel-helper-regex@^6.24.1: babel-helper-remap-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -539,7 +454,6 @@ babel-helper-remap-async-to-generator@^6.24.1: babel-helper-replace-supers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= dependencies: babel-helper-optimise-call-expression "^6.24.1" babel-messages "^6.23.0" @@ -551,7 +465,6 @@ babel-helper-replace-supers@^6.24.1: babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -559,61 +472,50 @@ babel-helpers@^6.24.1: babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= dependencies: babel-runtime "^6.22.0" babel-plugin-check-es2015-constants@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= dependencies: babel-runtime "^6.22.0" babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= babel-plugin-syntax-async-generators@^6.5.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - integrity sha1-a8lj67FuzLrmuStZbrfzXDQqi5o= babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= babel-plugin-syntax-decorators@^6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" - integrity sha1-MSVjtNvePMgGzuPkFszurd0RrAs= babel-plugin-syntax-dynamic-import@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" - integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= babel-plugin-transform-async-generator-functions@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" - integrity sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-generators "^6.5.0" @@ -622,7 +524,6 @@ babel-plugin-transform-async-generator-functions@^6.24.1: babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-functions "^6.8.0" @@ -631,7 +532,6 @@ babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async- babel-plugin-transform-class-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= dependencies: babel-helper-function-name "^6.24.1" babel-plugin-syntax-class-properties "^6.8.0" @@ -641,7 +541,6 @@ babel-plugin-transform-class-properties@^6.24.1: babel-plugin-transform-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" - integrity sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0= dependencies: babel-helper-explode-class "^6.24.1" babel-plugin-syntax-decorators "^6.13.0" @@ -652,21 +551,18 @@ babel-plugin-transform-decorators@^6.24.1: babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= dependencies: babel-runtime "^6.26.0" babel-template "^6.26.0" @@ -677,7 +573,6 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= dependencies: babel-helper-define-map "^6.24.1" babel-helper-function-name "^6.24.1" @@ -692,7 +587,6 @@ babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-cla babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -700,14 +594,12 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transfor babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -715,14 +607,12 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2 babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -731,14 +621,12 @@ babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= dependencies: babel-plugin-transform-es2015-modules-commonjs "^6.24.1" babel-runtime "^6.22.0" @@ -747,7 +635,6 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.26.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== dependencies: babel-plugin-transform-strict-mode "^6.24.1" babel-runtime "^6.26.0" @@ -757,7 +644,6 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -766,7 +652,6 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= dependencies: babel-plugin-transform-es2015-modules-amd "^6.24.1" babel-runtime "^6.22.0" @@ -775,7 +660,6 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= dependencies: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" @@ -783,7 +667,6 @@ babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= dependencies: babel-helper-call-delegate "^6.24.1" babel-helper-get-function-arity "^6.24.1" @@ -795,7 +678,6 @@ babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015- babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -803,14 +685,12 @@ babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transfo babel-plugin-transform-es2015-spread@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -819,21 +699,18 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -842,7 +719,6 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= dependencies: babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" babel-plugin-syntax-exponentiation-operator "^6.8.0" @@ -851,7 +727,6 @@ babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-e babel-plugin-transform-object-rest-spread@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" @@ -859,14 +734,12 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= dependencies: regenerator-transform "^0.10.0" babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -874,7 +747,6 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-polyfill@6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= dependencies: babel-runtime "^6.26.0" core-js "^2.5.0" @@ -883,7 +755,6 @@ babel-polyfill@6.26.0: babel-preset-env@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -919,7 +790,6 @@ babel-preset-env@^1.7.0: babel-preset-es2015@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - integrity sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk= dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-transform-es2015-arrow-functions "^6.22.0" @@ -949,7 +819,6 @@ babel-preset-es2015@6.24.1: babel-preset-stage-2@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" - integrity sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE= dependencies: babel-plugin-syntax-dynamic-import "^6.18.0" babel-plugin-transform-class-properties "^6.24.1" @@ -959,7 +828,6 @@ babel-preset-stage-2@6.24.1: babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" - integrity sha1-g2raCp56f6N8sTj7kyb4eTSkg5U= dependencies: babel-plugin-syntax-trailing-function-commas "^6.22.0" babel-plugin-transform-async-generator-functions "^6.24.1" @@ -970,7 +838,6 @@ babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: babel-register@6.26.0, babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= dependencies: babel-core "^6.26.0" babel-runtime "^6.26.0" @@ -983,7 +850,6 @@ babel-register@6.26.0, babel-register@^6.26.0: babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" @@ -991,7 +857,6 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= dependencies: babel-runtime "^6.26.0" babel-traverse "^6.26.0" @@ -1002,7 +867,6 @@ babel-template@^6.24.1, babel-template@^6.26.0: babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= dependencies: babel-code-frame "^6.26.0" babel-messages "^6.23.0" @@ -1017,7 +881,6 @@ babel-traverse@^6.24.1, babel-traverse@^6.26.0: babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= dependencies: babel-runtime "^6.26.0" esutils "^2.0.2" @@ -1027,7 +890,6 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: babelify@^7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= dependencies: babel-core "^6.0.14" object-assign "^4.0.0" @@ -1035,34 +897,28 @@ babelify@^7.3.0: babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base-x@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" - integrity sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA== dependencies: safe-buffer "^5.0.1" base64-js@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" - integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg= base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -1075,29 +931,24 @@ base@^0.11.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== bignumber.js@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" - integrity sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA== bignumber.js@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" - integrity sha512-KWTu6ZMVk9sxlDJQh2YH1UOnfDP8O8TpxUxgQG/vKASoSnEjK9aVuOueFaPcQEYQ5fyNXNTOYwYw3099RYebWg== bignumber.js@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-6.0.0.tgz#bbfa047644609a5af093e9cbd83b0461fa3f6002" - integrity sha512-x247jIuy60/+FtMRvscqfxtVHQf8AGx2hm9c6btkgC0x/hp9yt+teISNhvF8WlwRkCc5yF2fDECH8SIMe8j+GA== "bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" @@ -1114,24 +965,20 @@ bignumber.js@^6.0.0: binary-extensions@^1.0.0: version "1.12.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" - integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== bindings@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" - integrity sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw== bip66@^1.1.3: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" - integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= dependencies: safe-buffer "^5.0.1" bitcore-lib@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.15.0.tgz#f924be13869f2aab7e04aeec5642ad3359b6cec2" - integrity sha512-AeXLWhiivF6CDFzrABZHT4jJrflyylDWTi32o30rF92HW9msfuKpjzrHtFKYGa9w0kNVv5HABQjCB3OEav4PhQ== dependencies: bn.js "=4.11.8" bs58 "=4.0.1" @@ -1143,7 +990,6 @@ bitcore-lib@^0.15.0: bitcore-mnemonic@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-1.5.0.tgz#c7e785beb6bf0616ed4992785dc3658670425a39" - integrity sha512-sbeP4xwkindLMfIQhVxj6rZSDMwtiKmfc1DqvwpR6Yg+Qo4I4WHO5pvzb12Y04uDh1N3zgD45esHhfH0HHmE4g== dependencies: bitcore-lib "^0.15.0" unorm "^1.3.3" @@ -1151,7 +997,6 @@ bitcore-mnemonic@^1.5.0: bl@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== dependencies: readable-stream "^2.3.5" safe-buffer "^5.1.1" @@ -1159,39 +1004,32 @@ bl@^1.0.0: block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= dependencies: inherits "~2.0.0" bluebird@^2.9.34: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= bluebird@^3.4.6, bluebird@^3.5.0: version "3.5.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" - integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg== bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= bn.js@=4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== bn.js@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625" - integrity sha1-EhYrwq5x/EClYmwzQ486h1zTdiU= body-parser@1.18.3, body-parser@^1.16.0: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" - integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= dependencies: bytes "3.0.0" content-type "~1.0.4" @@ -1207,7 +1045,6 @@ body-parser@1.18.3, body-parser@^1.16.0: borc@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/borc/-/borc-2.0.3.tgz#08845ea73a6d3211120928ee3929f8dc2de9f52e" - integrity sha512-2mfipKUXn7yLgwn8D5jZkJqd2ZyzqmYZQX/9d4On33oGNDLwxj5qQMst+nkKyEdaujQRFfrZCId+k8wehQVANg== dependencies: bignumber.js "^6.0.0" commander "^2.15.0" @@ -1217,7 +1054,6 @@ borc@^2.0.2: brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1225,7 +1061,6 @@ brace-expansion@^1.1.7: braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= dependencies: expand-range "^1.8.1" preserve "^0.2.0" @@ -1234,7 +1069,6 @@ braces@^1.8.2: braces@^2.3.0, braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -1250,22 +1084,18 @@ braces@^2.3.0, braces@^2.3.1: brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1277,7 +1107,6 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: browserify-cipher@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -1286,7 +1115,6 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -1296,7 +1124,6 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= dependencies: bn.js "^4.1.0" randombytes "^2.0.1" @@ -1304,14 +1131,12 @@ browserify-rsa@^4.0.0: browserify-sha3@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" - integrity sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE= dependencies: js-sha3 "^0.3.1" browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= dependencies: bn.js "^4.1.1" browserify-rsa "^4.0.0" @@ -1324,14 +1149,12 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" browserslist@^3.2.6: version "3.2.8" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== dependencies: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" @@ -1339,19 +1162,16 @@ browserslist@^3.2.6: bs58@=4.0.1, bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= dependencies: base-x "^3.0.2" bs58@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" - integrity sha1-VZCNWPGYKrogCPob7Y+RmYopv40= bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== dependencies: bs58 "^4.0.0" create-hash "^1.1.0" @@ -1360,17 +1180,14 @@ bs58check@^2.1.2: bson@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.0.tgz#bee57d1fb6a87713471af4e32bcae36de814b5b0" - integrity sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA== buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== buffer-alloc@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== dependencies: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" @@ -1378,37 +1195,30 @@ buffer-alloc@^1.2.0: buffer-compare@=1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.1.1.tgz#5be7be853af89198d1f4ddc090d1d66a48aef596" - integrity sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY= buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-to-arraybuffer@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^3.0.1: version "3.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" - integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs= dependencies: base64-js "0.0.8" ieee754 "^1.1.4" @@ -1417,7 +1227,6 @@ buffer@^3.0.1: buffer@^4.3.0, buffer@^4.9.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1426,7 +1235,6 @@ buffer@^4.3.0, buffer@^4.9.0: buffer@^5.0.5: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" - integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1434,22 +1242,18 @@ buffer@^5.0.5: builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -1464,34 +1268,28 @@ cache-base@^1.0.1: caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= dependencies: callsites "^0.2.0" callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= caminte@0.3.7: version "0.3.7" resolved "https://registry.yarnpkg.com/caminte/-/caminte-0.3.7.tgz#ec1ec0457664a0f092643b7c646c457d5cd6f693" - integrity sha1-7B7ARXZkoPCSZDt8ZGxFfVzW9pM= dependencies: bluebird "^3.4.6" uuid "^3.0.1" @@ -1499,17 +1297,14 @@ caminte@0.3.7: caniuse-lite@^1.0.30000844: version "1.0.30000890" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000890.tgz#86a18ffcc65d79ec6a437e985761b8bf1c4efeaf" - integrity sha512-4NI3s4Y6ROm+SgZN5sLUG4k7nVWQnedis3c/RWkynV5G6cHSY7+a8fwFyn2yoBDE3E6VswhTNNwR3PvzGqlTkg== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= center-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= dependencies: align-text "^0.1.3" lazy-cache "^1.0.3" @@ -1517,7 +1312,6 @@ center-align@^0.1.1: chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -1528,7 +1322,6 @@ chalk@^1.1.3: chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1537,19 +1330,16 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= checkpoint-store@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= dependencies: functional-red-black-tree "^1.0.1" chokidar@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= dependencies: anymatch "^1.3.0" async-each "^1.0.0" @@ -1565,7 +1355,6 @@ chokidar@^1.6.0: chokidar@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" - integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== dependencies: anymatch "^2.0.0" async-each "^1.0.0" @@ -1585,12 +1374,10 @@ chokidar@^2.0.2: chownr@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -1598,12 +1385,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" @@ -1613,7 +1398,6 @@ class-utils@^0.3.5: cli-color@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.3.0.tgz#cd2ec212efbd1a0eeb5b017f17d4e2d15e91420f" - integrity sha512-XmbLr8MzgOup/sPHF4nOZerCOcL7rD7vKWpEl0axUsMAY+AEimOhYva1ksskWqkLGY/bjR9h7Cfbr+RrJRfmTQ== dependencies: ansi-regex "^2.1.1" d "1" @@ -1625,19 +1409,16 @@ cli-color@^1.2.0: cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= dependencies: center-align "^0.1.1" right-align "^0.1.1" @@ -1646,7 +1427,6 @@ cliui@^2.1.0: cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -1655,7 +1435,6 @@ cliui@^3.2.0: cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" @@ -1664,22 +1443,18 @@ cliui@^4.0.0: clone@2.x, clone@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= coinstring@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - integrity sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q= dependencies: bs58 "^2.0.1" create-hash "^1.1.1" @@ -1687,7 +1462,6 @@ coinstring@^2.0.0: collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -1695,85 +1469,70 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= colors@^1.1.2: version "1.3.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" - integrity sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ== combined-stream@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= dependencies: delayed-stream "~1.0.0" combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" - integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== dependencies: delayed-stream "~1.0.0" commander@2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== commander@2.15.1: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== commander@^2.11.0, commander@^2.14.1, commander@^2.15.0, commander@^2.8.1, commander@^2.9.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== commander@~2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= dependencies: graceful-readlink ">= 1.0.0" compare-versions@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" - integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg== component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" @@ -1783,76 +1542,62 @@ concat-stream@^1.6.0: console-browserify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= dependencies: date-now "^0.1.4" console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== dependencies: safe-buffer "~5.1.1" cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= cookiejar@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0, core-js@^2.5.0: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cors@^2.8.1: version "2.8.4" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" - integrity sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY= dependencies: object-assign "^4" vary "^1" @@ -1860,7 +1605,6 @@ cors@^2.8.1: coveralls@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" - integrity sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw== dependencies: growl "~> 1.10.0" js-yaml "^3.11.0" @@ -1872,7 +1616,6 @@ coveralls@^3.0.1: create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== dependencies: bn.js "^4.1.0" elliptic "^6.0.0" @@ -1880,7 +1623,6 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -1891,7 +1633,6 @@ create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -1903,7 +1644,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: cron-parser@^2.4.0: version "2.6.0" resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.6.0.tgz#ae2514ceda9ccb540256e201bdd23ae814e03674" - integrity sha512-KGfDDTjBIx85MnVYcdhLccoJH/7jcYW+5Z/t3Wsg2QlJhmmjf+97z+9sQftS71lopOYYapjEKEvmWaCsym5Z4g== dependencies: is-nan "^1.2.1" moment-timezone "^0.5.0" @@ -1911,7 +1651,6 @@ cron-parser@^2.4.0: cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" @@ -1920,7 +1659,6 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: crypto-browserify@3.12.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -1937,115 +1675,84 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0: crypto-js@^3.1.4, crypto-js@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" - integrity sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU= crypto-js@^3.1.9-1: version "3.1.9-1" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8" - integrity sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg= crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= csextends@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/csextends/-/csextends-1.2.0.tgz#6374b210984b54d4495f29c99d3dd069b80543e5" - integrity sha512-S/8k1bDTJIwuGgQYmsRoE+8P+ohV32WhQ0l4zqrc0XDdxOhjQQD7/wTZwCzoZX53jSX3V/qwjT+OkPTxWQcmjg== cycle@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= dependencies: es5-ext "^0.10.9" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" -date-extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/date-extended/-/date-extended-0.0.6.tgz#23802d57dd1bf7818813fe0c32e851a86da267c9" - integrity sha1-I4AtV90b94GIE/4MMuhRqG2iZ8k= - dependencies: - array-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" - date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= death@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" - integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= debug@*: version "4.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" - integrity sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg== dependencies: ms "^2.1.1" debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" debug@^3.0.1, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -declare.js@~0.0.4: - version "0.0.8" - resolved "https://registry.yarnpkg.com/declare.js/-/declare.js-0.0.8.tgz#0478adff9564c004f51df73d8bc134019d28dcde" - integrity sha1-BHit/5VkwAT1Hfc9i8E0AZ0o3N4= decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: mimic-response "^1.0.0" decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== dependencies: file-type "^5.2.0" is-stream "^1.1.0" @@ -2054,7 +1761,6 @@ decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: decompress-tarbz2@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== dependencies: decompress-tar "^4.1.0" file-type "^6.1.0" @@ -2065,7 +1771,6 @@ decompress-tarbz2@^4.0.0: decompress-targz@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== dependencies: decompress-tar "^4.1.1" file-type "^5.2.0" @@ -2074,7 +1779,6 @@ decompress-targz@^4.0.0: decompress-unzip@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= dependencies: file-type "^3.8.0" get-stream "^2.2.0" @@ -2084,7 +1788,6 @@ decompress-unzip@^4.0.1: decompress@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= dependencies: decompress-tar "^4.0.0" decompress-tarbz2 "^4.0.0" @@ -2098,57 +1801,52 @@ decompress@^4.0.0: deep-assign@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-2.0.0.tgz#ebe06b1f07f08dae597620e3dd1622f371a1c572" - integrity sha1-6+BrHwfwja5ZdiDj3RYi83GhxXI= dependencies: is-obj "^1.0.0" +deep-equal@~0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" + deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= deferred-leveldown@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== dependencies: abstract-leveldown "~2.6.0" define-properties@^1.1.1, define-properties@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" @@ -2156,12 +1854,10 @@ define-property@^2.0.2: defined@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag= dependencies: globby "^5.0.0" is-path-cwd "^1.0.0" @@ -2174,27 +1870,22 @@ del@^2.0.2: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= delimit-stream@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" - integrity sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs= depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -2202,34 +1893,28 @@ des.js@^1.0.0: destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= dependencies: repeating "^2.0.0" detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= diff@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" @@ -2238,7 +1923,6 @@ diffie-hellman@^5.0.0: doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= dependencies: esutils "^2.0.2" isarray "^1.0.0" @@ -2246,24 +1930,20 @@ doctrine@1.5.0: doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== drbg.js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= dependencies: browserify-aes "^1.0.6" create-hash "^1.1.2" @@ -2272,19 +1952,16 @@ drbg.js@^1.0.1: duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= eachr@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/eachr/-/eachr-2.0.4.tgz#466f7caa10708f610509e32c807aafe57fc122bf" - integrity sha1-Rm98qhBwj2EFCeMsgHqv5X/BIr8= dependencies: typechecker "^2.0.8" ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" @@ -2292,12 +1969,10 @@ ecc-jsbn@~0.1.1: editions@^1.1.1, editions@^1.3.3, editions@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" - integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== editions@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/editions/-/editions-2.0.2.tgz#54fdac6fb24b0a1a72ffc1ba0126c10602c3e0bd" - integrity sha512-0B8aSTWUu9+JW99zHoeogavCi+lkE5l35FK0OKe0pCobixJYoeof3ZujtqYzSsU2MskhRadY5V9oWUuyG4aJ3A== dependencies: errlop "^1.0.2" semver "^5.5.0" @@ -2305,17 +1980,14 @@ editions@^2.0.2: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.47: version "1.3.78" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.78.tgz#ecb72b5b166ba6598efb384461d63cad74678ebf" - integrity sha512-p4D/5iX08c3LNep5bWn/X3dFmec1K9le6O43lgRsO/vYKBTH2smWDMDfkGlPtERFcLVkI8xdKW5EokBZODh1xg== elliptic@6.3.3: version "6.3.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2325,7 +1997,6 @@ elliptic@6.3.3: elliptic@=6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" - integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2338,7 +2009,6 @@ elliptic@=6.4.0: elliptic@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-3.1.0.tgz#c21682ef762769b56a74201609105da11d5f60cc" - integrity sha1-whaC73YnabVqdCAWCRBdoR1fYMw= dependencies: bn.js "^2.0.3" brorand "^1.0.1" @@ -2348,7 +2018,6 @@ elliptic@^3.1.0: elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: version "6.4.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2361,31 +2030,26 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= dependencies: iconv-lite "~0.4.13" end-of-stream@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: once "^1.4.0" enhanced-resolve@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" - integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24= dependencies: graceful-fs "^4.1.2" memory-fs "^0.4.0" @@ -2395,33 +2059,28 @@ enhanced-resolve@^3.4.0: eol@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" - integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== errlop@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/errlop/-/errlop-1.0.3.tgz#dba29c90cf832c3d2ce469fe515d7e5eef2c6676" - integrity sha512-5VTnt0yikY4LlQEfCXVSqfE6oLj1HVM4zVSvAKMnoYjL/zrb6nqiLowZS4XlG7xENfyj7lpYWvT+wfSCr6dtlA== dependencies: editions "^1.3.4" errno@^0.1.3, errno@~0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== dependencies: prr "~1.0.1" error-ex@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" es-abstract@^1.5.0: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" @@ -2432,7 +2091,6 @@ es-abstract@^1.5.0: es-to-primitive@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -2441,7 +2099,6 @@ es-to-primitive@^1.1.1: es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: version "0.10.46" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572" - integrity sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw== dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" @@ -2450,7 +2107,6 @@ es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= dependencies: d "1" es5-ext "^0.10.35" @@ -2459,7 +2115,6 @@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0 es6-map@^0.1.3: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= dependencies: d "1" es5-ext "~0.10.14" @@ -2471,7 +2126,6 @@ es6-map@^0.1.3: es6-set@~0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= dependencies: d "1" es5-ext "~0.10.14" @@ -2482,7 +2136,6 @@ es6-set@~0.1.5: es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= dependencies: d "1" es5-ext "~0.10.14" @@ -2490,7 +2143,6 @@ es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8= dependencies: d "1" es5-ext "^0.10.14" @@ -2500,17 +2152,14 @@ es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= dependencies: esprima "^2.7.1" estraverse "^1.9.1" @@ -2522,7 +2171,6 @@ escodegen@1.8.x: escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= dependencies: es6-map "^0.1.3" es6-weak-map "^2.0.1" @@ -2532,12 +2180,10 @@ escope@^3.6.0: eslint-config-standard@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz#87ee0d3c9d95382dc761958cbb23da9eea31e0ba" - integrity sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw== eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" - integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== dependencies: debug "^2.6.9" resolve "^1.5.0" @@ -2545,7 +2191,6 @@ eslint-import-resolver-node@^0.3.1: eslint-module-utils@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" - integrity sha1-snA2LNiLGkitMIl2zn+lTphBF0Y= dependencies: debug "^2.6.8" pkg-dir "^1.0.0" @@ -2553,7 +2198,6 @@ eslint-module-utils@^2.2.0: eslint-plugin-import@^2.10.0: version "2.14.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" - integrity sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g== dependencies: contains-path "^0.1.0" debug "^2.6.8" @@ -2569,7 +2213,6 @@ eslint-plugin-import@^2.10.0: eslint-plugin-node@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz#bf19642298064379315d7a4b2a75937376fa05e4" - integrity sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw== dependencies: ignore "^3.3.6" minimatch "^3.0.4" @@ -2579,17 +2222,14 @@ eslint-plugin-node@^6.0.1: eslint-plugin-promise@^3.7.0: version "3.8.0" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" - integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ== eslint-plugin-standard@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz#2a9e21259ba4c47c02d53b2d0c9135d4b1022d47" - integrity sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w== eslint-scope@^3.7.1: version "3.7.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" - integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2597,12 +2237,10 @@ eslint-scope@^3.7.1: eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== eslint@^4.19.1: version "4.19.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" - integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" @@ -2646,7 +2284,6 @@ eslint@^4.19.1: espree@^3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== dependencies: acorn "^5.5.0" acorn-jsx "^3.0.0" @@ -2654,51 +2291,42 @@ espree@^3.5.4: esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== dependencies: estraverse "^4.1.0" estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eth-block-tracker@^2.2.2: version "2.3.1" resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz#ab6d177e5b50128fa06d7ae9e0489c7484bac95e" - integrity sha512-NamWuMBIl8kmkJFVj8WzGatySTzQPQag4Xr677yFxdVtIxACFbL/dQowk0MzEqIKk93U1TwY3MjVU6mOcwZnKA== dependencies: async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c eth-query "^2.1.0" @@ -2712,7 +2340,6 @@ eth-block-tracker@^2.2.2: eth-lib@0.1.27, eth-lib@^0.1.26: version "0.1.27" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" - integrity sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA== dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2725,7 +2352,6 @@ eth-lib@0.1.27, eth-lib@^0.1.26: eth-lib@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" - integrity sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco= dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2734,7 +2360,6 @@ eth-lib@0.2.7: eth-lightwallet@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eth-lightwallet/-/eth-lightwallet-3.0.1.tgz#297022932aa568f4e4eb0873bff257f5e5b78709" - integrity sha512-79vVCETy+4l1b6wuOWwjqPW3Bom5ZK46BgkUNwaXhiMG1rrMRHjpjYEWMqH0JHeCzOzB4HBIFz7eK1/4s6w5nA== dependencies: bitcore-lib "^0.15.0" bitcore-mnemonic "^1.5.0" @@ -2751,7 +2376,6 @@ eth-lightwallet@^3.0.1: eth-query@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= dependencies: json-rpc-random-id "^1.0.0" xtend "^4.0.1" @@ -2759,7 +2383,6 @@ eth-query@^2.1.0: eth-sig-util@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= dependencies: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" @@ -2767,7 +2390,6 @@ eth-sig-util@^1.4.2: ethereum-bridge@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/ethereum-bridge/-/ethereum-bridge-0.6.1.tgz#53c93ed7c0e21752a91e5f089a5997e1d6fea228" - integrity sha512-yDTivI85618BoLI71yNRzW6iVcVN2rjnviCIzs0QOCOENj4XpYQhMDGhdqDi8XWDdzTd0Ja/Canuuh3vfE2IcA== dependencies: async "^2.4.1" borc "^2.0.2" @@ -2798,17 +2420,14 @@ ethereum-bridge@^0.6.1: ethereum-common@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= ethereumjs-abi@0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.4.tgz#9ba1bb056492d00c27279f6eccd4d58275912c1a" - integrity sha1-m6G7BWSS0AwnJ59uzNTVgnWRLBo= dependencies: bn.js "^4.10.0" ethereumjs-util "^4.3.0" @@ -2823,7 +2442,6 @@ ethereumjs-abi@^0.6.5, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereu ethereumjs-account@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== dependencies: ethereumjs-util "^5.0.0" rlp "^2.0.0" @@ -2832,7 +2450,6 @@ ethereumjs-account@^2.0.3: ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: version "1.7.1" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== dependencies: async "^2.0.1" ethereum-common "0.2.0" @@ -2843,26 +2460,22 @@ ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: ethereumjs-common@~0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-0.4.1.tgz#27690a24a817b058cc3a2aedef9392e8d7d63984" - integrity sha512-ywYGsOeGCsMNWso5Y4GhjWI24FJv9FK7+VyVKiQgXg8ZRDPXJ7F/kJ1CnjtkjTvDF4e0yqU+FWswlqR3bmZQ9Q== ethereumjs-testrpc-sc@6.1.6: version "6.1.6" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.6.tgz#290595380b5182814564d4aa38f35b7788aab070" - integrity sha512-iv2qiGBFgk9mn5Nq2enX8dG5WQ7Lk+FCqpnxfPfH4Ns8KLPwttmNOy264nh3SXDJJvcQwz/XnlLteDQVILotbg== dependencies: source-map-support "^0.5.3" ethereumjs-testrpc@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc/-/ethereumjs-testrpc-6.0.3.tgz#7a0b87bf3670f92f607f98fa6a78801d9741b124" - integrity sha512-lAxxsxDKK69Wuwqym2K49VpXtBvLEsXr1sryNG4AkvL5DomMdeCBbu3D87UEevKenLHBiT8GTjARwN6Yj039gA== dependencies: webpack "^3.0.0" ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@^1.3.3: version "1.3.7" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== dependencies: ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" @@ -2870,7 +2483,6 @@ ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@ ethereumjs-util@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" - integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= dependencies: bn.js "^4.8.0" create-hash "^1.1.2" @@ -2881,7 +2493,6 @@ ethereumjs-util@^4.3.0: ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.3, ethereumjs-util@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" - integrity sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA== dependencies: bn.js "^4.11.0" create-hash "^1.1.2" @@ -2894,7 +2505,6 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum ethereumjs-vm@^2.0.2: version "2.4.0" resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.4.0.tgz#244f1e35f2755e537a13546111d1a4c159d34b13" - integrity sha512-MJ4lCWa5c6LhahhhvoDKW+YGjK00ZQn0RHHLh4L+WaH1k6Qv7/q3uTluew6sJGNCZdlO0yYMDXYW9qyxLHKlgQ== dependencies: async "^2.1.2" async-eventemitter "^0.2.2" @@ -2911,7 +2521,6 @@ ethereumjs-vm@^2.0.2: ethereumjs-wallet@^0.6.0: version "0.6.2" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz#67244b6af3e8113b53d709124b25477b64aeccda" - integrity sha512-DHEKPV9lYORM7dL8602dkb+AgdfzCYz2lxpdYQoD3OwG355LLDuivW9rGuLpDMCry/ORyBYV6n+QCo/71SwACg== dependencies: aes-js "^3.1.1" bs58check "^2.1.2" @@ -2925,7 +2534,6 @@ ethereumjs-wallet@^0.6.0: ethers@^3.0.15: version "3.0.29" resolved "https://registry.yarnpkg.com/ethers/-/ethers-3.0.29.tgz#ce8139955b4ed44456eb6764b089bb117c86775d" - integrity sha512-OGyA5pW5xFC5o/ZV5MfIoVp/EdA1QMg2bMJFf7Kznsz8m7IzzbgsPHTCjzSfKQDs/XDphGyRcA7A6bkIeJL4gw== dependencies: aes-js "3.0.0" bn.js "^4.4.0" @@ -2941,7 +2549,6 @@ ethers@^3.0.15: ethjs-abi@0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.1.8.tgz#cd288583ed628cdfadaf8adefa3ba1dbcbca6c18" - integrity sha1-zSiFg+1ijN+tr4re+juh28vKbBg= dependencies: bn.js "4.11.6" js-sha3 "0.5.5" @@ -2950,7 +2557,6 @@ ethjs-abi@0.1.8: ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= dependencies: bn.js "4.11.6" number-to-bn "1.7.0" @@ -2958,7 +2564,6 @@ ethjs-unit@0.1.6: ethjs-util@^0.1.3: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== dependencies: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" @@ -2966,7 +2571,6 @@ ethjs-util@^0.1.3: event-emitter@^0.3.5, event-emitter@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= dependencies: d "1" es5-ext "~0.10.14" @@ -2974,22 +2578,18 @@ event-emitter@^0.3.5, event-emitter@~0.3.5: eventemitter3@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" - integrity sha1-R3hr2qCHyvext15zq8XH1UAVjNA= events@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" @@ -2997,7 +2597,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -3010,14 +2609,12 @@ execa@^0.7.0: expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= dependencies: is-posix-bracket "^0.1.0" expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -3030,14 +2627,12 @@ expand-brackets@^2.1.4: expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= dependencies: fill-range "^2.1.0" express@^4.14.0: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" - integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== dependencies: accepts "~1.3.5" array-flatten "1.1.1" @@ -3073,14 +2668,12 @@ express@^4.14.0: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -3088,33 +2681,16 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extended@0.0.6, extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/extended/-/extended-0.0.6.tgz#7fb8bf7b9dae397586e48570acfd642c78e50669" - integrity sha1-f7i/e52uOXWG5IVwrP1kLHjlBmk= - dependencies: - extender "~0.0.5" - -extender@~0.0.5: - version "0.0.10" - resolved "https://registry.yarnpkg.com/extender/-/extender-0.0.10.tgz#589c07482be61a1460b6d81f9c24aa67e8f324cd" - integrity sha1-WJwHSCvmGhRgttgfnCSqZ+jzJM0= - dependencies: - declare.js "~0.0.4" extendr@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/extendr/-/extendr-2.1.0.tgz#301aa0bbea565f4d2dc8f570f2a22611a8527b56" - integrity sha1-MBqgu+pWX00tyPVw8qImEahSe1Y= dependencies: typechecker "~2.0.1" external-editor@^2.0.4: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== dependencies: chardet "^0.4.0" iconv-lite "^0.4.17" @@ -3123,14 +2699,12 @@ external-editor@^2.0.4: extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= dependencies: is-extglob "^1.0.0" extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -3144,87 +2718,64 @@ extglob@^2.0.4: extract-opts@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d" - integrity sha1-H6KOunNSxttID4hc63GkaBC+bX0= dependencies: typechecker "~2.0.1" extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= eyes@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= fake-merkle-patricia-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= dependencies: checkpoint-store "^1.1.0" -fast-csv@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-2.4.1.tgz#bd7dd268391f729367b59445b8dd0ad026881b26" - integrity sha1-vX3SaDkfcpNntZRFuN0K0CaIGyY= - dependencies: - extended "0.0.6" - is-extended "0.0.10" - object-extended "0.0.7" - string-extended "0.0.8" - fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= dependencies: pend "~1.2.0" fetch-ponyfill@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" - integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= dependencies: node-fetch "~1.7.1" figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" @@ -3232,27 +2783,22 @@ file-entry-cache@^2.0.0: file-type@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= file-type@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha1-LdvqfHP/42No365J3DOMBYwritY= file-type@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= fill-range@^2.1.0: version "2.2.4" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== dependencies: is-number "^2.1.0" isobject "^2.0.0" @@ -3263,7 +2809,6 @@ fill-range@^2.1.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -3273,7 +2818,6 @@ fill-range@^4.0.0: finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" - integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== dependencies: debug "2.6.9" encodeurl "~1.0.2" @@ -3286,7 +2830,6 @@ finalhandler@1.1.1: find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" @@ -3294,14 +2837,12 @@ find-up@^1.0.0: find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" - integrity sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE= dependencies: circular-json "^0.3.1" del "^2.0.2" @@ -3311,31 +2852,26 @@ flat-cache@^1.2.1: for-each@^0.3.2, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= dependencies: for-in "^1.0.1" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= dependencies: asynckit "^0.4.0" combined-stream "1.0.6" @@ -3344,29 +2880,24 @@ form-data@~2.3.2: forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3377,7 +2908,6 @@ fs-extra@^0.30.0: fs-extra@^2.0.0, fs-extra@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" - integrity sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3385,7 +2915,6 @@ fs-extra@^2.0.0, fs-extra@^2.1.2: fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3394,7 +2923,6 @@ fs-extra@^4.0.2: fs-extra@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3403,14 +2931,12 @@ fs-extra@^5.0.0: fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== dependencies: minipass "^2.2.1" fs-promise@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" - integrity sha1-9k5PhUvPaJqovdy6JokW2z20aFQ= dependencies: any-promise "^1.3.0" fs-extra "^2.0.0" @@ -3420,17 +2946,14 @@ fs-promise@^2.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fs@0.0.1-security: version "0.0.1-security" resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" - integrity sha1-invTcYa23d84E/I4WLV+yq9eQdQ= fsevents@^1.0.0, fsevents@^1.2.2: version "1.2.4" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -3438,7 +2961,6 @@ fsevents@^1.0.0, fsevents@^1.2.2: fstream@^1.0.2, fstream@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -3448,24 +2970,20 @@ fstream@^1.0.2, fstream@^1.0.8: function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= ganache-cli@^6.1.8: version "6.1.8" resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.8.tgz#49a8a331683a9652183f82ef1378d17e1814fcd3" - integrity sha512-yXzteu4SIgUL31mnpm9j+x6dpHUw0p/nsRVkcySKq0w+1vDxH9jMErP1QhZAJuTVE6ni4nfvGSNkaQx5cD3jfg== dependencies: source-map-support "^0.5.3" gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -3479,12 +2997,10 @@ gauge@~2.7.3: get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= dependencies: object-assign "^4.0.1" pinkie-promise "^2.0.0" @@ -3492,24 +3008,20 @@ get-stream@^2.2.0: get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= dependencies: glob-parent "^2.0.0" is-glob "^2.0.0" @@ -3517,14 +3029,12 @@ glob-base@^0.3.0: glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= dependencies: is-glob "^2.0.0" glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -3532,7 +3042,6 @@ glob-parent@^3.1.0: glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3544,7 +3053,6 @@ glob@7.1.2: glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= dependencies: inflight "^1.0.4" inherits "2" @@ -3555,7 +3063,6 @@ glob@^5.0.15: glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3567,7 +3074,6 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: glob@~6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= dependencies: inflight "^1.0.4" inherits "2" @@ -3578,7 +3084,6 @@ glob@~6.0.4: global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" - integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= dependencies: min-document "^2.19.0" process "~0.5.1" @@ -3586,17 +3091,14 @@ global@~4.3.0: globals@^11.0.1: version "11.8.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" - integrity sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA== globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0= dependencies: array-union "^1.0.1" arrify "^1.0.0" @@ -3608,7 +3110,6 @@ globby@^5.0.0: got@7.1.0, got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== dependencies: decompress-response "^3.2.0" duplexer3 "^0.1.4" @@ -3628,27 +3129,22 @@ got@7.1.0, got@^7.1.0: graceful-fs@*, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= growl@1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== growl@1.10.5, "growl@~> 1.10.0": version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: version "4.0.12" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" - integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA== dependencies: async "^2.5.0" optimist "^0.6.1" @@ -3659,12 +3155,10 @@ handlebars@^4.0.1: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" - integrity sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA== dependencies: ajv "^5.3.0" har-schema "^2.0.0" @@ -3672,51 +3166,42 @@ har-validator@~5.1.0: has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= has-to-string-tag-x@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== dependencies: has-symbol-support-x "^1.4.1" has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -3725,7 +3210,6 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -3734,12 +3218,10 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -3747,14 +3229,12 @@ has-values@^1.0.0: has@^1.0.1, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -3762,7 +3242,6 @@ hash-base@^3.0.0: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.5" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" - integrity sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" @@ -3770,7 +3249,6 @@ hash.js@^1.0.0, hash.js@^1.0.3: hdkey@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.0.tgz#e74e7b01d2c47f797fa65d1d839adb7a44639f29" - integrity sha512-E7aU8pNlWUJbXGjTz/+lKf1LkMcA3hUrC5ZleeizrmLSd++kvf8mSOe3q8CmBDA9j4hdfXO5iY6hGiTUCOV2jQ== dependencies: coinstring "^2.0.0" safe-buffer "^5.1.1" @@ -3779,12 +3257,10 @@ hdkey@^1.0.0: he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -3793,7 +3269,6 @@ hmac-drbg@^1.0.0: home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.1" @@ -3801,12 +3276,10 @@ home-or-tmp@^2.0.0: hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" @@ -3816,12 +3289,10 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: http-https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" @@ -3830,12 +3301,10 @@ http-signature@~1.2.0: https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= i18n@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/i18n/-/i18n-0.8.3.tgz#2d8cf1c24722602c2041d01ba6ae5eaa51388f0e" - integrity sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4= dependencies: debug "*" make-plural "^3.0.3" @@ -3844,41 +3313,39 @@ i18n@^0.8.3: mustache "*" sprintf-js ">=1.0.3" +i@0.3.x: + version "0.3.6" + resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d" + iconv-lite@0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" ieee754@^1.1.4, ieee754@^1.1.8: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== dependencies: minimatch "^3.0.4" ignore@^3.3.3, ignore@^3.3.6: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== ignorefs@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ignorefs/-/ignorefs-1.2.0.tgz#da59fb858976e4a5e43702ccd1f282fdbc9e5756" - integrity sha1-2ln7hYl25KXkNwLM0fKC/byeV1Y= dependencies: editions "^1.3.3" ignorepatterns "^1.1.0" @@ -3886,27 +3353,22 @@ ignorefs@^1.0.0: ignorepatterns@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ignorepatterns/-/ignorepatterns-1.1.0.tgz#ac8f436f2239b5dfb66d5f0d3a904a87ac67cc5e" - integrity sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4= immediate@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" @@ -3914,22 +3376,18 @@ inflight@^1.0.4: inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= inherits@2.0.1, inherits@=2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" - integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -3949,91 +3407,76 @@ inquirer@^3.0.6: interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" - integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= dependencies: builtin-modules "^1.0.0" is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -4042,7 +3485,6 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -4051,261 +3493,210 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= dependencies: is-primitive "^2.0.0" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" -is-extended@0.0.10, is-extended@~0.0.3, is-extended@~0.0.8: - version "0.0.10" - resolved "https://registry.yarnpkg.com/is-extended/-/is-extended-0.0.10.tgz#244e140df75bb1c9a3106f412ff182fb534a6d62" - integrity sha1-JE4UDfdbscmjEG9BL/GC+1NKbWI= - dependencies: - extended "~0.0.3" - is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= dependencies: number-is-nan "^1.0.0" is-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= dependencies: is-extglob "^1.0.0" is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= dependencies: is-extglob "^2.1.1" is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= is-nan@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" - integrity sha1-n69ltvttskt/XAYoR16nH5iEAeI= dependencies: define-properties "^1.1.1" is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= dependencies: kind-of "^3.0.2" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= is-path-in-cwd@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== dependencies: is-path-inside "^1.0.0" is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= dependencies: path-is-inside "^1.0.1" is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= is-promise@^2.1, is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= dependencies: has "^1.0.1" is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== dependencies: has-symbols "^1.0.0" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= dependencies: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" @@ -4313,12 +3704,10 @@ isomorphic-fetch@^2.2.0: isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= dependencies: abbrev "1.0.x" async "1.x" @@ -4338,7 +3727,6 @@ istanbul@^0.4.5: isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== dependencies: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" @@ -4346,37 +3734,30 @@ isurl@^1.0.0-alpha5: js-sha3@0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a" - integrity sha1-uvDA6MVK1ZA0R9+Wreekobynmko= js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= js-sha3@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" - integrity sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM= js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.9.1: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4384,27 +3765,22 @@ js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.9.1: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-loader@^0.5.4: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" - integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== json-rpc-engine@^3.6.0: version "3.8.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" - integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== dependencies: async "^2.0.1" babel-preset-env "^1.7.0" @@ -4416,82 +3792,68 @@ json-rpc-engine@^3.6.0: json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= dependencies: inherits "^2.0.1" json-rpc-random-id@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= dependencies: jsonify "~0.0.0" json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json-text-sequence@^0.1: version "0.1.1" resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" - integrity sha1-py8hfcSvxGKf/1/rME3BvVGi89I= dependencies: delimit-stream "0.1.0" json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= optionalDependencies: graceful-fs "^4.1.6" jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= optionalDependencies: graceful-fs "^4.1.6" jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" extsprintf "1.3.0" @@ -4501,7 +3863,6 @@ jsprim@^1.2.2: keccak@^1.0.2: version "1.4.0" resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" - integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== dependencies: bindings "^1.2.1" inherits "^2.0.3" @@ -4511,7 +3872,6 @@ keccak@^1.0.2: keccakjs@^0.2.0, keccakjs@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" - integrity sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0= dependencies: browserify-sha3 "^0.0.1" sha3 "^1.1.0" @@ -4519,74 +3879,62 @@ keccakjs@^0.2.0, keccakjs@^0.2.1: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= optionalDependencies: graceful-fs "^4.1.9" lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM= level-codec@~7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== level-errors@^1.0.3: version "1.1.2" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== dependencies: errno "~0.1.1" level-errors@~1.0.3: version "1.0.5" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== dependencies: errno "~0.1.1" level-iterator-stream@~1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= dependencies: inherits "^2.0.1" level-errors "^1.0.3" @@ -4596,7 +3944,6 @@ level-iterator-stream@~1.3.0: level-ws@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= dependencies: readable-stream "~1.0.15" xtend "~2.1.1" @@ -4604,7 +3951,6 @@ level-ws@0.0.0: levelup@^1.2.1: version "1.3.9" resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== dependencies: deferred-leveldown "~1.2.1" level-codec "~7.0.0" @@ -4617,7 +3963,6 @@ levelup@^1.2.1: levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -4625,7 +3970,6 @@ levn@^0.3.0, levn@~0.3.0: load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4636,7 +3980,6 @@ load-json-file@^1.0.0: load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4646,12 +3989,10 @@ load-json-file@^2.0.0: loader-runner@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.1.tgz#026f12fe7c3115992896ac02ba022ba92971b979" - integrity sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw== loader-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" - integrity sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0= dependencies: big.js "^3.1.3" emojis-list "^2.0.0" @@ -4660,7 +4001,6 @@ loader-utils@^1.1.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -4668,54 +4008,44 @@ locate-path@^2.0.0: lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash@4.x, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== lodash@=4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= log-driver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" - integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== long-timeout@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" - integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ= longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lru-cache@^4.0.1: version "4.1.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" - integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -4723,57 +4053,48 @@ lru-cache@^4.0.1: lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" - integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= dependencies: es5-ext "~0.10.2" ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== dependencies: pify "^3.0.0" make-plural@^3.0.3, make-plural@~3.0.3: version "3.0.6" resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-3.0.6.tgz#2033a03bac290b8f3bb91258f65b9df7e8b01ca7" - integrity sha1-IDOgO6wpC487uRJY9lud9+iwHKc= optionalDependencies: minimist "^1.2.0" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" math-interval-parser@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-interval-parser/-/math-interval-parser-1.1.0.tgz#dbeda5b06b3249973c6df6170fde2386f0afd893" - integrity sha1-2+2lsGsySZc8bfYXD94jhvCv2JM= dependencies: xregexp "^2.0.0" math-random@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" - integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -4782,19 +4103,16 @@ md5.js@^1.3.4: media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= dependencies: mimic-fn "^1.0.0" memdown@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= dependencies: abstract-leveldown "~2.7.1" functional-red-black-tree "^1.0.1" @@ -4806,7 +4124,6 @@ memdown@^1.0.0: memoizee@^0.4.14: version "0.4.14" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" - integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== dependencies: d "1" es5-ext "^0.10.45" @@ -4820,7 +4137,6 @@ memoizee@^0.4.14: memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= dependencies: errno "^0.1.3" readable-stream "^2.0.1" @@ -4828,17 +4144,14 @@ memory-fs@^0.4.0, memory-fs@~0.4.1: memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= merkle-patricia-tree@^2.1.2: version "2.3.2" resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== dependencies: async "^1.4.2" ethereumjs-util "^5.0.0" @@ -4852,7 +4165,6 @@ merkle-patricia-tree@^2.1.2: messageformat@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/messageformat/-/messageformat-0.3.1.tgz#e58fff8245e9b3971799e5b43db58b3e9417f5a2" - integrity sha1-5Y//gkXps5cXmeW0PbWLPpQX9aI= dependencies: async "~1.5.2" glob "~6.0.4" @@ -4863,12 +4175,10 @@ messageformat@^0.3.1: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@^2.1.5: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= dependencies: arr-diff "^2.0.0" array-unique "^0.2.1" @@ -4887,7 +4197,6 @@ micromatch@^2.1.5: micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4906,7 +4215,6 @@ micromatch@^3.1.10, micromatch@^3.1.4: miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" @@ -4914,73 +4222,60 @@ miller-rabin@^4.0.0: mime-db@~1.36.0: version "1.36.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" - integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw== mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.20" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" - integrity sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A== dependencies: mime-db "~1.36.0" mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= dependencies: dom-walk "^0.1.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@^1.2.0, minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= minipass@^2.2.1, minipass@^2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957" - integrity sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" @@ -4988,14 +4283,12 @@ minipass@^2.2.1, minipass@^2.3.3: minizlib@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" - integrity sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg== dependencies: minipass "^2.2.1" mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -5003,21 +4296,18 @@ mixin-deep@^1.2.0: mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" mocha@^4.0.1, mocha@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" - integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== dependencies: browser-stdout "1.3.0" commander "2.11.0" @@ -5033,7 +4323,6 @@ mocha@^4.0.1, mocha@^4.1.0: mocha@^5.0.1: version "5.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== dependencies: browser-stdout "1.3.1" commander "2.15.1" @@ -5050,39 +4339,32 @@ mocha@^5.0.1: mock-fs@^4.1.0: version "4.7.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" - integrity sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA== moment-timezone@^0.5.0: version "0.5.21" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.21.tgz#3cba247d84492174dbf71de2a9848fa13207b845" - integrity sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A== dependencies: moment ">= 2.9.0" "moment@>= 2.9.0", moment@^2.22.2: version "2.22.2" resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" - integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y= mout@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" - integrity sha1-ujYR318OWx/7/QEWa48C0fX6K5k= ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== multihashes@^0.4.5: version "0.4.14" resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.14.tgz#774db9a161f81a8a27dc60788f91248e020f5244" - integrity sha512-V/g/EIN6nALXfS/xHUAgtfPP3mn3sPIF/i9beuGKf25QXS2QZYCpeVJbDPEannkz32B2fihzCe2D/KMrbcmefg== dependencies: bs58 "^4.0.1" varint "^5.0.0" @@ -5090,22 +4372,18 @@ multihashes@^0.4.5: mustache@*: version "3.0.0" resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.0.tgz#3de22dd9ba38152f7355399a953dd4528c403338" - integrity sha512-bhBDkK/PioIbtQzRIbGUGypvc3MC4c389QnJt8KDIEJ666OidRPoXAQAHPivikfS3JkMEaWoPvcDL7YrQxtSwg== mustache@^2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" - integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== -mute-stream@0.0.7: +mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" object-assign "^4.0.1" @@ -5114,22 +4392,18 @@ mz@^2.6.0: nan@2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== nan@^2.0.8, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" - integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -5146,12 +4420,14 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +ncp@1.0.x: + version "1.0.1" + resolved "http://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== dependencies: debug "^2.1.2" iconv-lite "^0.4.4" @@ -5160,27 +4436,22 @@ needle@^2.2.1: negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= neo-async@^2.5.0: version "2.5.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc" - integrity sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw== next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= node-async-loop@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/node-async-loop/-/node-async-loop-1.2.2.tgz#c5870299bf6477b780c88b431aa5b37733f55a3d" - integrity sha1-xYcCmb9kd7eAyItDGqWzdzP1Wj0= node-cache@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.0.tgz#48ac796a874e762582692004a376d26dfa875811" - integrity sha512-obRu6/f7S024ysheAjoYFEEBqqDWv4LOMNJEuO8vMeEw2AT4z+NCzO4hlc2lhI4vATzbCQv6kke9FVdx0RbCOw== dependencies: clone "2.x" lodash "4.x" @@ -5188,7 +4459,6 @@ node-cache@^4.1.1: node-fetch@^1.0.1, node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== dependencies: encoding "^0.1.11" is-stream "^1.0.1" @@ -5196,7 +4466,6 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: node-libs-browser@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" - integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -5225,7 +4494,6 @@ node-libs-browser@^2.0.0: node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -5241,7 +4509,6 @@ node-pre-gyp@^0.10.0: node-schedule@^1.2.3: version "1.3.0" resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-1.3.0.tgz#e7a7e816a7f2550d5b170bd106e765db28bdf030" - integrity sha512-NNwO9SUPjBwFmPh3vXiPVEhJLn4uqYmZYvJV358SRGM06BR4UoIqxJpeJwDDXB6atULsgQA97MfD1zMd5xsu+A== dependencies: cron-parser "^2.4.0" long-timeout "0.1.1" @@ -5250,14 +4517,12 @@ node-schedule@^1.2.3: nopt@3.x, nopt@~3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" osenv "^0.1.4" @@ -5265,7 +4530,6 @@ nopt@^4.0.1: normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" @@ -5275,19 +4539,16 @@ normalize-package-data@^2.3.2: normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" - integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" - integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -5295,14 +4556,12 @@ npm-packlist@^1.1.6: npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" @@ -5312,12 +4571,10 @@ npmlog@^4.0.2: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -5325,57 +4582,40 @@ number-to-bn@1.7.0: oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" -object-extended@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/object-extended/-/object-extended-0.0.7.tgz#84fd23f56b15582aeb3e88b05cb55d2432d68a33" - integrity sha1-hP0j9WsVWCrrPoiwXLVdJDLWijM= - dependencies: - array-extended "~0.0.4" - extended "~0.0.3" - is-extended "~0.0.3" - object-inspect@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= dependencies: for-own "^0.1.4" is-extendable "^0.1.1" @@ -5383,47 +4623,40 @@ object.omit@^2.0.0: object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" oboe@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" - integrity sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8= dependencies: http-https "^1.0.0" on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" openzeppelin-solidity@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-1.10.0.tgz#d77eee6653f5958d051318a61ba0b436f92216c0" - integrity sha512-igkrumQQ2lrN2zjeQV4Dnb0GpTBj1fzMcd8HPyBUqwI0hhuscX/HzXiqKT6gFQl1j9Wy/ppVVs9fqL/foF7Gmg== optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= dependencies: minimist "~0.0.1" wordwrap "~0.0.2" @@ -5431,7 +4664,6 @@ optimist@^0.6.1: optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" @@ -5443,29 +4675,24 @@ optionator@^0.8.1, optionator@^0.8.2: original-require@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" - integrity sha1-DxMEcVhM0zURxew4yNWSE/msXiA= os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== dependencies: execa "^0.7.0" lcid "^1.0.0" @@ -5474,12 +4701,10 @@ os-locale@^2.0.0: os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -5487,48 +4712,40 @@ osenv@^0.1.4: p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= dependencies: p-limit "^1.1.0" p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= dependencies: p-finally "^1.0.0" p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" - integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== parse-asn1@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" - integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -5539,7 +4756,6 @@ parse-asn1@^5.0.0: parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= dependencies: glob-base "^0.3.0" is-dotfile "^1.0.0" @@ -5549,7 +4765,6 @@ parse-glob@^3.0.4: parse-headers@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" - integrity sha1-aug6eqJanZtwCswoaYzR8e1+lTY= dependencies: for-each "^0.3.2" trim "0.0.1" @@ -5557,71 +4772,58 @@ parse-headers@^2.0.0: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-parse@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -5630,14 +4832,12 @@ path-type@^1.0.0: path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= dependencies: pify "^2.0.0" pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -5648,119 +4848,116 @@ pbkdf2@^3.0.3: pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" - integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= dependencies: find-up "^1.0.0" +pkginfo@0.3.x: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" + +pkginfo@0.x.x: + version "0.4.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" + pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= pragma-singleton@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pragma-singleton/-/pragma-singleton-1.0.3.tgz#6894317bb8d47157e59de2a4a009db7e6f63e30e" - integrity sha1-aJQxe7jUcVflneKkoAnbfm9j4w4= prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= prettier@^1.14.3: version "1.14.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" - integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg== private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= process@~0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= progress@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= promise-to-callback@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= dependencies: is-fn "^1.0.0" set-immediate-shim "^1.0.1" +prompt@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe" + dependencies: + colors "^1.1.2" + pkginfo "0.x.x" + read "1.0.x" + revalidator "0.1.x" + utile "0.3.x" + winston "2.1.x" + prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" - integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== dependencies: loose-envify "^1.3.1" object-assign "^4.1.1" @@ -5768,7 +4965,6 @@ prop-types@^15.6.2: proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" - integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== dependencies: forwarded "~0.1.2" ipaddr.js "1.8.0" @@ -5776,22 +4972,18 @@ proxy-addr@~2.0.4: prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24: version "1.1.29" resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" - integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -5803,27 +4995,22 @@ public-encrypt@^4.0.0: punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== dependencies: decode-uri-component "^0.2.0" object-assign "^4.1.0" @@ -5832,17 +5019,14 @@ query-string@^5.0.1: querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= randomatic@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116" - integrity sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ== dependencies: is-number "^4.0.0" kind-of "^6.0.0" @@ -5851,14 +5035,12 @@ randomatic@^3.0.0: randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -5866,17 +5048,14 @@ randomfill@^1.0.3: randomhex@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" - integrity sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU= range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== dependencies: bytes "3.0.0" http-errors "1.6.3" @@ -5886,7 +5065,6 @@ raw-body@2.3.3: rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" ini "~1.3.0" @@ -5896,7 +5074,6 @@ rc@^1.2.7: react-dom@^16.2.0: version "16.5.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.5.2.tgz#b69ee47aa20bab5327b2b9d7c1fe2a30f2cfa9d7" - integrity sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5906,7 +5083,6 @@ react-dom@^16.2.0: react@^16.2.0: version "16.5.2" resolved "https://registry.yarnpkg.com/react/-/react-16.5.2.tgz#19f6b444ed139baa45609eee6dc3d318b3895d42" - integrity sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5916,7 +5092,6 @@ react@^16.2.0: read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -5924,7 +5099,6 @@ read-pkg-up@^1.0.1: read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= dependencies: find-up "^2.0.0" read-pkg "^2.0.0" @@ -5932,7 +5106,6 @@ read-pkg-up@^2.0.0: read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" @@ -5941,16 +5114,20 @@ read-pkg@^1.0.0: read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" path-type "^2.0.0" +read@1.0.x: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + dependencies: + mute-stream "~0.0.4" + readable-stream@^1.0.33: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5960,7 +5137,6 @@ readable-stream@^1.0.33: readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -5973,7 +5149,6 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5983,7 +5158,6 @@ readable-stream@~1.0.15: readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" @@ -5992,34 +5166,28 @@ readdirp@^2.0.0: readline-sync@^1.4.9: version "1.4.9" resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.9.tgz#3eda8e65f23cd2a17e61301b1f0003396af5ecda" - integrity sha1-PtqOZfI80qF+YTAbHwADOWr17No= rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" regenerate@^1.2.1: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" @@ -6028,14 +5196,12 @@ regenerator-transform@^0.10.0: regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== dependencies: is-equal-shallow "^0.1.3" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" @@ -6043,12 +5209,10 @@ regex-not@^1.0.0, regex-not@^1.0.2: regexpp@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" - integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= dependencies: regenerate "^1.2.1" regjsgen "^0.2.0" @@ -6057,62 +5221,52 @@ regexpu-core@^2.0.0: regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= regjsparser@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= dependencies: is-finite "^1.0.0" req-cwd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-1.0.1.tgz#0d73aeae9266e697a78f7976019677e76acf0fff" - integrity sha1-DXOurpJm5penj3l2AZZ352rPD/8= dependencies: req-from "^1.0.1" req-from@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-from/-/req-from-1.0.1.tgz#bf81da5147947d32d13b947dc12a58ad4587350e" - integrity sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4= dependencies: resolve-from "^2.0.0" request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" - integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= dependencies: lodash "^4.13.1" request-promise@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" - integrity sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ= dependencies: bluebird "^3.5.0" request-promise-core "1.1.1" @@ -6122,7 +5276,6 @@ request-promise@^4.2.2: request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -6148,22 +5301,18 @@ request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.8 require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" - integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" @@ -6171,41 +5320,34 @@ require-uncached@^1.0.3: resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.1.6, resolve@^1.3.3, resolve@^1.5.0, resolve@^1.6.0: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== dependencies: path-parse "^1.0.5" resolve@~1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" - integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw== dependencies: path-parse "^1.0.5" restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" signal-exit "^3.0.2" @@ -6213,33 +5355,32 @@ restore-cursor@^2.0.0: resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= dependencies: through "~2.3.4" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +revalidator@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1: +rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== dependencies: glob "^7.0.5" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -6247,79 +5388,66 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: rlp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9" - integrity sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA== dependencies: safe-buffer "^5.1.1" run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= dependencies: is-promise "^2.1.0" rustbn.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" - integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== rx-lite-aggregates@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= dependencies: rx-lite "*" rx-lite@*, rx-lite@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-event-emitter@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" - integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== dependencies: events "^3.0.0" safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" safe@^0.4.5: version "0.4.6" resolved "https://registry.yarnpkg.com/safe/-/safe-0.4.6.tgz#1d5580cf2635c5cb940ea48fb5081ae3c25b1be1" - integrity sha1-HVWAzyY1xcuUDqSPtQga48JbG+E= safefs@^3.1.2: version "3.2.2" resolved "https://registry.yarnpkg.com/safefs/-/safefs-3.2.2.tgz#8170c1444d7038e08caea05a374fae2fa349e15c" - integrity sha1-gXDBRE1wOOCMrqBaN0+uL6NJ4Vw= dependencies: graceful-fs "*" "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== scandirectory@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/scandirectory/-/scandirectory-2.5.0.tgz#6ce03f54a090b668e3cbedbf20edf9e310593e72" - integrity sha1-bOA/VKCQtmjjy+2/IO354xBZPnI= dependencies: ignorefs "^1.0.0" safefs "^3.1.2" @@ -6328,24 +5456,20 @@ scandirectory@^2.5.0: schedule@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.5.0.tgz#c128fffa0b402488b08b55ae74bb9df55cc29cc8" - integrity sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw== dependencies: object-assign "^4.1.1" scrypt-async@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-1.3.1.tgz#a11fd6fac981b4b823ee01dee0221169500ddae9" - integrity sha1-oR/W+smBtLgj7gHe4CIRaVAN2uk= scrypt-js@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" - integrity sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q= scrypt.js@0.2.0, scrypt.js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" - integrity sha1-r40UZbcemZARC+38WTuUeeA6ito= dependencies: scrypt "^6.0.2" scryptsy "^1.2.1" @@ -6353,21 +5477,18 @@ scrypt.js@0.2.0, scrypt.js@^0.2.0: scrypt@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" - integrity sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0= dependencies: nan "^2.0.8" scryptsy@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= dependencies: pbkdf2 "^3.0.3" secp256k1@^3.0.1: version "3.5.2" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.2.tgz#f95f952057310722184fe9c914e6b71281f2f2ae" - integrity sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ== dependencies: bindings "^1.2.1" bip66 "^1.1.3" @@ -6381,29 +5502,24 @@ secp256k1@^3.0.1: seek-bzip@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= dependencies: commander "~2.8.1" semaphore@>=1.0.1, semaphore@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== semver@~5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== dependencies: debug "2.6.9" depd "~1.1.2" @@ -6422,7 +5538,6 @@ send@0.16.2: serve-static@1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" @@ -6432,7 +5547,6 @@ serve-static@1.13.2: servify@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== dependencies: body-parser "^1.16.0" cors "^2.8.1" @@ -6443,17 +5557,14 @@ servify@^0.1.12: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6463,7 +5574,6 @@ set-value@^0.4.3: set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6473,22 +5583,18 @@ set-value@^2.0.0: setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -6496,35 +5602,30 @@ sha.js@^2.4.0, sha.js@^2.4.8: sha3@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" - integrity sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k= dependencies: nan "2.10.0" shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shelljs@^0.7.4: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= dependencies: glob "^7.0.0" interpret "^1.0.0" rechoir "^0.6.2" -shelljs@^0.8.1, shelljs@^0.8.2: +shelljs@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" - integrity sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ== dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -6533,17 +5634,14 @@ shelljs@^0.8.1, shelljs@^0.8.2: signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= simple-get@^2.7.0: version "2.8.1" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== dependencies: decompress-response "^3.3.0" once "^1.3.1" @@ -6552,19 +5650,16 @@ simple-get@^2.7.0: slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== dependencies: is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -6573,14 +5668,12 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -6594,22 +5687,18 @@ snapdragon@^0.8.1: sol-digger@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" - integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= sol-explore@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" - integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= sol-explore@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.2.tgz#43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2" - integrity sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI= sol-merger@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-0.1.2.tgz#1f12500f42d427dc0ec8e4c113392acd8a6f62d9" - integrity sha512-12Z84jxeb5VFlQOGS38HOiTrHYohU07oQ5wHOcFJmcRRbaL5kWN7IcldMO1QdW8kONyKdj0xhukzLlN5m5ix4w== dependencies: bluebird "^3.5.0" cli-color "^1.2.0" @@ -6621,7 +5710,6 @@ sol-merger@^0.1.2: solc@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.24.tgz#354f14b269b38cbaa82a47d1ff151723502b954e" - integrity sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -6632,7 +5720,6 @@ solc@0.4.24: solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: version "0.4.25" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.25.tgz#06b8321f7112d95b4b903639b1138a4d292f5faa" - integrity sha512-jU1YygRVy6zatgXrLY2rRm7HW1d7a8CkkEgNJwvH2VLpWhMFsMdWcJn6kUqZwcSz/Vm+w89dy7Z/aB5p6AFTrg== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -6643,7 +5730,6 @@ solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: solidity-coverage@^0.5.11: version "0.5.11" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" - integrity sha512-qikdsSi6+9XbfvwA0aI7HUVpF9fIFNqRWTw23M89GMDY+b6Gj0wWU9IngJS0fimoZIAdEp3bfChxvpfVcrUesg== dependencies: death "^1.1.0" ethereumjs-testrpc-sc "6.1.6" @@ -6659,7 +5745,6 @@ solidity-coverage@^0.5.11: solidity-docgen@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/solidity-docgen/-/solidity-docgen-0.1.0.tgz#f3a56ff074e8c7d832af3a3d462c3b5abf0f64cb" - integrity sha512-F7ufNWmlP5c5hIi66Ijv9tc+HNosyO7ijWq6pRtyBR1WqyJBH/0DJkD6QZI8HkE8p6LEXiPKxGBWbAeVT9Nu9g== dependencies: commander "^2.14.1" lodash "^4.17.5" @@ -6672,7 +5757,6 @@ solidity-docgen@^0.1.0: solidity-parser-sc@0.4.11: version "0.4.11" resolved "https://registry.yarnpkg.com/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz#86734c9205537007f4d6201b57176e41696ee607" - integrity sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw== dependencies: mocha "^4.1.0" pegjs "^0.10.0" @@ -6681,12 +5765,10 @@ solidity-parser-sc@0.4.11: solium-plugin-security@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" - integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== solium@^1.1.6: version "1.1.8" resolved "https://registry.yarnpkg.com/solium/-/solium-1.1.8.tgz#35d30a15c572a233ce8a90226d6cfccb762fadb7" - integrity sha512-fn0lusM6of14CytIDDHK73SGjn6NsVTaCVJjaKCKJyqKhT00rH/hDtvnIeZ2ZTD9z/xaXd4Js2brW3az6AV9RA== dependencies: ajv "^5.2.2" chokidar "^1.6.0" @@ -6704,7 +5786,6 @@ solium@^1.1.6: solparse@2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.5.tgz#72709c867cd6bfc50ec2325f4b81d2b3ea365d99" - integrity sha512-t7tvtR6KU6QfPYLMv1nlCh9DA8HYIu5tbjHpKu0fhGFZ1NuSp0KKDHfFHv07g6v1xgcuUY3rVqNFjZt5b9+5qA== dependencies: mocha "^4.0.1" pegjs "^0.10.0" @@ -6713,17 +5794,14 @@ solparse@2.2.5: sorted-array-functions@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.2.0.tgz#43265b21d6e985b7df31621b1c11cc68d8efc7c3" - integrity sha512-sWpjPhIZJtqO77GN+LD8dDsDKcWZ9GCOJNqKzi1tvtjGIzwfoyuRH8S0psunmc6Z5P+qfDqztSbwYR5X/e1UTg== source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== dependencies: atob "^2.1.1" decode-uri-component "^0.2.0" @@ -6734,14 +5812,12 @@ source-map-resolve@^0.5.0: source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== dependencies: source-map "^0.5.6" source-map-support@^0.5.3: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -6749,29 +5825,24 @@ source-map-support@^0.5.3: source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= dependencies: amdefine ">=0.0.4" spdx-correct@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" - integrity sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -6779,12 +5850,10 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" @@ -6792,29 +5861,24 @@ spdx-expression-parse@^3.0.0: spdx-license-ids@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f" - integrity sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@>=1.0.3: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" - integrity sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw= sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: version "1.15.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2" - integrity sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -6829,12 +5893,10 @@ sshpk@^1.7.0: stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -6842,27 +5904,22 @@ static-extend@^0.1.1: "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== stdio@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/stdio/-/stdio-0.2.7.tgz#a1c57da10fe1cfaa0c3bf683c9d0743d1b660839" - integrity sha1-ocV9oQ/hz6oMO/aDydB0PRtmCDk= stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds= dependencies: inherits "~2.0.1" readable-stream "^2.0.2" @@ -6870,7 +5927,6 @@ stream-browserify@^2.0.1: stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" @@ -6881,22 +5937,10 @@ stream-http@^2.7.2: strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - -string-extended@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/string-extended/-/string-extended-0.0.8.tgz#741957dff487b0272a79eec5a44f239ee6f17ccd" - integrity sha1-dBlX3/SHsCcqee7FpE8jnubxfM0= - dependencies: - array-extended "~0.0.5" - date-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -6905,7 +5949,6 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" @@ -6913,7 +5956,6 @@ string-width@^1.0.1: string.prototype.trim@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" - integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= dependencies: define-properties "^1.1.2" es-abstract "^1.5.0" @@ -6922,109 +5964,92 @@ string.prototype.trim@~1.1.2: string_decoder@^1.0.0, string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== dependencies: is-natural-number "^4.0.1" strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= dependencies: is-hex-prefixed "1.0.0" strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= supports-color@4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== dependencies: has-flag "^2.0.0" supports-color@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== dependencies: has-flag "^3.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" supports-color@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= dependencies: has-flag "^2.0.0" supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" swarm-js@0.1.37: version "0.1.37" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" - integrity sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ== dependencies: bluebird "^3.5.0" buffer "^5.0.5" @@ -7043,7 +6068,6 @@ swarm-js@0.1.37: table@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" - integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== dependencies: ajv "^5.2.3" ajv-keywords "^2.1.0" @@ -7055,12 +6079,10 @@ table@4.0.2: tapable@^0.2.7: version "0.2.8" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" - integrity sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI= tape@^4.4.0, tape@^4.6.3: version "4.9.1" resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9" - integrity sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw== dependencies: deep-equal "~1.0.1" defined "~1.0.0" @@ -7079,7 +6101,6 @@ tape@^4.4.0, tape@^4.6.3: tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== dependencies: bl "^1.0.0" buffer-alloc "^1.2.0" @@ -7092,7 +6113,6 @@ tar-stream@^1.5.2: tar.gz@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" - integrity sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg== dependencies: bluebird "^2.9.34" commander "^2.8.1" @@ -7103,7 +6123,6 @@ tar.gz@^1.0.5: tar@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= dependencies: block-stream "*" fstream "^1.0.2" @@ -7112,7 +6131,6 @@ tar@^2.1.1: tar@^4: version "4.4.6" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" - integrity sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg== dependencies: chownr "^1.0.1" fs-minipass "^1.2.5" @@ -7125,7 +6143,6 @@ tar@^4: taskgroup@^4.0.5, taskgroup@^4.2.0: version "4.3.1" resolved "https://registry.yarnpkg.com/taskgroup/-/taskgroup-4.3.1.tgz#7de193febd768273c457730497024d512c27915a" - integrity sha1-feGT/r12gnPEV3MElwJNUSwnkVo= dependencies: ambi "^2.2.0" csextends "^1.0.3" @@ -7133,43 +6150,36 @@ taskgroup@^4.0.5, taskgroup@^4.2.0: text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= thenify-all@^1.0.0, thenify-all@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.0" resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" - integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= dependencies: any-promise "^1.0.0" through@^2.3.6, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-browserify@^2.0.4: version "2.0.10" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== dependencies: setimmediate "^1.0.4" timers-ext@^0.1.5: version "0.1.7" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" - integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== dependencies: es5-ext "~0.10.46" next-tick "1" @@ -7177,7 +6187,6 @@ timers-ext@^0.1.5: tingodb@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/tingodb/-/tingodb-0.6.1.tgz#f63336259af7dfa6c90dfe2556a0dfb0d4eede59" - integrity sha1-9jM2JZr336bJDf4lVqDfsNTu3lk= dependencies: lodash "^4.17.5" safe "^0.4.5" @@ -7188,36 +6197,30 @@ tingodb@^0.6.1: tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= to-buffer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -7225,7 +6228,6 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" @@ -7235,7 +6237,6 @@ to-regex@^3.0.1, to-regex@^3.0.2: tough-cookie@>=2.3.3, tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: psl "^1.1.24" punycode "^1.4.1" @@ -7243,27 +6244,22 @@ tough-cookie@>=2.3.3, tough-cookie@~2.4.3: tree-kill@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" - integrity sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg== trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= truffle-blockchain-utils@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-blockchain-utils/-/truffle-blockchain-utils-0.0.5.tgz#a4e5c064dadd69f782a137f3d276d21095da7a47" - integrity sha1-pOXAZNrdafeCoTfz0nbSEJXaekc= truffle-contract-schema@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/truffle-contract-schema/-/truffle-contract-schema-2.0.1.tgz#9bf821d32e26e674ba15eb5d40f96b10b1c9d568" - integrity sha1-m/gh0y4m5nS6FetdQPlrELHJ1Wg= dependencies: ajv "^5.1.1" crypto-js "^3.1.9-1" @@ -7272,7 +6268,6 @@ truffle-contract-schema@^2.0.1: truffle-contract@^3.0.4: version "3.0.6" resolved "https://registry.yarnpkg.com/truffle-contract/-/truffle-contract-3.0.6.tgz#2ef6fc32d7faafa9f4aed8e50001a9fdea342192" - integrity sha1-Lvb8Mtf6r6n0rtjlAAGp/eo0IZI= dependencies: ethjs-abi "0.1.8" truffle-blockchain-utils "^0.0.5" @@ -7283,12 +6278,10 @@ truffle-contract@^3.0.4: truffle-error@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/truffle-error/-/truffle-error-0.0.3.tgz#4bf55242e14deee1c7194932709182deff2c97ca" - integrity sha1-S/VSQuFN7uHHGUkycJGC3v8sl8o= truffle-hdwallet-provider-privkey@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider-privkey/-/truffle-hdwallet-provider-privkey-0.1.0.tgz#9417047a74ad37d923df926154b6486ffb57f6c9" - integrity sha512-Vj04yr2d9qLRZspoHztbE/YQnVaoFb90JNZHtggRUm+JFm/NOiSJHLVI63+3mtUIuQ04EuKZ7Df8JQw0Ni7IeA== dependencies: ethereumjs-tx "^1.3.3" ethereumjs-wallet "^0.6.0" @@ -7298,7 +6291,6 @@ truffle-hdwallet-provider-privkey@^0.1.0: truffle-wallet-provider@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-wallet-provider/-/truffle-wallet-provider-0.0.5.tgz#db59ce6fa1c558766011137509a94dfca8d1408e" - integrity sha1-21nOb6HFWHZgERN1CalN/KjRQI4= dependencies: ethereumjs-wallet "^0.6.0" web3 "^0.18.2" @@ -7307,7 +6299,6 @@ truffle-wallet-provider@0.0.5: truffle@^4.1.13: version "4.1.14" resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.14.tgz#8d2c298e29abf9b1e486e44ff9faca6d34bb9030" - integrity sha512-e7tTLvKP3bN9dE7MagfWyFjy4ZgoEGbeujECy1me1ENBzbj/aO/+45gs72qsL3+3IkCNNcWNOJjjrm8BYZZNNg== dependencies: mocha "^4.1.0" original-require "1.0.1" @@ -7316,36 +6307,30 @@ truffle@^4.1.13: tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.13.2.tgz#453161770469d45cd266c36404e2bc99a8fa9944" - integrity sha1-RTFhdwRp1FzSZsNkBOK8maj6mUQ= tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" - integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== dependencies: media-typer "0.3.0" mime-types "~2.1.18" @@ -7353,36 +6338,30 @@ type-is@~1.6.16: typechecker@^2.0.8: version "2.1.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.1.0.tgz#d1c2093a54ff8a19f58cff877eeaa54f2242d383" - integrity sha1-0cIJOlT/ihn1jP+HfuqlTyJC04M= typechecker@^4.3.0: version "4.6.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.6.0.tgz#d245d9c2df21147d5e2a942fff170b68ece73c87" - integrity sha512-83OrXpyP3LNr7aRbLkt2nkjE/d7q8su8/uRvrKxCpswqVCVGOgyaKpaz8/MTjQqBYe4eLNuJ44pNakFZKqyPMA== dependencies: editions "^2.0.2" typechecker@~2.0.1: version "2.0.8" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.0.8.tgz#e83da84bb64c584ccb345838576c40b0337db82e" - integrity sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4= typedarray-to-buffer@^3.1.2: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -7392,7 +6371,6 @@ uglify-js@^2.8.29: uglify-js@^3.1.4: version "3.4.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" - integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== dependencies: commander "~2.17.1" source-map "~0.6.1" @@ -7400,12 +6378,10 @@ uglify-js@^3.1.4: uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= uglifyjs-webpack-plugin@^0.4.6: version "0.4.6" resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" - integrity sha1-uVH0q7a9YX5m9j64kUmOORdj4wk= dependencies: source-map "^0.5.6" uglify-js "^2.8.29" @@ -7414,12 +6390,10 @@ uglifyjs-webpack-plugin@^0.4.6: ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== unbzip2-stream@^1.0.9: version "1.3.1" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" - integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw== dependencies: buffer "^3.0.1" through "^2.3.6" @@ -7427,17 +6401,14 @@ unbzip2-stream@^1.0.9: underscore@1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= underscore@^1.8.3: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -7447,22 +6418,18 @@ union-value@^1.0.0: universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== unorm@^1.3.3: version "1.4.1" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300" - integrity sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA= unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -7470,41 +6437,34 @@ unset-value@^1.0.0: upath@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= dependencies: prepend-http "^1.0.1" url-set-query@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= dependencies: punycode "1.3.2" querystring "0.2.0" @@ -7512,66 +6472,65 @@ url@^0.11.0: use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== utf8@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" - integrity sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g= utf8@^2.1.1, utf8@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" - integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY= utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= dependencies: inherits "2.0.1" util@^0.10.3: version "0.10.4" resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== dependencies: inherits "2.0.3" +utile@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a" + dependencies: + async "~0.9.0" + deep-equal "~0.2.1" + i "0.3.x" + mkdirp "0.x.x" + ncp "1.0.x" + rimraf "2.x.x" + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== valid-url@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" @@ -7579,17 +6538,14 @@ validate-npm-package-license@^3.0.1: varint@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf" - integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8= vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -7598,14 +6554,12 @@ verror@1.10.0: vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= dependencies: indexof "0.0.1" watchpack@^1.4.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== dependencies: chokidar "^2.0.2" graceful-fs "^4.1.2" @@ -7614,7 +6568,6 @@ watchpack@^1.4.0: watchr@~2.4.13: version "2.4.13" resolved "https://registry.yarnpkg.com/watchr/-/watchr-2.4.13.tgz#d74847bb4d6f90f61fe2c74f9f68662aa0e07601" - integrity sha1-10hHu01vkPYf4sdPn2hmKqDgdgE= dependencies: eachr "^2.0.2" extendr "^2.1.0" @@ -7628,7 +6581,6 @@ watchr@~2.4.13: web3-bzz@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.34.tgz#068d37777ab65e5c60f8ec8b9a50cfe45277929c" - integrity sha1-Bo03d3q2Xlxg+OyLmlDP5FJ3kpw= dependencies: got "7.1.0" swarm-js "0.1.37" @@ -7637,7 +6589,6 @@ web3-bzz@1.0.0-beta.34: web3-core-helpers@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz#b168da00d3e19e156bc15ae203203dd4dfee2d03" - integrity sha1-sWjaANPhnhVrwVriAyA91N/uLQM= dependencies: underscore "1.8.3" web3-eth-iban "1.0.0-beta.34" @@ -7646,7 +6597,6 @@ web3-core-helpers@1.0.0-beta.34: web3-core-method@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz#ec163c8a2c490fa02a7ec15559fa7307fc7cc6dd" - integrity sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7657,7 +6607,6 @@ web3-core-method@1.0.0-beta.34: web3-core-promievent@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz#a4f4fa6784bb293e82c60960ae5b56a94cd03edc" - integrity sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw= dependencies: any-promise "1.3.0" eventemitter3 "1.1.1" @@ -7665,7 +6614,6 @@ web3-core-promievent@1.0.0-beta.34: web3-core-requestmanager@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz#01f8f6cf2ae6b6f0b70c38bae1ef741b5bab215c" - integrity sha1-Afj2zyrmtvC3DDi64e90G1urIVw= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7676,7 +6624,6 @@ web3-core-requestmanager@1.0.0-beta.34: web3-core-subscriptions@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz#9fed144033f221c3cf21060302ffdaf5ef2de2de" - integrity sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4= dependencies: eventemitter3 "1.1.1" underscore "1.8.3" @@ -7685,7 +6632,6 @@ web3-core-subscriptions@1.0.0-beta.34: web3-core@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.34.tgz#121be8555e9fb00d2c5d05ddd3381d0c9e46987e" - integrity sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4= dependencies: web3-core-helpers "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7695,7 +6641,6 @@ web3-core@1.0.0-beta.34: web3-eth-abi@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz#034533e3aa2f7e59ff31793eaea685c0ed5af67a" - integrity sha1-A0Uz46ovfln/MXk+rqaFwO1a9no= dependencies: bn.js "4.11.6" underscore "1.8.3" @@ -7705,7 +6650,6 @@ web3-eth-abi@1.0.0-beta.34: web3-eth-accounts@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz#e09142eeecc797ac3459b75e9b23946d3695f333" - integrity sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM= dependencies: any-promise "1.3.0" crypto-browserify "3.12.0" @@ -7721,7 +6665,6 @@ web3-eth-accounts@1.0.0-beta.34: web3-eth-contract@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz#9dbb38fae7643a808427a20180470ec7415c91e6" - integrity sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -7735,7 +6678,6 @@ web3-eth-contract@1.0.0-beta.34: web3-eth-iban@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz#9af458605867ccf74ea979aaf326b38ba6a5ba0c" - integrity sha1-mvRYYFhnzPdOqXmq8yazi6alugw= dependencies: bn.js "4.11.6" web3-utils "1.0.0-beta.34" @@ -7743,7 +6685,6 @@ web3-eth-iban@1.0.0-beta.34: web3-eth-personal@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz#9afba167342ebde5420bcd5895c3f6c34388f205" - integrity sha1-mvuhZzQuveVCC81YlcP2w0OI8gU= dependencies: web3-core "1.0.0-beta.34" web3-core-helpers "1.0.0-beta.34" @@ -7754,7 +6695,6 @@ web3-eth-personal@1.0.0-beta.34: web3-eth@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.34.tgz#74086000850c6fe6f535ef49837d6d4bb6113268" - integrity sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -7772,7 +6712,6 @@ web3-eth@1.0.0-beta.34: web3-net@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.34.tgz#427cea2f431881449c8e38d523290f173f9ff63d" - integrity sha1-QnzqL0MYgUScjjjVIykPFz+f9j0= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7781,7 +6720,6 @@ web3-net@1.0.0-beta.34: web3-provider-engine@^13.6.4: version "13.8.0" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz#4c7c1ad2af5f1fe10343b8a65495879a2f9c00df" - integrity sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ== dependencies: async "^2.5.0" clone "^2.0.0" @@ -7806,7 +6744,6 @@ web3-provider-engine@^13.6.4: web3-provider-engine@^8.4.0: version "8.6.1" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz#4d86e19e30caaf97df351511ec0f60136e5b30eb" - integrity sha1-TYbhnjDKr5ffNRUR7A9gE25bMOs= dependencies: async "^2.1.2" clone "^2.0.0" @@ -7826,7 +6763,6 @@ web3-provider-engine@^8.4.0: web3-providers-http@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz#e561b52bbb43766282007d40285bfe3550c27e7a" - integrity sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno= dependencies: web3-core-helpers "1.0.0-beta.34" xhr2 "0.1.4" @@ -7834,7 +6770,6 @@ web3-providers-http@1.0.0-beta.34: web3-providers-ipc@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz#a1b77f1a306d73649a9c039052e40cb71328d00a" - integrity sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao= dependencies: oboe "2.1.3" underscore "1.8.3" @@ -7843,7 +6778,6 @@ web3-providers-ipc@1.0.0-beta.34: web3-providers-ws@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz#7de70f1b83f2de36476772156becfef6e3516eb3" - integrity sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7852,7 +6786,6 @@ web3-providers-ws@1.0.0-beta.34: web3-shh@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.34.tgz#975061d71eaec42ccee576f7bd8f70f03844afe0" - integrity sha1-l1Bh1x6uxCzO5Xb3vY9w8DhEr+A= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7862,7 +6795,6 @@ web3-shh@1.0.0-beta.34: web3-utils@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.34.tgz#9411fc39aaef39ca4e06169f762297d9ff020970" - integrity sha1-lBH8OarvOcpOBhafdiKX2f8CCXA= dependencies: bn.js "4.11.6" eth-lib "0.1.27" @@ -7875,7 +6807,6 @@ web3-utils@1.0.0-beta.34: web3@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/web3/-/web3-0.19.1.tgz#e763d5b1107c4bc24abd4f8cbee1ba3659e6eb31" - integrity sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE= dependencies: bignumber.js "^4.0.2" crypto-js "^3.1.4" @@ -7886,7 +6817,6 @@ web3@0.19.1: web3@0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.2.tgz#c54dac5fc0e377399c04c1a6ecbb12e4513278d6" - integrity sha1-xU2sX8DjdzmcBMGm7LsS5FEyeNY= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7897,7 +6827,6 @@ web3@0.20.2: web3@0.20.6: version "0.20.6" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.6.tgz#3e97306ae024fb24e10a3d75c884302562215120" - integrity sha1-PpcwauAk+yThCj11yIQwJWIhUSA= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7908,7 +6837,6 @@ web3@0.20.6: web3@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.34.tgz#347e561b784098cb5563315f490479a1d91f2ab1" - integrity sha1-NH5WG3hAmMtVYzFfSQR5odkfKrE= dependencies: web3-bzz "1.0.0-beta.34" web3-core "1.0.0-beta.34" @@ -7921,7 +6849,6 @@ web3@1.0.0-beta.34: web3@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" - integrity sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js#master" crypto-js "^3.1.4" @@ -7931,7 +6858,6 @@ web3@^0.16.0: web3@^0.18.2, web3@^0.18.4: version "0.18.4" resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" - integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" crypto-js "^3.1.4" @@ -7942,7 +6868,6 @@ web3@^0.18.2, web3@^0.18.4: web3@^0.20.5: version "0.20.7" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.7.tgz#1605e6d81399ed6f85a471a4f3da0c8be57df2f7" - integrity sha512-VU6/DSUX93d1fCzBz7WP/SGCQizO1rKZi4Px9j/3yRyfssHyFcZamMw2/sj4E8TlfMXONvZLoforR8B4bRoyTQ== dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7953,7 +6878,6 @@ web3@^0.20.5: webpack-sources@^1.0.1: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" - integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== dependencies: source-list-map "^2.0.0" source-map "~0.6.1" @@ -7961,7 +6885,6 @@ webpack-sources@^1.0.1: webpack@^3.0.0: version "3.12.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.12.0.tgz#3f9e34360370602fcf639e97939db486f4ec0d74" - integrity sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ== dependencies: acorn "^5.0.0" acorn-dynamic-import "^2.0.0" @@ -7998,46 +6921,50 @@ webpack@^3.0.0: whatwg-fetch@>=0.10.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@^1.1.1, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= + +winston@2.1.x: + version "2.1.1" + resolved "http://registry.npmjs.org/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" + dependencies: + async "~1.0.0" + colors "1.0.x" + cycle "1.0.x" + eyes "0.1.x" + isstream "0.1.x" + pkginfo "0.3.x" + stack-trace "0.0.x" winston@^2.3.1: version "2.4.4" resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.4.tgz#a01e4d1d0a103cf4eada6fc1f886b3110d71c34b" - integrity sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q== dependencies: async "~1.0.0" colors "1.0.x" @@ -8049,22 +6976,18 @@ winston@^2.3.1: wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= wordwrap@^1.0.0, wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -8072,19 +6995,16 @@ wrap-ansi@^2.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= dependencies: mkdirp "^0.5.1" ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" @@ -8093,14 +7013,12 @@ ws@^3.0.0: xhr-request-promise@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" - integrity sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0= dependencies: xhr-request "^1.0.1" xhr-request@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== dependencies: buffer-to-arraybuffer "^0.0.5" object-assign "^4.1.1" @@ -8113,19 +7031,16 @@ xhr-request@^1.0.1: xhr2-cookies@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= dependencies: cookiejar "^2.1.1" xhr2@*, xhr2@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" - integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8= xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: version "2.5.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" - integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== dependencies: global "~4.3.0" is-function "^1.0.1" @@ -8135,49 +7050,40 @@ xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: xmlhttprequest@*, xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= xregexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" - integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= dependencies: object-keys "~0.4.0" y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= dependencies: camelcase "^3.0.0" lodash.assign "^4.0.6" @@ -8185,28 +7091,24 @@ yargs-parser@^2.4.1: yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k= dependencies: camelcase "^4.1.0" yargs-parser@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== dependencies: camelcase "^4.1.0" yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= dependencies: camelcase "^4.1.0" yargs@^10.0.3: version "10.1.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" - integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -8224,7 +7126,6 @@ yargs@^10.0.3: yargs@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -8242,7 +7143,6 @@ yargs@^11.0.0: yargs@^4.6.0, yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= dependencies: cliui "^3.2.0" decamelize "^1.1.1" @@ -8262,7 +7162,6 @@ yargs@^4.6.0, yargs@^4.7.1: yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - integrity sha1-YpmpBVsc78lp/355wdkY3Osiw2A= dependencies: camelcase "^4.1.0" cliui "^3.2.0" @@ -8281,7 +7180,6 @@ yargs@^8.0.2: yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= dependencies: camelcase "^1.0.2" cliui "^2.1.0" @@ -8291,7 +7189,6 @@ yargs@~3.10.0: yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" From 0bd03fb1142b13979fa421c635fb95c851a8bbeb Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 27 Nov 2018 15:11:17 +0530 Subject: [PATCH 209/582] suggested changes imlemented --- .../BlacklistTransferManager.sol | 22 +++++++++++++------ test/z_blacklist_transfer_manager.js | 8 ------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index ac4770462..15a57b82e 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -18,7 +18,7 @@ contract BlacklistTransferManager is ITransferManager { } //hold the different blacklist details corresponds to its name - mapping(bytes32 => BlacklistsDetails) blacklists; + mapping(bytes32 => BlacklistsDetails) public blacklists; //hold the different name of blacklist corresponds to a investor mapping(address => bytes32[]) investorToBlacklist; @@ -129,7 +129,7 @@ contract BlacklistTransferManager is ITransferManager { */ function addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) public withPerm(ADMIN) { require(blacklists[_name].endTime == 0, "Blacklist type already exist"); - _validParams(_startTime, _endTime, _name, _repeatPeriodTime); + _validParams(_startTime, _endTime, _name); blacklists[_name] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); emit AddBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); } @@ -151,10 +151,9 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Internal function */ - function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) internal pure { + function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _name) internal view { require(_name != bytes32(0), "Invalid blacklist name"); - require(_startTime != 0 && _startTime < _endTime, "Invalid start or end date"); - require(_repeatPeriodTime != 0, "Invalid repeat days"); + require(_startTime >= now && _startTime < _endTime, "Invalid start or end date"); } /** @@ -166,7 +165,7 @@ contract BlacklistTransferManager is ITransferManager { */ function modifyBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) public withPerm(ADMIN) { require(blacklists[_name].endTime != 0, "Blacklist type doesn't exist"); - _validParams(_startTime, _endTime, _name, _repeatPeriodTime); + _validParams(_startTime, _endTime, _name); blacklists[_name] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); emit ModifyBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); } @@ -334,11 +333,20 @@ contract BlacklistTransferManager is ITransferManager { * @param _blacklistName Name of the blacklist type * @return address List of investors associated with the blacklist */ - function getListOfAddresses(bytes32 _blacklistName) public view returns(address[]) { + function getListOfAddresses(bytes32 _blacklistName) external view returns(address[]) { require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); return blacklistToInvestor[_blacklistName]; } + /** + * @notice get the list of the investors of a blacklist type + * @param _user Address of the user + * @return bytes32 List of blacklist names associated with the given address + */ + function getBlacklistNamesToUser(address _user) external view returns(bytes32[]) { + return investorToBlacklist[_user]; + } + /** * @notice Return the permissions flag that are associated with blacklist transfer manager */ diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index ae6d8b9f2..e50efbd14 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -370,14 +370,6 @@ contract('BlacklistTransferManager', accounts => { ); }); - it("Should fail in adding the blacklist as repeat in days is invalid", async() => { - await catchRevert( - I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 0, { - from: token_owner - }) - ); - }); - it("Should fail in adding the blacklist because only owner can add the blacklist", async() => { await catchRevert( I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { From 55eac4b8e205e6af72d5c0eae6c3099a8e7aca88 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Tue, 27 Nov 2018 11:47:35 +0100 Subject: [PATCH 210/582] save WIP --- .../z_fuzz_test_adding_removing_modules_ST.js | 1263 +++++++++++++++++ 1 file changed, 1263 insertions(+) create mode 100644 test/z_fuzz_test_adding_removing_modules_ST.js diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js new file mode 100644 index 000000000..1250d8fc2 --- /dev/null +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -0,0 +1,1263 @@ +import latestTime from './helpers/latestTime'; +import {signData} from './helpers/signData'; +import { pk } from './helpers/testprivateKey'; +import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { catchRevert } from "./helpers/exceptions"; +import { setUpPolymathNetwork, + deployGPMAndVerifyed, + deployCountTMAndVerifyed, + deployLockupVolumeRTMAndVerified, + deployPercentageTMAndVerified, + deploySingleTradeVolumeRMAndVerified, + deployManualApprovalTMAndVerifyed +} from "./helpers/createInstances"; +import { encodeModuleCall } from "./helpers/encodeCall"; + +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const CountTransferManager = artifacts.require("./CountTransferManager"); +const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); +const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); +const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionTM'); +const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('GeneralPermissionManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let token_owner_pk; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_delegate; + let account_delegate2; + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let P_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let P_GeneralPermissionManager; + let I_GeneralTransferManagerFactory; + let I_VolumeRestrictionTransferManagerFactory; + let I_PercentageTransferManagerFactory; + let I_PercentageTransferManager; + let I_VolumeRestrictionTransferManager; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_DummySTOFactory; + let I_STFactory; + let I_SecurityToken; + let I_MRProxied; + let I_STRProxied; + let I_PolyToken; + let I_PolymathRegistry; + let I_CountTransferManagerFactory; + let I_CountTransferManager; + let I_SingleTradeVolumeRestrictionManagerFactory; + let I_SingleTradeVolumeRestrictionManager; + let I_SingleTradeVolumeRestrictionPercentageManager; + let P_SingleTradeVolumeRestrictionManager; + let P_SingleTradeVolumeRestrictionManagerFactory; + let I_ManualApprovalTransferManagerFactory; + let I_ManualApprovalTransferManager; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + const delegateDetails = "Hello I am legit delegate"; + const STVRParameters = ["bool", "uint256", "bool"]; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // CountTransferManager details + const holderCount = 2; // Maximum number of token holders + let bytesSTO = encodeModuleCall(["uint256"], [holderCount]); + + let _details = "details holding for test"; + let testRepeat = 20; + + // permission manager fuzz test + let perms = ['ADMIN','WHITELIST', 'FLAGS', 'TRANSFER_APPROVAL']; + let totalPerms = perms.length; + + before(async () => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + token_owner_pk = pk.account_1; + + account_investor1 = accounts[8]; + account_investor2 = accounts[9]; + account_investor3 = accounts[5]; + account_investor4 = accounts[6]; + account_delegate = accounts[7]; + // account_delegate2 = accounts[6]; + + + // Step 1: Deploy the genral PM ecosystem + let instances = await setUpPolymathNetwork(account_polymath, token_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; + + // STEP 5: Deploy the GeneralDelegateManagerFactory + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 6: Deploy the GeneralDelegateManagerFactory + [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + + // Deploy Modules + [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + + [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${I_PolymathRegistry.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistryProxy ${I_ModuleRegistryProxy.address} + ModuleRegistry: ${I_ModuleRegistry.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + STFactory: ${I_STFactory.address} + GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${I_GeneralPermissionManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async () => { + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from: token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal(web3.utils.toAscii(log.args._name).replace(/\u0000/g, ""), "GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + + it("Should successfully attach the General permission manager factory with the security token -- failed because Token is not paid", async () => { + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await catchRevert( + I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }) + ); + }); + + it("Should successfully attach the General permission manager factory with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); + const tx = await I_SecurityToken.addModule( + P_GeneralPermissionManagerFactory.address, + "0x", + web3.utils.toWei("500", "ether"), + 0, + { from: token_owner } + ); + assert.equal(tx.logs[3].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), + "GeneralPermissionManager", + "GeneralPermissionManagerFactory module was not added" + ); + P_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the General permission manager factory with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "GeneralPermissionManager", + "GeneralPermissionManagerFactory module was not added" + ); + I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); + }); + }); + + describe("fuzz test for general transfer manager", async () => { + + it("should pass fuzz test for changeIssuanceAddress(), changeSigningAddress() ", async () => { + + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, 'FLAGS') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, 'FLAGS', false, { from: token_owner }); + } else if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, 'WHITELIST') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, 'WHITELIST', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + + await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, randomPerms, true, { from: token_owner }); + + let currentAllowAllTransferStats = await I_GeneralTransferManager.allowAllTransfers(); + let currentAllowAllWhitelistTransfersStats = await I_GeneralTransferManager.allowAllWhitelistTransfers(); + let currentAllowAllWhitelistIssuancesStats = await I_GeneralTransferManager.allowAllWhitelistIssuances(); + let currentAllowAllBurnTransfersStats = await I_GeneralTransferManager.allowAllBurnTransfers(); + + // let userPerm = await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, 'FLAGS'); + if (randomPerms === 'FLAGS') { + await I_GeneralTransferManager.changeIssuanceAddress( accounts[j], { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.issuanceAddress(), accounts[j]); + + await I_GeneralTransferManager.changeSigningAddress( accounts[j], { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.signingAddress(), accounts[j]); + + await I_GeneralTransferManager.changeAllowAllTransfers(!currentAllowAllTransferStats, { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.allowAllTransfers(), !currentAllowAllTransferStats); + + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(!currentAllowAllWhitelistTransfersStats, { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.allowAllWhitelistTransfers(), !currentAllowAllWhitelistTransfersStats); + + await I_GeneralTransferManager.changeAllowAllWhitelistIssuances(!currentAllowAllWhitelistIssuancesStats, { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.allowAllWhitelistIssuances(), !currentAllowAllWhitelistIssuancesStats); + + await I_GeneralTransferManager.changeAllowAllBurnTransfers(!currentAllowAllBurnTransfersStats, { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.allowAllBurnTransfers(), !currentAllowAllBurnTransfersStats); + + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " for functions with require perm FLAGS passed") + } else { + await catchRevert(I_GeneralTransferManager.changeIssuanceAddress( accounts[j], { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeSigningAddress( accounts[j], { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeAllowAllTransfers( !currentAllowAllTransferStats, { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeAllowAllWhitelistTransfers( !currentAllowAllWhitelistTransfersStats, { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeAllowAllWhitelistIssuances( !currentAllowAllWhitelistIssuancesStats, { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeAllowAllBurnTransfers( !currentAllowAllBurnTransfersStats, { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " for functions require perm FLAGS failed as expected"); + } + if (randomPerms === 'WHITELIST') { + let tx = await I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, true, { from: accounts[j] }); + assert.equal(tx.logs[0].args._investor, accounts[j]); + + let tx2 = await I_GeneralTransferManager.modifyWhitelistMulti([accounts[3], accounts[4]], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], [true, true], { from: accounts[j] }); + console.log(tx2.logs[1].args); + assert.equal(tx2.logs[1].args._investor, accounts[4]); + } else { + await catchRevert(I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, true, { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.modifyWhitelistMulti([accounts[3], accounts[4]], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], [true, true], { from: accounts[j] })); + } + } + + await I_GeneralTransferManager.changeIssuanceAddress("0x0000000000000000000000000000000000000000", { from: token_owner }); + }) + }); + + describe("fuzz test for count transfer manager", async () => { + + it("Should successfully attach the CountTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "CountTransferManager", + "CountTransferManager module was not added" + ); + I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); + }); + + it("should pass fuzz test for changeHolderCount()", async () => { + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_CountTransferManager.address, 'ADMIN') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_CountTransferManager.address, 'ADMIN', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_CountTransferManager.address, randomPerms, true, { from: token_owner }); + if (randomPerms === 'ADMIN') { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + await I_CountTransferManager.changeHolderCount(i + 1, { from: accounts[j] }); + assert.equal((await I_CountTransferManager.maxHolderCount()).toNumber(), i + 1); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " passed"); + } else { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert(I_CountTransferManager.changeHolderCount(i+1, { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + } + }); + }); + + // lock up volume TM needs code change, not testing now but keeping the code for future testing + // describe("fuzz test for lockup volume restriction transfer manager", async () => { + + // it("Should Buy some tokens", async() => { + + // await I_GeneralTransferManager.changeIssuanceAddress("0x0000000000000000000000000000000000000000", { from: token_owner }); + + // // Add the Investor in to the whitelist + // console.log("0"); + // let tx = await I_GeneralTransferManager.modifyWhitelist( + // account_investor2, + // latestTime(), + // latestTime(), + // latestTime() + duration.days(10), + // true, + // { + // from: account_issuer + // }); + + // assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + // console.log("1"); + + // let tx2 = await I_GeneralTransferManager.modifyWhitelist( + // account_investor3, + // latestTime(), + // latestTime(), + // latestTime() + duration.days(10), + // true, + // { + // from: account_issuer + // }); + + // console.log("2"); + // // Jump time + // await increaseTime(5000); + + // // Mint some tokens + // await I_SecurityToken.mint(account_investor2, web3.utils.toWei('9', 'ether'), { from: token_owner }); + // console.log("1.5"); + // await I_SecurityToken.mint(account_investor3, web3.utils.toWei('9', 'ether'), { from: token_owner }); + // console.log("2"); + // // assert.equal( + // // (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + // // web3.utils.toWei('9', 'ether') + // // ); + // // assert.equal( + // // (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + // // web3.utils.toWei('9', 'ether') + // // ); + // }); + + // it("Should successfully attach the VolumeRestrictionTransferManager with the security token", async () => { + // const tx = await I_SecurityToken.addModule(I_VolumeRestrictionTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); + // assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManager doesn't get deployed"); + // assert.equal( + // web3.utils.toAscii(tx.logs[2].args._name) + // .replace(/\u0000/g, ''), + // "LockupVolumeRestrictionTM", + // "VolumeRestrictionTransferManager module was not added" + // ); + // I_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[2].args._module); + // }); + + // it("should pass fuzz test for addLockUp()", async () => { + // let balance = await I_SecurityToken.balanceOf(account_investor2); + // // await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from: token_owner }); + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + // for (var i = 2; i < testRepeat; i++) { + // var j = Math.floor(Math.random() * 10); + // if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not// + // if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + // await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + // } + + // // target permission should alaways be false for each test before assigning + // if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN') === true) { + // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN', false, { from: token_owner }); + // } + + // assign a random perm// + // let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, randomPerms, true, { from: token_owner }); + + // if (randomPerms === 'ADMIN') { + // // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + // await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from:accounts[j] }); + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " passed"); + // } else { + // // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + // await catchRevert(I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from:accounts[j] })); + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + // } + // } + // }); + + // it("should pass fuzz test for remove lock up", async () => { + // let balance = await I_SecurityToken.balanceOf(account_investor2); + // // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accountsconsole.log("1"); + // for (var i = 2; i < testRepeat; i++) { + // var j = Math.floor(Math.random() * 10); + // if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not// + // if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + // await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + // } + + // // target permission should alaways be false for each test before assigning + // if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN') === true) { + // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN', false, { from: token_owner }); + // } + + // assign a random perm// + // let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, randomPerms, true, { from: token_owner }); + + // // if lockup count is 0, add a lockup. + // let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2, { from : token_owner }); + + // if (lockUpCount === 0) { + // console.log("lock up count is " + lockUpCount); + // await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, token_owner); + // } + + // let lockUpCountNow = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2, { from : token_owner }); + + // console.log("lock up count now is "+lockUpCountNow); + + // // try remove lock up + // if (randomPerms === 'ADMIN') { + // // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + // await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from:accounts[j] }); + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " passed"); + // } else { + // // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + // await catchRevert(I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from:accounts[j] })); + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + // } + // } + // }); + + // it("should pass fuzz test for add multiple lock ups", async () => { + + // // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts// add mutiple lock ups at once + // for (var i = 2; i < testRepeat; i++) { + // var j = Math.floor(Math.random() * 10); + // if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not// + // if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + // await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + // } + + // // target permission should alaways be false for each test before assigning + // if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN') === true) { + // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN', false, { from: token_owner }); + // } + + // assign a random perm// + // let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, randomPerms, true, { from: token_owner }); + + // // check current lockup count before adding multiple + // let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); + // let lockUpCount2 = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); + + // let balance = await I_SecurityToken.balanceOf(account_investor2); + // let balance2 = await I_SecurityToken.balanceOf(account_investor3); + + // // try add multi lock ups + // if (randomPerms === 'ADMIN') { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + // console.log("current perm should be true --> " + await I_GeneralPermissionManager.checkPermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN')); + // await I_VolumeRestrictionTransferManager.addLockUpMulti( + // [account_investor2, account_investor3], + // [24, 8], + // [4, 4], + // [0, 0], + // [balance, balance2], + // { from: accounts[j] } + // ); + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " passed"); + // assert.equal(await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2), lockUpCount+1); + // assert.equal(await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3), lockUpCount2+1); + // } else { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + // await catchRevert( + // I_VolumeRestrictionTransferManager.addLockUpMulti( + // [account_investor2, account_investor3], + // [24, 8], + // [4, 4], + // [0, 0], + // [balance, balance2], + // { from: accounts[j] } + // )); + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + // } + // } + + // }); + + // it("should pass fuzz test for modify lock ups", async () => { + // // add a lock up if there is no existing one + + // // modify lock up + + // // paused due to the current module is not ready for test + // }); + + // }); + + + describe("fuzz test for percentage transfer manager", async () => { + + // PercentageTransferManager details + const holderPercentage = 70 * 10**16; // Maximum number of token holders + + let bytesSTO = web3.eth.abi.encodeFunctionCall({ + name: 'configure', + type: 'function', + inputs: [{ + type: 'uint256', + name: '_maxHolderPercentage' + },{ + type: 'bool', + name: '_allowPrimaryIssuance' + } + ] + }, [holderPercentage, false]); + + it("Should successfully attach the percentage transfer manager with the security token", async () => { + console.log("1"); + const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + I_PercentageTransferManager = PercentageTransferManager.at(tx.logs[2].args._module); + }); + + it("should pass fuzz test for modifyWhitelist with perm WHITELIST", async () => { + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, randomPerms, true, { from: token_owner }); + + //try add multi lock ups + if (randomPerms === 'WHITELIST') { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + await I_PercentageTransferManager.modifyWhitelist(account_investor3, true, { from: accounts[j] }); + console.log("Test number " + i + " with account " + j + " and perm WHITELIST passed as expected"); + } else { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert(I_PercentageTransferManager.modifyWhitelist(account_investor3, true, { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + } + }); + + it("should pass fuzz test for modifyWhitelistMulti with perm WHITELIST", async () => { + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms === 'WHITELIST') { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + await I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [false, true], { from: accounts[j] }); + console.log("Test number " + i + " with account " + j + " and perm WHITELIST passed as expected"); + + } else { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert( I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [false, true], { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + } + }); + + it("should pass fuzz test for setAllowPrimaryIssuance with perm ADMIN", async () => { + + // let snapId = await takeSnapshot(); + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, 'ADMIN') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, 'ADMIN', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, randomPerms, true, { from: token_owner }); + + let primaryIssuanceStat = await I_PercentageTransferManager.allowPrimaryIssuance({ from: token_owner }); + + if (randomPerms === 'ADMIN') { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + await I_PercentageTransferManager.setAllowPrimaryIssuance(!primaryIssuanceStat, { from: accounts[j] }); + console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); + + } else { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert( I_PercentageTransferManager.setAllowPrimaryIssuance(!primaryIssuanceStat, { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + // await revertToSnapshot(snapId); + } + }); + }); + + + describe("fuzz test for single trade volume manager", async () => { + + it("attach the single trade volume restriction manager ", async () => { + + let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); + + let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { + from: token_owner + }); + + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "SingleTradeVolumeRestrictionManager did not get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "SingleTradeVolumeRestrictionTM", + "SingleTradeVolumeRestrictionManagerFactory module was not added" + ); + P_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[3].args._module); + + managerArgs = encodeModuleCall(STVRParameters, [false, (7 * Math.pow(10, 16)).toString(), false]) + + let tx2 = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { from: token_owner }); + + I_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx2.logs[2].args._module); + + managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); + let tx3 = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { + from: token_owner + }); + + I_SingleTradeVolumeRestrictionPercentageManager = SingleTradeVolumeRestrictionManager.at(tx3.logs[2].args._module); + }); + + it("should pass fuzz test for setAllowPrimaryIssuance with perm ADMIN", async () => { + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + let snapId = await takeSnapshot(); + + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms === 'ADMIN') { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + await I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: accounts[j]}); + console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); + } else { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert( I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: accounts[j]}) ); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + + await revertToSnapshot(snapId); + } + }); + + it("should pass fuzz test for changeTransferLimitToTokens & changeGlobalLimitInTokens with perm ADMIN", async () => { + + let tx; + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + let snapId = await takeSnapshot(); + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, randomPerms, true, { from: token_owner }); + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms == 'ADMIN' ) { + console.log("current limit in percentage is "+ await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage({ from: token_owner })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + console.log("current permission for ADMIN is " + await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN')); + tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: accounts[j] }); + + // assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); + // assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); + console.log("1.1"); + tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, {from: accounts[j]}); + console.log("1.2"); + // assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); + console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); + } else { + console.log("current limit in percentage is "+ await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage({ from: token_owner })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should fail"); + console.log("current permission for ADMIN is" + await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN')); + await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: accounts[j] })); + // await catchRevert(I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, {from: token_owner})); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + + await revertToSnapshot(snapId); + } + }); + + it("should pass fuzz test for changeTransferLimitToPercentage & changeGlobalLimitInPercentage with perm ADMIN", async () => { + + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + let snapId = await takeSnapshot(); + + let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: token_owner }); + + tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { from: token_owner }); + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms == "ADMIN" ) { + console.log("Test number " + i + " with account " + j + " and perm ADMIN " + " should pass"); + // console.log("current permission ADMIN status is "+ await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN')); + tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { from: accounts[j] }); + // assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); + // assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); + console.log("1.1"); + tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(40, { from: accounts[j] }); + console.log("1.2"); + // assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); + console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); + } else { + console.log("current limit in percentage is "+ await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage({ from: token_owner })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: accounts[j] })); + // await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(10, {from: token_owner})); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + + await revertToSnapshot(snapId); + } + }); + + it("should pass fuzz test for addExemptWallet, removeExemptWallet, setTransferLimitInTokens, removeTransferLimitInTokens with perm ADMIN", async () => { + + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + let snapId = await takeSnapshot(); + + let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: token_owner }); + + tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { from: token_owner}); + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms === "ADMIN" ) { + console.log("Test number " + i + " with account " + j + " and perm ADMIN " + " should pass"); + + //add + let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { from: accounts[j]}); + assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet added as exempt"); + + console.log("passed add"); + + //remove + tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { from: accounts[j] }); + assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet removed from exempt"); + + console.log("passed remove"); + + //set transfer limit in tokens + tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { from: accounts[j] }); + assert.equal(tx.logs[0].args._wallet, accounts[4]); + assert.equal(tx.logs[0].args._amount, 100); + + console.log("passed set limit in tokens"); + + tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4], { from: accounts[j] }); + assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet removed"); + console.log("removed set limit in tokens"); + + console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); + } else { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert(I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { from: accounts[j]})); + + let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { from: token_owner}); + await catchRevert(I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { from: accounts[j] })); + + await catchRevert(I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { from: accounts[j] })); + + tx = I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { from: token_owner }); + await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 50, { from: accounts[j] })); + + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + + await revertToSnapshot(snapId); + } + }); + + it("should pass fuzz test for addExemptWalletMulti, removeExemptWalletMulti, setTransferLimitInTokensMulti, removeTransferLimitInTokensMulti, setTransferLimitInPercentageMulti, removeTransferLimitInPercentageMulti with perm ADMIN", async () => { + + // console.log("0"); + + let wallets = [accounts[0], accounts[1], accounts[2]]; + let tokenLimits = [1, 2, 3]; + let percentageLimits = [5, 6, 7]; + + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + let snapId = await takeSnapshot(); + + console.log("0.1"); + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + console.log("0.2"); + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN', false, { from: token_owner }); + } + + console.log("0.3"); + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, randomPerms, true, { from: token_owner }); + await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, randomPerms, true, { from: token_owner }); + + console.log("0.4"); + + if (randomPerms === "ADMIN" ) { + console.log("Test number " + i + " with account " + j + " and perm ADMIN " + " should pass"); + + // add exempt wallet multi + let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { + from: accounts[j] + }); + + console.log("1"); + + // remove exempt wallet multi + tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { + from: accounts[j] + }); + + console.log("2"); + + tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { + from: accounts[j] + }); + console.log("3"); + + tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, { + from: accounts[j] + }); + console.log("4"); + + console.log("transfer limit in percentage needs to be true to pass --> " + await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage({from: accounts[j]})); + + tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { + from: accounts[j] + }); + + let logs; + + logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageSet'); + assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); + + for (let i = 0; i < wallets.length; i++) { + assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); + assert.equal(logs[i].args._percentage.toNumber(), percentageLimits[i]); + } + console.log("5"); + + tx = await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { + from: accounts[j] + }); + logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageRemoved'); + assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); + + for (let i = 0; i < wallets.length; i++) { + assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); + } + console.log("6"); + + console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); + + } else { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + + // add exempt wallet multi + let tx; + + await catchRevert( P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { + from: accounts[j] + })); + + console.log("1"); + + await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { from: token_owner }); + await catchRevert(P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { from: accounts[j] })); + + // remove exempt wallet multi + await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { from: token_owner }); + await catchRevert(P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { from: accounts[j] })); + console.log("2"); + + await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { from: token_owner }); + await catchRevert(P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, {from: accounts[j]})); + + await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, {from: token_owner}); + await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { from: accounts[j] })); + console.log("3"); + + await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { from: token_owner }); + await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { from: accounts[j] })); + + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + await revertToSnapshot(snapId); + } + + }); + + }); + + + describe("fuzz test for manual approval transfer manager", async () => { + + it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toUtf8(tx.logs[2].args._name), + "ManualApprovalTransferManager", + "ManualApprovalTransferManager module was not added" + ); + I_ManualApprovalTransferManager = ManualApprovalTransferManager.at(tx.logs[2].args._module); + }); + + it("should pass fuzz test for addManualApproval & revokeManualApproval with perm TRANSFER_APPROVAL", async () => { + + let tx; + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + let snapId = await takeSnapshot(); + + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms === "TRANSFER_APPROVAL" ) { + console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL " + " should pass"); + await I_ManualApprovalTransferManager.addManualApproval( + account_investor1, + account_investor4, + web3.utils.toWei("2", "ether"), + latestTime() + duration.days(1), + { from: accounts[j] } + ); + + console.log("2"); + tx = await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { + from: accounts[j] + }); + assert.equal(tx.logs[0].args._from, account_investor1); + assert.equal(tx.logs[0].args._to, account_investor4); + assert.equal(tx.logs[0].args._addedBy, accounts[j]); + + console.log("3"); + console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL passed as expected"); + } else { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert( + I_ManualApprovalTransferManager.addManualApproval( + account_investor1, + account_investor4, + web3.utils.toWei("2", "ether"), + latestTime() + duration.days(1), + { from: accounts[j] } + ) + ); + + await I_ManualApprovalTransferManager.addManualApproval( + account_investor1, + account_investor4, + web3.utils.toWei("2", "ether"), + latestTime() + duration.days(1), + { from: token_owner } + ); + + await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { + from: accounts[j] + }) + ); + + + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + + await revertToSnapshot(snapId); + }; + + + }); + + it("should pass fuzz test for addManualBlocking and revokeManualBlocking with perm TRANSFER_APPROVAL", async () => { + console.log("1"); + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + from: token_owner + }); + console.log("2"); + await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: token_owner }); + console.log("3"); + + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + let snapId = await takeSnapshot(); + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms === "TRANSFER_APPROVAL") { + console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL " + " should pass"); + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + from: accounts[j] + }); + + console.log("2"); + await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }); + + console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL passed as expected"); + } else { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert( + I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + from: accounts[j] + }) + ); + + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + from: token_owner + }); + + await catchRevert( + I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }) + ); + + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + + await revertToSnapshot(snapId); + }; + }); + }); + +}); From 701ea2be25123a4bb5bb05827b2bfc8b37d60e2f Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Tue, 27 Nov 2018 12:03:42 +0100 Subject: [PATCH 211/582] wip --- module-labeling | 1 + .../z_fuzz_test_adding_removing_modules_ST.js | 1016 ----------------- 2 files changed, 1 insertion(+), 1016 deletions(-) create mode 100644 module-labeling diff --git a/module-labeling b/module-labeling new file mode 100644 index 000000000..0026fe372 --- /dev/null +++ b/module-labeling @@ -0,0 +1 @@ +Branch 'module-labeling' set up to track remote branch 'module-labeling' from 'origin'. diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index 1250d8fc2..577918a74 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -244,1020 +244,4 @@ contract('GeneralPermissionManager', accounts => { I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); }); }); - - describe("fuzz test for general transfer manager", async () => { - - it("should pass fuzz test for changeIssuanceAddress(), changeSigningAddress() ", async () => { - - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, 'FLAGS') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, 'FLAGS', false, { from: token_owner }); - } else if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, 'WHITELIST') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, 'WHITELIST', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - - await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, randomPerms, true, { from: token_owner }); - - let currentAllowAllTransferStats = await I_GeneralTransferManager.allowAllTransfers(); - let currentAllowAllWhitelistTransfersStats = await I_GeneralTransferManager.allowAllWhitelistTransfers(); - let currentAllowAllWhitelistIssuancesStats = await I_GeneralTransferManager.allowAllWhitelistIssuances(); - let currentAllowAllBurnTransfersStats = await I_GeneralTransferManager.allowAllBurnTransfers(); - - // let userPerm = await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, 'FLAGS'); - if (randomPerms === 'FLAGS') { - await I_GeneralTransferManager.changeIssuanceAddress( accounts[j], { from: accounts[j] }); - assert.equal(await I_GeneralTransferManager.issuanceAddress(), accounts[j]); - - await I_GeneralTransferManager.changeSigningAddress( accounts[j], { from: accounts[j] }); - assert.equal(await I_GeneralTransferManager.signingAddress(), accounts[j]); - - await I_GeneralTransferManager.changeAllowAllTransfers(!currentAllowAllTransferStats, { from: accounts[j] }); - assert.equal(await I_GeneralTransferManager.allowAllTransfers(), !currentAllowAllTransferStats); - - await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(!currentAllowAllWhitelistTransfersStats, { from: accounts[j] }); - assert.equal(await I_GeneralTransferManager.allowAllWhitelistTransfers(), !currentAllowAllWhitelistTransfersStats); - - await I_GeneralTransferManager.changeAllowAllWhitelistIssuances(!currentAllowAllWhitelistIssuancesStats, { from: accounts[j] }); - assert.equal(await I_GeneralTransferManager.allowAllWhitelistIssuances(), !currentAllowAllWhitelistIssuancesStats); - - await I_GeneralTransferManager.changeAllowAllBurnTransfers(!currentAllowAllBurnTransfersStats, { from: accounts[j] }); - assert.equal(await I_GeneralTransferManager.allowAllBurnTransfers(), !currentAllowAllBurnTransfersStats); - - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " for functions with require perm FLAGS passed") - } else { - await catchRevert(I_GeneralTransferManager.changeIssuanceAddress( accounts[j], { from: accounts[j] })); - await catchRevert(I_GeneralTransferManager.changeSigningAddress( accounts[j], { from: accounts[j] })); - await catchRevert(I_GeneralTransferManager.changeAllowAllTransfers( !currentAllowAllTransferStats, { from: accounts[j] })); - await catchRevert(I_GeneralTransferManager.changeAllowAllWhitelistTransfers( !currentAllowAllWhitelistTransfersStats, { from: accounts[j] })); - await catchRevert(I_GeneralTransferManager.changeAllowAllWhitelistIssuances( !currentAllowAllWhitelistIssuancesStats, { from: accounts[j] })); - await catchRevert(I_GeneralTransferManager.changeAllowAllBurnTransfers( !currentAllowAllBurnTransfersStats, { from: accounts[j] })); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " for functions require perm FLAGS failed as expected"); - } - if (randomPerms === 'WHITELIST') { - let tx = await I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, true, { from: accounts[j] }); - assert.equal(tx.logs[0].args._investor, accounts[j]); - - let tx2 = await I_GeneralTransferManager.modifyWhitelistMulti([accounts[3], accounts[4]], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], [true, true], { from: accounts[j] }); - console.log(tx2.logs[1].args); - assert.equal(tx2.logs[1].args._investor, accounts[4]); - } else { - await catchRevert(I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, true, { from: accounts[j] })); - await catchRevert(I_GeneralTransferManager.modifyWhitelistMulti([accounts[3], accounts[4]], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], [true, true], { from: accounts[j] })); - } - } - - await I_GeneralTransferManager.changeIssuanceAddress("0x0000000000000000000000000000000000000000", { from: token_owner }); - }) - }); - - describe("fuzz test for count transfer manager", async () => { - - it("Should successfully attach the CountTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), - "CountTransferManager", - "CountTransferManager module was not added" - ); - I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); - }); - - it("should pass fuzz test for changeHolderCount()", async () => { - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_CountTransferManager.address, 'ADMIN') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_CountTransferManager.address, 'ADMIN', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_CountTransferManager.address, randomPerms, true, { from: token_owner }); - if (randomPerms === 'ADMIN') { - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); - await I_CountTransferManager.changeHolderCount(i + 1, { from: accounts[j] }); - assert.equal((await I_CountTransferManager.maxHolderCount()).toNumber(), i + 1); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " passed"); - } else { - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert(I_CountTransferManager.changeHolderCount(i+1, { from: accounts[j] })); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - } - }); - }); - - // lock up volume TM needs code change, not testing now but keeping the code for future testing - // describe("fuzz test for lockup volume restriction transfer manager", async () => { - - // it("Should Buy some tokens", async() => { - - // await I_GeneralTransferManager.changeIssuanceAddress("0x0000000000000000000000000000000000000000", { from: token_owner }); - - // // Add the Investor in to the whitelist - // console.log("0"); - // let tx = await I_GeneralTransferManager.modifyWhitelist( - // account_investor2, - // latestTime(), - // latestTime(), - // latestTime() + duration.days(10), - // true, - // { - // from: account_issuer - // }); - - // assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - // console.log("1"); - - // let tx2 = await I_GeneralTransferManager.modifyWhitelist( - // account_investor3, - // latestTime(), - // latestTime(), - // latestTime() + duration.days(10), - // true, - // { - // from: account_issuer - // }); - - // console.log("2"); - // // Jump time - // await increaseTime(5000); - - // // Mint some tokens - // await I_SecurityToken.mint(account_investor2, web3.utils.toWei('9', 'ether'), { from: token_owner }); - // console.log("1.5"); - // await I_SecurityToken.mint(account_investor3, web3.utils.toWei('9', 'ether'), { from: token_owner }); - // console.log("2"); - // // assert.equal( - // // (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - // // web3.utils.toWei('9', 'ether') - // // ); - // // assert.equal( - // // (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - // // web3.utils.toWei('9', 'ether') - // // ); - // }); - - // it("Should successfully attach the VolumeRestrictionTransferManager with the security token", async () => { - // const tx = await I_SecurityToken.addModule(I_VolumeRestrictionTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); - // assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManager doesn't get deployed"); - // assert.equal( - // web3.utils.toAscii(tx.logs[2].args._name) - // .replace(/\u0000/g, ''), - // "LockupVolumeRestrictionTM", - // "VolumeRestrictionTransferManager module was not added" - // ); - // I_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[2].args._module); - // }); - - // it("should pass fuzz test for addLockUp()", async () => { - // let balance = await I_SecurityToken.balanceOf(account_investor2); - // // await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from: token_owner }); - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - // for (var i = 2; i < testRepeat; i++) { - // var j = Math.floor(Math.random() * 10); - // if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not// - // if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - // await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - // } - - // // target permission should alaways be false for each test before assigning - // if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN') === true) { - // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN', false, { from: token_owner }); - // } - - // assign a random perm// - // let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, randomPerms, true, { from: token_owner }); - - // if (randomPerms === 'ADMIN') { - // // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); - // await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from:accounts[j] }); - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " passed"); - // } else { - // // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - // await catchRevert(I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from:accounts[j] })); - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - // } - // } - // }); - - // it("should pass fuzz test for remove lock up", async () => { - // let balance = await I_SecurityToken.balanceOf(account_investor2); - // // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accountsconsole.log("1"); - // for (var i = 2; i < testRepeat; i++) { - // var j = Math.floor(Math.random() * 10); - // if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not// - // if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - // await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - // } - - // // target permission should alaways be false for each test before assigning - // if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN') === true) { - // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN', false, { from: token_owner }); - // } - - // assign a random perm// - // let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, randomPerms, true, { from: token_owner }); - - // // if lockup count is 0, add a lockup. - // let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2, { from : token_owner }); - - // if (lockUpCount === 0) { - // console.log("lock up count is " + lockUpCount); - // await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, token_owner); - // } - - // let lockUpCountNow = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2, { from : token_owner }); - - // console.log("lock up count now is "+lockUpCountNow); - - // // try remove lock up - // if (randomPerms === 'ADMIN') { - // // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); - // await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from:accounts[j] }); - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " passed"); - // } else { - // // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - // await catchRevert(I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from:accounts[j] })); - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - // } - // } - // }); - - // it("should pass fuzz test for add multiple lock ups", async () => { - - // // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts// add mutiple lock ups at once - // for (var i = 2; i < testRepeat; i++) { - // var j = Math.floor(Math.random() * 10); - // if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not// - // if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - // await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - // } - - // // target permission should alaways be false for each test before assigning - // if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN') === true) { - // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN', false, { from: token_owner }); - // } - - // assign a random perm// - // let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - // await I_GeneralPermissionManager.changePermission(accounts[j], I_VolumeRestrictionTransferManager.address, randomPerms, true, { from: token_owner }); - - // // check current lockup count before adding multiple - // let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - // let lockUpCount2 = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); - - // let balance = await I_SecurityToken.balanceOf(account_investor2); - // let balance2 = await I_SecurityToken.balanceOf(account_investor3); - - // // try add multi lock ups - // if (randomPerms === 'ADMIN') { - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); - // console.log("current perm should be true --> " + await I_GeneralPermissionManager.checkPermission(accounts[j], I_VolumeRestrictionTransferManager.address, 'ADMIN')); - // await I_VolumeRestrictionTransferManager.addLockUpMulti( - // [account_investor2, account_investor3], - // [24, 8], - // [4, 4], - // [0, 0], - // [balance, balance2], - // { from: accounts[j] } - // ); - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " passed"); - // assert.equal(await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2), lockUpCount+1); - // assert.equal(await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3), lockUpCount2+1); - // } else { - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - // await catchRevert( - // I_VolumeRestrictionTransferManager.addLockUpMulti( - // [account_investor2, account_investor3], - // [24, 8], - // [4, 4], - // [0, 0], - // [balance, balance2], - // { from: accounts[j] } - // )); - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - // } - // } - - // }); - - // it("should pass fuzz test for modify lock ups", async () => { - // // add a lock up if there is no existing one - - // // modify lock up - - // // paused due to the current module is not ready for test - // }); - - // }); - - - describe("fuzz test for percentage transfer manager", async () => { - - // PercentageTransferManager details - const holderPercentage = 70 * 10**16; // Maximum number of token holders - - let bytesSTO = web3.eth.abi.encodeFunctionCall({ - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_maxHolderPercentage' - },{ - type: 'bool', - name: '_allowPrimaryIssuance' - } - ] - }, [holderPercentage, false]); - - it("Should successfully attach the percentage transfer manager with the security token", async () => { - console.log("1"); - const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - I_PercentageTransferManager = PercentageTransferManager.at(tx.logs[2].args._module); - }); - - it("should pass fuzz test for modifyWhitelist with perm WHITELIST", async () => { - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, randomPerms, true, { from: token_owner }); - - //try add multi lock ups - if (randomPerms === 'WHITELIST') { - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); - await I_PercentageTransferManager.modifyWhitelist(account_investor3, true, { from: accounts[j] }); - console.log("Test number " + i + " with account " + j + " and perm WHITELIST passed as expected"); - } else { - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert(I_PercentageTransferManager.modifyWhitelist(account_investor3, true, { from: accounts[j] })); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - } - }); - - it("should pass fuzz test for modifyWhitelistMulti with perm WHITELIST", async () => { - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, randomPerms, true, { from: token_owner }); - - if (randomPerms === 'WHITELIST') { - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); - await I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [false, true], { from: accounts[j] }); - console.log("Test number " + i + " with account " + j + " and perm WHITELIST passed as expected"); - - } else { - // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert( I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [false, true], { from: accounts[j] })); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - } - }); - - it("should pass fuzz test for setAllowPrimaryIssuance with perm ADMIN", async () => { - - // let snapId = await takeSnapshot(); - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, 'ADMIN') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, 'ADMIN', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, randomPerms, true, { from: token_owner }); - - let primaryIssuanceStat = await I_PercentageTransferManager.allowPrimaryIssuance({ from: token_owner }); - - if (randomPerms === 'ADMIN') { - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); - await I_PercentageTransferManager.setAllowPrimaryIssuance(!primaryIssuanceStat, { from: accounts[j] }); - console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); - - } else { - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert( I_PercentageTransferManager.setAllowPrimaryIssuance(!primaryIssuanceStat, { from: accounts[j] })); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - // await revertToSnapshot(snapId); - } - }); - }); - - - describe("fuzz test for single trade volume manager", async () => { - - it("attach the single trade volume restriction manager ", async () => { - - let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); - - let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { - from: token_owner - }); - - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "SingleTradeVolumeRestrictionManager did not get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestrictionManagerFactory module was not added" - ); - P_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[3].args._module); - - managerArgs = encodeModuleCall(STVRParameters, [false, (7 * Math.pow(10, 16)).toString(), false]) - - let tx2 = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { from: token_owner }); - - I_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx2.logs[2].args._module); - - managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - let tx3 = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { - from: token_owner - }); - - I_SingleTradeVolumeRestrictionPercentageManager = SingleTradeVolumeRestrictionManager.at(tx3.logs[2].args._module); - }); - - it("should pass fuzz test for setAllowPrimaryIssuance with perm ADMIN", async () => { - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - - let snapId = await takeSnapshot(); - - - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, randomPerms, true, { from: token_owner }); - - if (randomPerms === 'ADMIN') { - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); - await I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: accounts[j]}); - console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); - } else { - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert( I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: accounts[j]}) ); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - - await revertToSnapshot(snapId); - } - }); - - it("should pass fuzz test for changeTransferLimitToTokens & changeGlobalLimitInTokens with perm ADMIN", async () => { - - let tx; - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - - let snapId = await takeSnapshot(); - - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, randomPerms, true, { from: token_owner }); - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, randomPerms, true, { from: token_owner }); - - if (randomPerms == 'ADMIN' ) { - console.log("current limit in percentage is "+ await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage({ from: token_owner })); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); - console.log("current permission for ADMIN is " + await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN')); - tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: accounts[j] }); - - // assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); - // assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); - console.log("1.1"); - tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, {from: accounts[j]}); - console.log("1.2"); - // assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); - } else { - console.log("current limit in percentage is "+ await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage({ from: token_owner })); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should fail"); - console.log("current permission for ADMIN is" + await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN')); - await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: accounts[j] })); - // await catchRevert(I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, {from: token_owner})); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - - await revertToSnapshot(snapId); - } - }); - - it("should pass fuzz test for changeTransferLimitToPercentage & changeGlobalLimitInPercentage with perm ADMIN", async () => { - - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - - let snapId = await takeSnapshot(); - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: token_owner }); - - tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { from: token_owner }); - - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, randomPerms, true, { from: token_owner }); - - if (randomPerms == "ADMIN" ) { - console.log("Test number " + i + " with account " + j + " and perm ADMIN " + " should pass"); - // console.log("current permission ADMIN status is "+ await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, 'ADMIN')); - tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { from: accounts[j] }); - // assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); - // assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); - console.log("1.1"); - tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(40, { from: accounts[j] }); - console.log("1.2"); - // assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); - } else { - console.log("current limit in percentage is "+ await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage({ from: token_owner })); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: accounts[j] })); - // await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(10, {from: token_owner})); - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - - await revertToSnapshot(snapId); - } - }); - - it("should pass fuzz test for addExemptWallet, removeExemptWallet, setTransferLimitInTokens, removeTransferLimitInTokens with perm ADMIN", async () => { - - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - - let snapId = await takeSnapshot(); - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { from: token_owner }); - - tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { from: token_owner}); - - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, randomPerms, true, { from: token_owner }); - - if (randomPerms === "ADMIN" ) { - console.log("Test number " + i + " with account " + j + " and perm ADMIN " + " should pass"); - - //add - let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { from: accounts[j]}); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet added as exempt"); - - console.log("passed add"); - - //remove - tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { from: accounts[j] }); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet removed from exempt"); - - console.log("passed remove"); - - //set transfer limit in tokens - tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { from: accounts[j] }); - assert.equal(tx.logs[0].args._wallet, accounts[4]); - assert.equal(tx.logs[0].args._amount, 100); - - console.log("passed set limit in tokens"); - - tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4], { from: accounts[j] }); - assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet removed"); - console.log("removed set limit in tokens"); - - console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); - } else { - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert(I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { from: accounts[j]})); - - let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { from: token_owner}); - await catchRevert(I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { from: accounts[j] })); - - await catchRevert(I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { from: accounts[j] })); - - tx = I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { from: token_owner }); - await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 50, { from: accounts[j] })); - - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - - await revertToSnapshot(snapId); - } - }); - - it("should pass fuzz test for addExemptWalletMulti, removeExemptWalletMulti, setTransferLimitInTokensMulti, removeTransferLimitInTokensMulti, setTransferLimitInPercentageMulti, removeTransferLimitInPercentageMulti with perm ADMIN", async () => { - - // console.log("0"); - - let wallets = [accounts[0], accounts[1], accounts[2]]; - let tokenLimits = [1, 2, 3]; - let percentageLimits = [5, 6, 7]; - - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - - let snapId = await takeSnapshot(); - - console.log("0.1"); - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - console.log("0.2"); - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, 'ADMIN', false, { from: token_owner }); - } - - console.log("0.3"); - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionManager.address, randomPerms, true, { from: token_owner }); - await I_GeneralPermissionManager.changePermission(accounts[j], I_SingleTradeVolumeRestrictionPercentageManager.address, randomPerms, true, { from: token_owner }); - - console.log("0.4"); - - if (randomPerms === "ADMIN" ) { - console.log("Test number " + i + " with account " + j + " and perm ADMIN " + " should pass"); - - // add exempt wallet multi - let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { - from: accounts[j] - }); - - console.log("1"); - - // remove exempt wallet multi - tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { - from: accounts[j] - }); - - console.log("2"); - - tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { - from: accounts[j] - }); - console.log("3"); - - tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, { - from: accounts[j] - }); - console.log("4"); - - console.log("transfer limit in percentage needs to be true to pass --> " + await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage({from: accounts[j]})); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { - from: accounts[j] - }); - - let logs; - - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageSet'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - assert.equal(logs[i].args._percentage.toNumber(), percentageLimits[i]); - } - console.log("5"); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { - from: accounts[j] - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageRemoved'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - } - console.log("6"); - - console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); - - } else { - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - - // add exempt wallet multi - let tx; - - await catchRevert( P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { - from: accounts[j] - })); - - console.log("1"); - - await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { from: token_owner }); - await catchRevert(P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { from: accounts[j] })); - - // remove exempt wallet multi - await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { from: token_owner }); - await catchRevert(P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { from: accounts[j] })); - console.log("2"); - - await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { from: token_owner }); - await catchRevert(P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, {from: accounts[j]})); - - await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, {from: token_owner}); - await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { from: accounts[j] })); - console.log("3"); - - await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { from: token_owner }); - await catchRevert(I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { from: accounts[j] })); - - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - await revertToSnapshot(snapId); - } - - }); - - }); - - - describe("fuzz test for manual approval transfer manager", async () => { - - it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toUtf8(tx.logs[2].args._name), - "ManualApprovalTransferManager", - "ManualApprovalTransferManager module was not added" - ); - I_ManualApprovalTransferManager = ManualApprovalTransferManager.at(tx.logs[2].args._module); - }); - - it("should pass fuzz test for addManualApproval & revokeManualApproval with perm TRANSFER_APPROVAL", async () => { - - let tx; - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - - let snapId = await takeSnapshot(); - - - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, randomPerms, true, { from: token_owner }); - - if (randomPerms === "TRANSFER_APPROVAL" ) { - console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL " + " should pass"); - await I_ManualApprovalTransferManager.addManualApproval( - account_investor1, - account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), - { from: accounts[j] } - ); - - console.log("2"); - tx = await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { - from: accounts[j] - }); - assert.equal(tx.logs[0].args._from, account_investor1); - assert.equal(tx.logs[0].args._to, account_investor4); - assert.equal(tx.logs[0].args._addedBy, accounts[j]); - - console.log("3"); - console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL passed as expected"); - } else { - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert( - I_ManualApprovalTransferManager.addManualApproval( - account_investor1, - account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), - { from: accounts[j] } - ) - ); - - await I_ManualApprovalTransferManager.addManualApproval( - account_investor1, - account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), - { from: token_owner } - ); - - await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { - from: accounts[j] - }) - ); - - - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - - await revertToSnapshot(snapId); - }; - - - }); - - it("should pass fuzz test for addManualBlocking and revokeManualBlocking with perm TRANSFER_APPROVAL", async () => { - console.log("1"); - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: token_owner - }); - console.log("2"); - await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: token_owner }); - console.log("3"); - - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - - let snapId = await takeSnapshot(); - - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, randomPerms, true, { from: token_owner }); - - if (randomPerms === "TRANSFER_APPROVAL") { - console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL " + " should pass"); - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: accounts[j] - }); - - console.log("2"); - await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }); - - console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL passed as expected"); - } else { - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: accounts[j] - }) - ); - - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: token_owner - }); - - await catchRevert( - I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }) - ); - - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - - await revertToSnapshot(snapId); - }; - }); - }); - }); From 56d0a573f1dfa6964173c2fbcadb1931a1782ef7 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 27 Nov 2018 17:16:43 +0530 Subject: [PATCH 212/582] minor fixes in the contract --- .../TransferManager/VolumeRestrictionTM.sol | 14 ++-- test/z_volume_restriction_tm.js | 68 +++++++++++++++++++ 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol index 9e16d60ef..2431b2045 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol @@ -440,7 +440,7 @@ contract VolumeRestrictionTM is ITransferManager { external withPerm(ADMIN) { - require(globalRestriction.startTime < now, "Not allowed"); + require(globalRestriction.startTime > now, "Not allowed"); _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); globalRestriction = VolumeRestriction( _allowedTokens, @@ -465,7 +465,6 @@ contract VolumeRestrictionTM is ITransferManager { * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. * @param _startTime Unix timestamp at which restriction get into effect - * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) */ @@ -473,20 +472,19 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _allowedTokens, uint256 _allowedPercentageOfTokens, uint256 _startTime, - uint256 _rollingPeriodInDays, uint256 _endTime, uint256 _restrictionType ) external withPerm(ADMIN) { - require(dailyGlobalRestriction.startTime < now, "Not allowed"); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + require(dailyGlobalRestriction.startTime > now, "Not allowed"); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); dailyGlobalRestriction = VolumeRestriction( _allowedTokens, _allowedPercentageOfTokens, _startTime, - _rollingPeriodInDays, + 1, _endTime, RestrictionType(_restrictionType) ); @@ -494,7 +492,7 @@ contract VolumeRestrictionTM is ITransferManager { _allowedTokens, _allowedPercentageOfTokens, _startTime, - _rollingPeriodInDays, + 1, _endTime, _restrictionType ); @@ -773,7 +771,7 @@ contract VolumeRestrictionTM is ITransferManager { internal { _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - require(individualRestriction[_holder].startTime < now, "Not allowed"); + require(individualRestriction[_holder].startTime > now, "Not allowed"); individualRestriction[_holder] = VolumeRestriction( _allowedTokens, diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js index f59e06486..7c4762fd7 100644 --- a/test/z_volume_restriction_tm.js +++ b/test/z_volume_restriction_tm.js @@ -1375,5 +1375,73 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(web3.utils.fromWei((diff.toNumber()).toString()), 3); }); }); + + describe("Test for modify functions", async() => { + + it("Should not able to modify the already started restrictions --global", async() =>{ + await catchRevert( + I_VolumeRestrictionTM.modifyGlobalRestriction( + web3.utils.toWei("50"), + 0, + latestTime() + duration.seconds(50), + 10, + latestTime() + duration.days(20), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should not able to modify the already started restrictions -- daily global", async() =>{ + await catchRevert( + I_VolumeRestrictionTM.modifyDailyGlobalRestriction( + web3.utils.toWei("50"), + 0, + latestTime() + duration.seconds(50), + latestTime() + duration.days(20), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should not able to modify the already started restrictions -- Individual", async() =>{ + await catchRevert( + I_VolumeRestrictionTM.modifyIndividualRestriction( + account_investor2, + web3.utils.toWei("50"), + 0, + latestTime() + duration.seconds(50), + 10, + latestTime() + duration.days(20), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should not able to modify the already started transaction -- multi Individuals", async() => { + await catchRevert( + I_VolumeRestrictionTM.modifyIndividualRestrictionMulti( + [account_investor2, account_investor1], + [web3.utils.toWei("50"), web3.utils.toWei("50")], + [0, 0], + [latestTime() + duration.seconds(50), latestTime() + duration.seconds(50)], + [10, 20], + [latestTime() + duration.days(20), latestTime() + duration.days(50)], + [0, 0], + { + from: token_owner + } + ) + ); + }); + }); }); \ No newline at end of file From 2d96fc2e7ed2ffdeac776a4d85d21591e28a6e59 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 27 Nov 2018 18:00:26 +0530 Subject: [PATCH 213/582] merge dev-2.1.0 and add new test case --- test/z_volume_restriction_tm.js | 65 ++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js index 7c4762fd7..96c96776d 100644 --- a/test/z_volume_restriction_tm.js +++ b/test/z_volume_restriction_tm.js @@ -180,7 +180,7 @@ contract('VolumeRestrictionTransferManager', accounts => { [latestTime(), latestTime(), latestTime()], [latestTime(), latestTime(), latestTime()], [latestTime() + duration.days(30), latestTime() + duration.days(30), latestTime() + duration.days(30)], - [true, true, true], + [0, 0, 0], { from: token_owner } @@ -1083,7 +1083,7 @@ contract('VolumeRestrictionTransferManager', accounts => { [latestTime(), latestTime()], [latestTime(), latestTime()], [latestTime() + duration.days(30), latestTime() + duration.days(30)], - [true, true], + [0, 0], { from: token_owner } @@ -1442,6 +1442,67 @@ contract('VolumeRestrictionTransferManager', accounts => { ) ); }); + + it("Should add the individual restriction for multiple investor", async() => { + await I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor3, account_delegate3], + [web3.utils.toWei("15"), 0], + [0, new BigNumber(12.78).times(new BigNumber(10).pow(16))], + [latestTime() + duration.days(1), latestTime() + duration.days(2)], + [15, 20], + [latestTime() + duration.days(40), latestTime() + duration.days(60)], + [0,1], + { + from: token_owner + } + ); + + let indi1 = await I_VolumeRestrictionTM.individualRestriction.call(account_investor3); + let indi2 = await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3); + + assert.equal(indi1[0].dividedBy(new BigNumber(10).pow(18)), 15); + assert.equal(indi2[0].dividedBy(new BigNumber(10).pow(18)), 0); + + assert.equal(indi1[1].dividedBy(new BigNumber(10).pow(18)), 0); + assert.equal(indi2[1].dividedBy(new BigNumber(10).pow(16)), 12.78); + + assert.equal(indi1[3].toNumber(), 15); + assert.equal(indi2[3].toNumber(), 20); + + assert.equal(indi1[5].toNumber(), 0); + assert.equal(indi2[5].toNumber(), 1); + }); + + it("Should modify the details before the starttime passed", async() => { + await I_VolumeRestrictionTM.modifyIndividualRestrictionMulti( + [account_investor3, account_delegate3], + [0, web3.utils.toWei("15")], + [new BigNumber(12.78).times(new BigNumber(10).pow(16)), 0], + [latestTime() + duration.days(1), latestTime() + duration.days(2)], + [20, 15], + [latestTime() + duration.days(40), latestTime() + duration.days(60)], + [1,0], + { + from: token_owner + } + ); + + let indi1 = await I_VolumeRestrictionTM.individualRestriction.call(account_investor3); + let indi2 = await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3); + + assert.equal(indi2[0].dividedBy(new BigNumber(10).pow(18)), 15); + assert.equal(indi1[0].dividedBy(new BigNumber(10).pow(18)), 0); + + assert.equal(indi2[1].dividedBy(new BigNumber(10).pow(18)), 0); + assert.equal(indi1[1].dividedBy(new BigNumber(10).pow(16)), 12.78); + + assert.equal(indi2[3].toNumber(), 15); + assert.equal(indi1[3].toNumber(), 20); + + assert.equal(indi2[5].toNumber(), 0); + assert.equal(indi1[5].toNumber(), 1); + }); + }); }); \ No newline at end of file From 881987da7b675a2dc94fb6d5750698b4203ea4df Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 27 Nov 2018 18:26:50 +0530 Subject: [PATCH 214/582] add getAllBlacklists() --- .../BlacklistTransferManager.sol | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 15a57b82e..4659baa8a 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -31,6 +31,8 @@ contract BlacklistTransferManager is ITransferManager { //mapping use to store the indexes for different investor for a blacklist type mapping(bytes32 => mapping(address => uint256)) blacklistToIndex; + + bytes32[] allBlacklists; // Emit when new blacklist type is added event AddBlacklistType( @@ -128,10 +130,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _repeatPeriodTime Repeat period of the blacklist type */ function addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) public withPerm(ADMIN) { - require(blacklists[_name].endTime == 0, "Blacklist type already exist"); - _validParams(_startTime, _endTime, _name); - blacklists[_name] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); - emit AddBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); + _addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); } /** @@ -144,7 +143,7 @@ contract BlacklistTransferManager is ITransferManager { function addBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _names, uint256[] _repeatPeriodTimes) public withPerm(ADMIN) { require (_startTimes.length == _endTimes.length && _endTimes.length == _names.length && _names.length == _repeatPeriodTimes.length, "Input array's length mismatch"); for (uint256 i = 0; i < _startTimes.length; i++){ - addBlacklistType(_startTimes[i], _endTimes[i], _names[i], _repeatPeriodTimes[i]); + _addBlacklistType(_startTimes[i], _endTimes[i], _names[i], _repeatPeriodTimes[i]); } } @@ -193,6 +192,16 @@ contract BlacklistTransferManager is ITransferManager { require(blacklistToInvestor[_name].length == 0, "Investors are associated with the blacklist"); // delete blacklist type delete(blacklists[_name]); + uint256 i = 0; + for (i = 0; i < allBlacklists.length; i++) { + if (allBlacklists[i] == _name) { + break; + } + } + if (i != allBlacklists.length -1) { + allBlacklists[i] = allBlacklists[allBlacklists.length -1]; + } + allBlacklists.length--; emit DeleteBlacklistType(_name); } @@ -257,7 +266,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _investor Address of the investor */ function addInvestorToNewBlacklist(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime, address _investor) public withPerm(ADMIN){ - addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); + _addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); addInvestorToBlacklist(_investor, _name); } @@ -327,6 +336,13 @@ contract BlacklistTransferManager is ITransferManager { } } + function _addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) internal { + require(blacklists[_name].endTime == 0, "Blacklist type already exist"); + _validParams(_startTime, _endTime, _name); + blacklists[_name] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); + allBlacklists.push(_name); + emit AddBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); + } /** * @notice get the list of the investors of a blacklist type @@ -347,6 +363,14 @@ contract BlacklistTransferManager is ITransferManager { return investorToBlacklist[_user]; } + /** + * @notice get the list of blacklist names + * @return bytes32 Array of blacklist names + */ + function getAllBlacklists() external view returns(bytes32[]) { + return allBlacklists; + } + /** * @notice Return the permissions flag that are associated with blacklist transfer manager */ From d30f80900ae97dbc594305ea246d0f308c4fd26f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 18:48:38 +0530 Subject: [PATCH 215/582] Added a comment --- contracts/modules/STO/USDTieredSTO.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index e3a16948c..9e6287087 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -18,6 +18,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Storage // ///////////// struct Tier { + // NB rates mentioned below are actually price and are used like price in the logic. // How many token units a buyer gets per USD in this tier (multiplied by 10**18) uint256 rate; From dd20c06bbf7eb914522d9516ff903287206a849d Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 18:52:52 +0530 Subject: [PATCH 216/582] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db3d8dcde..74c0a22c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. [__2.1.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-09-18__ # USDTieredSTO 2.0.1 +* Added support for multiple stable coins in USDTSTO. * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. * Added `getSTODetails` to USDTSTO. * Added an Array of Tiers that will hold data about every tier in USDTSTO. From ea663e75ca6f4377013afb8c971ca6fd5ce66248 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 27 Nov 2018 13:33:09 +0000 Subject: [PATCH 217/582] Revert "Optimise GTM (#433)" (#436) This reverts commit 42e4a789931d47984429d84b78e40bb3c3320f6a. --- CHANGELOG.md | 6 - .../modules/Checkpoint/DividendCheckpoint.sol | 37 +- .../Checkpoint/DividendCheckpointStorage.sol | 43 - .../Checkpoint/ERC20DividendCheckpoint.sol | 39 +- .../ERC20DividendCheckpointFactory.sol | 9 +- .../ERC20DividendCheckpointStorage.sol | 11 - .../Checkpoint/EtherDividendCheckpoint.sol | 25 +- .../EtherDividendCheckpointFactory.sol | 9 +- contracts/modules/Module.sol | 20 +- contracts/modules/ModuleStorage.sol | 30 - .../GeneralTransferManager.sol | 156 +-- .../GeneralTransferManagerFactory.sol | 10 +- .../GeneralTransferManagerStorage.sol | 53 - .../proxy/ERC20DividendCheckpointProxy.sol | 31 - .../proxy/EtherDividendCheckpointProxy.sol | 30 - .../proxy/GeneralTransferManagerProxy.sol | 30 - contracts/proxy/OwnedProxy.sol | 91 -- migrations/2_deploy_contracts.js | 24 +- package.json | 1 - scripts/compareStorageLayout.js | 139 -- test/b_capped_sto.js | 14 +- test/c_checkpoints.js | 6 +- test/d_count_transfer_manager.js | 8 +- test/e_erc20_dividends.js | 12 +- test/f_ether_dividends.js | 12 +- test/h_general_transfer_manager.js | 168 +-- test/helpers/createInstances.js | 32 +- test/helpers/signData.js | 2 +- test/i_Issuance.js | 4 +- test/j_manual_approval_transfer_manager.js | 6 +- test/l_percentage_transfer_manager.js | 8 +- test/m_presale_sto.js | 6 +- test/o_security_token.js | 20 +- test/p_usd_tiered_sto.js | 18 +- test/q_usd_tiered_sto_sim.js | 6 +- test/r_concurrent_STO.js | 6 +- test/u_module_registry_proxy.js | 5 +- test/v_tracked_redemptions.js | 6 +- ...kup_volume_restriction_transfer_manager.js | 14 +- test/x_single_trade_volume_restriction.js | 24 +- test/y_scheduled_checkpoints.js | 6 +- yarn.lock | 1247 ++++++++++++++++- 42 files changed, 1449 insertions(+), 975 deletions(-) delete mode 100644 contracts/modules/Checkpoint/DividendCheckpointStorage.sol delete mode 100644 contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol delete mode 100644 contracts/modules/ModuleStorage.sol delete mode 100644 contracts/modules/TransferManager/GeneralTransferManagerStorage.sol delete mode 100644 contracts/proxy/ERC20DividendCheckpointProxy.sol delete mode 100644 contracts/proxy/EtherDividendCheckpointProxy.sol delete mode 100644 contracts/proxy/GeneralTransferManagerProxy.sol delete mode 100644 contracts/proxy/OwnedProxy.sol delete mode 100644 scripts/compareStorageLayout.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e19e93ce..db3d8dcde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,12 +13,6 @@ All notable changes to this project will be documented in this file. * Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. * Removed individual mappings for tier data removed in UDSTSTO. -# GeneralTransferManager -* Add an Offset that can be used to move all from & to dates forwards or backwards by a fixed offset. -* Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`) -* Fix for when `allowAllWhitelistIssuances` is FALSE -* Make GTM a Proxy based implementation to reduce deployment gas costs - ##Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 3a345af25..452a48b13 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -8,7 +8,6 @@ pragma solidity ^0.4.24; import "./ICheckpoint.sol"; -import "./DividendCheckpointStorage.sol"; import "../Module.sol"; import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -18,9 +17,43 @@ import "openzeppelin-solidity/contracts/math/Math.sol"; * @title Checkpoint module for issuing ether dividends * @dev abstract contract */ -contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { +contract DividendCheckpoint is ICheckpoint, Module { using SafeMath for uint256; + uint256 public EXCLUDED_ADDRESS_LIMIT = 50; + bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; + bytes32 public constant MANAGE = "MANAGE"; + bytes32 public constant CHECKPOINT = "CHECKPOINT"; + + struct Dividend { + uint256 checkpointId; + uint256 created; // Time at which the dividend was created + uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass + uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - + // set to very high value to bypass + uint256 amount; // Dividend amount in WEI + uint256 claimedAmount; // Amount of dividend claimed so far + uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) + bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend + uint256 dividendWithheld; + uint256 dividendWithheldReclaimed; + mapping (address => bool) claimed; // List of addresses which have claimed dividend + mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends + bytes32 name; // Name/title - used for identification + } + + // List of all dividends + Dividend[] public dividends; + + // List of addresses which cannot claim dividends + address[] public excluded; + + // Mapping from address to withholding tax as a percentage * 10**16 + mapping (address => uint256) public withholdingTax; + + // Total amount of ETH withheld per investor + mapping (address => uint256) public investorWithheld; + event SetDefaultExcludedAddresses(address[] _excluded, uint256 _timestamp); event SetWithholding(address[] _investors, uint256[] _withholding, uint256 _timestamp); event SetWithholdingFixed(address[] _investors, uint256 _withholding, uint256 _timestamp); diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol deleted file mode 100644 index 4cf1f2838..000000000 --- a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol +++ /dev/null @@ -1,43 +0,0 @@ -pragma solidity ^0.4.24; - -/** - * @title Holds the storage variable for the DividendCheckpoint modules (i.e ERC20, Ether) - * @dev abstract contract - */ -contract DividendCheckpointStorage { - - uint256 public EXCLUDED_ADDRESS_LIMIT = 50; - bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; - bytes32 public constant MANAGE = "MANAGE"; - bytes32 public constant CHECKPOINT = "CHECKPOINT"; - - struct Dividend { - uint256 checkpointId; - uint256 created; // Time at which the dividend was created - uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass - uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - - // set to very high value to bypass - uint256 amount; // Dividend amount in WEI - uint256 claimedAmount; // Amount of dividend claimed so far - uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) - bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend - uint256 dividendWithheld; - uint256 dividendWithheldReclaimed; - mapping (address => bool) claimed; // List of addresses which have claimed dividend - mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends - bytes32 name; // Name/title - used for identification - } - - // List of all dividends - Dividend[] public dividends; - - // List of addresses which cannot claim dividends - address[] public excluded; - - // Mapping from address to withholding tax as a percentage * 10**16 - mapping (address => uint256) public withholdingTax; - - // Total amount of ETH withheld per investor - mapping (address => uint256) public investorWithheld; - -} diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index b779088f7..1f7f25cd5 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -1,16 +1,17 @@ pragma solidity ^0.4.24; import "./DividendCheckpoint.sol"; -import "./ERC20DividendCheckpointStorage.sol"; import "../../interfaces/IOwnable.sol"; import "../../interfaces/IERC20.sol"; /** * @title Checkpoint module for issuing ERC20 dividends */ -contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendCheckpoint { +contract ERC20DividendCheckpoint is DividendCheckpoint { using SafeMath for uint256; + // Mapping to token address for each dividend + mapping (uint256 => address) public dividendTokens; event ERC20DividendDeposited( address indexed _depositor, uint256 _checkpointId, @@ -67,8 +68,8 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec address _token, uint256 _amount, bytes32 _name - ) - external + ) + external withPerm(MANAGE) { createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name); @@ -132,16 +133,16 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec * @param _name Name/Title for identification */ function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, address[] _excluded, bytes32 _name - ) + ) public - withPerm(MANAGE) + withPerm(MANAGE) { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, _excluded, _name); } @@ -157,15 +158,15 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec * @param _name Name/Title for identification */ function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, address[] _excluded, bytes32 _name - ) - internal + ) + internal { ISecurityToken securityTokenInstance = ISecurityToken(securityToken); require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); @@ -209,7 +210,7 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec } /** - * @notice Emits the ERC20DividendDeposited event. + * @notice Emits the ERC20DividendDeposited event. * Seperated into a different function as a workaround for stack too deep error */ function _emitERC20DividendDepositedEvent( diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index a684e553b..5fd158c26 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../../proxy/ERC20DividendCheckpointProxy.sol"; +import "./ERC20DividendCheckpoint.sol"; import "../ModuleFactory.sol"; /** @@ -8,8 +8,6 @@ import "../ModuleFactory.sol"; */ contract ERC20DividendCheckpointFactory is ModuleFactory { - address public logicContract; - /** * @notice Constructor * @param _polyAddress Address of the polytoken @@ -17,7 +15,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; @@ -26,7 +24,6 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { description = "Create ERC20 dividends for token holders at a specific checkpoint"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - logicContract = _logicContract; } /** @@ -36,7 +33,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "insufficent allowance"); - address erc20DividendCheckpoint = new ERC20DividendCheckpointProxy(msg.sender, address(polyToken), logicContract); + address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender, address(polyToken)); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return erc20DividendCheckpoint; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol deleted file mode 100644 index 29401f8d9..000000000 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.4.24; - -/** - * @title It holds the storage variables related to ERC20DividendCheckpoint module - */ -contract ERC20DividendCheckpointStorage { - - // Mapping to token address for each dividend - mapping (uint256 => address) public dividendTokens; - -} diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index f5a916818..4def51468 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -8,7 +8,6 @@ import "../../interfaces/IOwnable.sol"; */ contract EtherDividendCheckpoint is DividendCheckpoint { using SafeMath for uint256; - event EtherDividendDeposited( address indexed _depositor, uint256 _checkpointId, @@ -57,7 +56,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, uint256 _checkpointId, bytes32 _name - ) + ) external payable withPerm(MANAGE) @@ -77,7 +76,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, address[] _excluded, bytes32 _name - ) + ) public payable withPerm(MANAGE) @@ -95,10 +94,10 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _name Name/title for identification */ function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] _excluded, + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] _excluded, bytes32 _name ) public @@ -117,12 +116,12 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _name Name/title for identification */ function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] _excluded, + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] _excluded, bytes32 _name - ) + ) internal { require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); @@ -170,7 +169,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { */ function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee); - _dividend.claimed[_payee] = true; + _dividend.claimed[_payee] = true; uint256 claimAfterWithheld = claim.sub(withheld); if (claimAfterWithheld > 0) { /*solium-disable-next-line security/no-send*/ diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 3129fba42..315760be1 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../../proxy/EtherDividendCheckpointProxy.sol"; +import "./EtherDividendCheckpoint.sol"; import "../ModuleFactory.sol"; /** @@ -8,8 +8,6 @@ import "../ModuleFactory.sol"; */ contract EtherDividendCheckpointFactory is ModuleFactory { - address public logicContract; - /** * @notice Constructor * @param _polyAddress Address of the polytoken @@ -17,7 +15,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; @@ -26,7 +24,6 @@ contract EtherDividendCheckpointFactory is ModuleFactory { description = "Create ETH dividends for token holders at a specific checkpoint"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - logicContract = _logicContract; } /** @@ -36,7 +33,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent allowance or balance"); - address ethDividendCheckpoint = new EtherDividendCheckpointProxy(msg.sender, address(polyToken), logicContract); + address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender, address(polyToken)); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return ethDividendCheckpoint; diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index 1566a3428..1e27d424e 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -2,23 +2,33 @@ pragma solidity ^0.4.24; import "../interfaces/IModule.sol"; import "../interfaces/ISecurityToken.sol"; -import "./ModuleStorage.sol"; +import "../interfaces/IERC20.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; /** * @title Interface that any module contract should implement * @notice Contract is abstract */ -contract Module is IModule, ModuleStorage { +contract Module is IModule { + + address public factory; + + address public securityToken; + + bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; + + IERC20 public polyToken; /** * @notice Constructor * @param _securityToken Address of the security token * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public - ModuleStorage(_securityToken, _polyAddress) - { + constructor (address _securityToken, address _polyAddress) public { + require(_securityToken != address(0) && _polyAddress != address(0), "Invalid address"); + securityToken = _securityToken; + factory = msg.sender; + polyToken = IERC20(_polyAddress); } //Allows owner, factory or permissioned delegate diff --git a/contracts/modules/ModuleStorage.sol b/contracts/modules/ModuleStorage.sol deleted file mode 100644 index cd52c9de2..000000000 --- a/contracts/modules/ModuleStorage.sol +++ /dev/null @@ -1,30 +0,0 @@ -pragma solidity ^0.4.24; - -import "../interfaces/IERC20.sol"; - -/** - * @title Storage for Module contract - * @notice Contract is abstract - */ -contract ModuleStorage { - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) public { - securityToken = _securityToken; - factory = msg.sender; - polyToken = IERC20(_polyAddress); - } - - address public factory; - - address public securityToken; - - bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; - - IERC20 public polyToken; - -} diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 04028fead..814d54d7b 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -1,16 +1,47 @@ pragma solidity ^0.4.24; import "./ITransferManager.sol"; -import "./GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Transfer Manager module for core transfer validation functionality */ -contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManager { +contract GeneralTransferManager is ITransferManager { using SafeMath for uint256; + //Address from which issuances come + address public issuanceAddress = address(0); + + //Address which can sign whitelist changes + address public signingAddress = address(0); + + bytes32 public constant WHITELIST = "WHITELIST"; + bytes32 public constant FLAGS = "FLAGS"; + + //from and to timestamps that an investor can send / receive tokens respectively + struct TimeRestriction { + uint256 fromTime; + uint256 toTime; + uint256 expiryTime; + bool canBuyFromSTO; + } + + // An address can only send / receive tokens once their corresponding uint256 > block.number + // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) + mapping (address => TimeRestriction) public whitelist; + // Map of used nonces by customer + mapping(address => mapping(uint256 => bool)) public nonceMap; + + //If true, there are no transfer restrictions, for any addresses + bool public allowAllTransfers = false; + //If true, time lock is ignored for transfers (address must still be on whitelist) + bool public allowAllWhitelistTransfers = false; + //If true, time lock is ignored for issuances (address must still be on whitelist) + bool public allowAllWhitelistIssuances = true; + //If true, time lock is ignored for burn transactions + bool public allowAllBurnTransfers = false; + // Emit when Issuance address get changed event ChangeIssuanceAddress(address _issuanceAddress); // Emit when there is change in the flag variable called allowAllTransfers @@ -24,21 +55,14 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag // Emit when there is change in the flag variable called signingAddress event ChangeSigningAddress(address _signingAddress); // Emit when investor details get modified related to their whitelisting - event OffsetModified(uint64 _time, uint8 _isForward); - - // _fromTime is the time from which the _investor can send tokens - // _toTime is the time from which the _investor can receive tokens - // if allowAllWhitelistIssuances is TRUE, then _toTime is ignored when receiving tokens from the issuance address - // if allowAllWhitelistTransfers is TRUE, then _toTime and _fromTime is ignored when sending or receiving tokens - // in any case, any investor sending or receiving tokens, must have a _expiryTime in the future event ModifyWhitelist( address _investor, uint256 _dateAdded, address _addedBy, - uint64 _fromTime, - uint64 _toTime, - uint64 _expiryTime, - uint8 _canBuyFromSTO + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, + bool _canBuyFromSTO ); /** @@ -52,12 +76,6 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag { } - function modifyOffset(uint64 _time, uint8 _isForward) public withPerm(FLAGS) { - offset.time = _time; - offset.isForward = _isForward; - emit OffsetModified(_time, _isForward); - } - /** * @notice This function returns the signature of configure function */ @@ -150,19 +168,16 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag //Anyone on the whitelist can transfer, regardless of time return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA; } - if (_from == issuanceAddress && (whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { - return Result.NA; - } if (allowAllWhitelistIssuances && _from == issuanceAddress) { + if (!whitelist[_to].canBuyFromSTO && _isSTOAttached()) { + return Result.NA; + } return _onWhitelist(_to) ? Result.VALID : Result.NA; } - if (_from == issuanceAddress) { - return (_onWhitelist(_to) && _adjustTimes(whitelist[_to].toTime) <= uint64(now)) ? Result.VALID : Result.NA; - } //Anyone on the whitelist can transfer provided the blocknumber is large enough /*solium-disable-next-line security/no-block-members*/ - return ((_onWhitelist(_from) && _adjustTimes(whitelist[_from].fromTime) <= uint64(now)) && - (_onWhitelist(_to) && _adjustTimes(whitelist[_to].toTime) <= uint64(now))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return ((_onWhitelist(_from) && whitelist[_from].fromTime <= now) && + (_onWhitelist(_to) && whitelist[_to].toTime <= now)) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -177,39 +192,16 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag */ function modifyWhitelist( address _investor, - uint64 _fromTime, - uint64 _toTime, - uint64 _expiryTime, - uint8 _canBuyFromSTO + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, + bool _canBuyFromSTO ) public withPerm(WHITELIST) { - _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); - } - - /** - * @notice Adds or removes addresses from the whitelist. - * @param _investor is the address to whitelist - * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens - * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others - * @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC - * @param _canBuyFromSTO is used to know whether the investor is restricted investor or not. - */ - function _modifyWhitelist( - address _investor, - uint64 _fromTime, - uint64 _toTime, - uint64 _expiryTime, - uint8 _canBuyFromSTO - ) - internal - { - require(_investor != address(0), "Invalid investor"); - if (whitelist[_investor].added == uint8(0)) { - investors.push(_investor); - } - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO, uint8(1)); + //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist + whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -224,17 +216,17 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag */ function modifyWhitelistMulti( address[] _investors, - uint64[] _fromTimes, - uint64[] _toTimes, - uint64[] _expiryTimes, - uint8[] _canBuyFromSTO + uint256[] _fromTimes, + uint256[] _toTimes, + uint256[] _expiryTimes, + bool[] _canBuyFromSTO ) public withPerm(WHITELIST) { require(_investors.length == _fromTimes.length, "Mismatched input lengths"); require(_fromTimes.length == _toTimes.length, "Mismatched input lengths"); require(_toTimes.length == _expiryTimes.length, "Mismatched input lengths"); require(_canBuyFromSTO.length == _toTimes.length, "Mismatched input length"); for (uint256 i = 0; i < _investors.length; i++) { - _modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); + modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); } } @@ -254,31 +246,29 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag */ function modifyWhitelistSigned( address _investor, - uint64 _fromTime, - uint64 _toTime, - uint64 _expiryTime, - uint8 _canBuyFromSTO, - uint64 _validFrom, - uint64 _validTo, + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, + bool _canBuyFromSTO, + uint256 _validFrom, + uint256 _validTo, uint256 _nonce, uint8 _v, bytes32 _r, bytes32 _s ) public { /*solium-disable-next-line security/no-block-members*/ - require(_validFrom <= uint64(now), "ValidFrom is too early"); + require(_validFrom <= now, "ValidFrom is too early"); /*solium-disable-next-line security/no-block-members*/ - require(_validTo >= uint64(now), "ValidTo is too late"); + require(_validTo >= now, "ValidTo is too late"); require(!nonceMap[_investor][_nonce], "Already used signature"); nonceMap[_investor][_nonce] = true; bytes32 hash = keccak256( abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) ); _checkSig(hash, _v, _r, _s); - if (whitelist[_investor].added == uint8(0)) { - investors.push(_investor); - } - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO, uint8(1)); + //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist + whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -299,7 +289,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag * @param _investor Address of the investor */ function _onWhitelist(address _investor) internal view returns(bool) { - return (whitelist[_investor].expiryTime >= uint64(now)); /*solium-disable-line security/no-block-members*/ + return (((whitelist[_investor].fromTime != 0) || (whitelist[_investor].toTime != 0)) && + (whitelist[_investor].expiryTime >= now)); /*solium-disable-line security/no-block-members*/ } /** @@ -310,23 +301,6 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag return attached; } - function _adjustTimes(uint64 _time) internal view returns(uint64) { - if (offset.isForward != 0) { - require(_time + offset.time > _time); - return _time + offset.time; - } else { - require(_time >= offset.time); - return _time - offset.time; - } - } - - /** - * @dev Returns list of all investors - */ - function getInvestors() external view returns(address[]) { - return investors; - } - /** * @notice Return the permissions flag that are associated with general trnasfer manager */ diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 4c81be20a..c15eb52aa 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../../proxy/GeneralTransferManagerProxy.sol"; +import "./GeneralTransferManager.sol"; import "../ModuleFactory.sol"; /** @@ -8,23 +8,19 @@ import "../ModuleFactory.sol"; */ contract GeneralTransferManagerFactory is ModuleFactory { - address public logicContract; - /** * @notice Constructor * @param _polyAddress Address of the polytoken */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - require(_logicContract != address(0), "Invalid logic contract"); version = "1.0.0"; name = "GeneralTransferManager"; title = "General Transfer Manager"; description = "Manage transfers using a time based whitelist"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - logicContract = _logicContract; } @@ -35,7 +31,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - address generalTransferManager = new GeneralTransferManagerProxy(msg.sender, address(polyToken), logicContract); + address generalTransferManager = new GeneralTransferManager(msg.sender, address(polyToken)); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(generalTransferManager); diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol deleted file mode 100644 index f5c162080..000000000 --- a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol +++ /dev/null @@ -1,53 +0,0 @@ -pragma solidity ^0.4.24; - -/** - * @title Transfer Manager module for core transfer validation functionality - */ -contract GeneralTransferManagerStorage { - - //Address from which issuances come - address public issuanceAddress = address(0); - - //Address which can sign whitelist changes - address public signingAddress = address(0); - - bytes32 public constant WHITELIST = "WHITELIST"; - bytes32 public constant FLAGS = "FLAGS"; - - //from and to timestamps that an investor can send / receive tokens respectively - struct TimeRestriction { - uint64 fromTime; - uint64 toTime; - uint64 expiryTime; - uint8 canBuyFromSTO; - uint8 added; - } - - // Allows all TimeRestrictions to be offset - struct Offset { - uint64 time; - uint8 isForward; - } - - // Offset to be applied to all timings (except KYC expiry) - Offset public offset; - - // List of all addresses that have been added to the GTM at some point - address[] public investors; - - // An address can only send / receive tokens once their corresponding uint256 > block.number - // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) - mapping (address => TimeRestriction) public whitelist; - // Map of used nonces by customer - mapping(address => mapping(uint256 => bool)) public nonceMap; - - //If true, there are no transfer restrictions, for any addresses - bool public allowAllTransfers = false; - //If true, time lock is ignored for transfers (address must still be on whitelist) - bool public allowAllWhitelistTransfers = false; - //If true, time lock is ignored for issuances (address must still be on whitelist) - bool public allowAllWhitelistIssuances = true; - //If true, time lock is ignored for burn transactions - bool public allowAllBurnTransfers = false; - -} diff --git a/contracts/proxy/ERC20DividendCheckpointProxy.sol b/contracts/proxy/ERC20DividendCheckpointProxy.sol deleted file mode 100644 index 8839d30e1..000000000 --- a/contracts/proxy/ERC20DividendCheckpointProxy.sol +++ /dev/null @@ -1,31 +0,0 @@ -pragma solidity ^0.4.24; - -import "../modules/Checkpoint/ERC20DividendCheckpointStorage.sol"; -import "../modules/Checkpoint/DividendCheckpointStorage.sol"; -import "./OwnedProxy.sol"; -import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; - -/** - * @title Transfer Manager module for core transfer validation functionality - */ -contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - * @param _implementation representing the address of the new implementation to be set - */ - constructor (address _securityToken, address _polyAddress, address _implementation) - public - ModuleStorage(_securityToken, _polyAddress) - { - require( - _implementation != address(0), - "Implementation address should not be 0x" - ); - __implementation = _implementation; - } - -} diff --git a/contracts/proxy/EtherDividendCheckpointProxy.sol b/contracts/proxy/EtherDividendCheckpointProxy.sol deleted file mode 100644 index 40b1c1332..000000000 --- a/contracts/proxy/EtherDividendCheckpointProxy.sol +++ /dev/null @@ -1,30 +0,0 @@ -pragma solidity ^0.4.24; - -import "../modules/Checkpoint/DividendCheckpointStorage.sol"; -import "./OwnedProxy.sol"; -import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; - -/** - * @title Transfer Manager module for core transfer validation functionality - */ -contract EtherDividendCheckpointProxy is DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - * @param _implementation representing the address of the new implementation to be set - */ - constructor (address _securityToken, address _polyAddress, address _implementation) - public - ModuleStorage(_securityToken, _polyAddress) - { - require( - _implementation != address(0), - "Implementation address should not be 0x" - ); - __implementation = _implementation; - } - -} diff --git a/contracts/proxy/GeneralTransferManagerProxy.sol b/contracts/proxy/GeneralTransferManagerProxy.sol deleted file mode 100644 index cb9b69070..000000000 --- a/contracts/proxy/GeneralTransferManagerProxy.sol +++ /dev/null @@ -1,30 +0,0 @@ -pragma solidity ^0.4.24; - -import "../modules/TransferManager/GeneralTransferManagerStorage.sol"; -import "./OwnedProxy.sol"; -import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; - -/** - * @title Transfer Manager module for core transfer validation functionality - */ -contract GeneralTransferManagerProxy is GeneralTransferManagerStorage, ModuleStorage, Pausable, OwnedProxy { - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - * @param _implementation representing the address of the new implementation to be set - */ - constructor (address _securityToken, address _polyAddress, address _implementation) - public - ModuleStorage(_securityToken, _polyAddress) - { - require( - _implementation != address(0), - "Implementation address should not be 0x" - ); - __implementation = _implementation; - } - -} diff --git a/contracts/proxy/OwnedProxy.sol b/contracts/proxy/OwnedProxy.sol deleted file mode 100644 index b75142fbe..000000000 --- a/contracts/proxy/OwnedProxy.sol +++ /dev/null @@ -1,91 +0,0 @@ -pragma solidity ^0.4.18; - -import "./Proxy.sol"; - -/** - * @title OwnedProxy - * @dev This contract combines an upgradeability proxy with basic authorization control functionalities - */ -contract OwnedProxy is Proxy { - - // Owner of the contract - address private __owner; - - // Address of the current implementation - address internal __implementation; - - /** - * @dev Event to show ownership has been transferred - * @param _previousOwner representing the address of the previous owner - * @param _newOwner representing the address of the new owner - */ - event ProxyOwnershipTransferred(address _previousOwner, address _newOwner); - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier ifOwner() { - if (msg.sender == _owner()) { - _; - } else { - _fallback(); - } - } - - /** - * @dev the constructor sets the original owner of the contract to the sender account. - */ - constructor() public { - _setOwner(msg.sender); - } - - /** - * @dev Tells the address of the owner - * @return the address of the owner - */ - function _owner() internal view returns (address) { - return __owner; - } - - /** - * @dev Sets the address of the owner - */ - function _setOwner(address _newOwner) internal { - require(_newOwner != address(0), "Address should not be 0x"); - __owner = _newOwner; - } - - /** - * @notice Internal function to provide the address of the implementation contract - */ - function _implementation() internal view returns (address) { - return __implementation; - } - - /** - * @dev Tells the address of the proxy owner - * @return the address of the proxy owner - */ - function proxyOwner() external ifOwner returns (address) { - return _owner(); - } - - /** - * @dev Tells the address of the current implementation - * @return address of the current implementation - */ - function implementation() external ifOwner returns (address) { - return _implementation(); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param _newOwner The address to transfer ownership to. - */ - function transferProxyOwnership(address _newOwner) external ifOwner { - require(_newOwner != address(0), "Address should not be 0x"); - emit ProxyOwnershipTransferred(_owner(), _newOwner); - _setOwner(_newOwner); - } - -} diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index f25cfab35..694fdf03e 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,12 +1,9 @@ const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') -const GeneralTransferManagerLogic = artifacts.require('./GeneralTransferManager.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') -const EtherDividendCheckpointLogic = artifacts.require('./EtherDividendCheckpoint.sol') -const ERC20DividendCheckpointLogic = artifacts.require('./ERC20DividendCheckpoint.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); @@ -148,22 +145,10 @@ module.exports = function (deployer, network, accounts) { moduleRegistry = ModuleRegistry.at(ModuleRegistryProxy.address); // Add module registry to polymath registry return polymathRegistry.changeAddress("ModuleRegistry", ModuleRegistryProxy.address, {from: PolymathAccount}); - }).then(() => { - // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this - // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(GeneralTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); - }).then(() => { - // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this - // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(ERC20DividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); - }).then(() => { - // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this - // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(EtherDividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); }).then(() => { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, GeneralTransferManagerLogic.address, {from: PolymathAccount}); + return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // C) Deploy the GeneralPermissionManagerFactory Contract (Factory used to generate the GeneralPermissionManager contract and // this manager attach with the securityToken contract at the time of deployment) @@ -179,11 +164,11 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // D) Deploy the EtherDividendCheckpointFactory Contract (Factory used to generate the EtherDividendCheckpoint contract use // to provide the functionality of the dividend in terms of ETH) - return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, EtherDividendCheckpointLogic.address, {from: PolymathAccount}); + return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // D) Deploy the ERC20DividendCheckpointFactory Contract (Factory used to generate the ERC20DividendCheckpoint contract use // to provide the functionality of the dividend in terms of ERC20 token) - return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, ERC20DividendCheckpointLogic.address, {from: PolymathAccount}); + return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // D) Deploy the ManualApprovalTransferManagerFactory Contract (Factory used to generate the ManualApprovalTransferManager contract use // to manual approve the transfer that will overcome the other transfer restrictions) @@ -318,7 +303,6 @@ module.exports = function (deployer, network, accounts) { POLYOracle: ${POLYOracle} STFactory: ${STFactory.address} - GeneralTransferManagerLogic: ${GeneralTransferManagerLogic.address} GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} @@ -329,8 +313,6 @@ module.exports = function (deployer, network, accounts) { CountTransferManagerFactory: ${CountTransferManagerFactory.address} PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} - EtherDividendCheckpointLogic: ${EtherDividendCheckpointLogic.address} - ERC20DividendCheckpointLogic: ${ERC20DividendCheckpointLogic.address} EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} --------------------------------------------------------------------------------- diff --git a/package.json b/package.json index 58104d99b..ef2d76c38 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "ethers": "^3.0.15", "fs": "0.0.1-security", "openzeppelin-solidity": "1.10.0", - "prompt": "^1.0.0", "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", diff --git a/scripts/compareStorageLayout.js b/scripts/compareStorageLayout.js deleted file mode 100644 index c339bf095..000000000 --- a/scripts/compareStorageLayout.js +++ /dev/null @@ -1,139 +0,0 @@ -const fs = require('fs'); -const _ = require('underscore'); -const solc = require('solc'); -const prompt = require('prompt'); -const path = require('path'); -const util = require('util'); -const exec = util.promisify(require('child_process').exec); - -prompt.start(); - -prompt.get(['LogicContract', 'ProxyContract'], async(err, result) => { - - let logicContract; - let proxyContract; - - const fileList = walkSync('./contracts', []); - - let paths = findPath(result.LogicContract, result.ProxyContract, fileList); - - if (paths.length == 2) { - - console.log("Contracts exists \n"); - - await flatContracts(paths); - - if (path.basename(paths[0]) === result.LogicContract) { - logicContract = fs.readFileSync(`./flat/${path.basename(paths[0])}`, 'utf8'); - } else { - logicContract = fs.readFileSync(`./flat/${path.basename(paths[1])}`, 'utf8'); - } - if (path.basename(paths[0]) === result.ProxyContract) { - proxyContract = fs.readFileSync(`./flat/${path.basename(paths[0])}`, 'utf8'); - } else { - proxyContract = fs.readFileSync(`./flat/${path.basename(paths[1])}`, 'utf8'); - } - - let logicInput = { - 'contracts': logicContract - } - let proxyInput = { - 'contracts': proxyContract - } - - console.log(compareStorageLayouts(parseContract(logicInput), parseContract(proxyInput))); - - } else { - console.log("Contracts doesn't exists"); - } -}); - -function traverseAST(_input, _elements) { - if(_input.children) { - for(var i=0;i<_input.children.length;i++) { - traverseAST(_input.children[i], _elements); - } - } - _elements.push(_input); -} - -function compareStorageLayouts(logicLayout, proxyLayout) { - function makeComp(x) { - return [x.constant, x.name, x.stateVariable, x.storageLocation, x.type, x.value, x.visibility].join(':'); - } - // if(newLayout.length < oldLayout.length) return false; - for(var i=0; i < logicLayout.length; i++) { - const a = logicLayout[i].attributes; - const comp1 = makeComp(a) - console.log(comp1); - const b = proxyLayout[i].attributes; - const comp2 = makeComp(b); - console.log(comp2); - if(comp1 != comp2) { - return false; - } - } - return true; -} - -function parseContract(input) { - - var output = solc.compile({ sources: input }, 1, _.noop); - const elements = []; - const AST = output.sources.contracts.AST; - // console.log(AST); - traverseAST(AST, elements); - // console.log(elements); - - // filter out all Contract Definitions - const contractDefinitions = _.filter(elements, (e,i) => e.name == 'ContractDefinition'); - - // filter out all linearizedBaseContracts - // pick the last one as the last contract always has the full inheritance - const linearizedBaseContracts = _.last(_.map(contractDefinitions, e => e.attributes.linearizedBaseContracts)); - - // get all stateVariables - const stateVariables = _.filter(elements, e => e.attributes && e.attributes.stateVariable ) - - // group them by scope - const stateVariableMap = _.groupBy(stateVariables, e => e.attributes.scope); - - orderedStateVariables = _.reduceRight(linearizedBaseContracts, (a, b) => { - return a.concat(stateVariableMap[b] || []) - }, []); - return orderedStateVariables; -} - -var walkSync = function(dir, filelist) { - files = fs.readdirSync(dir); - filelist = filelist || []; - files.forEach(function(file) { - if (fs.statSync(path.join(dir, file)).isDirectory()) { - filelist = walkSync(path.join(dir, file), filelist); - } - else { - filelist.push(path.join(dir, file)); - } - }); - return filelist; -}; - -var findPath = function(logicContractName, proxyContractName, fileList) { - let paths = new Array(); - for (let i =0; i < fileList.length; i++) { - if ((logicContractName === path.basename(fileList[i]) || logicContractName === (path.basename(fileList[i])).split(".")[0]) || - (proxyContractName === path.basename(fileList[i]) || proxyContractName === (path.basename(fileList[i])).split(".")[0])) { - paths.push(fileList[i]); - } - } - return paths; -} - -async function flatContracts(_paths, _logic) { - let promises = new Array(); - for (let i = 0; i< _paths.length; i++) { - promises.push(await exec(`./node_modules/.bin/sol-merger ${_paths[i]} ./flat`)); - } - await Promise.all(promises); -} - diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index b1365ad3b..fce1ee5e5 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -130,7 +130,7 @@ contract("CappedSTO", accounts => { // STEP 5: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - + // STEP 6: Deploy the CappedSTOFactory I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); @@ -360,7 +360,7 @@ contract("CappedSTO", accounts => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { from: account_issuer }); @@ -443,7 +443,7 @@ contract("CappedSTO", accounts => { fromTime, toTime + duration.days(20), expiryTime, - 1, + true, { from: account_issuer } @@ -565,7 +565,7 @@ contract("CappedSTO", accounts => { it("Should successfully whitelist investor 3", async () => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { from: account_issuer, gas: 500000 }); @@ -733,7 +733,7 @@ contract("CappedSTO", accounts => { "Tokens are not transfered properly" ); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, P_fromTime, P_toTime, P_expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, P_fromTime, P_toTime, P_expiryTime, true, { from: account_issuer, gas: 500000 }); @@ -800,7 +800,7 @@ contract("CappedSTO", accounts => { P_fromTime, P_toTime + duration.days(20), P_expiryTime, - 1, + true, { from: account_issuer, gas: 500000 @@ -997,7 +997,7 @@ contract("CappedSTO", accounts => { await I_PolyToken.getTokens(polyToInvest * Math.pow(10, 18), account_investor3); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, true, { from: account_issuer, gas: 500000 }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 2ba198f83..6a08b6dea 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -149,7 +149,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 0, + false, { from: account_issuer, gas: 6000000 @@ -176,7 +176,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 0, + false, { from: account_issuer, gas: 6000000 @@ -201,7 +201,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 0, + false, { from: account_issuer, gas: 6000000 diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 4e86bdbb6..1a1e7717a 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -200,7 +200,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -230,7 +230,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -257,7 +257,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -282,7 +282,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 6a4baeab6..b832bcee2 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -89,7 +89,7 @@ contract("ERC20DividendCheckpoint", accounts => { account_investor4 = accounts[9]; account_temp = accounts[2]; account_manager = accounts[5]; - + // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -202,7 +202,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -232,7 +232,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -372,7 +372,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(20), - 1, + true, { from: account_issuer, gas: 500000 @@ -434,7 +434,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -970,7 +970,7 @@ contract("ERC20DividendCheckpoint", accounts => { let expiry = latestTime() + duration.days(10); let exclusions = [1]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); - await I_SecurityToken.createCheckpoint({ from: token_owner }); + await I_SecurityToken.createCheckpoint({ from: token_owner }); await catchRevert(I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 68c11f72f..b4e5bbf2b 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -200,7 +200,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -230,7 +230,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -364,7 +364,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(20), - 1, + true, { from: account_issuer, gas: 500000 @@ -415,7 +415,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -719,7 +719,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -851,7 +851,7 @@ contract("EtherDividendCheckpoint", accounts => { let expiry = latestTime() + duration.days(10); let exclusions = [1]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); - await I_SecurityToken.createCheckpoint({ from: token_owner }); + await I_SecurityToken.createCheckpoint({ from: token_owner }); await catchRevert(I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 5dbcf5a6c..3e060c288 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -92,7 +92,6 @@ contract("GeneralTransferManager", accounts => { account_investor1 = accounts[8]; account_investor2 = accounts[9]; account_delegate = accounts[7]; - account_investor3 = accounts[5]; account_investor4 = accounts[6]; account_affiliates1 = accounts[3]; @@ -173,14 +172,14 @@ contract("GeneralTransferManager", accounts => { await catchRevert( I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}) ); - }); + }) it("Should attach the paid GTM", async() => { let snap_id = await takeSnapshot(); await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); await I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}); await revertToSnapshot(snap_id); - }); + }) it("Should whitelist the affiliates before the STO attached", async () => { let tx = await I_GeneralTransferManager.modifyWhitelistMulti( @@ -188,7 +187,7 @@ contract("GeneralTransferManager", accounts => { [latestTime() + duration.days(30), latestTime() + duration.days(30)], [latestTime() + duration.days(90), latestTime() + duration.days(90)], [latestTime() + duration.years(1), latestTime() + duration.years(1)], - [0, 0], + [false, false], { from: account_issuer, gas: 6000000 @@ -196,30 +195,6 @@ contract("GeneralTransferManager", accounts => { ); assert.equal(tx.logs[0].args._investor, account_affiliates1); assert.equal(tx.logs[1].args._investor, account_affiliates2); - assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2]); - }); - - it("Should whitelist lots of addresses and check gas", async () => { - let mockInvestors = []; - for (let i = 0; i < 50; i++) { - mockInvestors.push("0x1000000000000000000000000000000000000000".substring(0,42-i.toString().length) + i.toString()); - } - - let times = range1(50); - let bools = rangeB(50); - let tx = await I_GeneralTransferManager.modifyWhitelistMulti( - mockInvestors, - times, - times, - times, - bools, - { - from: account_issuer, - gas: 7900000 - } - ); - console.log("Multi Whitelist x 50: " + tx.receipt.gasUsed); - assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2].concat(mockInvestors)); }); it("Should mint the tokens to the affiliates", async () => { @@ -316,7 +291,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -345,7 +320,7 @@ contract("GeneralTransferManager", accounts => { it("Should fail in buying the tokens from the STO -- because amount is 0", async() => { await catchRevert( I_DummySTO.generateTokens(account_investor1, 0, { from: token_owner }) - ); + ); }); it("Should fail in buying the tokens from the STO -- because STO is paused", async() => { @@ -367,106 +342,6 @@ contract("GeneralTransferManager", accounts => { }); }); - describe("Buy tokens using on-chain whitelist and negative offset", async () => { - // let snap_id; - - it("Should Buy the tokens", async () => { - // Add the Investor in to the whitelist - // snap_id = await takeSnapshot(); - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime() + duration.days(10), - latestTime() + duration.days(10), - latestTime() + duration.days(20), - 1, - { - from: account_issuer, - gas: 6000000 - } - ); - - assert.equal( - tx.logs[0].args._investor.toLowerCase(), - account_investor1.toLowerCase(), - "Failed in adding the investor in whitelist" - ); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); - - await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("3", "ether")); - }); - - it("Add an offset and check transfers are disabled", async () => { - let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 0, {from: token_owner}); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("3", "ether")); - tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); - // await revertToSnapshot(snap_id); - }); - - }); - - - describe("Buy tokens using on-chain whitelist and positive offset", async () => { - // let snap_id; - - it("Should Buy the tokens", async () => { - - // Add the Investor in to the whitelist - // snap_id = await takeSnapshot(); - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(20), - 1, - { - from: account_issuer, - gas: 6000000 - } - ); - - assert.equal( - tx.logs[0].args._investor.toLowerCase(), - account_investor1.toLowerCase(), - "Failed in adding the investor in whitelist" - ); - - // Jump time - await increaseTime(5000); - // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); - // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); - - // Mint some tokens - console.log(await I_GeneralTransferManager.offset.call()); - await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); - }); - - it("Add an offset and check transfers are disabled", async () => { - let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 1, {from: token_owner}); - // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); - // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); - - await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); - await increaseTime(duration.days(10)); - // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); - // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); - - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); - tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); - // await revertToSnapshot(snap_id); - }); - - }); - describe("Buy tokens using off-chain whitelist", async () => { it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { await catchRevert(I_DummySTO.generateTokens(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner })); @@ -484,7 +359,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -501,7 +376,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -528,7 +403,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -545,7 +420,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -572,7 +447,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -589,7 +464,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -616,7 +491,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - 1, + true, validFrom, validTo, nonce, @@ -632,7 +507,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - 1, + true, validFrom, validTo, nonce, @@ -672,7 +547,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - 1, + true, validFrom, validTo, nonce, @@ -688,7 +563,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - 1, + true, validFrom, validTo, nonce, @@ -795,7 +670,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [1, 1], + [true, true], { from: account_delegate, gas: 6000000 @@ -815,7 +690,7 @@ contract("GeneralTransferManager", accounts => { [fromTime], [toTime, toTime], [expiryTime, expiryTime], - [1, 1], + [true, true], { from: account_delegate, gas: 6000000 @@ -835,7 +710,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime], [expiryTime, expiryTime], - [1, 1], + [true, true], { from: account_delegate, gas: 6000000 @@ -855,7 +730,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime], - [1, 1], + [true, true], { from: account_delegate, gas: 6000000 @@ -874,7 +749,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [1, 1], + [true, true], { from: token_owner, gas: 6000000 @@ -961,6 +836,3 @@ contract("GeneralTransferManager", accounts => { }) }); }); - -function range1(i) {return i?range1(i-1).concat(i):[]} -function rangeB(i) {return i?rangeB(i-1).concat(0):[]} diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index a6118741f..2021d350e 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -8,8 +8,6 @@ const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); -const ERC20DividendCheckpoint = artifacts.require("./ERC20DividendCheckpoint.sol"); -const EtherDividendCheckpoint = artifacts.require("./EtherDividendCheckpoint.sol"); const ERC20DividendCheckpointFactory = artifacts.require("./ERC20DividendCheckpointFactory.sol"); const EtherDividendCheckpointFactory = artifacts.require("./EtherDividendCheckpointFactory.sol"); const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); @@ -22,7 +20,6 @@ const USDTieredSTOProxyFactory = artifacts.require("./USDTieredSTOProxyFactory") const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); const FeatureRegistry = artifacts.require("./FeatureRegistry.sol"); const STFactory = artifacts.require("./STFactory.sol"); -const GeneralTransferManager = artifacts.require("./GeneralTransferManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); @@ -48,13 +45,10 @@ let I_SingleTradeVolumeRestrictionManagerFactory; let I_ManualApprovalTransferManagerFactory; let I_VolumeRestrictionTransferManagerFactory; let I_PercentageTransferManagerFactory; -let I_EtherDividendCheckpointLogic; let I_EtherDividendCheckpointFactory; let I_CountTransferManagerFactory; -let I_ERC20DividendCheckpointLogic; let I_ERC20DividendCheckpointFactory; let I_GeneralPermissionManagerFactory; -let I_GeneralTransferManagerLogic; let I_GeneralTransferManagerFactory; let I_GeneralTransferManager; let I_ModuleRegistryProxy; @@ -88,9 +82,7 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { let b = await deployFeatureRegistry(account_polymath); // STEP 3: Deploy the ModuleRegistry let c = await deployModuleRegistry(account_polymath); - // STEP 4a: Deploy the GeneralTransferManagerFactory - let logic = await deployGTMLogic(account_polymath); - // STEP 4b: Deploy the GeneralTransferManagerFactory + // STEP 4: Deploy the GeneralTransferManagerFactory let d = await deployGTM(account_polymath); // Step 6: Deploy the STversionProxy contract let e = await deploySTFactory(account_polymath); @@ -135,20 +127,8 @@ async function deployModuleRegistry(account_polymath) { return new Array(I_ModuleRegistry, I_ModuleRegistryProxy, I_MRProxied); } -async function deployGTMLogic(account_polymath) { - I_GeneralTransferManagerLogic = await GeneralTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); - - assert.notEqual( - I_GeneralTransferManagerLogic.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerLogic contract was not deployed" - ); - - return new Array(I_GeneralTransferManagerLogic); -} - async function deployGTM(account_polymath) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); assert.notEqual( I_GeneralTransferManagerFactory.address.valueOf(), @@ -213,7 +193,7 @@ async function registerAndVerifyByMR(factoryAdrress, owner, mr) { /// Deploy the TransferManagers export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(polyToken, setupCost, 0, 0, I_GeneralTransferManagerLogic.address, { from: accountPolymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), @@ -375,8 +355,7 @@ export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInst /// Deploy the Dividend Modules export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_ERC20DividendCheckpointLogic = await ERC20DividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(polyToken, setupCost, 0, 0, I_ERC20DividendCheckpointLogic.address, { from: accountPolymath }); + I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_ERC20DividendCheckpointFactory.address.valueOf(), @@ -388,8 +367,7 @@ export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyIns } export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_EtherDividendCheckpointLogic = await EtherDividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(polyToken, setupCost, 0, 0, I_EtherDividendCheckpointLogic.address, { from: accountPolymath }); + I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_EtherDividendCheckpointFactory.address.valueOf(), diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 2e5c1ad61..ea7476cc3 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -6,7 +6,7 @@ const ethUtil = require("ethereumjs-util"); function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce, pk) { let packedData = utils .solidityKeccak256( - ["address", "address", "uint64", "uint64", "uint64", "uint8", "uint64", "uint64", "uint256"], + ["address", "address", "uint256", "uint256", "uint256", "bool", "uint256", "uint256", "uint256"], [tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce] ) .slice(2); diff --git a/test/i_Issuance.js b/test/i_Issuance.js index efcf0db96..ac1fcdd37 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -215,7 +215,7 @@ contract("Issuance", accounts => { fromTime + duration.days(70), toTime + duration.days(90), expiryTime + duration.days(50), - 1, + true, { from: account_polymath } @@ -271,7 +271,7 @@ contract("Issuance", accounts => { }); it("should add the investor into the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { from: account_delegate, gas: 7000000 }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index c817f5c44..0461f287a 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -171,7 +171,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -201,7 +201,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -290,7 +290,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index 530b202c8..b15ee41a0 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -120,7 +120,7 @@ contract("PercentageTransferManager", accounts => { // STEP 4(b): Deploy the PercentageTransferManager [P_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); - + // Printing all the contract addresses console.log(` --------------------- Polymath Network Smart Contracts: --------------------- @@ -192,7 +192,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -222,7 +222,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -287,7 +287,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index 35a348c30..a89932dc4 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -236,7 +236,7 @@ contract("PreSaleSTO", accounts => { expiryTime = toTime + duration.days(100); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { from: account_issuer, gas: 6000000 }); @@ -277,7 +277,7 @@ contract("PreSaleSTO", accounts => { expiryTime = toTime + duration.days(100); // Add the Investor in to the whitelist - let tx1 = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { + let tx1 = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { from: account_issuer, gas: 6000000 }); @@ -285,7 +285,7 @@ contract("PreSaleSTO", accounts => { assert.equal(tx1.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); // Add the Investor in to the whitelist - let tx2 = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { + let tx2 = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { from: account_issuer, gas: 6000000 }); diff --git a/test/o_security_token.js b/test/o_security_token.js index 7d2722a20..52521181e 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -193,7 +193,7 @@ contract("SecurityToken", accounts => { let toTime = fromTime + duration.days(100); let expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 6000000 }); @@ -212,7 +212,7 @@ contract("SecurityToken", accounts => { let toTime = fromTime + duration.days(100); let expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 6000000 }); @@ -517,7 +517,7 @@ contract("SecurityToken", accounts => { toTime = fromTime + duration.days(100); expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 6000000 }); @@ -614,7 +614,7 @@ contract("SecurityToken", accounts => { }); it("Should transfer from whitelist investor1 to whitelist investor 2", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 500000 }); @@ -636,7 +636,7 @@ contract("SecurityToken", accounts => { it("Should transferFrom from one investor to other", async () => { await I_SecurityToken.approve(account_investor1, 2 * Math.pow(10, 18), { from: account_investor2 }); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 500000 }); @@ -682,7 +682,7 @@ contract("SecurityToken", accounts => { }); it("Should add the investor in the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, true, { from: account_delegate, gas: 6000000 }); @@ -722,7 +722,7 @@ contract("SecurityToken", accounts => { }); it("Should remove investor from the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, 0, 0, 0, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, 0, 0, 0, true, { from: account_delegate, gas: 6000000 }); @@ -751,7 +751,7 @@ contract("SecurityToken", accounts => { }); it("Should fail in buying to tokens", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, true, { from: account_delegate, gas: 6000000 }); @@ -939,7 +939,7 @@ contract("SecurityToken", accounts => { latestTime(), latestTime() + duration.seconds(2), latestTime() + duration.days(50), - 1, + true, { from: account_delegate, gas: 6000000 @@ -982,7 +982,7 @@ contract("SecurityToken", accounts => { latestTime(), latestTime() + duration.seconds(2), latestTime() + duration.days(50), - 1, + true, { from: account_delegate, gas: 6000000 diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 8a274942a..604eb1aaf 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -222,7 +222,7 @@ contract("USDTieredSTO", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 4: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, I_PolyToken.address, 0); @@ -1005,7 +1005,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1105,7 +1105,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1160,7 +1160,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1230,7 +1230,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1285,7 +1285,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime(); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1353,7 +1353,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER @@ -4482,7 +4482,7 @@ contract("USDTieredSTO", accounts => { "fundsRaisedUSD not changed as expected" ); }); - + it("should return minted tokens in a tier", async () => { let totalMinted = (await I_USDTieredSTO_Array[0].getTokensSoldByTier.call(0)).toNumber(); let individualMinted = await I_USDTieredSTO_Array[0].getTokensMintedByTier.call(0); @@ -4564,7 +4564,7 @@ contract("USDTieredSTO", accounts => { assert.equal((await I_USDTieredSTOFactory.getSetupCost.call()).toNumber(), STOSetupCost); assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0], 3); assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), "USDTieredSTO", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.description.call(), + assert.equal(await I_USDTieredSTOFactory.description.call(), "It allows both accredited and non-accredited investors to contribute into the STO. Non-accredited investors will be capped at a maximum investment limit (as a default or specific to their jurisdiction). Tokens will be sold according to tiers sequentially & each tier has its own price and volume of tokens to sell. Upon receipt of funds (ETH, POLY or DAI), security tokens will automatically transfer to investor’s wallet address", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.title.call(), "USD Tiered STO", "Wrong Module added"); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 31929ade5..55f84f2b3 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -195,7 +195,7 @@ contract("USDTieredSTO Sim", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 5: Deploy the USDTieredSTOFactory @@ -353,13 +353,13 @@ contract("USDTieredSTO Sim", accounts => { let fromTime = latestTime() + duration.days(15); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = 1; + let canBuyFromSTO = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, 0, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, { from: ISSUER }); await increaseTime(duration.days(3)); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 36761308e..7912658a4 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -2,7 +2,7 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import { takeSnapshot, increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; -import { +import { setUpPolymathNetwork, deployDummySTOAndVerifyed, deployCappedSTOAndVerifyed, @@ -94,7 +94,7 @@ contract("Concurrent STO", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + // STEP 2: Deploy the STO Factories [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, STOSetupCost); @@ -159,7 +159,7 @@ contract("Concurrent STO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = 1; + let canBuyFromSTO = true; let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: account_issuer, diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 877d173d4..6d00b8fe2 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -9,7 +9,6 @@ const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); const ModuleRegistry = artifacts.require("./ModuleRegistry.sol"); const STFactory = artifacts.require("./STFactory.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); -const GeneralTransferManagerLogic = artifacts.require("./GeneralTransferManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); @@ -123,9 +122,7 @@ contract("ModuleRegistryProxy", accounts => { await I_MRProxied.updateFromRegistry({ from: account_polymath }); // STEP 4: Deploy the GeneralTransferManagerFactory - let I_GeneralTransferManagerLogic = await GeneralTransferManagerLogic.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, I_GeneralTransferManagerLogic.address, { + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index eacddd87e..159564651 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -102,7 +102,7 @@ contract("TrackedRedemption", accounts => { I_STRProxied ] = instances; - + // STEP 4: Deploy the TrackedRedemption [I_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); [P_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); @@ -190,7 +190,7 @@ contract("TrackedRedemption", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -220,7 +220,7 @@ contract("TrackedRedemption", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index 7646fb031..fe06f3f5c 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -112,7 +112,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { STFactory: ${I_STFactory.address} GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} - LockupVolumeRestrictionTransferManagerFactory: + LockupVolumeRestrictionTransferManagerFactory: ${I_VolumeRestrictionTransferManagerFactory.address} ----------------------------------------------------------------------------- `); @@ -165,7 +165,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer }); @@ -192,7 +192,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer }); @@ -249,7 +249,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer }); @@ -346,14 +346,14 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // balance should be 9000000000000000000 here (9 eth) let balance = await I_SecurityToken.balanceOf(account_investor2) - + // create a lockup for their entire balance // over 16 seconds total, with 4 periods of 4 seconds each. // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 await catchRevert( I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }) ); - + }); it("Should prevent the transfer of tokens in a lockup", async() => { @@ -572,7 +572,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); it("Should revert if the parameters are bad when creating multiple lockups", async() => { - + await catchRevert( // pass in the wrong number of params. txn should revert I_VolumeRestrictionTransferManager.addLockUpMulti( diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index 25243a638..15c01e68c 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -107,7 +107,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); - + }); describe("Generate the SecurityToken", async () => { @@ -165,7 +165,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer }); @@ -193,7 +193,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer }); @@ -212,7 +212,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { // it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { let managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); await catchRevert( I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { from: token_owner}) @@ -222,7 +222,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); - + let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); @@ -291,7 +291,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]) ); - await catchRevert( + await catchRevert( I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { from: token_owner }) ); @@ -342,7 +342,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { await catchRevert ( I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { from: token_owner }) ); - // Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage + // Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage await catchRevert ( I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { from: token_owner }) ); @@ -393,7 +393,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { from: token_owner }); assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - + //Global limit can be set by non-admins await catchRevert( I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89) @@ -542,7 +542,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer } ); @@ -552,7 +552,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer } ); @@ -562,7 +562,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer } ); @@ -667,7 +667,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { }); it('should change transfer limits to tokens', async () => { - // Should not change to percentage again + // Should not change to percentage again await catchRevert( I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { from: token_owner }) ); diff --git a/test/y_scheduled_checkpoints.js b/test/y_scheduled_checkpoints.js index 864c6b9a1..5fcc03a74 100644 --- a/test/y_scheduled_checkpoints.js +++ b/test/y_scheduled_checkpoints.js @@ -192,7 +192,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -235,7 +235,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -270,7 +270,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 diff --git a/yarn.lock b/yarn.lock index 31973936e..27308427c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,10 +5,12 @@ "@soldoc/markdown@^0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@soldoc/markdown/-/markdown-0.1.0.tgz#9f85be75049af9721b5129f133d52dafbf5f671e" + integrity sha512-V0UnvVVJ1qDzpuKLMuh7oHG94puwi8BI3t99Vrr7dQgIHuJdfZJ4SbGuWuFV/fSthyH++WY4ePO3d6gxfZ2//w== "@soldoc/soldoc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@soldoc/soldoc/-/soldoc-0.4.3.tgz#24ffee9264228e1c3edd61fd3162d63587954933" + integrity sha1-JP/ukmQijhw+3WH9MWLWNYeVSTM= dependencies: "@soldoc/markdown" "^0.1.0" chalk "^2.3.1" @@ -22,26 +24,31 @@ abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= abstract-leveldown@~2.6.0: version "2.6.3" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== dependencies: xtend "~4.0.0" abstract-leveldown@~2.7.1: version "2.7.2" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== dependencies: xtend "~4.0.0" accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" + integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= dependencies: mime-types "~2.1.18" negotiator "0.6.1" @@ -49,46 +56,56 @@ accepts@~1.3.5: acorn-dynamic-import@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" + integrity sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ= dependencies: acorn "^4.0.3" acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= dependencies: acorn "^3.0.4" acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= acorn@^5.0.0, acorn@^5.5.0: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= aes-js@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072" + integrity sha512-cEA0gBelItZZV7iBiL8ApCiNgc+gBWJJ4uoORhbu6vOqAJ0UL9wIlxr4RI7ij9SSVzy6AnPwiu37kVYiHCl3nw== ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" + integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= ajv@^5.1.1, ajv@^5.2.2, ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" @@ -98,6 +115,7 @@ ajv@^5.1.1, ajv@^5.2.2, ajv@^5.2.3, ajv@^5.3.0: ajv@^6.1.0: version "6.5.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59" + integrity sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -107,6 +125,7 @@ ajv@^6.1.0: align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= dependencies: kind-of "^3.0.2" longest "^1.0.1" @@ -115,6 +134,7 @@ align-text@^0.1.1, align-text@^0.1.3: ambi@^2.2.0: version "2.5.0" resolved "https://registry.yarnpkg.com/ambi/-/ambi-2.5.0.tgz#7c8e372be48891157e7cea01cb6f9143d1f74220" + integrity sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA= dependencies: editions "^1.1.1" typechecker "^4.3.0" @@ -122,36 +142,44 @@ ambi@^2.2.0: amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= ansi-escapes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" + integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== dependencies: micromatch "^2.1.5" normalize-path "^2.0.0" @@ -159,6 +187,7 @@ anymatch@^1.3.0: anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" normalize-path "^2.1.1" @@ -166,10 +195,12 @@ anymatch@^2.0.0: aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -177,56 +208,85 @@ are-we-there-yet@~1.1.2: argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" +arguments-extended@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/arguments-extended/-/arguments-extended-0.0.3.tgz#6107e4917d0eb6f0a4dd66320fc15afc72ef4946" + integrity sha1-YQfkkX0OtvCk3WYyD8Fa/HLvSUY= + dependencies: + extended "~0.0.3" + is-extended "~0.0.8" + arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= dependencies: arr-flatten "^1.0.1" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-extended@~0.0.3, array-extended@~0.0.4, array-extended@~0.0.5: + version "0.0.11" + resolved "https://registry.yarnpkg.com/array-extended/-/array-extended-0.0.11.tgz#d7144ae748de93ca726f121009dbff1626d164bd" + integrity sha1-1xRK50jek8pybxIQCdv/FibRZL0= + dependencies: + arguments-extended "~0.0.3" + extended "~0.0.3" + is-extended "~0.0.3" array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= dependencies: array-uniq "^1.0.1" array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -235,30 +295,36 @@ asn1.js@^4.0.0: asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assert@^1.1.1: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= dependencies: util "0.10.3" assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-eventemitter@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== dependencies: async "^2.4.0" @@ -271,44 +337,49 @@ async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== async@1.x, async@^1.4.2, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.4.1, async@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== dependencies: lodash "^4.17.10" -async@~0.9.0: - version "0.9.2" - resolved "http://registry.npmjs.org/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - async@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" + integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -317,6 +388,7 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: babel-core@^6.0.14, babel-core@^6.26.0: version "6.26.3" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== dependencies: babel-code-frame "^6.26.0" babel-generator "^6.26.0" @@ -341,6 +413,7 @@ babel-core@^6.0.14, babel-core@^6.26.0: babel-generator@^6.26.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" @@ -354,6 +427,7 @@ babel-generator@^6.26.0: babel-helper-bindify-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" + integrity sha1-FMGeXxQte0fxmlJDHlKxzLxAozA= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -362,6 +436,7 @@ babel-helper-bindify-decorators@^6.24.1: babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= dependencies: babel-helper-explode-assignable-expression "^6.24.1" babel-runtime "^6.22.0" @@ -370,6 +445,7 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -379,6 +455,7 @@ babel-helper-call-delegate@^6.24.1: babel-helper-define-map@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.26.0" @@ -388,6 +465,7 @@ babel-helper-define-map@^6.24.1: babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -396,6 +474,7 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-helper-explode-class@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" + integrity sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes= dependencies: babel-helper-bindify-decorators "^6.24.1" babel-runtime "^6.22.0" @@ -405,6 +484,7 @@ babel-helper-explode-class@^6.24.1: babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= dependencies: babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" @@ -415,6 +495,7 @@ babel-helper-function-name@^6.24.1: babel-helper-get-function-arity@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -422,6 +503,7 @@ babel-helper-get-function-arity@^6.24.1: babel-helper-hoist-variables@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -429,6 +511,7 @@ babel-helper-hoist-variables@^6.24.1: babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -436,6 +519,7 @@ babel-helper-optimise-call-expression@^6.24.1: babel-helper-regex@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= dependencies: babel-runtime "^6.26.0" babel-types "^6.26.0" @@ -444,6 +528,7 @@ babel-helper-regex@^6.24.1: babel-helper-remap-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -454,6 +539,7 @@ babel-helper-remap-async-to-generator@^6.24.1: babel-helper-replace-supers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= dependencies: babel-helper-optimise-call-expression "^6.24.1" babel-messages "^6.23.0" @@ -465,6 +551,7 @@ babel-helper-replace-supers@^6.24.1: babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -472,50 +559,61 @@ babel-helpers@^6.24.1: babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= dependencies: babel-runtime "^6.22.0" babel-plugin-check-es2015-constants@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= dependencies: babel-runtime "^6.22.0" babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= babel-plugin-syntax-async-generators@^6.5.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" + integrity sha1-a8lj67FuzLrmuStZbrfzXDQqi5o= babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= babel-plugin-syntax-decorators@^6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" + integrity sha1-MSVjtNvePMgGzuPkFszurd0RrAs= babel-plugin-syntax-dynamic-import@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= babel-plugin-transform-async-generator-functions@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" + integrity sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-generators "^6.5.0" @@ -524,6 +622,7 @@ babel-plugin-transform-async-generator-functions@^6.24.1: babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-functions "^6.8.0" @@ -532,6 +631,7 @@ babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async- babel-plugin-transform-class-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= dependencies: babel-helper-function-name "^6.24.1" babel-plugin-syntax-class-properties "^6.8.0" @@ -541,6 +641,7 @@ babel-plugin-transform-class-properties@^6.24.1: babel-plugin-transform-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" + integrity sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0= dependencies: babel-helper-explode-class "^6.24.1" babel-plugin-syntax-decorators "^6.13.0" @@ -551,18 +652,21 @@ babel-plugin-transform-decorators@^6.24.1: babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= dependencies: babel-runtime "^6.26.0" babel-template "^6.26.0" @@ -573,6 +677,7 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= dependencies: babel-helper-define-map "^6.24.1" babel-helper-function-name "^6.24.1" @@ -587,6 +692,7 @@ babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-cla babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -594,12 +700,14 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transfor babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -607,12 +715,14 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2 babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -621,12 +731,14 @@ babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= dependencies: babel-plugin-transform-es2015-modules-commonjs "^6.24.1" babel-runtime "^6.22.0" @@ -635,6 +747,7 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.26.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== dependencies: babel-plugin-transform-strict-mode "^6.24.1" babel-runtime "^6.26.0" @@ -644,6 +757,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -652,6 +766,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= dependencies: babel-plugin-transform-es2015-modules-amd "^6.24.1" babel-runtime "^6.22.0" @@ -660,6 +775,7 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= dependencies: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" @@ -667,6 +783,7 @@ babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= dependencies: babel-helper-call-delegate "^6.24.1" babel-helper-get-function-arity "^6.24.1" @@ -678,6 +795,7 @@ babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015- babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -685,12 +803,14 @@ babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transfo babel-plugin-transform-es2015-spread@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -699,18 +819,21 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -719,6 +842,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= dependencies: babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" babel-plugin-syntax-exponentiation-operator "^6.8.0" @@ -727,6 +851,7 @@ babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-e babel-plugin-transform-object-rest-spread@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" + integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" @@ -734,12 +859,14 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= dependencies: regenerator-transform "^0.10.0" babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -747,6 +874,7 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-polyfill@6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" + integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= dependencies: babel-runtime "^6.26.0" core-js "^2.5.0" @@ -755,6 +883,7 @@ babel-polyfill@6.26.0: babel-preset-env@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -790,6 +919,7 @@ babel-preset-env@^1.7.0: babel-preset-es2015@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" + integrity sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk= dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-transform-es2015-arrow-functions "^6.22.0" @@ -819,6 +949,7 @@ babel-preset-es2015@6.24.1: babel-preset-stage-2@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" + integrity sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE= dependencies: babel-plugin-syntax-dynamic-import "^6.18.0" babel-plugin-transform-class-properties "^6.24.1" @@ -828,6 +959,7 @@ babel-preset-stage-2@6.24.1: babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" + integrity sha1-g2raCp56f6N8sTj7kyb4eTSkg5U= dependencies: babel-plugin-syntax-trailing-function-commas "^6.22.0" babel-plugin-transform-async-generator-functions "^6.24.1" @@ -838,6 +970,7 @@ babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: babel-register@6.26.0, babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= dependencies: babel-core "^6.26.0" babel-runtime "^6.26.0" @@ -850,6 +983,7 @@ babel-register@6.26.0, babel-register@^6.26.0: babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" @@ -857,6 +991,7 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= dependencies: babel-runtime "^6.26.0" babel-traverse "^6.26.0" @@ -867,6 +1002,7 @@ babel-template@^6.24.1, babel-template@^6.26.0: babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= dependencies: babel-code-frame "^6.26.0" babel-messages "^6.23.0" @@ -881,6 +1017,7 @@ babel-traverse@^6.24.1, babel-traverse@^6.26.0: babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= dependencies: babel-runtime "^6.26.0" esutils "^2.0.2" @@ -890,6 +1027,7 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: babelify@^7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" + integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= dependencies: babel-core "^6.0.14" object-assign "^4.0.0" @@ -897,28 +1035,34 @@ babelify@^7.3.0: babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base-x@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" + integrity sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA== dependencies: safe-buffer "^5.0.1" base64-js@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" + integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg= base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -931,24 +1075,29 @@ base@^0.11.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== bignumber.js@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" + integrity sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA== bignumber.js@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" + integrity sha512-KWTu6ZMVk9sxlDJQh2YH1UOnfDP8O8TpxUxgQG/vKASoSnEjK9aVuOueFaPcQEYQ5fyNXNTOYwYw3099RYebWg== bignumber.js@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-6.0.0.tgz#bbfa047644609a5af093e9cbd83b0461fa3f6002" + integrity sha512-x247jIuy60/+FtMRvscqfxtVHQf8AGx2hm9c6btkgC0x/hp9yt+teISNhvF8WlwRkCc5yF2fDECH8SIMe8j+GA== "bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" @@ -965,20 +1114,24 @@ bignumber.js@^6.0.0: binary-extensions@^1.0.0: version "1.12.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" + integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== bindings@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" + integrity sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw== bip66@^1.1.3: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" + integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= dependencies: safe-buffer "^5.0.1" bitcore-lib@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.15.0.tgz#f924be13869f2aab7e04aeec5642ad3359b6cec2" + integrity sha512-AeXLWhiivF6CDFzrABZHT4jJrflyylDWTi32o30rF92HW9msfuKpjzrHtFKYGa9w0kNVv5HABQjCB3OEav4PhQ== dependencies: bn.js "=4.11.8" bs58 "=4.0.1" @@ -990,6 +1143,7 @@ bitcore-lib@^0.15.0: bitcore-mnemonic@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-1.5.0.tgz#c7e785beb6bf0616ed4992785dc3658670425a39" + integrity sha512-sbeP4xwkindLMfIQhVxj6rZSDMwtiKmfc1DqvwpR6Yg+Qo4I4WHO5pvzb12Y04uDh1N3zgD45esHhfH0HHmE4g== dependencies: bitcore-lib "^0.15.0" unorm "^1.3.3" @@ -997,6 +1151,7 @@ bitcore-mnemonic@^1.5.0: bl@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== dependencies: readable-stream "^2.3.5" safe-buffer "^5.1.1" @@ -1004,32 +1159,39 @@ bl@^1.0.0: block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= dependencies: inherits "~2.0.0" bluebird@^2.9.34: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" + integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= bluebird@^3.4.6, bluebird@^3.5.0: version "3.5.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" + integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg== bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= bn.js@=4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== bn.js@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625" + integrity sha1-EhYrwq5x/EClYmwzQ486h1zTdiU= body-parser@1.18.3, body-parser@^1.16.0: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" + integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= dependencies: bytes "3.0.0" content-type "~1.0.4" @@ -1045,6 +1207,7 @@ body-parser@1.18.3, body-parser@^1.16.0: borc@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/borc/-/borc-2.0.3.tgz#08845ea73a6d3211120928ee3929f8dc2de9f52e" + integrity sha512-2mfipKUXn7yLgwn8D5jZkJqd2ZyzqmYZQX/9d4On33oGNDLwxj5qQMst+nkKyEdaujQRFfrZCId+k8wehQVANg== dependencies: bignumber.js "^6.0.0" commander "^2.15.0" @@ -1054,6 +1217,7 @@ borc@^2.0.2: brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1061,6 +1225,7 @@ brace-expansion@^1.1.7: braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= dependencies: expand-range "^1.8.1" preserve "^0.2.0" @@ -1069,6 +1234,7 @@ braces@^1.8.2: braces@^2.3.0, braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -1084,18 +1250,22 @@ braces@^2.3.0, braces@^2.3.1: brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1107,6 +1277,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: browserify-cipher@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -1115,6 +1286,7 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -1124,6 +1296,7 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= dependencies: bn.js "^4.1.0" randombytes "^2.0.1" @@ -1131,12 +1304,14 @@ browserify-rsa@^4.0.0: browserify-sha3@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" + integrity sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE= dependencies: js-sha3 "^0.3.1" browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= dependencies: bn.js "^4.1.1" browserify-rsa "^4.0.0" @@ -1149,12 +1324,14 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" browserslist@^3.2.6: version "3.2.8" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== dependencies: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" @@ -1162,16 +1339,19 @@ browserslist@^3.2.6: bs58@=4.0.1, bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= dependencies: base-x "^3.0.2" bs58@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" + integrity sha1-VZCNWPGYKrogCPob7Y+RmYopv40= bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== dependencies: bs58 "^4.0.0" create-hash "^1.1.0" @@ -1180,14 +1360,17 @@ bs58check@^2.1.2: bson@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.0.tgz#bee57d1fb6a87713471af4e32bcae36de814b5b0" + integrity sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA== buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== buffer-alloc@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== dependencies: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" @@ -1195,30 +1378,37 @@ buffer-alloc@^1.2.0: buffer-compare@=1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.1.1.tgz#5be7be853af89198d1f4ddc090d1d66a48aef596" + integrity sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY= buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-to-arraybuffer@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^3.0.1: version "3.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" + integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs= dependencies: base64-js "0.0.8" ieee754 "^1.1.4" @@ -1227,6 +1417,7 @@ buffer@^3.0.1: buffer@^4.3.0, buffer@^4.9.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1235,6 +1426,7 @@ buffer@^4.3.0, buffer@^4.9.0: buffer@^5.0.5: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" + integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1242,18 +1434,22 @@ buffer@^5.0.5: builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -1268,28 +1464,34 @@ cache-base@^1.0.1: caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= dependencies: callsites "^0.2.0" callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= caminte@0.3.7: version "0.3.7" resolved "https://registry.yarnpkg.com/caminte/-/caminte-0.3.7.tgz#ec1ec0457664a0f092643b7c646c457d5cd6f693" + integrity sha1-7B7ARXZkoPCSZDt8ZGxFfVzW9pM= dependencies: bluebird "^3.4.6" uuid "^3.0.1" @@ -1297,14 +1499,17 @@ caminte@0.3.7: caniuse-lite@^1.0.30000844: version "1.0.30000890" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000890.tgz#86a18ffcc65d79ec6a437e985761b8bf1c4efeaf" + integrity sha512-4NI3s4Y6ROm+SgZN5sLUG4k7nVWQnedis3c/RWkynV5G6cHSY7+a8fwFyn2yoBDE3E6VswhTNNwR3PvzGqlTkg== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= center-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= dependencies: align-text "^0.1.3" lazy-cache "^1.0.3" @@ -1312,6 +1517,7 @@ center-align@^0.1.1: chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -1322,6 +1528,7 @@ chalk@^1.1.3: chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1330,16 +1537,19 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= checkpoint-store@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= dependencies: functional-red-black-tree "^1.0.1" chokidar@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= dependencies: anymatch "^1.3.0" async-each "^1.0.0" @@ -1355,6 +1565,7 @@ chokidar@^1.6.0: chokidar@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" + integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== dependencies: anymatch "^2.0.0" async-each "^1.0.0" @@ -1374,10 +1585,12 @@ chokidar@^2.0.2: chownr@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" + integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -1385,10 +1598,12 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" @@ -1398,6 +1613,7 @@ class-utils@^0.3.5: cli-color@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.3.0.tgz#cd2ec212efbd1a0eeb5b017f17d4e2d15e91420f" + integrity sha512-XmbLr8MzgOup/sPHF4nOZerCOcL7rD7vKWpEl0axUsMAY+AEimOhYva1ksskWqkLGY/bjR9h7Cfbr+RrJRfmTQ== dependencies: ansi-regex "^2.1.1" d "1" @@ -1409,16 +1625,19 @@ cli-color@^1.2.0: cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= dependencies: center-align "^0.1.1" right-align "^0.1.1" @@ -1427,6 +1646,7 @@ cliui@^2.1.0: cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -1435,6 +1655,7 @@ cliui@^3.2.0: cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" @@ -1443,18 +1664,22 @@ cliui@^4.0.0: clone@2.x, clone@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= coinstring@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" + integrity sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q= dependencies: bs58 "^2.0.1" create-hash "^1.1.1" @@ -1462,6 +1687,7 @@ coinstring@^2.0.0: collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -1469,70 +1695,85 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= colors@^1.1.2: version "1.3.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" + integrity sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ== combined-stream@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= dependencies: delayed-stream "~1.0.0" combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== dependencies: delayed-stream "~1.0.0" commander@2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== commander@2.15.1: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== commander@^2.11.0, commander@^2.14.1, commander@^2.15.0, commander@^2.8.1, commander@^2.9.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== commander@~2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" + integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= dependencies: graceful-readlink ">= 1.0.0" compare-versions@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" + integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg== component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" @@ -1542,62 +1783,76 @@ concat-stream@^1.6.0: console-browserify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= dependencies: date-now "^0.1.4" console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== dependencies: safe-buffer "~5.1.1" cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= cookiejar@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" + integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0, core-js@^2.5.0: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cors@^2.8.1: version "2.8.4" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" + integrity sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY= dependencies: object-assign "^4" vary "^1" @@ -1605,6 +1860,7 @@ cors@^2.8.1: coveralls@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" + integrity sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw== dependencies: growl "~> 1.10.0" js-yaml "^3.11.0" @@ -1616,6 +1872,7 @@ coveralls@^3.0.1: create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== dependencies: bn.js "^4.1.0" elliptic "^6.0.0" @@ -1623,6 +1880,7 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -1633,6 +1891,7 @@ create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -1644,6 +1903,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: cron-parser@^2.4.0: version "2.6.0" resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.6.0.tgz#ae2514ceda9ccb540256e201bdd23ae814e03674" + integrity sha512-KGfDDTjBIx85MnVYcdhLccoJH/7jcYW+5Z/t3Wsg2QlJhmmjf+97z+9sQftS71lopOYYapjEKEvmWaCsym5Z4g== dependencies: is-nan "^1.2.1" moment-timezone "^0.5.0" @@ -1651,6 +1911,7 @@ cron-parser@^2.4.0: cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" @@ -1659,6 +1920,7 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: crypto-browserify@3.12.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -1675,84 +1937,115 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0: crypto-js@^3.1.4, crypto-js@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" + integrity sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU= crypto-js@^3.1.9-1: version "3.1.9-1" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8" + integrity sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg= crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= csextends@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/csextends/-/csextends-1.2.0.tgz#6374b210984b54d4495f29c99d3dd069b80543e5" + integrity sha512-S/8k1bDTJIwuGgQYmsRoE+8P+ohV32WhQ0l4zqrc0XDdxOhjQQD7/wTZwCzoZX53jSX3V/qwjT+OkPTxWQcmjg== cycle@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" + integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= dependencies: es5-ext "^0.10.9" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" +date-extended@~0.0.3: + version "0.0.6" + resolved "https://registry.yarnpkg.com/date-extended/-/date-extended-0.0.6.tgz#23802d57dd1bf7818813fe0c32e851a86da267c9" + integrity sha1-I4AtV90b94GIE/4MMuhRqG2iZ8k= + dependencies: + array-extended "~0.0.3" + extended "~0.0.3" + is-extended "~0.0.3" + date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= death@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" + integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= debug@*: version "4.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" + integrity sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg== dependencies: ms "^2.1.1" debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" debug@^3.0.1, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +declare.js@~0.0.4: + version "0.0.8" + resolved "https://registry.yarnpkg.com/declare.js/-/declare.js-0.0.8.tgz#0478adff9564c004f51df73d8bc134019d28dcde" + integrity sha1-BHit/5VkwAT1Hfc9i8E0AZ0o3N4= decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: mimic-response "^1.0.0" decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== dependencies: file-type "^5.2.0" is-stream "^1.1.0" @@ -1761,6 +2054,7 @@ decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: decompress-tarbz2@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== dependencies: decompress-tar "^4.1.0" file-type "^6.1.0" @@ -1771,6 +2065,7 @@ decompress-tarbz2@^4.0.0: decompress-targz@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== dependencies: decompress-tar "^4.1.1" file-type "^5.2.0" @@ -1779,6 +2074,7 @@ decompress-targz@^4.0.0: decompress-unzip@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= dependencies: file-type "^3.8.0" get-stream "^2.2.0" @@ -1788,6 +2084,7 @@ decompress-unzip@^4.0.1: decompress@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" + integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= dependencies: decompress-tar "^4.0.0" decompress-tarbz2 "^4.0.0" @@ -1801,52 +2098,57 @@ decompress@^4.0.0: deep-assign@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-2.0.0.tgz#ebe06b1f07f08dae597620e3dd1622f371a1c572" + integrity sha1-6+BrHwfwja5ZdiDj3RYi83GhxXI= dependencies: is-obj "^1.0.0" -deep-equal@~0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" - deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= deferred-leveldown@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== dependencies: abstract-leveldown "~2.6.0" define-properties@^1.1.1, define-properties@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" @@ -1854,10 +2156,12 @@ define-property@^2.0.2: defined@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag= dependencies: globby "^5.0.0" is-path-cwd "^1.0.0" @@ -1870,22 +2174,27 @@ del@^2.0.2: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= delimit-stream@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" + integrity sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs= depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -1893,28 +2202,34 @@ des.js@^1.0.0: destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= dependencies: repeating "^2.0.0" detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= diff@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" @@ -1923,6 +2238,7 @@ diffie-hellman@^5.0.0: doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= dependencies: esutils "^2.0.2" isarray "^1.0.0" @@ -1930,20 +2246,24 @@ doctrine@1.5.0: doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== drbg.js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" + integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= dependencies: browserify-aes "^1.0.6" create-hash "^1.1.2" @@ -1952,16 +2272,19 @@ drbg.js@^1.0.1: duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= eachr@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/eachr/-/eachr-2.0.4.tgz#466f7caa10708f610509e32c807aafe57fc122bf" + integrity sha1-Rm98qhBwj2EFCeMsgHqv5X/BIr8= dependencies: typechecker "^2.0.8" ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" @@ -1969,10 +2292,12 @@ ecc-jsbn@~0.1.1: editions@^1.1.1, editions@^1.3.3, editions@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" + integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== editions@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/editions/-/editions-2.0.2.tgz#54fdac6fb24b0a1a72ffc1ba0126c10602c3e0bd" + integrity sha512-0B8aSTWUu9+JW99zHoeogavCi+lkE5l35FK0OKe0pCobixJYoeof3ZujtqYzSsU2MskhRadY5V9oWUuyG4aJ3A== dependencies: errlop "^1.0.2" semver "^5.5.0" @@ -1980,14 +2305,17 @@ editions@^2.0.2: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.47: version "1.3.78" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.78.tgz#ecb72b5b166ba6598efb384461d63cad74678ebf" + integrity sha512-p4D/5iX08c3LNep5bWn/X3dFmec1K9le6O43lgRsO/vYKBTH2smWDMDfkGlPtERFcLVkI8xdKW5EokBZODh1xg== elliptic@6.3.3: version "6.3.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" + integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -1997,6 +2325,7 @@ elliptic@6.3.3: elliptic@=6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" + integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2009,6 +2338,7 @@ elliptic@=6.4.0: elliptic@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-3.1.0.tgz#c21682ef762769b56a74201609105da11d5f60cc" + integrity sha1-whaC73YnabVqdCAWCRBdoR1fYMw= dependencies: bn.js "^2.0.3" brorand "^1.0.1" @@ -2018,6 +2348,7 @@ elliptic@^3.1.0: elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: version "6.4.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" + integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2030,26 +2361,31 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= dependencies: iconv-lite "~0.4.13" end-of-stream@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: once "^1.4.0" enhanced-resolve@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" + integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24= dependencies: graceful-fs "^4.1.2" memory-fs "^0.4.0" @@ -2059,28 +2395,33 @@ enhanced-resolve@^3.4.0: eol@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" + integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== errlop@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/errlop/-/errlop-1.0.3.tgz#dba29c90cf832c3d2ce469fe515d7e5eef2c6676" + integrity sha512-5VTnt0yikY4LlQEfCXVSqfE6oLj1HVM4zVSvAKMnoYjL/zrb6nqiLowZS4XlG7xENfyj7lpYWvT+wfSCr6dtlA== dependencies: editions "^1.3.4" errno@^0.1.3, errno@~0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== dependencies: prr "~1.0.1" error-ex@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" es-abstract@^1.5.0: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" + integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" @@ -2091,6 +2432,7 @@ es-abstract@^1.5.0: es-to-primitive@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -2099,6 +2441,7 @@ es-to-primitive@^1.1.1: es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: version "0.10.46" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572" + integrity sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw== dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" @@ -2107,6 +2450,7 @@ es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= dependencies: d "1" es5-ext "^0.10.35" @@ -2115,6 +2459,7 @@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0 es6-map@^0.1.3: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= dependencies: d "1" es5-ext "~0.10.14" @@ -2126,6 +2471,7 @@ es6-map@^0.1.3: es6-set@~0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= dependencies: d "1" es5-ext "~0.10.14" @@ -2136,6 +2482,7 @@ es6-set@~0.1.5: es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= dependencies: d "1" es5-ext "~0.10.14" @@ -2143,6 +2490,7 @@ es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8= dependencies: d "1" es5-ext "^0.10.14" @@ -2152,14 +2500,17 @@ es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= dependencies: esprima "^2.7.1" estraverse "^1.9.1" @@ -2171,6 +2522,7 @@ escodegen@1.8.x: escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= dependencies: es6-map "^0.1.3" es6-weak-map "^2.0.1" @@ -2180,10 +2532,12 @@ escope@^3.6.0: eslint-config-standard@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz#87ee0d3c9d95382dc761958cbb23da9eea31e0ba" + integrity sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw== eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== dependencies: debug "^2.6.9" resolve "^1.5.0" @@ -2191,6 +2545,7 @@ eslint-import-resolver-node@^0.3.1: eslint-module-utils@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" + integrity sha1-snA2LNiLGkitMIl2zn+lTphBF0Y= dependencies: debug "^2.6.8" pkg-dir "^1.0.0" @@ -2198,6 +2553,7 @@ eslint-module-utils@^2.2.0: eslint-plugin-import@^2.10.0: version "2.14.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" + integrity sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g== dependencies: contains-path "^0.1.0" debug "^2.6.8" @@ -2213,6 +2569,7 @@ eslint-plugin-import@^2.10.0: eslint-plugin-node@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz#bf19642298064379315d7a4b2a75937376fa05e4" + integrity sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw== dependencies: ignore "^3.3.6" minimatch "^3.0.4" @@ -2222,14 +2579,17 @@ eslint-plugin-node@^6.0.1: eslint-plugin-promise@^3.7.0: version "3.8.0" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" + integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ== eslint-plugin-standard@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz#2a9e21259ba4c47c02d53b2d0c9135d4b1022d47" + integrity sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w== eslint-scope@^3.7.1: version "3.7.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" + integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2237,10 +2597,12 @@ eslint-scope@^3.7.1: eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== eslint@^4.19.1: version "4.19.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" + integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" @@ -2284,6 +2646,7 @@ eslint@^4.19.1: espree@^3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== dependencies: acorn "^5.5.0" acorn-jsx "^3.0.0" @@ -2291,42 +2654,51 @@ espree@^3.5.4: esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== dependencies: estraverse "^4.1.0" estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eth-block-tracker@^2.2.2: version "2.3.1" resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz#ab6d177e5b50128fa06d7ae9e0489c7484bac95e" + integrity sha512-NamWuMBIl8kmkJFVj8WzGatySTzQPQag4Xr677yFxdVtIxACFbL/dQowk0MzEqIKk93U1TwY3MjVU6mOcwZnKA== dependencies: async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c eth-query "^2.1.0" @@ -2340,6 +2712,7 @@ eth-block-tracker@^2.2.2: eth-lib@0.1.27, eth-lib@^0.1.26: version "0.1.27" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" + integrity sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA== dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2352,6 +2725,7 @@ eth-lib@0.1.27, eth-lib@^0.1.26: eth-lib@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" + integrity sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco= dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2360,6 +2734,7 @@ eth-lib@0.2.7: eth-lightwallet@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eth-lightwallet/-/eth-lightwallet-3.0.1.tgz#297022932aa568f4e4eb0873bff257f5e5b78709" + integrity sha512-79vVCETy+4l1b6wuOWwjqPW3Bom5ZK46BgkUNwaXhiMG1rrMRHjpjYEWMqH0JHeCzOzB4HBIFz7eK1/4s6w5nA== dependencies: bitcore-lib "^0.15.0" bitcore-mnemonic "^1.5.0" @@ -2376,6 +2751,7 @@ eth-lightwallet@^3.0.1: eth-query@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= dependencies: json-rpc-random-id "^1.0.0" xtend "^4.0.1" @@ -2383,6 +2759,7 @@ eth-query@^2.1.0: eth-sig-util@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= dependencies: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" @@ -2390,6 +2767,7 @@ eth-sig-util@^1.4.2: ethereum-bridge@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/ethereum-bridge/-/ethereum-bridge-0.6.1.tgz#53c93ed7c0e21752a91e5f089a5997e1d6fea228" + integrity sha512-yDTivI85618BoLI71yNRzW6iVcVN2rjnviCIzs0QOCOENj4XpYQhMDGhdqDi8XWDdzTd0Ja/Canuuh3vfE2IcA== dependencies: async "^2.4.1" borc "^2.0.2" @@ -2420,14 +2798,17 @@ ethereum-bridge@^0.6.1: ethereum-common@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= ethereumjs-abi@0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.4.tgz#9ba1bb056492d00c27279f6eccd4d58275912c1a" + integrity sha1-m6G7BWSS0AwnJ59uzNTVgnWRLBo= dependencies: bn.js "^4.10.0" ethereumjs-util "^4.3.0" @@ -2442,6 +2823,7 @@ ethereumjs-abi@^0.6.5, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereu ethereumjs-account@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== dependencies: ethereumjs-util "^5.0.0" rlp "^2.0.0" @@ -2450,6 +2832,7 @@ ethereumjs-account@^2.0.3: ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: version "1.7.1" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== dependencies: async "^2.0.1" ethereum-common "0.2.0" @@ -2460,22 +2843,26 @@ ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: ethereumjs-common@~0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-0.4.1.tgz#27690a24a817b058cc3a2aedef9392e8d7d63984" + integrity sha512-ywYGsOeGCsMNWso5Y4GhjWI24FJv9FK7+VyVKiQgXg8ZRDPXJ7F/kJ1CnjtkjTvDF4e0yqU+FWswlqR3bmZQ9Q== ethereumjs-testrpc-sc@6.1.6: version "6.1.6" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.6.tgz#290595380b5182814564d4aa38f35b7788aab070" + integrity sha512-iv2qiGBFgk9mn5Nq2enX8dG5WQ7Lk+FCqpnxfPfH4Ns8KLPwttmNOy264nh3SXDJJvcQwz/XnlLteDQVILotbg== dependencies: source-map-support "^0.5.3" ethereumjs-testrpc@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc/-/ethereumjs-testrpc-6.0.3.tgz#7a0b87bf3670f92f607f98fa6a78801d9741b124" + integrity sha512-lAxxsxDKK69Wuwqym2K49VpXtBvLEsXr1sryNG4AkvL5DomMdeCBbu3D87UEevKenLHBiT8GTjARwN6Yj039gA== dependencies: webpack "^3.0.0" ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@^1.3.3: version "1.3.7" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== dependencies: ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" @@ -2483,6 +2870,7 @@ ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@ ethereumjs-util@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" + integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= dependencies: bn.js "^4.8.0" create-hash "^1.1.2" @@ -2493,6 +2881,7 @@ ethereumjs-util@^4.3.0: ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.3, ethereumjs-util@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" + integrity sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA== dependencies: bn.js "^4.11.0" create-hash "^1.1.2" @@ -2505,6 +2894,7 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum ethereumjs-vm@^2.0.2: version "2.4.0" resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.4.0.tgz#244f1e35f2755e537a13546111d1a4c159d34b13" + integrity sha512-MJ4lCWa5c6LhahhhvoDKW+YGjK00ZQn0RHHLh4L+WaH1k6Qv7/q3uTluew6sJGNCZdlO0yYMDXYW9qyxLHKlgQ== dependencies: async "^2.1.2" async-eventemitter "^0.2.2" @@ -2521,6 +2911,7 @@ ethereumjs-vm@^2.0.2: ethereumjs-wallet@^0.6.0: version "0.6.2" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz#67244b6af3e8113b53d709124b25477b64aeccda" + integrity sha512-DHEKPV9lYORM7dL8602dkb+AgdfzCYz2lxpdYQoD3OwG355LLDuivW9rGuLpDMCry/ORyBYV6n+QCo/71SwACg== dependencies: aes-js "^3.1.1" bs58check "^2.1.2" @@ -2534,6 +2925,7 @@ ethereumjs-wallet@^0.6.0: ethers@^3.0.15: version "3.0.29" resolved "https://registry.yarnpkg.com/ethers/-/ethers-3.0.29.tgz#ce8139955b4ed44456eb6764b089bb117c86775d" + integrity sha512-OGyA5pW5xFC5o/ZV5MfIoVp/EdA1QMg2bMJFf7Kznsz8m7IzzbgsPHTCjzSfKQDs/XDphGyRcA7A6bkIeJL4gw== dependencies: aes-js "3.0.0" bn.js "^4.4.0" @@ -2549,6 +2941,7 @@ ethers@^3.0.15: ethjs-abi@0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.1.8.tgz#cd288583ed628cdfadaf8adefa3ba1dbcbca6c18" + integrity sha1-zSiFg+1ijN+tr4re+juh28vKbBg= dependencies: bn.js "4.11.6" js-sha3 "0.5.5" @@ -2557,6 +2950,7 @@ ethjs-abi@0.1.8: ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= dependencies: bn.js "4.11.6" number-to-bn "1.7.0" @@ -2564,6 +2958,7 @@ ethjs-unit@0.1.6: ethjs-util@^0.1.3: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== dependencies: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" @@ -2571,6 +2966,7 @@ ethjs-util@^0.1.3: event-emitter@^0.3.5, event-emitter@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= dependencies: d "1" es5-ext "~0.10.14" @@ -2578,18 +2974,22 @@ event-emitter@^0.3.5, event-emitter@~0.3.5: eventemitter3@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" + integrity sha1-R3hr2qCHyvext15zq8XH1UAVjNA= events@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" @@ -2597,6 +2997,7 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -2609,12 +3010,14 @@ execa@^0.7.0: expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= dependencies: is-posix-bracket "^0.1.0" expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -2627,12 +3030,14 @@ expand-brackets@^2.1.4: expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= dependencies: fill-range "^2.1.0" express@^4.14.0: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" + integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== dependencies: accepts "~1.3.5" array-flatten "1.1.1" @@ -2668,12 +3073,14 @@ express@^4.14.0: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -2681,16 +3088,33 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extended@0.0.6, extended@~0.0.3: + version "0.0.6" + resolved "https://registry.yarnpkg.com/extended/-/extended-0.0.6.tgz#7fb8bf7b9dae397586e48570acfd642c78e50669" + integrity sha1-f7i/e52uOXWG5IVwrP1kLHjlBmk= + dependencies: + extender "~0.0.5" + +extender@~0.0.5: + version "0.0.10" + resolved "https://registry.yarnpkg.com/extender/-/extender-0.0.10.tgz#589c07482be61a1460b6d81f9c24aa67e8f324cd" + integrity sha1-WJwHSCvmGhRgttgfnCSqZ+jzJM0= + dependencies: + declare.js "~0.0.4" extendr@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/extendr/-/extendr-2.1.0.tgz#301aa0bbea565f4d2dc8f570f2a22611a8527b56" + integrity sha1-MBqgu+pWX00tyPVw8qImEahSe1Y= dependencies: typechecker "~2.0.1" external-editor@^2.0.4: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" + integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== dependencies: chardet "^0.4.0" iconv-lite "^0.4.17" @@ -2699,12 +3123,14 @@ external-editor@^2.0.4: extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= dependencies: is-extglob "^1.0.0" extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -2718,64 +3144,87 @@ extglob@^2.0.4: extract-opts@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d" + integrity sha1-H6KOunNSxttID4hc63GkaBC+bX0= dependencies: typechecker "~2.0.1" extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= eyes@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= fake-merkle-patricia-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= dependencies: checkpoint-store "^1.1.0" +fast-csv@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-2.4.1.tgz#bd7dd268391f729367b59445b8dd0ad026881b26" + integrity sha1-vX3SaDkfcpNntZRFuN0K0CaIGyY= + dependencies: + extended "0.0.6" + is-extended "0.0.10" + object-extended "0.0.7" + string-extended "0.0.8" + fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= dependencies: pend "~1.2.0" fetch-ponyfill@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= dependencies: node-fetch "~1.7.1" figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" @@ -2783,22 +3232,27 @@ file-entry-cache@^2.0.0: file-type@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= file-type@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + integrity sha1-LdvqfHP/42No365J3DOMBYwritY= file-type@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= fill-range@^2.1.0: version "2.2.4" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== dependencies: is-number "^2.1.0" isobject "^2.0.0" @@ -2809,6 +3263,7 @@ fill-range@^2.1.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -2818,6 +3273,7 @@ fill-range@^4.0.0: finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" + integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== dependencies: debug "2.6.9" encodeurl "~1.0.2" @@ -2830,6 +3286,7 @@ finalhandler@1.1.1: find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" @@ -2837,12 +3294,14 @@ find-up@^1.0.0: find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + integrity sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE= dependencies: circular-json "^0.3.1" del "^2.0.2" @@ -2852,26 +3311,31 @@ flat-cache@^1.2.1: for-each@^0.3.2, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= dependencies: for-in "^1.0.1" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= dependencies: asynckit "^0.4.0" combined-stream "1.0.6" @@ -2880,24 +3344,29 @@ form-data@~2.3.2: forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -2908,6 +3377,7 @@ fs-extra@^0.30.0: fs-extra@^2.0.0, fs-extra@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" + integrity sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -2915,6 +3385,7 @@ fs-extra@^2.0.0, fs-extra@^2.1.2: fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -2923,6 +3394,7 @@ fs-extra@^4.0.2: fs-extra@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" + integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -2931,12 +3403,14 @@ fs-extra@^5.0.0: fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== dependencies: minipass "^2.2.1" fs-promise@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" + integrity sha1-9k5PhUvPaJqovdy6JokW2z20aFQ= dependencies: any-promise "^1.3.0" fs-extra "^2.0.0" @@ -2946,14 +3420,17 @@ fs-promise@^2.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fs@0.0.1-security: version "0.0.1-security" resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" + integrity sha1-invTcYa23d84E/I4WLV+yq9eQdQ= fsevents@^1.0.0, fsevents@^1.2.2: version "1.2.4" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -2961,6 +3438,7 @@ fsevents@^1.0.0, fsevents@^1.2.2: fstream@^1.0.2, fstream@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -2970,20 +3448,24 @@ fstream@^1.0.2, fstream@^1.0.8: function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= ganache-cli@^6.1.8: version "6.1.8" resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.8.tgz#49a8a331683a9652183f82ef1378d17e1814fcd3" + integrity sha512-yXzteu4SIgUL31mnpm9j+x6dpHUw0p/nsRVkcySKq0w+1vDxH9jMErP1QhZAJuTVE6ni4nfvGSNkaQx5cD3jfg== dependencies: source-map-support "^0.5.3" gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -2997,10 +3479,12 @@ gauge@~2.7.3: get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= dependencies: object-assign "^4.0.1" pinkie-promise "^2.0.0" @@ -3008,20 +3492,24 @@ get-stream@^2.2.0: get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= dependencies: glob-parent "^2.0.0" is-glob "^2.0.0" @@ -3029,12 +3517,14 @@ glob-base@^0.3.0: glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= dependencies: is-glob "^2.0.0" glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -3042,6 +3532,7 @@ glob-parent@^3.1.0: glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3053,6 +3544,7 @@ glob@7.1.2: glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= dependencies: inflight "^1.0.4" inherits "2" @@ -3063,6 +3555,7 @@ glob@^5.0.15: glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3074,6 +3567,7 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: glob@~6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= dependencies: inflight "^1.0.4" inherits "2" @@ -3084,6 +3578,7 @@ glob@~6.0.4: global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= dependencies: min-document "^2.19.0" process "~0.5.1" @@ -3091,14 +3586,17 @@ global@~4.3.0: globals@^11.0.1: version "11.8.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" + integrity sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA== globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0= dependencies: array-union "^1.0.1" arrify "^1.0.0" @@ -3110,6 +3608,7 @@ globby@^5.0.0: got@7.1.0, got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== dependencies: decompress-response "^3.2.0" duplexer3 "^0.1.4" @@ -3129,22 +3628,27 @@ got@7.1.0, got@^7.1.0: graceful-fs@*, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= growl@1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" + integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== growl@1.10.5, "growl@~> 1.10.0": version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: version "4.0.12" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" + integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA== dependencies: async "^2.5.0" optimist "^0.6.1" @@ -3155,10 +3659,12 @@ handlebars@^4.0.1: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" + integrity sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA== dependencies: ajv "^5.3.0" har-schema "^2.0.0" @@ -3166,42 +3672,51 @@ har-validator@~5.1.0: has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= has-to-string-tag-x@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== dependencies: has-symbol-support-x "^1.4.1" has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -3210,6 +3725,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -3218,10 +3734,12 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -3229,12 +3747,14 @@ has-values@^1.0.0: has@^1.0.1, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -3242,6 +3762,7 @@ hash-base@^3.0.0: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.5" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" + integrity sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" @@ -3249,6 +3770,7 @@ hash.js@^1.0.0, hash.js@^1.0.3: hdkey@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.0.tgz#e74e7b01d2c47f797fa65d1d839adb7a44639f29" + integrity sha512-E7aU8pNlWUJbXGjTz/+lKf1LkMcA3hUrC5ZleeizrmLSd++kvf8mSOe3q8CmBDA9j4hdfXO5iY6hGiTUCOV2jQ== dependencies: coinstring "^2.0.0" safe-buffer "^5.1.1" @@ -3257,10 +3779,12 @@ hdkey@^1.0.0: he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -3269,6 +3793,7 @@ hmac-drbg@^1.0.0: home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.1" @@ -3276,10 +3801,12 @@ home-or-tmp@^2.0.0: hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" @@ -3289,10 +3816,12 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: http-https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" @@ -3301,10 +3830,12 @@ http-signature@~1.2.0: https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= i18n@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/i18n/-/i18n-0.8.3.tgz#2d8cf1c24722602c2041d01ba6ae5eaa51388f0e" + integrity sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4= dependencies: debug "*" make-plural "^3.0.3" @@ -3313,39 +3844,41 @@ i18n@^0.8.3: mustache "*" sprintf-js ">=1.0.3" -i@0.3.x: - version "0.3.6" - resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d" - iconv-lite@0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" ieee754@^1.1.4, ieee754@^1.1.8: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" + integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== dependencies: minimatch "^3.0.4" ignore@^3.3.3, ignore@^3.3.6: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== ignorefs@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ignorefs/-/ignorefs-1.2.0.tgz#da59fb858976e4a5e43702ccd1f282fdbc9e5756" + integrity sha1-2ln7hYl25KXkNwLM0fKC/byeV1Y= dependencies: editions "^1.3.3" ignorepatterns "^1.1.0" @@ -3353,22 +3886,27 @@ ignorefs@^1.0.0: ignorepatterns@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ignorepatterns/-/ignorepatterns-1.1.0.tgz#ac8f436f2239b5dfb66d5f0d3a904a87ac67cc5e" + integrity sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4= immediate@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" @@ -3376,18 +3914,22 @@ inflight@^1.0.4: inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= inherits@2.0.1, inherits@=2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -3407,76 +3949,91 @@ inquirer@^3.0.6: interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" + integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= dependencies: builtin-modules "^1.0.0" is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -3485,6 +4042,7 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -3493,210 +4051,261 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= dependencies: is-primitive "^2.0.0" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" +is-extended@0.0.10, is-extended@~0.0.3, is-extended@~0.0.8: + version "0.0.10" + resolved "https://registry.yarnpkg.com/is-extended/-/is-extended-0.0.10.tgz#244e140df75bb1c9a3106f412ff182fb534a6d62" + integrity sha1-JE4UDfdbscmjEG9BL/GC+1NKbWI= + dependencies: + extended "~0.0.3" + is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= dependencies: number-is-nan "^1.0.0" is-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= dependencies: is-extglob "^1.0.0" is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= dependencies: is-extglob "^2.1.1" is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= is-nan@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" + integrity sha1-n69ltvttskt/XAYoR16nH5iEAeI= dependencies: define-properties "^1.1.1" is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= dependencies: kind-of "^3.0.2" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" + integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= is-path-in-cwd@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" + integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== dependencies: is-path-inside "^1.0.0" is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= dependencies: path-is-inside "^1.0.1" is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= is-promise@^2.1, is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= dependencies: has "^1.0.1" is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== dependencies: has-symbols "^1.0.0" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= dependencies: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" @@ -3704,10 +4313,12 @@ isomorphic-fetch@^2.2.0: isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" + integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= dependencies: abbrev "1.0.x" async "1.x" @@ -3727,6 +4338,7 @@ istanbul@^0.4.5: isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== dependencies: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" @@ -3734,30 +4346,37 @@ isurl@^1.0.0-alpha5: js-sha3@0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a" + integrity sha1-uvDA6MVK1ZA0R9+Wreekobynmko= js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= js-sha3@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" + integrity sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM= js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.9.1: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -3765,22 +4384,27 @@ js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.9.1: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-loader@^0.5.4: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" + integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== json-rpc-engine@^3.6.0: version "3.8.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== dependencies: async "^2.0.1" babel-preset-env "^1.7.0" @@ -3792,68 +4416,82 @@ json-rpc-engine@^3.6.0: json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" + integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= dependencies: inherits "^2.0.1" json-rpc-random-id@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= dependencies: jsonify "~0.0.0" json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json-text-sequence@^0.1: version "0.1.1" resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" + integrity sha1-py8hfcSvxGKf/1/rME3BvVGi89I= dependencies: delimit-stream "0.1.0" json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= optionalDependencies: graceful-fs "^4.1.6" jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= optionalDependencies: graceful-fs "^4.1.6" jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" extsprintf "1.3.0" @@ -3863,6 +4501,7 @@ jsprim@^1.2.2: keccak@^1.0.2: version "1.4.0" resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" + integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== dependencies: bindings "^1.2.1" inherits "^2.0.3" @@ -3872,6 +4511,7 @@ keccak@^1.0.2: keccakjs@^0.2.0, keccakjs@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" + integrity sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0= dependencies: browserify-sha3 "^0.0.1" sha3 "^1.1.0" @@ -3879,62 +4519,74 @@ keccakjs@^0.2.0, keccakjs@^0.2.1: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= optionalDependencies: graceful-fs "^4.1.9" lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" + integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM= level-codec@~7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== level-errors@^1.0.3: version "1.1.2" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== dependencies: errno "~0.1.1" level-errors@~1.0.3: version "1.0.5" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== dependencies: errno "~0.1.1" level-iterator-stream@~1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= dependencies: inherits "^2.0.1" level-errors "^1.0.3" @@ -3944,6 +4596,7 @@ level-iterator-stream@~1.3.0: level-ws@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= dependencies: readable-stream "~1.0.15" xtend "~2.1.1" @@ -3951,6 +4604,7 @@ level-ws@0.0.0: levelup@^1.2.1: version "1.3.9" resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== dependencies: deferred-leveldown "~1.2.1" level-codec "~7.0.0" @@ -3963,6 +4617,7 @@ levelup@^1.2.1: levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -3970,6 +4625,7 @@ levn@^0.3.0, levn@~0.3.0: load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -3980,6 +4636,7 @@ load-json-file@^1.0.0: load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -3989,10 +4646,12 @@ load-json-file@^2.0.0: loader-runner@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.1.tgz#026f12fe7c3115992896ac02ba022ba92971b979" + integrity sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw== loader-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" + integrity sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0= dependencies: big.js "^3.1.3" emojis-list "^2.0.0" @@ -4001,6 +4660,7 @@ loader-utils@^1.1.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -4008,44 +4668,54 @@ locate-path@^2.0.0: lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash@4.x, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== lodash@=4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= log-driver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== long-timeout@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" + integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ= longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lru-cache@^4.0.1: version "4.1.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -4053,48 +4723,57 @@ lru-cache@^4.0.1: lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= dependencies: es5-ext "~0.10.2" ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== dependencies: pify "^3.0.0" make-plural@^3.0.3, make-plural@~3.0.3: version "3.0.6" resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-3.0.6.tgz#2033a03bac290b8f3bb91258f65b9df7e8b01ca7" + integrity sha1-IDOgO6wpC487uRJY9lud9+iwHKc= optionalDependencies: minimist "^1.2.0" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" math-interval-parser@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-interval-parser/-/math-interval-parser-1.1.0.tgz#dbeda5b06b3249973c6df6170fde2386f0afd893" + integrity sha1-2+2lsGsySZc8bfYXD94jhvCv2JM= dependencies: xregexp "^2.0.0" math-random@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -4103,16 +4782,19 @@ md5.js@^1.3.4: media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= dependencies: mimic-fn "^1.0.0" memdown@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" + integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= dependencies: abstract-leveldown "~2.7.1" functional-red-black-tree "^1.0.1" @@ -4124,6 +4806,7 @@ memdown@^1.0.0: memoizee@^0.4.14: version "0.4.14" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" + integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== dependencies: d "1" es5-ext "^0.10.45" @@ -4137,6 +4820,7 @@ memoizee@^0.4.14: memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= dependencies: errno "^0.1.3" readable-stream "^2.0.1" @@ -4144,14 +4828,17 @@ memory-fs@^0.4.0, memory-fs@~0.4.1: memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= merkle-patricia-tree@^2.1.2: version "2.3.2" resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== dependencies: async "^1.4.2" ethereumjs-util "^5.0.0" @@ -4165,6 +4852,7 @@ merkle-patricia-tree@^2.1.2: messageformat@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/messageformat/-/messageformat-0.3.1.tgz#e58fff8245e9b3971799e5b43db58b3e9417f5a2" + integrity sha1-5Y//gkXps5cXmeW0PbWLPpQX9aI= dependencies: async "~1.5.2" glob "~6.0.4" @@ -4175,10 +4863,12 @@ messageformat@^0.3.1: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@^2.1.5: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= dependencies: arr-diff "^2.0.0" array-unique "^0.2.1" @@ -4197,6 +4887,7 @@ micromatch@^2.1.5: micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4215,6 +4906,7 @@ micromatch@^3.1.10, micromatch@^3.1.4: miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" @@ -4222,60 +4914,73 @@ miller-rabin@^4.0.0: mime-db@~1.36.0: version "1.36.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" + integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw== mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.20" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" + integrity sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A== dependencies: mime-db "~1.36.0" mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= dependencies: dom-walk "^0.1.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@^1.2.0, minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= minipass@^2.2.1, minipass@^2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957" + integrity sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" @@ -4283,12 +4988,14 @@ minipass@^2.2.1, minipass@^2.3.3: minizlib@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" + integrity sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg== dependencies: minipass "^2.2.1" mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -4296,18 +5003,21 @@ mixin-deep@^1.2.0: mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" mocha@^4.0.1, mocha@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" + integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== dependencies: browser-stdout "1.3.0" commander "2.11.0" @@ -4323,6 +5033,7 @@ mocha@^4.0.1, mocha@^4.1.0: mocha@^5.0.1: version "5.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== dependencies: browser-stdout "1.3.1" commander "2.15.1" @@ -4339,32 +5050,39 @@ mocha@^5.0.1: mock-fs@^4.1.0: version "4.7.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" + integrity sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA== moment-timezone@^0.5.0: version "0.5.21" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.21.tgz#3cba247d84492174dbf71de2a9848fa13207b845" + integrity sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A== dependencies: moment ">= 2.9.0" "moment@>= 2.9.0", moment@^2.22.2: version "2.22.2" resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" + integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y= mout@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" + integrity sha1-ujYR318OWx/7/QEWa48C0fX6K5k= ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== multihashes@^0.4.5: version "0.4.14" resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.14.tgz#774db9a161f81a8a27dc60788f91248e020f5244" + integrity sha512-V/g/EIN6nALXfS/xHUAgtfPP3mn3sPIF/i9beuGKf25QXS2QZYCpeVJbDPEannkz32B2fihzCe2D/KMrbcmefg== dependencies: bs58 "^4.0.1" varint "^5.0.0" @@ -4372,18 +5090,22 @@ multihashes@^0.4.5: mustache@*: version "3.0.0" resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.0.tgz#3de22dd9ba38152f7355399a953dd4528c403338" + integrity sha512-bhBDkK/PioIbtQzRIbGUGypvc3MC4c389QnJt8KDIEJ666OidRPoXAQAHPivikfS3JkMEaWoPvcDL7YrQxtSwg== mustache@^2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" + integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== -mute-stream@0.0.7, mute-stream@~0.0.4: +mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" object-assign "^4.0.1" @@ -4392,18 +5114,22 @@ mz@^2.6.0: nan@2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== nan@^2.0.8, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" + integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4420,14 +5146,12 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - -ncp@1.0.x: - version "1.0.1" - resolved "http://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" + integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== dependencies: debug "^2.1.2" iconv-lite "^0.4.4" @@ -4436,22 +5160,27 @@ needle@^2.2.1: negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= neo-async@^2.5.0: version "2.5.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc" + integrity sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw== next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= node-async-loop@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/node-async-loop/-/node-async-loop-1.2.2.tgz#c5870299bf6477b780c88b431aa5b37733f55a3d" + integrity sha1-xYcCmb9kd7eAyItDGqWzdzP1Wj0= node-cache@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.0.tgz#48ac796a874e762582692004a376d26dfa875811" + integrity sha512-obRu6/f7S024ysheAjoYFEEBqqDWv4LOMNJEuO8vMeEw2AT4z+NCzO4hlc2lhI4vATzbCQv6kke9FVdx0RbCOw== dependencies: clone "2.x" lodash "4.x" @@ -4459,6 +5188,7 @@ node-cache@^4.1.1: node-fetch@^1.0.1, node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== dependencies: encoding "^0.1.11" is-stream "^1.0.1" @@ -4466,6 +5196,7 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: node-libs-browser@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" + integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -4494,6 +5225,7 @@ node-libs-browser@^2.0.0: node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -4509,6 +5241,7 @@ node-pre-gyp@^0.10.0: node-schedule@^1.2.3: version "1.3.0" resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-1.3.0.tgz#e7a7e816a7f2550d5b170bd106e765db28bdf030" + integrity sha512-NNwO9SUPjBwFmPh3vXiPVEhJLn4uqYmZYvJV358SRGM06BR4UoIqxJpeJwDDXB6atULsgQA97MfD1zMd5xsu+A== dependencies: cron-parser "^2.4.0" long-timeout "0.1.1" @@ -4517,12 +5250,14 @@ node-schedule@^1.2.3: nopt@3.x, nopt@~3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" osenv "^0.1.4" @@ -4530,6 +5265,7 @@ nopt@^4.0.1: normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" @@ -4539,16 +5275,19 @@ normalize-package-data@^2.3.2: normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" + integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" + integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -4556,12 +5295,14 @@ npm-packlist@^1.1.6: npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" @@ -4571,10 +5312,12 @@ npmlog@^4.0.2: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -4582,40 +5325,57 @@ number-to-bn@1.7.0: oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" +object-extended@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/object-extended/-/object-extended-0.0.7.tgz#84fd23f56b15582aeb3e88b05cb55d2432d68a33" + integrity sha1-hP0j9WsVWCrrPoiwXLVdJDLWijM= + dependencies: + array-extended "~0.0.4" + extended "~0.0.3" + is-extended "~0.0.3" + object-inspect@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= dependencies: for-own "^0.1.4" is-extendable "^0.1.1" @@ -4623,40 +5383,47 @@ object.omit@^2.0.0: object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" oboe@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" + integrity sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8= dependencies: http-https "^1.0.0" on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" openzeppelin-solidity@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-1.10.0.tgz#d77eee6653f5958d051318a61ba0b436f92216c0" + integrity sha512-igkrumQQ2lrN2zjeQV4Dnb0GpTBj1fzMcd8HPyBUqwI0hhuscX/HzXiqKT6gFQl1j9Wy/ppVVs9fqL/foF7Gmg== optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= dependencies: minimist "~0.0.1" wordwrap "~0.0.2" @@ -4664,6 +5431,7 @@ optimist@^0.6.1: optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" @@ -4675,24 +5443,29 @@ optionator@^0.8.1, optionator@^0.8.2: original-require@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" + integrity sha1-DxMEcVhM0zURxew4yNWSE/msXiA= os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== dependencies: execa "^0.7.0" lcid "^1.0.0" @@ -4701,10 +5474,12 @@ os-locale@^2.0.0: os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -4712,40 +5487,48 @@ osenv@^0.1.4: p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= dependencies: p-limit "^1.1.0" p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= dependencies: p-finally "^1.0.0" p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" + integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== parse-asn1@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" + integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -4756,6 +5539,7 @@ parse-asn1@^5.0.0: parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= dependencies: glob-base "^0.3.0" is-dotfile "^1.0.0" @@ -4765,6 +5549,7 @@ parse-glob@^3.0.4: parse-headers@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" + integrity sha1-aug6eqJanZtwCswoaYzR8e1+lTY= dependencies: for-each "^0.3.2" trim "0.0.1" @@ -4772,58 +5557,71 @@ parse-headers@^2.0.0: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-parse@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -4832,12 +5630,14 @@ path-type@^1.0.0: path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= dependencies: pify "^2.0.0" pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" + integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -4848,116 +5648,119 @@ pbkdf2@^3.0.3: pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" + integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= dependencies: find-up "^1.0.0" -pkginfo@0.3.x: - version "0.3.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" - -pkginfo@0.x.x: - version "0.4.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" - pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= pragma-singleton@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pragma-singleton/-/pragma-singleton-1.0.3.tgz#6894317bb8d47157e59de2a4a009db7e6f63e30e" + integrity sha1-aJQxe7jUcVflneKkoAnbfm9j4w4= prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= prettier@^1.14.3: version "1.14.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" + integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg== private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= process@~0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= progress@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= promise-to-callback@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= dependencies: is-fn "^1.0.0" set-immediate-shim "^1.0.1" -prompt@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe" - dependencies: - colors "^1.1.2" - pkginfo "0.x.x" - read "1.0.x" - revalidator "0.1.x" - utile "0.3.x" - winston "2.1.x" - prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" + integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== dependencies: loose-envify "^1.3.1" object-assign "^4.1.1" @@ -4965,6 +5768,7 @@ prop-types@^15.6.2: proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" + integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== dependencies: forwarded "~0.1.2" ipaddr.js "1.8.0" @@ -4972,18 +5776,22 @@ proxy-addr@~2.0.4: prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24: version "1.1.29" resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" + integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -4995,22 +5803,27 @@ public-encrypt@^4.0.0: punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== dependencies: decode-uri-component "^0.2.0" object-assign "^4.1.0" @@ -5019,14 +5832,17 @@ query-string@^5.0.1: querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= randomatic@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116" + integrity sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ== dependencies: is-number "^4.0.0" kind-of "^6.0.0" @@ -5035,12 +5851,14 @@ randomatic@^3.0.0: randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" + integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -5048,14 +5866,17 @@ randomfill@^1.0.3: randomhex@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" + integrity sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU= range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" + integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== dependencies: bytes "3.0.0" http-errors "1.6.3" @@ -5065,6 +5886,7 @@ raw-body@2.3.3: rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" ini "~1.3.0" @@ -5074,6 +5896,7 @@ rc@^1.2.7: react-dom@^16.2.0: version "16.5.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.5.2.tgz#b69ee47aa20bab5327b2b9d7c1fe2a30f2cfa9d7" + integrity sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5083,6 +5906,7 @@ react-dom@^16.2.0: react@^16.2.0: version "16.5.2" resolved "https://registry.yarnpkg.com/react/-/react-16.5.2.tgz#19f6b444ed139baa45609eee6dc3d318b3895d42" + integrity sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5092,6 +5916,7 @@ react@^16.2.0: read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -5099,6 +5924,7 @@ read-pkg-up@^1.0.1: read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= dependencies: find-up "^2.0.0" read-pkg "^2.0.0" @@ -5106,6 +5932,7 @@ read-pkg-up@^2.0.0: read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" @@ -5114,20 +5941,16 @@ read-pkg@^1.0.0: read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" path-type "^2.0.0" -read@1.0.x: - version "1.0.7" - resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - dependencies: - mute-stream "~0.0.4" - readable-stream@^1.0.33: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5137,6 +5960,7 @@ readable-stream@^1.0.33: readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -5149,6 +5973,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5158,6 +5983,7 @@ readable-stream@~1.0.15: readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" @@ -5166,28 +5992,34 @@ readdirp@^2.0.0: readline-sync@^1.4.9: version "1.4.9" resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.9.tgz#3eda8e65f23cd2a17e61301b1f0003396af5ecda" + integrity sha1-PtqOZfI80qF+YTAbHwADOWr17No= rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" regenerate@^1.2.1: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" + integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" @@ -5196,12 +6028,14 @@ regenerator-transform@^0.10.0: regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== dependencies: is-equal-shallow "^0.1.3" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" @@ -5209,10 +6043,12 @@ regex-not@^1.0.0, regex-not@^1.0.2: regexpp@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= dependencies: regenerate "^1.2.1" regjsgen "^0.2.0" @@ -5221,52 +6057,62 @@ regexpu-core@^2.0.0: regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= regjsparser@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= dependencies: is-finite "^1.0.0" req-cwd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-1.0.1.tgz#0d73aeae9266e697a78f7976019677e76acf0fff" + integrity sha1-DXOurpJm5penj3l2AZZ352rPD/8= dependencies: req-from "^1.0.1" req-from@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-from/-/req-from-1.0.1.tgz#bf81da5147947d32d13b947dc12a58ad4587350e" + integrity sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4= dependencies: resolve-from "^2.0.0" request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" + integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= dependencies: lodash "^4.13.1" request-promise@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" + integrity sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ= dependencies: bluebird "^3.5.0" request-promise-core "1.1.1" @@ -5276,6 +6122,7 @@ request-promise@^4.2.2: request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -5301,18 +6148,22 @@ request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.8 require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" @@ -5320,34 +6171,41 @@ require-uncached@^1.0.3: resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.1.6, resolve@^1.3.3, resolve@^1.5.0, resolve@^1.6.0: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== dependencies: path-parse "^1.0.5" resolve@~1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" + integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw== dependencies: path-parse "^1.0.5" restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" signal-exit "^3.0.2" @@ -5355,32 +6213,33 @@ restore-cursor@^2.0.0: resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= dependencies: through "~2.3.4" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - -revalidator@0.1.x: - version "0.1.8" - resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= dependencies: align-text "^0.1.1" -rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== dependencies: glob "^7.0.5" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -5388,66 +6247,79 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: rlp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9" + integrity sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA== dependencies: safe-buffer "^5.1.1" run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= dependencies: is-promise "^2.1.0" rustbn.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== rx-lite-aggregates@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= dependencies: rx-lite "*" rx-lite@*, rx-lite@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-event-emitter@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== dependencies: events "^3.0.0" safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" safe@^0.4.5: version "0.4.6" resolved "https://registry.yarnpkg.com/safe/-/safe-0.4.6.tgz#1d5580cf2635c5cb940ea48fb5081ae3c25b1be1" + integrity sha1-HVWAzyY1xcuUDqSPtQga48JbG+E= safefs@^3.1.2: version "3.2.2" resolved "https://registry.yarnpkg.com/safefs/-/safefs-3.2.2.tgz#8170c1444d7038e08caea05a374fae2fa349e15c" + integrity sha1-gXDBRE1wOOCMrqBaN0+uL6NJ4Vw= dependencies: graceful-fs "*" "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== scandirectory@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/scandirectory/-/scandirectory-2.5.0.tgz#6ce03f54a090b668e3cbedbf20edf9e310593e72" + integrity sha1-bOA/VKCQtmjjy+2/IO354xBZPnI= dependencies: ignorefs "^1.0.0" safefs "^3.1.2" @@ -5456,20 +6328,24 @@ scandirectory@^2.5.0: schedule@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.5.0.tgz#c128fffa0b402488b08b55ae74bb9df55cc29cc8" + integrity sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw== dependencies: object-assign "^4.1.1" scrypt-async@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-1.3.1.tgz#a11fd6fac981b4b823ee01dee0221169500ddae9" + integrity sha1-oR/W+smBtLgj7gHe4CIRaVAN2uk= scrypt-js@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" + integrity sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q= scrypt.js@0.2.0, scrypt.js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" + integrity sha1-r40UZbcemZARC+38WTuUeeA6ito= dependencies: scrypt "^6.0.2" scryptsy "^1.2.1" @@ -5477,18 +6353,21 @@ scrypt.js@0.2.0, scrypt.js@^0.2.0: scrypt@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" + integrity sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0= dependencies: nan "^2.0.8" scryptsy@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= dependencies: pbkdf2 "^3.0.3" secp256k1@^3.0.1: version "3.5.2" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.2.tgz#f95f952057310722184fe9c914e6b71281f2f2ae" + integrity sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ== dependencies: bindings "^1.2.1" bip66 "^1.1.3" @@ -5502,24 +6381,29 @@ secp256k1@^3.0.1: seek-bzip@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" + integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= dependencies: commander "~2.8.1" semaphore@>=1.0.1, semaphore@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== semver@~5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== dependencies: debug "2.6.9" depd "~1.1.2" @@ -5538,6 +6422,7 @@ send@0.16.2: serve-static@1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" @@ -5547,6 +6432,7 @@ serve-static@1.13.2: servify@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== dependencies: body-parser "^1.16.0" cors "^2.8.1" @@ -5557,14 +6443,17 @@ servify@^0.1.12: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -5574,6 +6463,7 @@ set-value@^0.4.3: set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -5583,18 +6473,22 @@ set-value@^2.0.0: setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -5602,30 +6496,35 @@ sha.js@^2.4.0, sha.js@^2.4.8: sha3@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" + integrity sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k= dependencies: nan "2.10.0" shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shelljs@^0.7.4: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= dependencies: glob "^7.0.0" interpret "^1.0.0" rechoir "^0.6.2" -shelljs@^0.8.1: +shelljs@^0.8.1, shelljs@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" + integrity sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ== dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -5634,14 +6533,17 @@ shelljs@^0.8.1: signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= simple-get@^2.7.0: version "2.8.1" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" + integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== dependencies: decompress-response "^3.3.0" once "^1.3.1" @@ -5650,16 +6552,19 @@ simple-get@^2.7.0: slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== dependencies: is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -5668,12 +6573,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -5687,18 +6594,22 @@ snapdragon@^0.8.1: sol-digger@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" + integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= sol-explore@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" + integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= sol-explore@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.2.tgz#43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2" + integrity sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI= sol-merger@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-0.1.2.tgz#1f12500f42d427dc0ec8e4c113392acd8a6f62d9" + integrity sha512-12Z84jxeb5VFlQOGS38HOiTrHYohU07oQ5wHOcFJmcRRbaL5kWN7IcldMO1QdW8kONyKdj0xhukzLlN5m5ix4w== dependencies: bluebird "^3.5.0" cli-color "^1.2.0" @@ -5710,6 +6621,7 @@ sol-merger@^0.1.2: solc@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.24.tgz#354f14b269b38cbaa82a47d1ff151723502b954e" + integrity sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -5720,6 +6632,7 @@ solc@0.4.24: solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: version "0.4.25" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.25.tgz#06b8321f7112d95b4b903639b1138a4d292f5faa" + integrity sha512-jU1YygRVy6zatgXrLY2rRm7HW1d7a8CkkEgNJwvH2VLpWhMFsMdWcJn6kUqZwcSz/Vm+w89dy7Z/aB5p6AFTrg== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -5730,6 +6643,7 @@ solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: solidity-coverage@^0.5.11: version "0.5.11" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" + integrity sha512-qikdsSi6+9XbfvwA0aI7HUVpF9fIFNqRWTw23M89GMDY+b6Gj0wWU9IngJS0fimoZIAdEp3bfChxvpfVcrUesg== dependencies: death "^1.1.0" ethereumjs-testrpc-sc "6.1.6" @@ -5745,6 +6659,7 @@ solidity-coverage@^0.5.11: solidity-docgen@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/solidity-docgen/-/solidity-docgen-0.1.0.tgz#f3a56ff074e8c7d832af3a3d462c3b5abf0f64cb" + integrity sha512-F7ufNWmlP5c5hIi66Ijv9tc+HNosyO7ijWq6pRtyBR1WqyJBH/0DJkD6QZI8HkE8p6LEXiPKxGBWbAeVT9Nu9g== dependencies: commander "^2.14.1" lodash "^4.17.5" @@ -5757,6 +6672,7 @@ solidity-docgen@^0.1.0: solidity-parser-sc@0.4.11: version "0.4.11" resolved "https://registry.yarnpkg.com/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz#86734c9205537007f4d6201b57176e41696ee607" + integrity sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw== dependencies: mocha "^4.1.0" pegjs "^0.10.0" @@ -5765,10 +6681,12 @@ solidity-parser-sc@0.4.11: solium-plugin-security@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" + integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== solium@^1.1.6: version "1.1.8" resolved "https://registry.yarnpkg.com/solium/-/solium-1.1.8.tgz#35d30a15c572a233ce8a90226d6cfccb762fadb7" + integrity sha512-fn0lusM6of14CytIDDHK73SGjn6NsVTaCVJjaKCKJyqKhT00rH/hDtvnIeZ2ZTD9z/xaXd4Js2brW3az6AV9RA== dependencies: ajv "^5.2.2" chokidar "^1.6.0" @@ -5786,6 +6704,7 @@ solium@^1.1.6: solparse@2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.5.tgz#72709c867cd6bfc50ec2325f4b81d2b3ea365d99" + integrity sha512-t7tvtR6KU6QfPYLMv1nlCh9DA8HYIu5tbjHpKu0fhGFZ1NuSp0KKDHfFHv07g6v1xgcuUY3rVqNFjZt5b9+5qA== dependencies: mocha "^4.0.1" pegjs "^0.10.0" @@ -5794,14 +6713,17 @@ solparse@2.2.5: sorted-array-functions@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.2.0.tgz#43265b21d6e985b7df31621b1c11cc68d8efc7c3" + integrity sha512-sWpjPhIZJtqO77GN+LD8dDsDKcWZ9GCOJNqKzi1tvtjGIzwfoyuRH8S0psunmc6Z5P+qfDqztSbwYR5X/e1UTg== source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== dependencies: atob "^2.1.1" decode-uri-component "^0.2.0" @@ -5812,12 +6734,14 @@ source-map-resolve@^0.5.0: source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== dependencies: source-map "^0.5.6" source-map-support@^0.5.3: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" + integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -5825,24 +6749,29 @@ source-map-support@^0.5.3: source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= dependencies: amdefine ">=0.0.4" spdx-correct@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" + integrity sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -5850,10 +6779,12 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" @@ -5861,24 +6792,29 @@ spdx-expression-parse@^3.0.0: spdx-license-ids@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f" + integrity sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@>=1.0.3: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" + integrity sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw= sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: version "1.15.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2" + integrity sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -5893,10 +6829,12 @@ sshpk@^1.7.0: stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -5904,22 +6842,27 @@ static-extend@^0.1.1: "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== stdio@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/stdio/-/stdio-0.2.7.tgz#a1c57da10fe1cfaa0c3bf683c9d0743d1b660839" + integrity sha1-ocV9oQ/hz6oMO/aDydB0PRtmCDk= stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" + integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds= dependencies: inherits "~2.0.1" readable-stream "^2.0.2" @@ -5927,6 +6870,7 @@ stream-browserify@^2.0.1: stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" @@ -5937,10 +6881,22 @@ stream-http@^2.7.2: strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-extended@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/string-extended/-/string-extended-0.0.8.tgz#741957dff487b0272a79eec5a44f239ee6f17ccd" + integrity sha1-dBlX3/SHsCcqee7FpE8jnubxfM0= + dependencies: + array-extended "~0.0.5" + date-extended "~0.0.3" + extended "~0.0.3" + is-extended "~0.0.3" string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -5949,6 +6905,7 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" @@ -5956,6 +6913,7 @@ string-width@^1.0.1: string.prototype.trim@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" + integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= dependencies: define-properties "^1.1.2" es-abstract "^1.5.0" @@ -5964,92 +6922,109 @@ string.prototype.trim@~1.1.2: string_decoder@^1.0.0, string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== dependencies: is-natural-number "^4.0.1" strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= dependencies: is-hex-prefixed "1.0.0" strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= supports-color@4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" + integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== dependencies: has-flag "^2.0.0" supports-color@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== dependencies: has-flag "^3.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" supports-color@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= dependencies: has-flag "^2.0.0" supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" swarm-js@0.1.37: version "0.1.37" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" + integrity sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ== dependencies: bluebird "^3.5.0" buffer "^5.0.5" @@ -6068,6 +7043,7 @@ swarm-js@0.1.37: table@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" + integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== dependencies: ajv "^5.2.3" ajv-keywords "^2.1.0" @@ -6079,10 +7055,12 @@ table@4.0.2: tapable@^0.2.7: version "0.2.8" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" + integrity sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI= tape@^4.4.0, tape@^4.6.3: version "4.9.1" resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9" + integrity sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw== dependencies: deep-equal "~1.0.1" defined "~1.0.0" @@ -6101,6 +7079,7 @@ tape@^4.4.0, tape@^4.6.3: tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== dependencies: bl "^1.0.0" buffer-alloc "^1.2.0" @@ -6113,6 +7092,7 @@ tar-stream@^1.5.2: tar.gz@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" + integrity sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg== dependencies: bluebird "^2.9.34" commander "^2.8.1" @@ -6123,6 +7103,7 @@ tar.gz@^1.0.5: tar@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= dependencies: block-stream "*" fstream "^1.0.2" @@ -6131,6 +7112,7 @@ tar@^2.1.1: tar@^4: version "4.4.6" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" + integrity sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg== dependencies: chownr "^1.0.1" fs-minipass "^1.2.5" @@ -6143,6 +7125,7 @@ tar@^4: taskgroup@^4.0.5, taskgroup@^4.2.0: version "4.3.1" resolved "https://registry.yarnpkg.com/taskgroup/-/taskgroup-4.3.1.tgz#7de193febd768273c457730497024d512c27915a" + integrity sha1-feGT/r12gnPEV3MElwJNUSwnkVo= dependencies: ambi "^2.2.0" csextends "^1.0.3" @@ -6150,36 +7133,43 @@ taskgroup@^4.0.5, taskgroup@^4.2.0: text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= thenify-all@^1.0.0, thenify-all@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.0" resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= dependencies: any-promise "^1.0.0" through@^2.3.6, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-browserify@^2.0.4: version "2.0.10" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" + integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== dependencies: setimmediate "^1.0.4" timers-ext@^0.1.5: version "0.1.7" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== dependencies: es5-ext "~0.10.46" next-tick "1" @@ -6187,6 +7177,7 @@ timers-ext@^0.1.5: tingodb@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/tingodb/-/tingodb-0.6.1.tgz#f63336259af7dfa6c90dfe2556a0dfb0d4eede59" + integrity sha1-9jM2JZr336bJDf4lVqDfsNTu3lk= dependencies: lodash "^4.17.5" safe "^0.4.5" @@ -6197,30 +7188,36 @@ tingodb@^0.6.1: tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= to-buffer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -6228,6 +7225,7 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" @@ -6237,6 +7235,7 @@ to-regex@^3.0.1, to-regex@^3.0.2: tough-cookie@>=2.3.3, tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: psl "^1.1.24" punycode "^1.4.1" @@ -6244,22 +7243,27 @@ tough-cookie@>=2.3.3, tough-cookie@~2.4.3: tree-kill@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" + integrity sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg== trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= truffle-blockchain-utils@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-blockchain-utils/-/truffle-blockchain-utils-0.0.5.tgz#a4e5c064dadd69f782a137f3d276d21095da7a47" + integrity sha1-pOXAZNrdafeCoTfz0nbSEJXaekc= truffle-contract-schema@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/truffle-contract-schema/-/truffle-contract-schema-2.0.1.tgz#9bf821d32e26e674ba15eb5d40f96b10b1c9d568" + integrity sha1-m/gh0y4m5nS6FetdQPlrELHJ1Wg= dependencies: ajv "^5.1.1" crypto-js "^3.1.9-1" @@ -6268,6 +7272,7 @@ truffle-contract-schema@^2.0.1: truffle-contract@^3.0.4: version "3.0.6" resolved "https://registry.yarnpkg.com/truffle-contract/-/truffle-contract-3.0.6.tgz#2ef6fc32d7faafa9f4aed8e50001a9fdea342192" + integrity sha1-Lvb8Mtf6r6n0rtjlAAGp/eo0IZI= dependencies: ethjs-abi "0.1.8" truffle-blockchain-utils "^0.0.5" @@ -6278,10 +7283,12 @@ truffle-contract@^3.0.4: truffle-error@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/truffle-error/-/truffle-error-0.0.3.tgz#4bf55242e14deee1c7194932709182deff2c97ca" + integrity sha1-S/VSQuFN7uHHGUkycJGC3v8sl8o= truffle-hdwallet-provider-privkey@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider-privkey/-/truffle-hdwallet-provider-privkey-0.1.0.tgz#9417047a74ad37d923df926154b6486ffb57f6c9" + integrity sha512-Vj04yr2d9qLRZspoHztbE/YQnVaoFb90JNZHtggRUm+JFm/NOiSJHLVI63+3mtUIuQ04EuKZ7Df8JQw0Ni7IeA== dependencies: ethereumjs-tx "^1.3.3" ethereumjs-wallet "^0.6.0" @@ -6291,6 +7298,7 @@ truffle-hdwallet-provider-privkey@^0.1.0: truffle-wallet-provider@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-wallet-provider/-/truffle-wallet-provider-0.0.5.tgz#db59ce6fa1c558766011137509a94dfca8d1408e" + integrity sha1-21nOb6HFWHZgERN1CalN/KjRQI4= dependencies: ethereumjs-wallet "^0.6.0" web3 "^0.18.2" @@ -6299,6 +7307,7 @@ truffle-wallet-provider@0.0.5: truffle@^4.1.13: version "4.1.14" resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.14.tgz#8d2c298e29abf9b1e486e44ff9faca6d34bb9030" + integrity sha512-e7tTLvKP3bN9dE7MagfWyFjy4ZgoEGbeujECy1me1ENBzbj/aO/+45gs72qsL3+3IkCNNcWNOJjjrm8BYZZNNg== dependencies: mocha "^4.1.0" original-require "1.0.1" @@ -6307,30 +7316,36 @@ truffle@^4.1.13: tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.13.2.tgz#453161770469d45cd266c36404e2bc99a8fa9944" + integrity sha1-RTFhdwRp1FzSZsNkBOK8maj6mUQ= tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" + integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== dependencies: media-typer "0.3.0" mime-types "~2.1.18" @@ -6338,30 +7353,36 @@ type-is@~1.6.16: typechecker@^2.0.8: version "2.1.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.1.0.tgz#d1c2093a54ff8a19f58cff877eeaa54f2242d383" + integrity sha1-0cIJOlT/ihn1jP+HfuqlTyJC04M= typechecker@^4.3.0: version "4.6.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.6.0.tgz#d245d9c2df21147d5e2a942fff170b68ece73c87" + integrity sha512-83OrXpyP3LNr7aRbLkt2nkjE/d7q8su8/uRvrKxCpswqVCVGOgyaKpaz8/MTjQqBYe4eLNuJ44pNakFZKqyPMA== dependencies: editions "^2.0.2" typechecker@~2.0.1: version "2.0.8" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.0.8.tgz#e83da84bb64c584ccb345838576c40b0337db82e" + integrity sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4= typedarray-to-buffer@^3.1.2: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -6371,6 +7392,7 @@ uglify-js@^2.8.29: uglify-js@^3.1.4: version "3.4.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" + integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== dependencies: commander "~2.17.1" source-map "~0.6.1" @@ -6378,10 +7400,12 @@ uglify-js@^3.1.4: uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= uglifyjs-webpack-plugin@^0.4.6: version "0.4.6" resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" + integrity sha1-uVH0q7a9YX5m9j64kUmOORdj4wk= dependencies: source-map "^0.5.6" uglify-js "^2.8.29" @@ -6390,10 +7414,12 @@ uglifyjs-webpack-plugin@^0.4.6: ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== unbzip2-stream@^1.0.9: version "1.3.1" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" + integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw== dependencies: buffer "^3.0.1" through "^2.3.6" @@ -6401,14 +7427,17 @@ unbzip2-stream@^1.0.9: underscore@1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= underscore@^1.8.3: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -6418,18 +7447,22 @@ union-value@^1.0.0: universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== unorm@^1.3.3: version "1.4.1" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300" + integrity sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA= unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -6437,34 +7470,41 @@ unset-value@^1.0.0: upath@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" + integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= dependencies: prepend-http "^1.0.1" url-set-query@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= dependencies: punycode "1.3.2" querystring "0.2.0" @@ -6472,65 +7512,66 @@ url@^0.11.0: use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== utf8@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" + integrity sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g= utf8@^2.1.1, utf8@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" + integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY= utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= dependencies: inherits "2.0.1" util@^0.10.3: version "0.10.4" resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== dependencies: inherits "2.0.3" -utile@0.3.x: - version "0.3.0" - resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a" - dependencies: - async "~0.9.0" - deep-equal "~0.2.1" - i "0.3.x" - mkdirp "0.x.x" - ncp "1.0.x" - rimraf "2.x.x" - utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== valid-url@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" + integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" @@ -6538,14 +7579,17 @@ validate-npm-package-license@^3.0.1: varint@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf" + integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8= vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -6554,12 +7598,14 @@ verror@1.10.0: vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= dependencies: indexof "0.0.1" watchpack@^1.4.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" + integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== dependencies: chokidar "^2.0.2" graceful-fs "^4.1.2" @@ -6568,6 +7614,7 @@ watchpack@^1.4.0: watchr@~2.4.13: version "2.4.13" resolved "https://registry.yarnpkg.com/watchr/-/watchr-2.4.13.tgz#d74847bb4d6f90f61fe2c74f9f68662aa0e07601" + integrity sha1-10hHu01vkPYf4sdPn2hmKqDgdgE= dependencies: eachr "^2.0.2" extendr "^2.1.0" @@ -6581,6 +7628,7 @@ watchr@~2.4.13: web3-bzz@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.34.tgz#068d37777ab65e5c60f8ec8b9a50cfe45277929c" + integrity sha1-Bo03d3q2Xlxg+OyLmlDP5FJ3kpw= dependencies: got "7.1.0" swarm-js "0.1.37" @@ -6589,6 +7637,7 @@ web3-bzz@1.0.0-beta.34: web3-core-helpers@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz#b168da00d3e19e156bc15ae203203dd4dfee2d03" + integrity sha1-sWjaANPhnhVrwVriAyA91N/uLQM= dependencies: underscore "1.8.3" web3-eth-iban "1.0.0-beta.34" @@ -6597,6 +7646,7 @@ web3-core-helpers@1.0.0-beta.34: web3-core-method@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz#ec163c8a2c490fa02a7ec15559fa7307fc7cc6dd" + integrity sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -6607,6 +7657,7 @@ web3-core-method@1.0.0-beta.34: web3-core-promievent@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz#a4f4fa6784bb293e82c60960ae5b56a94cd03edc" + integrity sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw= dependencies: any-promise "1.3.0" eventemitter3 "1.1.1" @@ -6614,6 +7665,7 @@ web3-core-promievent@1.0.0-beta.34: web3-core-requestmanager@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz#01f8f6cf2ae6b6f0b70c38bae1ef741b5bab215c" + integrity sha1-Afj2zyrmtvC3DDi64e90G1urIVw= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -6624,6 +7676,7 @@ web3-core-requestmanager@1.0.0-beta.34: web3-core-subscriptions@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz#9fed144033f221c3cf21060302ffdaf5ef2de2de" + integrity sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4= dependencies: eventemitter3 "1.1.1" underscore "1.8.3" @@ -6632,6 +7685,7 @@ web3-core-subscriptions@1.0.0-beta.34: web3-core@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.34.tgz#121be8555e9fb00d2c5d05ddd3381d0c9e46987e" + integrity sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4= dependencies: web3-core-helpers "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -6641,6 +7695,7 @@ web3-core@1.0.0-beta.34: web3-eth-abi@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz#034533e3aa2f7e59ff31793eaea685c0ed5af67a" + integrity sha1-A0Uz46ovfln/MXk+rqaFwO1a9no= dependencies: bn.js "4.11.6" underscore "1.8.3" @@ -6650,6 +7705,7 @@ web3-eth-abi@1.0.0-beta.34: web3-eth-accounts@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz#e09142eeecc797ac3459b75e9b23946d3695f333" + integrity sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM= dependencies: any-promise "1.3.0" crypto-browserify "3.12.0" @@ -6665,6 +7721,7 @@ web3-eth-accounts@1.0.0-beta.34: web3-eth-contract@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz#9dbb38fae7643a808427a20180470ec7415c91e6" + integrity sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -6678,6 +7735,7 @@ web3-eth-contract@1.0.0-beta.34: web3-eth-iban@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz#9af458605867ccf74ea979aaf326b38ba6a5ba0c" + integrity sha1-mvRYYFhnzPdOqXmq8yazi6alugw= dependencies: bn.js "4.11.6" web3-utils "1.0.0-beta.34" @@ -6685,6 +7743,7 @@ web3-eth-iban@1.0.0-beta.34: web3-eth-personal@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz#9afba167342ebde5420bcd5895c3f6c34388f205" + integrity sha1-mvuhZzQuveVCC81YlcP2w0OI8gU= dependencies: web3-core "1.0.0-beta.34" web3-core-helpers "1.0.0-beta.34" @@ -6695,6 +7754,7 @@ web3-eth-personal@1.0.0-beta.34: web3-eth@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.34.tgz#74086000850c6fe6f535ef49837d6d4bb6113268" + integrity sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -6712,6 +7772,7 @@ web3-eth@1.0.0-beta.34: web3-net@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.34.tgz#427cea2f431881449c8e38d523290f173f9ff63d" + integrity sha1-QnzqL0MYgUScjjjVIykPFz+f9j0= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -6720,6 +7781,7 @@ web3-net@1.0.0-beta.34: web3-provider-engine@^13.6.4: version "13.8.0" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz#4c7c1ad2af5f1fe10343b8a65495879a2f9c00df" + integrity sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ== dependencies: async "^2.5.0" clone "^2.0.0" @@ -6744,6 +7806,7 @@ web3-provider-engine@^13.6.4: web3-provider-engine@^8.4.0: version "8.6.1" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz#4d86e19e30caaf97df351511ec0f60136e5b30eb" + integrity sha1-TYbhnjDKr5ffNRUR7A9gE25bMOs= dependencies: async "^2.1.2" clone "^2.0.0" @@ -6763,6 +7826,7 @@ web3-provider-engine@^8.4.0: web3-providers-http@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz#e561b52bbb43766282007d40285bfe3550c27e7a" + integrity sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno= dependencies: web3-core-helpers "1.0.0-beta.34" xhr2 "0.1.4" @@ -6770,6 +7834,7 @@ web3-providers-http@1.0.0-beta.34: web3-providers-ipc@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz#a1b77f1a306d73649a9c039052e40cb71328d00a" + integrity sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao= dependencies: oboe "2.1.3" underscore "1.8.3" @@ -6778,6 +7843,7 @@ web3-providers-ipc@1.0.0-beta.34: web3-providers-ws@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz#7de70f1b83f2de36476772156becfef6e3516eb3" + integrity sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -6786,6 +7852,7 @@ web3-providers-ws@1.0.0-beta.34: web3-shh@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.34.tgz#975061d71eaec42ccee576f7bd8f70f03844afe0" + integrity sha1-l1Bh1x6uxCzO5Xb3vY9w8DhEr+A= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -6795,6 +7862,7 @@ web3-shh@1.0.0-beta.34: web3-utils@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.34.tgz#9411fc39aaef39ca4e06169f762297d9ff020970" + integrity sha1-lBH8OarvOcpOBhafdiKX2f8CCXA= dependencies: bn.js "4.11.6" eth-lib "0.1.27" @@ -6807,6 +7875,7 @@ web3-utils@1.0.0-beta.34: web3@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/web3/-/web3-0.19.1.tgz#e763d5b1107c4bc24abd4f8cbee1ba3659e6eb31" + integrity sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE= dependencies: bignumber.js "^4.0.2" crypto-js "^3.1.4" @@ -6817,6 +7886,7 @@ web3@0.19.1: web3@0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.2.tgz#c54dac5fc0e377399c04c1a6ecbb12e4513278d6" + integrity sha1-xU2sX8DjdzmcBMGm7LsS5FEyeNY= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -6827,6 +7897,7 @@ web3@0.20.2: web3@0.20.6: version "0.20.6" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.6.tgz#3e97306ae024fb24e10a3d75c884302562215120" + integrity sha1-PpcwauAk+yThCj11yIQwJWIhUSA= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -6837,6 +7908,7 @@ web3@0.20.6: web3@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.34.tgz#347e561b784098cb5563315f490479a1d91f2ab1" + integrity sha1-NH5WG3hAmMtVYzFfSQR5odkfKrE= dependencies: web3-bzz "1.0.0-beta.34" web3-core "1.0.0-beta.34" @@ -6849,6 +7921,7 @@ web3@1.0.0-beta.34: web3@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" + integrity sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js#master" crypto-js "^3.1.4" @@ -6858,6 +7931,7 @@ web3@^0.16.0: web3@^0.18.2, web3@^0.18.4: version "0.18.4" resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" + integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" crypto-js "^3.1.4" @@ -6868,6 +7942,7 @@ web3@^0.18.2, web3@^0.18.4: web3@^0.20.5: version "0.20.7" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.7.tgz#1605e6d81399ed6f85a471a4f3da0c8be57df2f7" + integrity sha512-VU6/DSUX93d1fCzBz7WP/SGCQizO1rKZi4Px9j/3yRyfssHyFcZamMw2/sj4E8TlfMXONvZLoforR8B4bRoyTQ== dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -6878,6 +7953,7 @@ web3@^0.20.5: webpack-sources@^1.0.1: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" + integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== dependencies: source-list-map "^2.0.0" source-map "~0.6.1" @@ -6885,6 +7961,7 @@ webpack-sources@^1.0.1: webpack@^3.0.0: version "3.12.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.12.0.tgz#3f9e34360370602fcf639e97939db486f4ec0d74" + integrity sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ== dependencies: acorn "^5.0.0" acorn-dynamic-import "^2.0.0" @@ -6921,50 +7998,46 @@ webpack@^3.0.0: whatwg-fetch@>=0.10.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" + integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@^1.1.1, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - -winston@2.1.x: - version "2.1.1" - resolved "http://registry.npmjs.org/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" - dependencies: - async "~1.0.0" - colors "1.0.x" - cycle "1.0.x" - eyes "0.1.x" - isstream "0.1.x" - pkginfo "0.3.x" - stack-trace "0.0.x" + integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= winston@^2.3.1: version "2.4.4" resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.4.tgz#a01e4d1d0a103cf4eada6fc1f886b3110d71c34b" + integrity sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q== dependencies: async "~1.0.0" colors "1.0.x" @@ -6976,18 +8049,22 @@ winston@^2.3.1: wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= wordwrap@^1.0.0, wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -6995,16 +8072,19 @@ wrap-ansi@^2.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= dependencies: mkdirp "^0.5.1" ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" @@ -7013,12 +8093,14 @@ ws@^3.0.0: xhr-request-promise@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" + integrity sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0= dependencies: xhr-request "^1.0.1" xhr-request@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== dependencies: buffer-to-arraybuffer "^0.0.5" object-assign "^4.1.1" @@ -7031,16 +8113,19 @@ xhr-request@^1.0.1: xhr2-cookies@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= dependencies: cookiejar "^2.1.1" xhr2@*, xhr2@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" + integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8= xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: version "2.5.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" + integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== dependencies: global "~4.3.0" is-function "^1.0.1" @@ -7050,40 +8135,49 @@ xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: xmlhttprequest@*, xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= xregexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" + integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= dependencies: object-keys "~0.4.0" y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= dependencies: camelcase "^3.0.0" lodash.assign "^4.0.6" @@ -7091,24 +8185,28 @@ yargs-parser@^2.4.1: yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k= dependencies: camelcase "^4.1.0" yargs-parser@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== dependencies: camelcase "^4.1.0" yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= dependencies: camelcase "^4.1.0" yargs@^10.0.3: version "10.1.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -7126,6 +8224,7 @@ yargs@^10.0.3: yargs@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" + integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -7143,6 +8242,7 @@ yargs@^11.0.0: yargs@^4.6.0, yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= dependencies: cliui "^3.2.0" decamelize "^1.1.1" @@ -7162,6 +8262,7 @@ yargs@^4.6.0, yargs@^4.7.1: yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + integrity sha1-YpmpBVsc78lp/355wdkY3Osiw2A= dependencies: camelcase "^4.1.0" cliui "^3.2.0" @@ -7180,6 +8281,7 @@ yargs@^8.0.2: yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= dependencies: camelcase "^1.0.2" cliui "^2.1.0" @@ -7189,6 +8291,7 @@ yargs@~3.10.0: yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" From 557d286869d85bf5906a2f63576e5a4e4f23d138 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 19:38:09 +0530 Subject: [PATCH 218/582] Combined modifiers --- contracts/modules/STO/USDTieredSTO.sol | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 9e6287087..9e838592a 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -154,12 +154,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _; } - modifier validSC { + modifier validSC(address _usdToken) { require(fundRaiseTypes[uint8(FundRaiseType.SC)], "Stable coins not allowed"); - _; - } - - modifier validUSDToken(address _usdToken) { require(usdTokenEnabled[_usdToken], "Invalid USD token"); _; } @@ -476,7 +472,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @param _usdToken Address of USD stable coin to buy tokens with */ function buyWithUSDRateLimited(address _beneficiary, uint256 _investedSC, uint256 _minTokens, IERC20 _usdToken) - public validSC validUSDToken(_usdToken) + public validSC(_usdToken) { _buyWithTokens(_beneficiary, _investedSC, FundRaiseType.SC, _minTokens, _usdToken); } From 5fdd2e2d79b8ba39f4823a98bd767ec0e358ef05 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 19:42:34 +0530 Subject: [PATCH 219/582] Added data validation --- contracts/modules/STO/USDTieredSTO.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 9e838592a..58a3bdc2a 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -339,6 +339,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } usdTokens = _usdTokens; for(i = 0; i < _usdTokens.length; i++) { + require(_usdTokens[i] != address(0), "Invalid USD token"); usdTokenEnabled[_usdTokens[i]] = true; } emit SetAddresses(wallet, reserveWallet, _usdTokens); From 9802d8abd0aca4c3c980ef3f46c12a17ed659fbf Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 27 Nov 2018 19:43:21 +0530 Subject: [PATCH 220/582] test cases fixed --- test/z_volume_restriction_tm.js | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js index 96c96776d..e302b9926 100644 --- a/test/z_volume_restriction_tm.js +++ b/test/z_volume_restriction_tm.js @@ -677,7 +677,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); let totalAmountTransacted = 0; for (let i = 0; i < 10; i++) { - let amount = Math.random(); + let amount = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); totalAmountTransacted += amount; @@ -742,13 +742,10 @@ contract('VolumeRestrictionTransferManager', accounts => { let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - let totalAmountTransacted = 0; - for (let i = 0; i < 2; i++) { - let amount = Math.random(); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); - console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); - totalAmountTransacted += amount; - } + + let totalAmountTransacted = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(totalAmountTransacted.toString()), {from: account_investor1}); + // Check the balance of the investors let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances @@ -772,7 +769,7 @@ contract('VolumeRestrictionTransferManager', accounts => { `); assert.equal(data[0].length - 1, 2); assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), - oldData[1].dividedBy(new BigNumber(10).pow(18)).toNumber() + totalAmountTransacted, 0.00001); + oldData[1].dividedBy(new BigNumber(10).pow(18)).toNumber() + totalAmountTransacted, 0.001); }); it("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { @@ -828,7 +825,7 @@ contract('VolumeRestrictionTransferManager', accounts => { `); assert.equal(newData[0][i].toNumber(), startTime + duration.days(i)) assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.00001); + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((newData[1].toNumber()).toString())} @@ -860,7 +857,7 @@ contract('VolumeRestrictionTransferManager', accounts => { `); assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.00001); + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} @@ -871,7 +868,7 @@ contract('VolumeRestrictionTransferManager', accounts => { sumOflastperiod += tempArray[i]; } assert.equal(data[0].length - 1, 4); - assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), sumOflastperiod, 0.00001); + assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), sumOflastperiod, 0.001); }); }); @@ -968,7 +965,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(); let totalAmountTransacted = 0; for (let i = 0; i < 10; i++) { - let amount = Math.random(); + let amount = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor2}); console.log(`${i}: Restricted investor 2 able to transact ${amount} tokens to investor 3`); totalAmountTransacted += amount; @@ -1125,7 +1122,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(data[0].length - 1, 0); console.log(`Transfer the tokens from the another investor comes under the global category`); - + await increaseTime(duration.minutes(10)); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4"), {from: account_delegate3}); tempArrayGlobal[tempArrayGlobal.length - 1] += 4; data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); From ed9406809116ba72d5264b60897cb269f076b7f9 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 27 Nov 2018 19:50:30 +0530 Subject: [PATCH 221/582] minor test fix because of gtm --- test/z_volume_restriction_tm.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/z_volume_restriction_tm.js b/test/z_volume_restriction_tm.js index e302b9926..48645f5f4 100644 --- a/test/z_volume_restriction_tm.js +++ b/test/z_volume_restriction_tm.js @@ -180,7 +180,7 @@ contract('VolumeRestrictionTransferManager', accounts => { [latestTime(), latestTime(), latestTime()], [latestTime(), latestTime(), latestTime()], [latestTime() + duration.days(30), latestTime() + duration.days(30), latestTime() + duration.days(30)], - [0, 0, 0], + [true, true, true], { from: token_owner } @@ -1080,7 +1080,7 @@ contract('VolumeRestrictionTransferManager', accounts => { [latestTime(), latestTime()], [latestTime(), latestTime()], [latestTime() + duration.days(30), latestTime() + duration.days(30)], - [0, 0], + [true, true], { from: token_owner } From 846d03f463e879116940a297cebbfa5934612153 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 27 Nov 2018 20:05:15 +0530 Subject: [PATCH 222/582] test case fixed --- test/p_usd_tiered_sto.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 0af78cf01..7cc69286a 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -935,7 +935,7 @@ contract("USDTieredSTO", accounts => { await I_USDTieredSTO_Array[stoId].modifyAddresses( "0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", - [address_zero], + [0x0000000000000000000003000000000000057a00], { from: ISSUER } ); assert.equal( @@ -950,7 +950,7 @@ contract("USDTieredSTO", accounts => { ); assert.equal( await I_USDTieredSTO_Array[stoId].usdTokens.call(0), - address_zero, + "0x0000000000000000000003000000000000057a00", "STO Configuration doesn't set as expected" ); }); From b172ce6fb95dfe6f2733b960bcea0e5f18302988 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 27 Nov 2018 17:51:11 +0200 Subject: [PATCH 223/582] Applied review comments (not finished) --- .../modules/Wallet/VestingEscrowWallet.sol | 117 +++++++++++------- test/z_vesting_escrow_wallet.js | 17 +-- 2 files changed, 79 insertions(+), 55 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index a1d98c7e0..e5226dda0 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -3,7 +3,6 @@ pragma solidity ^0.4.24; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; import "./IWallet.sol"; /** @@ -44,7 +43,8 @@ contract VestingEscrowWallet is IWallet { uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, - uint256 _startTime + uint256 _startTime, + uint256 _index ); event ModifySchedule( address indexed _beneficiary, @@ -54,7 +54,7 @@ contract VestingEscrowWallet is IWallet { uint256 _frequency, uint256 _startTime ); - event RevokeSchedules(address indexed _beneficiary); + event RevokeAllSchedules(address indexed _beneficiary); event RevokeSchedule(address indexed _beneficiary, uint256 _index); event DepositTokens(uint256 _numberOfTokens); event SendToTreasury(uint256 _numberOfTokens); @@ -178,6 +178,18 @@ contract VestingEscrowWallet is IWallet { ) public withPerm(ADMIN) + { + _addSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); + } + + function _addSchedule( + address _beneficiary, + uint256 _numberOfTokens, + uint256 _duration, + uint256 _frequency, + uint256 _startTime + ) + internal { _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); if (_numberOfTokens > unassignedTokens) { @@ -189,7 +201,8 @@ contract VestingEscrowWallet is IWallet { beneficiaries.push(_beneficiary); } schedules[_beneficiary].push(Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime)); - emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); + uint256 index = schedules[_beneficiary].length - 1; + emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime, index); } /** @@ -205,7 +218,7 @@ contract VestingEscrowWallet is IWallet { function _addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) internal { require(_index < templates.length, "Template not found"); Template memory template = templates[_index]; - addSchedule(_beneficiary, template.numberOfTokens, template.duration, template.frequency, _startTime); + _addSchedule(_beneficiary, template.numberOfTokens, template.duration, template.frequency, _startTime); } /** @@ -227,6 +240,19 @@ contract VestingEscrowWallet is IWallet { ) public withPerm(ADMIN) + { + _modifySchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); + } + + function _modifySchedule( + address _beneficiary, + uint256 _index, + uint256 _numberOfTokens, + uint256 _duration, + uint256 _frequency, + uint256 _startTime + ) + internal { _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); require(_index < schedules[_beneficiary].length, "Schedule not found"); @@ -234,12 +260,12 @@ contract VestingEscrowWallet is IWallet { /*solium-disable-next-line security/no-block-members*/ require(now < schedule.startTime, "Schedule started"); if (_numberOfTokens <= schedule.numberOfTokens) { - unassignedTokens = unassignedTokens.add(schedule.numberOfTokens - _numberOfTokens); + unassignedTokens = unassignedTokens.add(schedule.numberOfTokens.sub(_numberOfTokens)); } else { - if (_numberOfTokens - schedule.numberOfTokens > unassignedTokens) { - _depositTokens(_numberOfTokens - schedule.numberOfTokens - unassignedTokens); + if (_numberOfTokens.sub(schedule.numberOfTokens) > unassignedTokens) { + _depositTokens(_numberOfTokens.sub(schedule.numberOfTokens).sub(unassignedTokens)); } - unassignedTokens = unassignedTokens.sub(_numberOfTokens - schedule.numberOfTokens); + unassignedTokens = unassignedTokens.sub(_numberOfTokens.sub(schedule.numberOfTokens)); } schedules[_beneficiary][_index] = Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime); emit ModifySchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); @@ -255,14 +281,11 @@ contract VestingEscrowWallet is IWallet { require(_index < schedules[_beneficiary].length, "Schedule not found"); _sendTokens(_beneficiary); Schedule[] storage userSchedules = schedules[_beneficiary]; - unassignedTokens = unassignedTokens.add(userSchedules[_index].numberOfTokens - userSchedules[_index].releasedTokens); + unassignedTokens = unassignedTokens.add(userSchedules[_index].numberOfTokens.sub(userSchedules[_index].releasedTokens)); if (_index != userSchedules.length - 1) { userSchedules[_index] = userSchedules[userSchedules.length - 1]; } userSchedules.length--; - if (userSchedules.length == 0) { - _removeBeneficiary(_beneficiary); - } emit RevokeSchedule(_beneficiary, _index); } @@ -270,15 +293,19 @@ contract VestingEscrowWallet is IWallet { * @notice Revokes all beneficiary's schedules * @param _beneficiary beneficiary's address */ - function revokeSchedules(address _beneficiary) public withPerm(ADMIN) { + function revokeAllSchedules(address _beneficiary) public withPerm(ADMIN) { + _revokeAllSchedules(_beneficiary); + } + + function _revokeAllSchedules(address _beneficiary) internal { require(_beneficiary != address(0), "Invalid address"); _sendTokens(_beneficiary); - Schedule[] storage data = schedules[_beneficiary]; - for (uint256 i = 0; i < data.length; i++) { - unassignedTokens = unassignedTokens.add(data[i].numberOfTokens - data[i].releasedTokens); + Schedule[] storage userSchedules = schedules[_beneficiary]; + for (uint256 i = 0; i < userSchedules.length; i++) { + unassignedTokens = unassignedTokens.add(userSchedules[i].numberOfTokens.sub(userSchedules[i].releasedTokens)); } - _removeBeneficiary(_beneficiary); - emit RevokeSchedules(_beneficiary); + userSchedules.length = 0; + emit RevokeAllSchedules(_beneficiary); } /** @@ -296,11 +323,11 @@ contract VestingEscrowWallet is IWallet { schedule.duration, schedule.frequency, schedule.startTime, - _getScheduleState(_beneficiary, _index) + getScheduleState(_beneficiary, _index) ); } - function _getScheduleState(address _beneficiary, uint256 _index) internal view returns(State) { + function getScheduleState(address _beneficiary, uint256 _index) public view returns(State) { Schedule memory schedule = schedules[_beneficiary][_index]; if (now < schedule.startTime) { return State.CREATED; @@ -326,11 +353,7 @@ contract VestingEscrowWallet is IWallet { * @param _beneficiary beneficiary's address * @return available tokens for beneficiary */ - function getAvailableTokens(address _beneficiary) external view returns(uint256) { - return _getAvailableTokens(_beneficiary); - } - - function _getAvailableTokens(address _beneficiary) internal view returns(uint256) { + function getAvailableTokens(address _beneficiary) public view returns(uint256) { require(_beneficiary != address(0)); uint256 availableTokens; for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { @@ -350,6 +373,22 @@ contract VestingEscrowWallet is IWallet { } } + /** + * @notice Used to remove beneficiaries without schedules + */ + function trimBeneficiaries() external withPerm(ADMIN) { + //TODO commented because of contract size +// for (uint256 i = 0; i < beneficiaries.length; i++) { +// if (schedules[beneficiaries[i]].length == 0) { +// delete schedules[beneficiaries[i]]; +// if (i != beneficiaries.length - 1) { +// beneficiaries[i] = beneficiaries[beneficiaries.length - 1]; +// } +// beneficiaries.length--; +// } +// } + } + /** * @notice Used to bulk add vesting schedules for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses @@ -369,7 +408,7 @@ contract VestingEscrowWallet is IWallet { withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { - addSchedule(_beneficiaries[i], _numberOfTokens, _duration, _frequency, _startTime); + _addSchedule(_beneficiaries[i], _numberOfTokens, _duration, _frequency, _startTime); } } @@ -391,7 +430,7 @@ contract VestingEscrowWallet is IWallet { */ function revokeSchedulesMulti(address[] _beneficiaries) external withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { - revokeSchedules(_beneficiaries[i]); + _revokeAllSchedules(_beneficiaries[i]); } } @@ -417,7 +456,7 @@ contract VestingEscrowWallet is IWallet { { require(_beneficiaries.length == _indexes.length, "Arrays sizes mismatch"); for (uint256 i = 0; i < _beneficiaries.length; i++) { - modifySchedule(_beneficiaries[i], _indexes[i], _numberOfTokens, _duration, _frequency, _startTime); + _modifySchedule(_beneficiaries[i], _indexes[i], _numberOfTokens, _duration, _frequency, _startTime); } } @@ -444,7 +483,7 @@ contract VestingEscrowWallet is IWallet { } function _sendTokens(address _beneficiary) internal { - uint256 amount = _getAvailableTokens(_beneficiary); + uint256 amount = getAvailableTokens(_beneficiary); if (amount > 0) { for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { schedules[_beneficiary][i].availableTokens = 0; @@ -471,7 +510,7 @@ contract VestingEscrowWallet is IWallet { } uint256 releasedTokens = schedule.numberOfTokens.mul(periodNumber).div(periodCount); if (schedule.releasedTokens < releasedTokens) { - schedule.availableTokens = schedule.availableTokens.add(releasedTokens - schedule.releasedTokens); + schedule.availableTokens = schedule.availableTokens.add(releasedTokens.sub(schedule.releasedTokens)); schedule.releasedTokens = releasedTokens; } } @@ -479,22 +518,6 @@ contract VestingEscrowWallet is IWallet { } } - function _removeBeneficiary(address _beneficiary) internal { - bool isFound = false; - uint256 index; - for (uint256 i = 0; i < beneficiaries.length; i++) { - if (_beneficiary == beneficiaries[i]) { - isFound = true; - index = i; - } - } - if (isFound && index != beneficiaries.length - 1) { - beneficiaries[index] = beneficiaries[beneficiaries.length - 1]; - } - beneficiaries.length--; - delete schedules[_beneficiary]; - } - /** * @notice Return the permissions flag that are associated with VestingEscrowWallet */ diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 9728f0140..6bebcff8e 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -366,7 +366,7 @@ contract('VestingEscrowWallet', accounts => { I_VestingEscrowWallet.modifySchedule(account_beneficiary3, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) ); - await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); @@ -393,7 +393,7 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, COMPLETED); await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); - await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); @@ -451,7 +451,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), totalNumberOfTokens); await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); - await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); @@ -675,7 +675,7 @@ contract('VestingEscrowWallet', accounts => { it("Should fail to revoke vesting schedules -- fail because address is invalid", async () => { await catchRevert( - I_VestingEscrowWallet.revokeSchedules(0, {from: wallet_admin}) + I_VestingEscrowWallet.revokeAllSchedules(0, {from: wallet_admin}) ); }); @@ -702,7 +702,7 @@ contract('VestingEscrowWallet', accounts => { it("Should not be able to revoke schedules -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.revokeSchedules(account_beneficiary1, {from: account_beneficiary1}) + I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary1, {from: account_beneficiary1}) ); }); @@ -721,7 +721,7 @@ contract('VestingEscrowWallet', accounts => { }); it("Should revoke 2 vesting schedules from the beneficiary address", async () => { - const tx = await I_VestingEscrowWallet.revokeSchedules(account_beneficiary2, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary2, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); @@ -776,7 +776,7 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.updateAll({from: wallet_admin}); numberOfTokens = (2000 / 10 * stepCount); - const tx2 = await I_VestingEscrowWallet.revokeSchedules(account_beneficiary3, {from: wallet_admin}); + const tx2 = await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); assert.equal(tx2.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx2.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); @@ -1006,7 +1006,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), 5000); await I_SecurityToken.transfer(token_owner, balance, {from: beneficiary}); - await I_VestingEscrowWallet.revokeSchedules(beneficiary, {from: wallet_admin}); + await I_VestingEscrowWallet.revokeAllSchedules(beneficiary, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); } }); @@ -1073,6 +1073,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 0); } + await I_VestingEscrowWallet.trimBeneficiaries({from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); From c0878e84165e97bcdfa9e72eb0d48cf59319652a Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 27 Nov 2018 22:32:32 +0530 Subject: [PATCH 224/582] update the permission doc --- docs/permissions_list.md | 58 +++++++++++----------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/docs/permissions_list.md b/docs/permissions_list.md index b49c95a0e..dba79396d 100644 --- a/docs/permissions_list.md +++ b/docs/permissions_list.md @@ -143,7 +143,7 @@ allocateTokensMulti() - TransferManager + TransferManager CountTransferManager changeHolderCount() withPerm(ADMIN) @@ -205,71 +205,45 @@ changeHolderPercentage() - LockupVolumeRestrictionTM - addLockup() - withPerm(ADMIN) + VolumeRestrictionTM + changeExemptWalletList() + withPerm(ADMIN) - addLockUpMulti() + addIndividualRestriction() - removeLockUp() + addIndividualRestrictionMulti() - modifyLockUp() + addGlobalRestriction() - SingleTradeVolumeRestrictionTM - setAllowPrimaryIssuance() - withPerm(ADMIN) - - - changeTransferLimitToPercentage() - - - changeTransferLimitToTokens() - - - changeGlobalLimitInTokens() - - - changeGlobalLimitInPercentage() - - - addExemptWallet() - - - removeExemptWallet() - - - addExemptWalletMulti() - - - removeExemptWalletMulti() + addDailyGlobalRestriction() - setTransferLimitInTokens() + removeIndividualRestriction() - setTransferLimitInPercentage() + removeIndividualRestrictionMulti() - removeTransferLimitInPercentage() + removeGlobalRestriction() - removeTransferLimitInTokens() + removeDailyGlobalRestriction() - setTransferLimitInTokensMulti() + modifyIndividualRestriction() - setTransferLimitInPercentageMulti() + modifyIndividualRestrictionMulti() - removeTransferLimitInTokensMulti() + modifyGlobalRestriction() - removeTransferLimitInPercentageMulti + modifyDailyGlobalRestriction() From bcfe5a034bba2326734283479ded189ea7e5b82b Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 27 Nov 2018 14:16:41 -0300 Subject: [PATCH 225/582] MATM CLI support --- CLI/commands/helpers/contract_abis.js | 44 +++--- CLI/commands/transfer_manager.js | 202 +++++++++++++++++++++++--- 2 files changed, 206 insertions(+), 40 deletions(-) diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index 38f063aec..70e9430e8 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -7,7 +7,7 @@ let stoInterfaceABI; let cappedSTOABI; let usdTieredSTOABI; let generalTransferManagerABI; -let stvrTransferManagerABI; +let manualApprovalTransferManagerABI; let generalPermissionManagerABI; let polyTokenABI; let cappedSTOFactoryABI; @@ -19,27 +19,27 @@ let ownableABI; let moduleFactoryABI; try { - polymathRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolymathRegistry.json').toString()).abi; - securityTokenRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/SecurityTokenRegistry.json').toString()).abi; - featureRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/FeatureRegistry.json').toString()).abi; - moduleRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleRegistry.json').toString()).abi; - securityTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/SecurityToken.json').toString()).abi; - stoInterfaceABI = JSON.parse(require('fs').readFileSync('./build/contracts/ISTO.json').toString()).abi; - cappedSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTO.json').toString()).abi; - usdTieredSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTO.json').toString()).abi; - generalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralTransferManager.json').toString()).abi; - stvrTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/SingleTradeVolumeRestrictionTM.json').toString()).abi; + polymathRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolymathRegistry.json').toString()).abi; + securityTokenRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/SecurityTokenRegistry.json').toString()).abi; + featureRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/FeatureRegistry.json').toString()).abi; + moduleRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleRegistry.json').toString()).abi; + securityTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/SecurityToken.json').toString()).abi; + stoInterfaceABI = JSON.parse(require('fs').readFileSync('./build/contracts/ISTO.json').toString()).abi; + cappedSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTO.json').toString()).abi; + usdTieredSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTO.json').toString()).abi; + generalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralTransferManager.json').toString()).abi; + manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ManualApprovalTransferManager.json').toString()).abi; generalPermissionManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralPermissionManager.json').toString()).abi; - polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; - cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; - usdTieredSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTOFactory.json').toString()).abi; - erc20DividendCheckpointABI = JSON.parse(require('fs').readFileSync('./build/contracts/ERC20DividendCheckpoint.json').toString()).abi; - etherDividendCheckpointABI = JSON.parse(require('fs').readFileSync('./build/contracts/EtherDividendCheckpoint.json').toString()).abi; - moduleInterfaceABI = JSON.parse(require('fs').readFileSync('./build/contracts/IModule.json').toString()).abi; - ownableABI = JSON.parse(require('fs').readFileSync('./build/contracts/Ownable.json').toString()).abi; - moduleFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleFactory.json').toString()).abi; + polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; + cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; + usdTieredSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTOFactory.json').toString()).abi; + erc20DividendCheckpointABI = JSON.parse(require('fs').readFileSync('./build/contracts/ERC20DividendCheckpoint.json').toString()).abi; + etherDividendCheckpointABI = JSON.parse(require('fs').readFileSync('./build/contracts/EtherDividendCheckpoint.json').toString()).abi; + moduleInterfaceABI = JSON.parse(require('fs').readFileSync('./build/contracts/IModule.json').toString()).abi; + ownableABI = JSON.parse(require('fs').readFileSync('./build/contracts/Ownable.json').toString()).abi; + moduleFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleFactory.json').toString()).abi; } catch (err) { - console.log('\x1b[31m%s\x1b[0m',"Couldn't find contracts' artifacts. Make sure you ran truffle compile first"); + console.log('\x1b[31m%s\x1b[0m', "Couldn't find contracts' artifacts. Make sure you ran truffle compile first"); throw err; } @@ -71,8 +71,8 @@ module.exports = { generalTransferManager: function () { return generalTransferManagerABI; }, - singleTradeVolumeRestrictionTM: function() { - return stvrTransferManagerABI; + manualApprovalTransferManager: function () { + return manualApprovalTransferManagerABI; }, generalPermissionManager: function () { return generalPermissionManagerABI; diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 6725f3529..e4a62891a 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1,5 +1,6 @@ var readlineSync = require('readline-sync'); var chalk = require('chalk'); +var moment = require('moment'); var common = require('./common/common_functions'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); @@ -188,12 +189,9 @@ async function configExistingModules(tmModules) { await generalTransferManager(); break; case 'ManualApprovalTransferManager': - //await manualApprovalTransferManager(); - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); + currentTransferManager = new web3.eth.Contract(abis.manualApprovalTransferManager(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await manualApprovalTransferManager(); break; case 'PercentageTransferManager': //await percentageTransferManager(); @@ -228,20 +226,13 @@ async function configExistingModules(tmModules) { } async function addTransferManagerModule() { - let options = ['GeneralTransferManager'/*, 'ManualApprovalTransferManager', 'PercentageTransferManager', + let options = ['GeneralTransferManager', 'ManualApprovalTransferManager'/*, 'PercentageTransferManager', 'CountTransferManager', 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM'*/]; let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', { cancel: 'Return' }); if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { let bytes = web3.utils.fromAscii('', 16); switch (options[index]) { - case 'ManualApprovalTransferManager': - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); - break; case 'PercentageTransferManager': console.log(chalk.red(` ********************************* @@ -357,9 +348,9 @@ async function generalTransferManager() { options.push('Allow all burn transfers'); } - let index = readlineSync.keyInSelect(options, 'What do you want to do?'); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); + console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); switch (optionSelected) { case 'Modify whitelist': let investor = readlineSync.question('Enter the address to whitelist: ', { @@ -477,6 +468,181 @@ async function generalTransferManager() { } } +async function manualApprovalTransferManager() { + console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + + let options = ['Check manual approval', 'Add manual approval', 'Revoke manual approval', + 'Check manual blocking', 'Add manual blocking', 'Revoke manual blocking']; + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); + let optionSelected = options[index]; + console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + let from; + let to; + switch (optionSelected) { + case 'Check manual approval': + from = readlineSync.question('Enter the address from which transfers would be approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + to = readlineSync.question('Enter the address to which transfers would be approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + console.log(); + let manualApproval = await getManualApproval(from, to); + if (manualApproval) { + console.log(`Manual approval found!`); + console.log(`Allowance: ${web3.utils.fromWei(manualApproval.allowance)}`); + console.log(`Expiry time: ${moment.unix(manualApproval.expiryTime).format('MMMM Do YYYY, HH:mm:ss')};`) + } else { + console.log(chalk.yellow(`There are no manual approvals from ${from} to ${to}.`)); + } + break; + case 'Add manual approval': + from = readlineSync.question('Enter the address from which transfers will be approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + to = readlineSync.question('Enter the address to which transfers will be approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + if (!await getManualApproval(from, to)) { + let allowance = readlineSync.question('Enter the amount of tokens which will be approved: '); + let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); + let expiryTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) until which the transfer is allowed (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let addManualApprovalAction = currentTransferManager.methods.addManualApproval(from, to, web3.utils.toWei(allowance), expiryTime); + let addManualApprovalReceipt = await common.sendTransaction(addManualApprovalAction); + let addManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualApprovalReceipt.logs, 'AddManualApproval'); + console.log(chalk.green(`Manual approval has been added successfully!`)); + } else { + console.log(chalk.red(`A manual approval already exists from ${from} to ${to}. Revoke it first if you want to add a new one.`)); + } + break; + case 'Revoke manual approval': + from = readlineSync.question('Enter the address from which transfers were approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + to = readlineSync.question('Enter the address to which transfers were approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + if (await getManualApproval(from, to)) { + let revokeManualApprovalAction = currentTransferManager.methods.revokeManualApproval(from, to); + let revokeManualApprovalReceipt = await common.sendTransaction(revokeManualApprovalAction); + let revokeManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, revokeManualApprovalReceipt.logs, 'RevokeManualApproval'); + console.log(chalk.green(`Manual approval has been revoked successfully!`)); + } else { + console.log(chalk.red(`Manual approval from ${from} to ${to} does not exist.`)); + } + break; + case 'Check manual blocking': + from = readlineSync.question('Enter the address from which transfers would be blocked: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + to = readlineSync.question('Enter the address to which transfers would be blocked: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + console.log(); + let manualBlocking = await getManualBlocking(from, to); + if (manualBlocking) { + console.log(`Manual blocking found!`); + console.log(`Expiry time: ${moment.unix(manualBlocking).format('MMMM Do YYYY, HH:mm:ss')};`) + } else { + console.log(chalk.yellow(`There are no manual blockings from ${from} to ${to}.`)); + } + break; + case 'Add manual blocking': + from = readlineSync.question('Enter the address from which transfers will be blocked: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + to = readlineSync.question('Enter the address to which transfers will be blocked: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + if (!await getManualBlocking(from, to)) { + let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); + let expiryTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) until which the transfer is blocked (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let addManualBlockingAction = currentTransferManager.methods.addManualBlocking(from, to, expiryTime); + let addManualBlockingReceipt = await common.sendTransaction(addManualBlockingAction); + let addManualBlockingEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualBlockingReceipt.logs, 'AddManualBlocking'); + console.log(chalk.green(`Manual blocking has been added successfully!`)); + } else { + console.log(chalk.red(`A manual blocking already exists from ${from} to ${to}. Revoke it first if you want to add a new one.`)); + } + break; + case 'Revoke manual blocking': + from = readlineSync.question('Enter the address from which transfers were blocked: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + to = readlineSync.question('Enter the address to which transfers were blocked: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + if (await getManualBlocking(from, to)) { + let revokeManualBlockingAction = currentTransferManager.methods.revokeManualBlocking(from, to); + let revokeManualBlockingReceipt = await common.sendTransaction(revokeManualBlockingAction); + let revokeManualBlockingEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, revokeManualBlockingReceipt.logs, 'RevokeManualBlocking'); + console.log(chalk.green(`Manual blocking has been revoked successfully!`)); + } else { + console.log(chalk.red(`Manual blocking from ${from} to ${to} does not exist.`)); + } + break; + } +} + +async function getManualApproval(_from, _to) { + let result = null; + + let manualApproval = await currentTransferManager.methods.manualApprovals(_from, _to).call(); + if (manualApproval.expiryTime !== "0") { + result = manualApproval; + } + + return result; +} + +async function getManualBlocking(_from, _to) { + let result = null; + + let manualBlocking = await currentTransferManager.methods.manualBlockings(_from, _to).call(); + if (manualBlocking !== "0") { + result = manualBlocking; + } + + return result; +} + async function singleTradeVolumeRestrictionTM() { console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address}`)); console.log(); @@ -511,9 +677,9 @@ async function singleTradeVolumeRestrictionTM() { 'Set tokens transfer limit per account', 'Remove tokens transfer limit per account'); } - let index = readlineSync.keyInSelect(options, 'What do you want to do?'); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Cancel', '\n'); + console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); switch (optionSelected) { case 'Allow primary issuance': case 'Disallow primary issuance': From 8c2b1408be7f22a258dba8f247be9a614fe4ca52 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 27 Nov 2018 22:03:25 +0200 Subject: [PATCH 226/582] get rid of updateAll function --- .../modules/Wallet/VestingEscrowWallet.sol | 101 ++++++++---------- test/z_vesting_escrow_wallet.js | 54 ++++------ 2 files changed, 65 insertions(+), 90 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index e5226dda0..275d12e96 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -15,8 +15,7 @@ contract VestingEscrowWallet is IWallet { struct Schedule { uint256 numberOfTokens; - uint256 releasedTokens; - uint256 availableTokens; + uint256 claimedTokens; uint256 duration; uint256 frequency; uint256 startTime; @@ -200,7 +199,7 @@ contract VestingEscrowWallet is IWallet { if (schedules[_beneficiary].length == 0) { beneficiaries.push(_beneficiary); } - schedules[_beneficiary].push(Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime)); + schedules[_beneficiary].push(Schedule(_numberOfTokens, 0, _duration, _frequency, _startTime)); uint256 index = schedules[_beneficiary].length - 1; emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime, index); } @@ -267,7 +266,7 @@ contract VestingEscrowWallet is IWallet { } unassignedTokens = unassignedTokens.sub(_numberOfTokens.sub(schedule.numberOfTokens)); } - schedules[_beneficiary][_index] = Schedule(_numberOfTokens, 0, 0, _duration, _frequency, _startTime); + schedules[_beneficiary][_index] = Schedule(_numberOfTokens, 0, _duration, _frequency, _startTime); emit ModifySchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); } @@ -279,9 +278,10 @@ contract VestingEscrowWallet is IWallet { function revokeSchedule(address _beneficiary, uint256 _index) external withPerm(ADMIN) { require(_beneficiary != address(0), "Invalid address"); require(_index < schedules[_beneficiary].length, "Schedule not found"); - _sendTokens(_beneficiary); + _sendTokens(_beneficiary, _index); Schedule[] storage userSchedules = schedules[_beneficiary]; - unassignedTokens = unassignedTokens.add(userSchedules[_index].numberOfTokens.sub(userSchedules[_index].releasedTokens)); + uint256 releasedTokens = _getReleasedTokens(_beneficiary, _index); + unassignedTokens = unassignedTokens.add(userSchedules[_index].numberOfTokens.sub(releasedTokens)); if (_index != userSchedules.length - 1) { userSchedules[_index] = userSchedules[userSchedules.length - 1]; } @@ -302,7 +302,8 @@ contract VestingEscrowWallet is IWallet { _sendTokens(_beneficiary); Schedule[] storage userSchedules = schedules[_beneficiary]; for (uint256 i = 0; i < userSchedules.length; i++) { - unassignedTokens = unassignedTokens.add(userSchedules[i].numberOfTokens.sub(userSchedules[i].releasedTokens)); + uint256 releasedTokens = _getReleasedTokens(_beneficiary, i); + unassignedTokens = unassignedTokens.add(userSchedules[i].numberOfTokens.sub(releasedTokens)); } userSchedules.length = 0; emit RevokeAllSchedules(_beneficiary); @@ -348,18 +349,26 @@ contract VestingEscrowWallet is IWallet { return schedules[_beneficiary].length; } - /** - * @notice Returns available tokens for beneficiary - * @param _beneficiary beneficiary's address - * @return available tokens for beneficiary - */ - function getAvailableTokens(address _beneficiary) public view returns(uint256) { - require(_beneficiary != address(0)); - uint256 availableTokens; - for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { - availableTokens = availableTokens.add(schedules[_beneficiary][i].availableTokens); + function _getAvailableTokens(address _beneficiary, uint256 _index) internal view returns(uint256) { + Schedule storage schedule = schedules[_beneficiary][_index]; + uint256 releasedTokens = _getReleasedTokens(_beneficiary, _index); + return releasedTokens.sub(schedule.claimedTokens); + } + + function _getReleasedTokens(address _beneficiary, uint256 _index) internal view returns(uint256) { + Schedule storage schedule = schedules[_beneficiary][_index]; + /*solium-disable-next-line security/no-block-members*/ + if (now > schedule.startTime) { + uint256 periodCount = schedule.duration.div(schedule.frequency); + /*solium-disable-next-line security/no-block-members*/ + uint256 periodNumber = (now.sub(schedule.startTime)).div(schedule.frequency); + if (periodNumber > periodCount) { + periodNumber = periodCount; + } + return schedule.numberOfTokens.mul(periodNumber).div(periodCount); + } else { + return 0; } - return availableTokens; } /** @@ -377,16 +386,15 @@ contract VestingEscrowWallet is IWallet { * @notice Used to remove beneficiaries without schedules */ function trimBeneficiaries() external withPerm(ADMIN) { - //TODO commented because of contract size -// for (uint256 i = 0; i < beneficiaries.length; i++) { -// if (schedules[beneficiaries[i]].length == 0) { -// delete schedules[beneficiaries[i]]; -// if (i != beneficiaries.length - 1) { -// beneficiaries[i] = beneficiaries[beneficiaries.length - 1]; -// } -// beneficiaries.length--; -// } -// } + for (uint256 i = 0; i < beneficiaries.length; i++) { + if (schedules[beneficiaries[i]].length == 0) { + delete schedules[beneficiaries[i]]; + if (i != beneficiaries.length - 1) { + beneficiaries[i] = beneficiaries[beneficiaries.length - 1]; + } + beneficiaries.length--; + } + } } /** @@ -483,38 +491,17 @@ contract VestingEscrowWallet is IWallet { } function _sendTokens(address _beneficiary) internal { - uint256 amount = getAvailableTokens(_beneficiary); - if (amount > 0) { - for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { - schedules[_beneficiary][i].availableTokens = 0; - } - ISecurityToken(securityToken).transfer(_beneficiary, amount); - emit SendTokens(_beneficiary, amount); + for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { + _sendTokens(_beneficiary, i); } } - /** - * @notice manually triggers update outside for all schedules (can be used to reduce user gas costs) - */ - function updateAll() external withPerm(ADMIN) { - for (uint256 i = 0; i < beneficiaries.length; i++) { - Schedule[] storage data = schedules[beneficiaries[i]]; - for (uint256 j = 0; j < data.length; j++) { - Schedule storage schedule = data[j]; - if (schedule.releasedTokens < schedule.numberOfTokens) { - uint256 periodCount = schedule.duration.div(schedule.frequency); - /*solium-disable-next-line security/no-block-members*/ - uint256 periodNumber = (now.sub(schedule.startTime)).div(schedule.frequency); - if (periodNumber > periodCount) { - periodNumber = periodCount; - } - uint256 releasedTokens = schedule.numberOfTokens.mul(periodNumber).div(periodCount); - if (schedule.releasedTokens < releasedTokens) { - schedule.availableTokens = schedule.availableTokens.add(releasedTokens.sub(schedule.releasedTokens)); - schedule.releasedTokens = releasedTokens; - } - } - } + function _sendTokens(address _beneficiary, uint256 _index) internal { + uint256 amount = _getAvailableTokens(_beneficiary, _index); + if (amount > 0) { + schedules[_beneficiary][_index].claimedTokens = schedules[_beneficiary][_index].claimedTokens.add(amount); + ISecurityToken(securityToken).transfer(_beneficiary, amount); + emit SendTokens(_beneficiary, amount); } } diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 6bebcff8e..6c629628e 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -331,19 +331,12 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency); - await I_VestingEscrowWallet.updateAll({from: wallet_admin}); await catchRevert( I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: account_beneficiary1}) ); }); - it("Should not be able update all schedules -- fail because of permissions check", async () => { - await catchRevert( - I_VestingEscrowWallet.updateAll({from: account_beneficiary1}) - ); - }); - it("Should push available tokens to the beneficiary address", async () => { let numberOfTokens = 75000; const tx = await I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: wallet_admin}); @@ -380,7 +373,6 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency * 3); - await I_VestingEscrowWallet.updateAll({from: wallet_admin}); const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); @@ -428,24 +420,26 @@ contract('VestingEscrowWallet', accounts => { } let stepCount = 6; await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); - await I_VestingEscrowWallet.updateAll({from: wallet_admin}); let numberOfTokens = 100000 + (30000 / 6 * stepCount) + (2000 / 10 * stepCount); const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); - assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), 100000); + assert.equal(tx.logs[1].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[1].args._numberOfTokens.toNumber(), 30000 / 6 * stepCount); + assert.equal(tx.logs[2].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[2].args._numberOfTokens.toNumber(), 2000 / 10 * stepCount); let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens); stepCount = 4; await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); - await I_VestingEscrowWallet.updateAll({from: wallet_admin}); - numberOfTokens = (2000 / 10 * stepCount); const tx2 = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); assert.equal(tx2.logs[0].args._beneficiary, account_beneficiary3); - assert.equal(tx2.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + assert.equal(tx2.logs[0].args._numberOfTokens.toNumber(), 2000 / 10 * stepCount); balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), totalNumberOfTokens); @@ -528,12 +522,6 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should fail to get available tokens -- fail because address is invalid", async () => { - await catchRevert( - I_VestingEscrowWallet.getAvailableTokens(0) - ); - }); - it("Should not be able to add schedule -- fail because of permissions check", async () => { let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; @@ -583,6 +571,10 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_admin}); + + + + await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); @@ -612,7 +604,7 @@ contract('VestingEscrowWallet', accounts => { checkScheduleLog(tx.logs[0], account_beneficiary1, numberOfTokens, duration, frequency, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); - assert.equal(scheduleCount, 1); + assert.equal(scheduleCount.toNumber(), 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); @@ -759,29 +751,27 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + durationUtil.seconds(100); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); } - let stepCount = 6; + let stepCount = 3; await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); - await I_VestingEscrowWallet.updateAll({from: wallet_admin}); - let numberOfTokens = 100000 + (30000 / 6 * stepCount) + (2000 / 10 * stepCount); const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary3, 0, {from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); - assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), 100000 / 4 * stepCount); let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); - assert.equal(balance.toNumber(), numberOfTokens); + assert.equal(balance.toNumber(), 100000 / 4 * stepCount); - stepCount = 4; - await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); - await I_VestingEscrowWallet.updateAll({from: wallet_admin}); + stepCount = 7; + await increaseTime(durationUtil.minutes(stepCount)); - numberOfTokens = (2000 / 10 * stepCount); const tx2 = await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); assert.equal(tx2.logs[0].args._beneficiary, account_beneficiary3); - assert.equal(tx2.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); + assert.equal(tx2.logs[0].args._numberOfTokens.toNumber(), 2000); + assert.equal(tx2.logs[1].args._beneficiary, account_beneficiary3); + assert.equal(tx2.logs[1].args._numberOfTokens.toNumber(), 30000); balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); - assert.equal(balance.toNumber(), totalNumberOfTokens); + assert.equal(balance.toNumber(), totalNumberOfTokens - 100000 / 4); await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); @@ -992,8 +982,6 @@ contract('VestingEscrowWallet', accounts => { }); it("Should send available tokens to the beneficiaries addresses", async () => { - await I_VestingEscrowWallet.updateAll({from: wallet_admin}); - const tx = await I_VestingEscrowWallet.pushAvailableTokensMulti(beneficiaries, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { From cc933303d580c53f4bcf1209c94e8801393fd9fc Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 28 Nov 2018 11:32:32 +0530 Subject: [PATCH 227/582] Rate changed --- contracts/modules/STO/CappedSTO.sol | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 60373ae37..0d79d285c 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -13,7 +13,8 @@ contract CappedSTO is ISTO, ReentrancyGuard { // Determine whether users can invest on behalf of a beneficiary bool public allowBeneficialInvestments = false; - // How many token units a buyer gets per wei / base unit of POLY + // How many token units multiplied by 10^18 a buyer gets per wei / base unit of POLY + // If rate is 10^18, buyer will get 1 token unit for every wei / base unit of poly. uint256 public rate; //How many tokens this STO will be allowed to sell to investors uint256 public cap; @@ -49,7 +50,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @param _startTime Unix timestamp at which offering get started * @param _endTime Unix timestamp at which offering get ended * @param _cap Maximum No. of tokens for sale - * @param _rate Token units a buyer gets per wei / base unit of POLY + * @param _rate Token units multiplied by 10^18 a buyer gets per wei / base unit of POLY * @param _fundRaiseTypes Type of currency used to collect the funds * @param _fundsReceiver Ethereum account address to hold the funds */ @@ -154,6 +155,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @return Unixtimestamp at which offering gets start. * @return Unixtimestamp at which offering ends. * @return Number of tokens this STO will be allowed to sell to investors. + * @return Token units multiplied by 10^18 a buyer gets per wei / base unit of POLY * @return Amount of funds raised * @return Number of individual investors this STO have. * @return Amount of tokens get sold. @@ -259,8 +261,10 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @param _investedAmount Value in wei to be converted into tokens * @return Number of tokens that can be purchased with the specified _investedAmount */ - function _getTokenAmount(uint256 _investedAmount) internal view returns (uint256) { - return _investedAmount.mul(rate); + function _getTokenAmount(uint256 _investedAmount) internal view returns (uint256 tokenAmount) { + tokenAmount = _investedAmount.mul(rate); + tokenAmount = tokenAmount.div(uint256(10) ** 18); + return tokenAmount; } /** From 39c38f0056361eb1af299722af5e7d2fa499f842 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 28 Nov 2018 11:32:47 +0530 Subject: [PATCH 228/582] changelog updated --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db3d8dcde..dc15e692e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file. [__2.1.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-09-18__ +# CappedSTO 2.0.1 +* `rate` is now accepted as multiplied by 10^18 to allow settting higher price than 1ETH/POLY per token. + # USDTieredSTO 2.0.1 * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. * Added `getSTODetails` to USDTSTO. From 236cd179fbd68706a80e77b0900f43c0da35d987 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 28 Nov 2018 11:36:59 +0530 Subject: [PATCH 229/582] Updated tests for rate changes --- test/b_capped_sto.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index fce1ee5e5..539d91b26 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -86,7 +86,7 @@ contract("CappedSTO", accounts => { let startTime_ETH2; let endTime_ETH2; const cap = web3.utils.toWei("10000"); - const rate = 1000; + const rate = web3.utils.toWei("1000"); const E_fundRaiseType = 0; const address_zero = "0x0000000000000000000000000000000000000000"; @@ -97,7 +97,7 @@ contract("CappedSTO", accounts => { let blockNo; const P_cap = web3.utils.toWei("50000"); const P_fundRaiseType = 1; - const P_rate = 5; + const P_rate = web3.utils.toWei("5"); const cappedSTOSetupCost = web3.utils.toWei("20000", "ether"); const maxCost = cappedSTOSetupCost; const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; @@ -298,7 +298,7 @@ contract("CappedSTO", accounts => { assert.equal(await I_CappedSTO_Array_ETH[0].startTime.call(), startTime_ETH1, "STO Configuration doesn't set as expected"); assert.equal(await I_CappedSTO_Array_ETH[0].endTime.call(), endTime_ETH1, "STO Configuration doesn't set as expected"); assert.equal((await I_CappedSTO_Array_ETH[0].cap.call()).toNumber(), cap, "STO Configuration doesn't set as expected"); - assert.equal(await I_CappedSTO_Array_ETH[0].rate.call(), rate, "STO Configuration doesn't set as expected"); + assert.equal((await I_CappedSTO_Array_ETH[0].rate.call()).toNumber(), rate, "STO Configuration doesn't set as expected"); assert.equal( await I_CappedSTO_Array_ETH[0].fundRaiseTypes.call(E_fundRaiseType), true, @@ -554,7 +554,7 @@ contract("CappedSTO", accounts => { assert.equal(await I_CappedSTO_Array_ETH[1].startTime.call(), startTime_ETH2, "STO Configuration doesn't set as expected"); assert.equal(await I_CappedSTO_Array_ETH[1].endTime.call(), endTime_ETH2, "STO Configuration doesn't set as expected"); assert.equal((await I_CappedSTO_Array_ETH[1].cap.call()).toNumber(), cap, "STO Configuration doesn't set as expected"); - assert.equal(await I_CappedSTO_Array_ETH[1].rate.call(), rate, "STO Configuration doesn't set as expected"); + assert.equal((await I_CappedSTO_Array_ETH[1].rate.call()).toNumber(), rate, "STO Configuration doesn't set as expected"); assert.equal( await I_CappedSTO_Array_ETH[1].fundRaiseTypes.call(E_fundRaiseType), true, @@ -993,8 +993,8 @@ contract("CappedSTO", accounts => { it("Should successfully invest in second STO", async () => { const polyToInvest = 1000; - const stToReceive = polyToInvest * P_rate; - + const stToReceive = (polyToInvest * P_rate)/Math.pow(10, 18); + await I_PolyToken.getTokens(polyToInvest * Math.pow(10, 18), account_investor3); let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, true, { From 0afae263ff0b7099d29ce4b47c180517301246b1 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 28 Nov 2018 11:44:00 +0530 Subject: [PATCH 230/582] VRTM moved from experimental to usable TM list --- CHANGELOG.md | 9 ++++++++- .../TransferManager/VolumeRestrictionTM.sol | 4 ++-- .../VolumeRestrictionTMFactory.sol | 2 +- migrations/2_deploy_contracts.js | 15 +++++++++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) rename contracts/modules/{Experimental => }/TransferManager/VolumeRestrictionTM.sol (99%) rename contracts/modules/{Experimental => }/TransferManager/VolumeRestrictionTMFactory.sol (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index db3d8dcde..aa7d6c60c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. [__2.1.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-09-18__ -# USDTieredSTO 2.0.1 +## USDTieredSTO 2.0.1 * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. * Added `getSTODetails` to USDTSTO. * Added an Array of Tiers that will hold data about every tier in USDTSTO. @@ -13,9 +13,16 @@ All notable changes to this project will be documented in this file. * Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. * Removed individual mappings for tier data removed in UDSTSTO. +## Experimental modules +* Remove the `SingleTradeVolumeRestrictionTMFactory.sol` and its corresponding module `SingleTradeVolumeRestrictionTM.sol`. + ##Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. +## Added +* Add new module called `VolumeRestrictionTM.sol` under the TransferManager modules list. It will be used to restrict the token +volume traded in a given rolling period. + # v1.5.0 [__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol similarity index 99% rename from contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol rename to contracts/modules/TransferManager/VolumeRestrictionTM.sol index 2431b2045..1ccb525be 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -1,8 +1,8 @@ pragma solidity ^0.4.24; -import "../../TransferManager/ITransferManager.sol"; +import "./ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../../../libraries/BokkyPooBahsDateTimeLibrary.sol"; +import "../../libraries/BokkyPooBahsDateTimeLibrary.sol"; contract VolumeRestrictionTM is ITransferManager { diff --git a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol similarity index 98% rename from contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol rename to contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol index 4609ea2ff..03d6e89fc 100644 --- a/contracts/modules/Experimental/TransferManager/VolumeRestrictionTMFactory.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "./VolumeRestrictionTM.sol"; -import "../../ModuleFactory.sol"; +import "../ModuleFactory.sol"; /** * @title Factory for deploying VolumeRestrictionTM module diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 694fdf03e..b28be4c92 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -13,6 +13,7 @@ const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol') const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol') const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol') const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol') +const VolumeRestrictionTMFactory = artifacts.require('./VolumeRestrictionTMFactory.sol') const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') const STFactory = artifacts.require('./tokens/STFactory.sol') const DevPolyToken = artifacts.require('./helpers/PolyTokenFaucet.sol') @@ -169,6 +170,10 @@ module.exports = function (deployer, network, accounts) { // D) Deploy the ERC20DividendCheckpointFactory Contract (Factory used to generate the ERC20DividendCheckpoint contract use // to provide the functionality of the dividend in terms of ERC20 token) return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // D) Deploy the VolumeRestrictionTMFactory Contract (Factory used to generate the VolumeRestrictionTM contract use + // to provide the functionality of restricting the token volume) + return deployer.deploy(VolumeRestrictionTMFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // D) Deploy the ManualApprovalTransferManagerFactory Contract (Factory used to generate the ManualApprovalTransferManager contract use // to manual approve the transfer that will overcome the other transfer restrictions) @@ -216,6 +221,10 @@ module.exports = function (deployer, network, accounts) { // E) Register the GeneralPermissionManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the GeneralPermissionManager contract. return moduleRegistry.registerModule(EtherDividendCheckpointFactory.address, {from: PolymathAccount}); + }).then(() => { + // D) Register the VolumeRestrictionTMFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the VolumeRestrictionTM contract. + return moduleRegistry.registerModule(VolumeRestrictionTMFactory.address, {from: PolymathAccount}); }).then(() => { // D) Register the ManualApprovalTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the ManualApprovalTransferManager contract. @@ -254,6 +263,11 @@ module.exports = function (deployer, network, accounts) { // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(ERC20DividendCheckpointFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // G) Once the VolumeRestrictionTMFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(VolumeRestrictionTMFactory.address, true, {from: PolymathAccount}); }).then(() => { // G) Once the ManualApprovalTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. @@ -315,6 +329,7 @@ module.exports = function (deployer, network, accounts) { ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} + VolumeRestrictionTMFactory: ${VolumeRestrictionTMFactory.address} --------------------------------------------------------------------------------- `); console.log('\n'); From e29027b4b58aa46ed19257cd50652f1a6bcf11c4 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 28 Nov 2018 11:44:28 +0530 Subject: [PATCH 231/582] remove the STVRTM --- .../SingleTradeVolumeRestrictionTM.sol | 331 -------- .../SingleTradeVolumeRestrictionTMFactory.sol | 79 -- test/helpers/createInstances.js | 14 - ...ckpoints.js => x_scheduled_checkpoints.js} | 0 test/x_single_trade_volume_restriction.js | 726 ------------------ ...ction_tm.js => y_volume_restriction_tm.js} | 0 6 files changed, 1150 deletions(-) delete mode 100644 contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol delete mode 100644 contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol rename test/{y_scheduled_checkpoints.js => x_scheduled_checkpoints.js} (100%) delete mode 100644 test/x_single_trade_volume_restriction.js rename test/{z_volume_restriction_tm.js => y_volume_restriction_tm.js} (100%) diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol deleted file mode 100644 index b92272167..000000000 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol +++ /dev/null @@ -1,331 +0,0 @@ -pragma solidity ^0.4.24; - -import "./../../TransferManager/ITransferManager.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -/** - * @title Transfer Manager for limiting volume of tokens in a single trade - */ - -contract SingleTradeVolumeRestrictionTM is ITransferManager { - using SafeMath for uint256; - - bytes32 constant public ADMIN = "ADMIN"; - - bool public isTransferLimitInPercentage; - - uint256 public globalTransferLimitInTokens; - - // should be multipled by 10^16. if the transfer percentage is 20%, then globalTransferLimitInPercentage should be 20*10^16 - uint256 public globalTransferLimitInPercentage; - - // Ignore transactions which are part of the primary issuance - bool public allowPrimaryIssuance = true; - - //mapping to store the wallets that are exempted from the volume restriction - mapping(address => bool) public exemptWallets; - - //addresses on this list have special transfer restrictions apart from global - mapping(address => uint) public specialTransferLimitsInTokens; - - mapping(address => uint) public specialTransferLimitsInPercentages; - - event ExemptWalletAdded(address _wallet); - event ExemptWalletRemoved(address _wallet); - event TransferLimitInTokensSet(address _wallet, uint256 _amount); - event TransferLimitInPercentageSet(address _wallet, uint _percentage); - event TransferLimitInPercentageRemoved(address _wallet); - event TransferLimitInTokensRemoved(address _wallet); - event GlobalTransferLimitInTokensSet(uint256 _amount, uint256 _oldAmount); - event GlobalTransferLimitInPercentageSet(uint256 _percentage, uint256 _oldPercentage); - event TransferLimitChangedToTokens(); - event TransferLimitChangedtoPercentage(); - event SetAllowPrimaryIssuance(bool _allowPrimaryIssuance, uint256 _timestamp); - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor(address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) - { - - } - - /** @notice Used to verify the transfer transaction and prevent an account from sending more tokens than allowed in a single transfer - * @param _from Address of the sender - * @param _amount The amount of tokens to transfer - */ - function verifyTransfer( - address _from, - address /* _to */, - uint256 _amount, - bytes /* _data */, - bool /* _isTransfer */ - ) - public - returns(Result) - { - bool validTransfer; - - if (exemptWallets[_from] || paused) return Result.NA; - - if (_from == address(0) && allowPrimaryIssuance) { - return Result.NA; - } - - if (isTransferLimitInPercentage) { - if(specialTransferLimitsInPercentages[_from] > 0) { - validTransfer = (_amount.mul(10**18).div(ISecurityToken(securityToken).totalSupply())) <= specialTransferLimitsInPercentages[_from]; - } else { - validTransfer = (_amount.mul(10**18).div(ISecurityToken(securityToken).totalSupply())) <= globalTransferLimitInPercentage; - } - } else { - if (specialTransferLimitsInTokens[_from] > 0) { - validTransfer = _amount <= specialTransferLimitsInTokens[_from]; - } else { - validTransfer = _amount <= globalTransferLimitInTokens; - } - } - if (validTransfer) return Result.NA; - return Result.INVALID; - } - - /** - * @notice Used to intialize the variables of the contract - * @param _isTransferLimitInPercentage true if the transfer limit is in percentage else false - * @param _globalTransferLimitInPercentageOrToken transfer limit per single transaction. - */ - function configure( - bool _isTransferLimitInPercentage, - uint256 _globalTransferLimitInPercentageOrToken, - bool _allowPrimaryIssuance - ) public onlyFactory { - isTransferLimitInPercentage = _isTransferLimitInPercentage; - if (isTransferLimitInPercentage) { - changeGlobalLimitInPercentage(_globalTransferLimitInPercentageOrToken); - } else { - changeGlobalLimitInTokens(_globalTransferLimitInPercentageOrToken); - } - allowPrimaryIssuance = _allowPrimaryIssuance; - } - - /** - * @notice Sets whether or not to consider primary issuance transfers - * @param _allowPrimaryIssuance whether to allow all primary issuance transfers - */ - function setAllowPrimaryIssuance(bool _allowPrimaryIssuance) public withPerm(ADMIN) { - require(_allowPrimaryIssuance != allowPrimaryIssuance, "Must change setting"); - allowPrimaryIssuance = _allowPrimaryIssuance; - /*solium-disable-next-line security/no-block-members*/ - emit SetAllowPrimaryIssuance(_allowPrimaryIssuance, now); - } - - /** - * @notice Changes the manager to use transfer limit as Percentages - * @param _newGlobalTransferLimitInPercentage uint256 new global Transfer Limit In Percentage. - * @dev specialTransferLimits set for wallets have to re-configured - */ - function changeTransferLimitToPercentage(uint256 _newGlobalTransferLimitInPercentage) public withPerm(ADMIN) { - require(!isTransferLimitInPercentage, "Transfer limit already in percentage"); - isTransferLimitInPercentage = true; - changeGlobalLimitInPercentage(_newGlobalTransferLimitInPercentage); - emit TransferLimitChangedtoPercentage(); - } - - /** - * @notice Changes the manager to use transfer limit as tokens - * @param _newGlobalTransferLimit uint256 new global Transfer Limit in tokens. - * @dev specialTransferLimits set for wallets have to re-configured - */ - function changeTransferLimitToTokens(uint _newGlobalTransferLimit) public withPerm(ADMIN) { - require(isTransferLimitInPercentage, "Transfer limit already in tokens"); - isTransferLimitInPercentage = false; - changeGlobalLimitInTokens(_newGlobalTransferLimit); - emit TransferLimitChangedToTokens(); - } - /** - * @notice Changes the global transfer limit - * @param _newGlobalTransferLimitInTokens new transfer limit in tokens - * @dev This function can be used only when The manager is configured to use limits in tokens - */ - function changeGlobalLimitInTokens(uint256 _newGlobalTransferLimitInTokens) public withPerm(ADMIN) { - require(!isTransferLimitInPercentage, "Transfer limit not set in tokens"); - require(_newGlobalTransferLimitInTokens > 0, "Transfer limit has to greater than zero"); - emit GlobalTransferLimitInTokensSet(_newGlobalTransferLimitInTokens, globalTransferLimitInTokens); - globalTransferLimitInTokens = _newGlobalTransferLimitInTokens; - - } - - /** - * @notice Changes the global transfer limit - * @param _newGlobalTransferLimitInPercentage new transfer limit in percentage. - * Multiply the percentage by 10^16. Eg 22% will be 22*10^16 - * @dev This function can be used only when The manager is configured to use limits in percentage - */ - function changeGlobalLimitInPercentage(uint256 _newGlobalTransferLimitInPercentage) public withPerm(ADMIN) { - require(isTransferLimitInPercentage, "Transfer limit not set in Percentage"); - require(_newGlobalTransferLimitInPercentage > 0 && _newGlobalTransferLimitInPercentage <= 100 * 10 ** 16, "Limit not within [0,100]"); - emit GlobalTransferLimitInPercentageSet(_newGlobalTransferLimitInPercentage, globalTransferLimitInPercentage); - globalTransferLimitInPercentage = _newGlobalTransferLimitInPercentage; - - } - - /** - * @notice Adds an exempt wallet - * @param _wallet exempt wallet address - */ - function addExemptWallet(address _wallet) public withPerm(ADMIN) { - require(_wallet != address(0), "Wallet address cannot be a zero address"); - exemptWallets[_wallet] = true; - emit ExemptWalletAdded(_wallet); - } - - /** - * @notice Removes an exempt wallet - * @param _wallet exempt wallet address - */ - function removeExemptWallet(address _wallet) public withPerm(ADMIN) { - require(_wallet != address(0), "Wallet address cannot be a zero address"); - exemptWallets[_wallet] = false; - emit ExemptWalletRemoved(_wallet); - } - - /** - * @notice Adds an array of exempt wallet - * @param _wallets array of exempt wallet addresses - */ - function addExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - for (uint256 i = 0; i < _wallets.length; i++) { - addExemptWallet(_wallets[i]); - } - } - - /** - * @notice Removes an array of exempt wallet - * @param _wallets array of exempt wallet addresses - */ - function removeExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - for (uint256 i = 0; i < _wallets.length; i++) { - removeExemptWallet(_wallets[i]); - } - } - - /** - * @notice Sets transfer limit per wallet - * @param _wallet wallet address - * @param _transferLimit transfer limit for the wallet in tokens - * @dev the manager has to be configured to use limits in tokens - */ - function setTransferLimitInTokens(address _wallet, uint _transferLimit) public withPerm(ADMIN) { - require(_transferLimit > 0, "Transfer limit has to be greater than 0"); - require(!isTransferLimitInPercentage, "Transfer limit not in token amount"); - specialTransferLimitsInTokens[_wallet] = _transferLimit; - emit TransferLimitInTokensSet(_wallet, _transferLimit); - } - - /** - * @notice Sets transfer limit for a wallet - * @param _wallet wallet address - * @param _transferLimitInPercentage transfer limit for the wallet in percentage. - * Multiply the percentage by 10^16. Eg 22% will be 22*10^16 - * @dev The manager has to be configured to use percentages - */ - function setTransferLimitInPercentage(address _wallet, uint _transferLimitInPercentage) public withPerm(ADMIN) { - require(isTransferLimitInPercentage, "Transfer limit not in percentage"); - require(_transferLimitInPercentage > 0 && _transferLimitInPercentage <= 100 * 10 ** 16, "Transfer limit not in required range"); - specialTransferLimitsInPercentages[_wallet] = _transferLimitInPercentage; - emit TransferLimitInPercentageSet(_wallet, _transferLimitInPercentage); - } - - - /** - * @notice Removes transfer limit set in percentage for a wallet - * @param _wallet wallet address - */ - function removeTransferLimitInPercentage(address _wallet) public withPerm(ADMIN) { - require(specialTransferLimitsInPercentages[_wallet] > 0, "Wallet Address does not have a transfer limit"); - specialTransferLimitsInPercentages[_wallet] = 0; - emit TransferLimitInPercentageRemoved(_wallet); - } - - /** - * @notice Removes transfer limit set in tokens for a wallet - * @param _wallet wallet address - */ - function removeTransferLimitInTokens(address _wallet) public withPerm(ADMIN) { - require(specialTransferLimitsInTokens[_wallet] > 0, "Wallet Address does not have a transfer limit"); - specialTransferLimitsInTokens[_wallet] = 0; - emit TransferLimitInTokensRemoved(_wallet); - } - - /** - * @notice Sets transfer limits for an array of wallet - * @param _wallets array of wallet addresses - * @param _transferLimits array of transfer limits for each wallet in tokens - * @dev The manager has to be configured to use tokens as limit - */ - function setTransferLimitInTokensMulti(address[] _wallets, uint[] _transferLimits) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - require(_wallets.length == _transferLimits.length, "Wallets don't match to transfer limits"); - for (uint256 i = 0; i < _wallets.length; i++ ) { - setTransferLimitInTokens(_wallets[i], _transferLimits[i]); - } - } - - /** - * @notice Sets transfer limits for an array of wallet - * @param _wallets array of wallet addresses - * @param _transferLimitsInPercentage array of transfer limits for each wallet in percentages - * The percentage has to be multipled by 10 ** 16. Eg: 20% would be 20 * 10 ** 16 - * @dev The manager has to be configured to use percentage as limit - */ - function setTransferLimitInPercentageMulti(address[] _wallets, uint[] _transferLimitsInPercentage) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - require(_wallets.length == _transferLimitsInPercentage.length, "Wallets don't match to percentage limits"); - for (uint256 i = 0; i < _wallets.length; i++) { - setTransferLimitInPercentage(_wallets[i], _transferLimitsInPercentage[i]); - } - } - - /** - * @notice Removes transfer limits set in tokens for an array of wallet - * @param _wallets array of wallet addresses - */ - function removeTransferLimitInTokensMulti(address[] _wallets) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - for (uint i = 0; i < _wallets.length; i++) { - removeTransferLimitInTokens(_wallets[i]); - } - } - - /** - * @notice Removes transfer limits set in percentage for an array of wallet - * @param _wallets array of wallet addresses - */ - function removeTransferLimitInPercentageMulti(address[] _wallets) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - for (uint i = 0; i < _wallets.length; i++) { - removeTransferLimitInPercentage(_wallets[i]); - } - } - - /** - * @notice This function returns the signature of configure function - */ - function getInitFunction() public pure returns (bytes4) { - return bytes4(keccak256("configure(bool,uint256,bool)")); - } - - /** - * @notice Returns the permissions flag that are associated with SingleTradeVolumeRestrictionManager - */ - function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](1); - allPermissions[0] = ADMIN; - return allPermissions; - } -} diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol deleted file mode 100644 index e6d8ed2be..000000000 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol +++ /dev/null @@ -1,79 +0,0 @@ -pragma solidity ^0.4.24; - -import "./../../ModuleFactory.sol"; -import "./SingleTradeVolumeRestrictionTM.sol"; -import "../../../libraries/Util.sol"; - -/** - * @title Factory for deploying SingleTradeVolumeRestrictionManager - */ -contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { - - - /** - * @notice Constructor - * @param _polyAddress Address of the polytoken - * @param _setupCost Setup cost of the module - * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module - */ - constructor(address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { - version = "1.0.0"; - name = "SingleTradeVolumeRestrictionTM"; - title = "Single Trade Volume Restriction Manager"; - description = "Imposes volume restriction on a single trade"; - compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - } - - /** - * @notice Used to launch the Module with the help of factory - * @return address Contract address of the Module - */ - function deploy(bytes _data) external returns(address) { - if (setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - SingleTradeVolumeRestrictionTM singleTradeVolumeRestrictionManager = new SingleTradeVolumeRestrictionTM(msg.sender, address(polyToken)); - - require(Util.getSig(_data) == singleTradeVolumeRestrictionManager.getInitFunction(), "Provided data is not valid"); - /*solium-disable-next-line security/no-low-level-calls*/ - require(address(singleTradeVolumeRestrictionManager).call(_data), "Unsuccessful call"); - /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(singleTradeVolumeRestrictionManager), getName(), address(this), msg.sender, setupCost, now); - return address(singleTradeVolumeRestrictionManager); - } - - /** - * @notice Get the types of the Module factory - * @return uint8[] - */ - function getTypes() external view returns(uint8[]) { - uint8[] memory res = new uint8[](1); - res[0] = 2; - return res; - } - - /** - * @notice Get the Instructions that help to use the module - * @return string - */ - function getInstructions() external view returns(string) { - /*solium-disable-next-line max-len*/ - return "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens"; - } - - /** - * @notice Get the tags related to the module factory - * @return bytes32[] - */ - function getTags() external view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](3); - availableTags[0] = "Single Trade"; - availableTags[1] = "Transfer"; - availableTags[2] = "Volume"; - return availableTags; - } - -} diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 2303e7eed..6c130ab9f 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -11,7 +11,6 @@ const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock const ERC20DividendCheckpointFactory = artifacts.require("./ERC20DividendCheckpointFactory.sol"); const EtherDividendCheckpointFactory = artifacts.require("./EtherDividendCheckpointFactory.sol"); const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); -const SingleTradeVolumeRestrictionManagerFactory = artifacts.require('./SingleTradeVolumeRestrictionTMFactory.sol'); const TrackedRedemptionFactory = artifacts.require("./TrackedRedemptionFactory.sol"); const PercentageTransferManagerFactory = artifacts.require("./PercentageTransferManagerFactory.sol"); const ScheduledCheckpointFactory = artifacts.require('./ScheduledCheckpointFactory.sol'); @@ -42,7 +41,6 @@ let I_TrackedRedemptionFactory; let I_ScheduledCheckpointFactory; let I_MockBurnFactory; let I_MockWrongTypeBurnFactory; -let I_SingleTradeVolumeRestrictionManagerFactory; let I_ManualApprovalTransferManagerFactory; let I_VolumeRestrictionTransferManagerFactory; let I_PercentageTransferManagerFactory; @@ -271,18 +269,6 @@ export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyI return new Array(I_VolumeRestrictionTransferManagerFactory); } -export async function deploySingleTradeVolumeRMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); - assert.notEqual( - I_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" - ); - - await registerAndVerifyByMR(I_SingleTradeVolumeRestrictionManagerFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_SingleTradeVolumeRestrictionManagerFactory); -} - export async function deployScheduleCheckpointAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { I_ScheduledCheckpointFactory = await ScheduledCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( diff --git a/test/y_scheduled_checkpoints.js b/test/x_scheduled_checkpoints.js similarity index 100% rename from test/y_scheduled_checkpoints.js rename to test/x_scheduled_checkpoints.js diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js deleted file mode 100644 index 15c01e68c..000000000 --- a/test/x_single_trade_volume_restriction.js +++ /dev/null @@ -1,726 +0,0 @@ -import latestTime from './helpers/latestTime'; -import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeModuleCall } from './helpers/encodeCall'; -import {deploySingleTradeVolumeRMAndVerified, setUpPolymathNetwork } from "./helpers/createInstances"; -import { catchRevert } from "./helpers/exceptions"; - -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionTM'); -const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('SingleTradeVolumeRestrictionManager', accounts => { - - - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_investor5; - let zero_address = '0x0000000000000000000000000000000000000000'; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_SecurityTokenRegistryProxy - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_SingleTradeVolumeRestrictionManagerFactory; - let I_SingleTradeVolumeRestrictionManager; - let P_SingleTradeVolumeRestrictionManagerFactory; - let P_SingleTradeVolumeRestrictionManager; - let I_SingleTradeVolumeRestrictionPercentageManager; - let I_ModuleRegistry; - let I_MRProxied; - let I_ModuleRegistryProxy; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - const STVRParameters = ["bool", "uint256", "bool"]; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - before(async () => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[6]; - account_investor2 = accounts[7]; - account_investor3 = accounts[8]; - account_investor4 = accounts[9]; - account_investor5 = accounts[5]; - - let instances = await setUpPolymathNetwork(account_polymath, token_owner); - - [ - I_PolymathRegistry, - I_PolyToken, - I_FeatureRegistry, - I_ModuleRegistry, - I_ModuleRegistryProxy, - I_MRProxied, - I_GeneralTransferManagerFactory, - I_STFactory, - I_SecurityTokenRegistry, - I_SecurityTokenRegistryProxy, - I_STRProxied - ] = instances; - - // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory - [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); - - }); - - describe("Generate the SecurityToken", async () => { - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { - from: token_owner - }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { - from: token_owner - }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { - from: token_owner - }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { - from: token_owner - }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ - from: _blockNo - }), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - }); - // - describe("Buy tokens using whitelist & manual approvals", async () => { - - it("Should Buy the tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('100', 'ether'), { - from: token_owner - }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('100', 'ether') - ); - }); - - it("Should Buy some more tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { - from: token_owner - }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - // - it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - await catchRevert( - I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { from: token_owner}) - ); - }); - - it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); - - let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { - from: token_owner - }); - - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "SingleTradeVolumeRestrictionManager did not get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestrictionManagerFactory module was not added" - ); - P_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[3].args._module); - }); - - it("Should successfully attach the SingleTradeVolumeRestrictionManager with the security token", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [false, (7 * Math.pow(10, 16)).toString(), false]) - const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { - from: token_owner - }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "TransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestriction module was not added" - ); - I_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); - }); - - it("Should successfully attach the SingleTradeVolumeRestrictionManager (Percentage) with the security token", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { - from: token_owner - }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestriction module was not added" - ); - I_SingleTradeVolumeRestrictionPercentageManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); - }); - - it('should return get permissions', async () => { - let permissions = await I_SingleTradeVolumeRestrictionPercentageManager.getPermissions(); - assert.equal(permissions.length, 1, "Invalid Permissions"); - assert.equal( - web3.utils.toAscii(permissions[0]).replace(/\u0000/g, ''), - "ADMIN", - 'Wrong permissions' - ); - }); - - it("Should allow the primary issuance", async() => { - let snapId = await takeSnapshot(); - await I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}); - await catchRevert( - I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}) - ) - await revertToSnapshot(snapId); - }) - - it("add exempt wallet -- Not authorised ", async () => { - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]) - ); - - await catchRevert( - I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet added as exempt"); - }); - - it("Should remove an exempt wallet", async () => { - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5]) - ); - // 0 address are not allowed to add - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeExemptWallet(zero_address, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { from: token_owner }); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet removed from exempt"); - }); - - it('should set transfer limit for a wallet', async () => { - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100) - ); - - // Transfer limits can't be set to 0 - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 0, { from: token_owner }) - ); - - // Transfer limit cannot be set in percentage - await catchRevert( - I_SingleTradeVolumeRestrictionManager.setTransferLimitInPercentage(accounts[4], 10, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[4]); - assert.equal(tx.logs[0].args._amount, 100); - - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 0, { from: token_owner }) - ); - // Transfer limit can not be set to more 0 - await catchRevert ( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { from: token_owner }) - ); - // Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage - await catchRevert ( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { from: token_owner }) - ); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 50, { from: token_owner }); - assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet added to transfer limits"); - assert.equal(tx.logs[0].args._percentage, 50, "Wrong percentage set"); - }); - - it('should remove transfer limit for wallet', async () => { - // Non Admins cannot set/remove transfer limits - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4]) - ); - - // Non Admins cannot set/remove transfer limits - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[0], { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4], { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet removed"); - }); - - it("Should pause the tranfers at Manager level", async () => { - let tx = await I_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - }); - - it('Should be able to set a global transfer limit', async () => { - // only owner is allowed - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(100 * 10 ** 18) - ); - //Cannot change global limit in percentage when set to tokens - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(100 * 10 ** 18, { from: token_owner }) - ); - // Global limit cannot be set to 0 - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(0, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { - from: token_owner - }); - assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - - //Global limit can be set by non-admins - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89) - ); - // cannot change global limit in tokens if transfer limit is set to percentage - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89, { from: token_owner }) - ); - // Cannot set global limit in tokens to 0 - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(0, { from: token_owner }) - ); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(40, { from: token_owner }); - assert.equal(tx.logs[0].args._percentage, 40, "Global Limit not set"); - // Global limit cannot be set to more than 100 - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(101 * 10 ** 16, { from: token_owner }) - ); - // Global limit in percentage cannot be set when limit is in tokens - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(10, { from: token_owner }) - ); - // Global limit in tokens cannot be set when limit is in percentage - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(10, { from: token_owner }) - ); - }); - - it("Should perform batch updates", async () => { - let wallets = [accounts[0], accounts[1], accounts[2]]; - let tokenLimits = [1, 2, 3]; - let percentageLimits = [5, 6, 7]; - - // Exempt wallet multi cannot be empty wallet - await catchRevert( - P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti([], { from: token_owner }) - ); - - // add exempt wallet multi - let tx = await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { - from: token_owner - }); - let logs = tx.logs.filter(log => log.event === 'ExemptWalletAdded'); - assert.equal(logs.length, wallets.length, "Batch Exempt wallets not added"); - for (let i = 0; i < logs.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); - } - - // Exempt wallet multi cannot be empty wallet - await catchRevert( - P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti([], { from: token_owner }) - ); - - // remove exempt wallet multi - tx = await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { - from: token_owner - }) - logs = tx.logs.filter(log => log.event === 'ExemptWalletRemoved'); - assert.equal(logs.length, wallets.length, "Batch Exempt wallets not removed"); - - for (let i = 0; i < logs.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); - } - // wallets cannot be empty - await catchRevert( - P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([], tokenLimits, { from: token_owner }) - ); - // wallet array length dont match - await catchRevert( - P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([accounts[0]], tokenLimits, { from: token_owner }) - ); - - tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInTokensSet'); - assert.equal(wallets.length, logs.length, "Transfer limit not set"); - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not set for wallet"); - assert.equal(logs[i].args._amount.toNumber(), tokenLimits[i]); - } - // Wallets cannot be empty - await catchRevert( - P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti([], { from: token_owner }) - ); - tx = await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event === 'TransferLimitInTokensRemoved'); - assert.equal(logs.length, wallets.length, "Transfer limit not removed"); - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not removed for wallet"); - } - // wallets cannot be empty - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti([], percentageLimits, { from: token_owner }) - ); - // wallets and amounts dont match be empty - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, [], { from: token_owner }) - ); - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageSet'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - assert.equal(logs[i].args._percentage.toNumber(), percentageLimits[i]); - } - // Wallets cannot be empty - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti([], { from: token_owner }) - ); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageRemoved'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - } - // Wallet should not be removed - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentage(wallets[0], { from: token_owner }) - ); - }) - - it('should be able to transfer tokens SingleTradeVolumeRestriction', async () => { - await I_SingleTradeVolumeRestrictionManager.unpause({ - from: token_owner - }) - await I_SingleTradeVolumeRestrictionPercentageManager.pause({ - from: token_owner - }) - await P_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor4, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor5, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - - //setting a max of 5 tokens - await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(web3.utils.toWei('5', 'ether'), { - from: token_owner - }) - // Transfer should have not happened - await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei('6', 'ether'), { from: account_investor1 }) - ); - - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('4', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('4', 'ether')); - - // exempt wallet - await I_SingleTradeVolumeRestrictionManager.addExemptWallet(account_investor1, { - from: token_owner - }); - await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('7', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toNumber(), web3.utils.toWei('7', 'ether')); - - //special limits wallet - await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(account_investor5, web3.utils.toWei('5', 'ether'), { - from: token_owner - }); - - // Transfer should have not happened - await catchRevert( - I_SecurityToken.transfer(account_investor4, web3.utils.toWei('7', 'ether'), { from: account_investor5 }) - ); - - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('4', 'ether'), { - from: account_investor5 - }) - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei('4', 'ether')) - }) - - it('should be able to transfer tokens (percentage transfer limit)', async () => { - await I_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - let balance = (await I_SecurityToken.balanceOf(account_investor2)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor2 - }); - - - balance = (await I_SecurityToken.balanceOf(account_investor3)).toNumber(); - - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor3 - }); - - - balance = (await I_SecurityToken.balanceOf(account_investor4)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor4 - }); - - balance = (await I_SecurityToken.balanceOf(account_investor5)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor5 - }); - - await I_SingleTradeVolumeRestrictionPercentageManager.unpause({ - from: token_owner - }); - // // - await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(49 * 10 ** 16, { - from: token_owner - }); - - // Transfer above limit happened - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('90', 'ether'), { from: account_investor1 }) - ); - - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('20', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei('20', 'ether')) - - await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(account_investor1, 5 * 10 ** 16, { - from: token_owner - }); - // transfer happened above limit - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('35', 'ether'), { from: account_investor1 }) - ); - - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('1', 'ether')); - }); - - it('should change transfer limits to tokens', async () => { - // Should not change to percentage again - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { from: token_owner }) - ); - - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { - from: token_owner - }); - assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); - assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); - }) - - it('should change transfer limits to percentage', async () => { - // Should not change to tokens again - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeTransferLimitToTokens(1, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { - from: token_owner - }); - assert.ok(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), "Error Changing"); - assert.equal(tx.logs[0].args._percentage.toNumber(), 1, "Transfer limit not changed"); - }) - - - - }); - - describe("SingleTradeVolumeRestrictionManager Factory test cases", async () => { - - it("Should get the exact details of the factory", async () => { - assert.equal(await I_SingleTradeVolumeRestrictionManagerFactory.getSetupCost.call(), 0); - assert.equal((await I_SingleTradeVolumeRestrictionManagerFactory.getTypes.call())[0], 2); - let name = web3.utils.toUtf8(await I_SingleTradeVolumeRestrictionManagerFactory.getName.call()); - assert.equal(name, "SingleTradeVolumeRestrictionTM", "Wrong Module added"); - let desc = await I_SingleTradeVolumeRestrictionManagerFactory.description.call(); - assert.equal(desc, "Imposes volume restriction on a single trade", "Wrong Module added"); - let title = await I_SingleTradeVolumeRestrictionManagerFactory.title.call(); - assert.equal(title, "Single Trade Volume Restriction Manager", "Wrong Module added"); - let inst = await I_SingleTradeVolumeRestrictionManagerFactory.getInstructions.call(); - assert.equal(inst, "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens", "Wrong Module added"); - let version = await I_SingleTradeVolumeRestrictionManagerFactory.version.call(); - assert.equal(version, "1.0.0", "Version not correct"); - }); - - it("Should get the tags of the factory", async () => { - let tags = await I_SingleTradeVolumeRestrictionManagerFactory.getTags.call(); - assert.equal(web3.utils.toUtf8(tags[0]), "Single Trade"); - assert.equal(web3.utils.toUtf8(tags[1]), "Transfer"); - assert.equal(web3.utils.toUtf8(tags[2]), "Volume"); - }); - - - }); -}); diff --git a/test/z_volume_restriction_tm.js b/test/y_volume_restriction_tm.js similarity index 100% rename from test/z_volume_restriction_tm.js rename to test/y_volume_restriction_tm.js From 3cb2ce258fecca500ad09203e38538bc64a84115 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 28 Nov 2018 11:57:33 +0530 Subject: [PATCH 232/582] Issuance test fixed --- test/i_Issuance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/i_Issuance.js b/test/i_Issuance.js index ac1fcdd37..5cef65baf 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -72,7 +72,7 @@ contract("Issuance", accounts => { //let startTime; // Start time will be 5000 seconds more than the latest time //let endTime; // Add 30 days more const cap = web3.utils.toWei("10000"); - const rate = 1000; + const rate = web3.utils.toWei("1000"); const fundRaiseType = [0]; const cappedSTOSetupCost = web3.utils.toWei("20000", "ether"); const maxCost = cappedSTOSetupCost; From f62f9f782f69c931213a01d4c42234cd9d425e4a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 28 Nov 2018 12:39:29 +0530 Subject: [PATCH 233/582] test cases updated --- test/o_security_token.js | 2 +- test/r_concurrent_STO.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/o_security_token.js b/test/o_security_token.js index 52521181e..f475f6ab8 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -93,7 +93,7 @@ contract("SecurityToken", accounts => { let startTime; let endTime; const cap = web3.utils.toWei("10000"); - const rate = 1000; + const rate = web3.utils.toWei("1000"); const fundRaiseType = [0]; const cappedSTOSetupCost = web3.utils.toWei("20000", "ether"); const maxCost = cappedSTOSetupCost; diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 7912658a4..cfe2767af 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -176,7 +176,7 @@ contract("Concurrent STO", accounts => { const startTime = latestTime() + duration.days(1); const endTime = latestTime() + duration.days(90); const cap = web3.utils.toWei("10000"); - const rate = 1000; + const rate = web3.utils.toWei("1000"); const fundRaiseType = [0]; const budget = 0; const maxCost = STOSetupCost; From 0a3999546c262891f123f92ed17524b730648aac Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 28 Nov 2018 13:20:14 +0530 Subject: [PATCH 234/582] bug fixed --- .../BlacklistTransferManager.sol | 18 ++++---- docs/permissions_list.md | 46 ++++++++++++++++++- migrations/2_deploy_contracts.js | 15 ++++++ test/z_blacklist_transfer_manager.js | 2 +- 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 4659baa8a..e4142874f 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -140,7 +140,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _names Name of the blacklist type * @param _repeatPeriodTimes Repeat period of the blacklist type */ - function addBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _names, uint256[] _repeatPeriodTimes) public withPerm(ADMIN) { + function addBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _names, uint256[] _repeatPeriodTimes) external withPerm(ADMIN) { require (_startTimes.length == _endTimes.length && _endTimes.length == _names.length && _names.length == _repeatPeriodTimes.length, "Input array's length mismatch"); for (uint256 i = 0; i < _startTimes.length; i++){ _addBlacklistType(_startTimes[i], _endTimes[i], _names[i], _repeatPeriodTimes[i]); @@ -176,7 +176,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _names Name of the blacklist type * @param _repeatPeriodTimes Repeat period of the blacklist type */ - function modifyBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _names, uint256[] _repeatPeriodTimes) public withPerm(ADMIN) { + function modifyBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _names, uint256[] _repeatPeriodTimes) external withPerm(ADMIN) { require (_startTimes.length == _endTimes.length && _endTimes.length == _names.length && _names.length == _repeatPeriodTimes.length, "Input array's length mismatch"); for (uint256 i = 0; i < _startTimes.length; i++){ modifyBlacklistType(_startTimes[i], _endTimes[i], _names[i], _repeatPeriodTimes[i]); @@ -209,7 +209,7 @@ contract BlacklistTransferManager is ITransferManager { * @notice Used to delete the multiple blacklist type * @param _names Name of the blacklist type */ - function deleteBlacklistTypeMulti(bytes32[] _names) public withPerm(ADMIN) { + function deleteBlacklistTypeMulti(bytes32[] _names) external withPerm(ADMIN) { for(uint256 i = 0; i < _names.length; i++){ deleteBlacklistType(_names[i]); } @@ -221,7 +221,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _blacklistName Name of the blacklist */ function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { - require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); + require(blacklists[_blacklistName].startTime >= now, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); uint256 investorIndex = investorToBlacklist[_investor].length; // Add blacklist index to the investor @@ -239,7 +239,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _investors Address of the investor * @param _blacklistName Name of the blacklist */ - function addInvestorToBlacklistMulti(address[] _investors, bytes32 _blacklistName) public withPerm(ADMIN){ + function addInvestorToBlacklistMulti(address[] _investors, bytes32 _blacklistName) external withPerm(ADMIN){ for(uint256 i = 0; i < _investors.length; i++){ addInvestorToBlacklist(_investors[i], _blacklistName); } @@ -250,7 +250,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _investors Address of the investor * @param _blacklistNames Name of the blacklist */ - function addMultiInvestorToBlacklistMulti(address[] _investors, bytes32[] _blacklistNames) public withPerm(ADMIN){ + function addMultiInvestorToBlacklistMulti(address[] _investors, bytes32[] _blacklistNames) external withPerm(ADMIN){ require (_investors.length == _blacklistNames.length, "Input array's length mismatch"); for(uint256 i = 0; i < _investors.length; i++){ addInvestorToBlacklist(_investors[i], _blacklistNames[i]); @@ -265,7 +265,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _repeatPeriodTime Repeat period of the blacklist type * @param _investor Address of the investor */ - function addInvestorToNewBlacklist(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime, address _investor) public withPerm(ADMIN){ + function addInvestorToNewBlacklist(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime, address _investor) external withPerm(ADMIN){ _addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); addInvestorToBlacklist(_investor, _name); } @@ -286,7 +286,7 @@ contract BlacklistTransferManager is ITransferManager { * @notice Used to delete the multiple investor from all the associated blacklist types * @param _investor Address of the investor */ - function deleteInvestorFromAllBlacklistMulti(address[] _investor) public withPerm(ADMIN) { + function deleteInvestorFromAllBlacklistMulti(address[] _investor) external withPerm(ADMIN) { for(uint256 i = 0; i < _investor.length; i++){ deleteInvestorFromAllBlacklist(_investor[i]); } @@ -329,7 +329,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _investors address of the investor * @param _blacklistNames name of the blacklist */ - function deleteMultiInvestorsFromBlacklistMulti(address[] _investors, bytes32[] _blacklistNames) public withPerm(ADMIN) { + function deleteMultiInvestorsFromBlacklistMulti(address[] _investors, bytes32[] _blacklistNames) external withPerm(ADMIN) { require (_investors.length == _blacklistNames.length, "Input array's length mismatch"); for(uint256 i = 0; i < _investors.length; i++){ deleteInvestorFromBlacklist(_investors[i], _blacklistNames[i]); diff --git a/docs/permissions_list.md b/docs/permissions_list.md index b49c95a0e..f71b99d19 100644 --- a/docs/permissions_list.md +++ b/docs/permissions_list.md @@ -143,7 +143,7 @@ allocateTokensMulti() - TransferManager + TransferManager CountTransferManager changeHolderCount() withPerm(ADMIN) @@ -271,6 +271,50 @@ removeTransferLimitInPercentageMulti + + BlacklistTransferManager + addBlacklistType() + withPerm(ADMIN) + + + addBlacklistTypeMulti() + + + modifyBlacklistType() + + + modifyBlacklistTypeMulti() + + + deleteBlacklistType() + + + deleteBlacklistTypeMulti() + + + addInvestorToBlacklist() + + + addInvestorToBlacklistMulti() + + + addMultiInvestorToBlacklistMulti() + + + addInvestorToNewBlacklist() + + + deleteInvestorFromAllBlacklist() + + + deleteInvestorFromAllBlacklistMulti() + + + deleteInvestorFromBlacklist() + + + deleteMultiInvestorsFromBlacklistMulti() + diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 694fdf03e..4888a34bf 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -6,6 +6,7 @@ const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.s const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') +const BlacklistTransferManagerFactory = artifacts.require('./BlacklistTransferManagerFactory.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol') @@ -157,6 +158,10 @@ module.exports = function (deployer, network, accounts) { // D) Deploy the CountTransferManagerFactory Contract (Factory used to generate the CountTransferManager contract use // to track the counts of the investors of the security token) return deployer.deploy(CountTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // D) Deploy the BlacklistTransferManagerFactory Contract (Factory used to generate the BlacklistTransferManager contract use + // to to automate blacklist and restrict transfers) + return deployer.deploy(BlacklistTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // D) Deploy the PercentageTransferManagerFactory Contract (Factory used to generate the PercentageTransferManager contract use // to track the percentage of investment the investors could do for a particular security token) @@ -208,6 +213,10 @@ module.exports = function (deployer, network, accounts) { // D) Register the GeneralTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the GeneralTransferManager contract. return moduleRegistry.registerModule(GeneralTransferManagerFactory.address, {from: PolymathAccount}); + }).then(() => { + // D) Register the BlacklistTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the GeneralTransferManager contract. + return moduleRegistry.registerModule(BlacklistTransferManagerFactory.address, {from: PolymathAccount}); }).then(() => { // E) Register the GeneralPermissionManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the GeneralPermissionManager contract. @@ -229,6 +238,11 @@ module.exports = function (deployer, network, accounts) { // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(GeneralTransferManagerFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // G) Once the BlacklistTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(BlacklistTransferManagerFactory.address, true, {from: PolymathAccount}); }).then(() => { // G) Once the CountTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. @@ -315,6 +329,7 @@ module.exports = function (deployer, network, accounts) { ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} + BlacklistTransferManagerFactory: ${BlacklistTransferManagerFactory.address} --------------------------------------------------------------------------------- `); console.log('\n'); diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index e50efbd14..a3dbee46d 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -736,7 +736,7 @@ contract('BlacklistTransferManager', accounts => { }); it("Only owner has the permission to delete the investor from all the blacklist type", async() => { - await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "a_blacklist", { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "g_blacklist", { from: token_owner }); await catchRevert( I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: account_investor2 From b416076067d6a6ba3be9d150b465932d5b88e4cf Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 28 Nov 2018 11:21:29 +0200 Subject: [PATCH 235/582] changes in multi-operations --- .../modules/Wallet/VestingEscrowWallet.sol | 96 +++++++++++-------- test/z_vesting_escrow_wallet.js | 84 +++++++++------- 2 files changed, 105 insertions(+), 75 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 275d12e96..a1141977c 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -254,7 +254,7 @@ contract VestingEscrowWallet is IWallet { internal { _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); - require(_index < schedules[_beneficiary].length, "Schedule not found"); + _checkSchedule(_beneficiary, _index); Schedule storage schedule = schedules[_beneficiary][_index]; /*solium-disable-next-line security/no-block-members*/ require(now < schedule.startTime, "Schedule started"); @@ -276,8 +276,7 @@ contract VestingEscrowWallet is IWallet { * @param _index index of the schedule */ function revokeSchedule(address _beneficiary, uint256 _index) external withPerm(ADMIN) { - require(_beneficiary != address(0), "Invalid address"); - require(_index < schedules[_beneficiary].length, "Schedule not found"); + _checkSchedule(_beneficiary, _index); _sendTokens(_beneficiary, _index); Schedule[] storage userSchedules = schedules[_beneficiary]; uint256 releasedTokens = _getReleasedTokens(_beneficiary, _index); @@ -316,8 +315,7 @@ contract VestingEscrowWallet is IWallet { * @return beneficiary's schedule */ function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256, State) { - require(_beneficiary != address(0), "Invalid address"); - require(_index < schedules[_beneficiary].length, "Schedule not found"); + _checkSchedule(_beneficiary, _index); Schedule storage schedule = schedules[_beneficiary][_index]; return ( schedule.numberOfTokens, @@ -371,17 +369,6 @@ contract VestingEscrowWallet is IWallet { } } - /** - * @notice Used to bulk send available tokens for each of beneficiaries - * @param _beneficiaries array of beneficiary's addresses - */ - function pushAvailableTokensMulti(address[] _beneficiaries) external withPerm(ADMIN) { - require(_beneficiaries.length > 1, "Array size should be greater than one"); - for (uint256 i = 0; i < _beneficiaries.length; i++) { - pushAvailableTokens(_beneficiaries[i]); - } - } - /** * @notice Used to remove beneficiaries without schedules */ @@ -397,26 +384,44 @@ contract VestingEscrowWallet is IWallet { } } + /** + * @notice Used to bulk send available tokens for each of beneficiaries + * @param _beneficiaries array of beneficiary's addresses + */ + function pushAvailableTokensMulti(address[] _beneficiaries) external withPerm(ADMIN) { + require(_beneficiaries.length > 1, "Array size should be greater than one"); + for (uint256 i = 0; i < _beneficiaries.length; i++) { + pushAvailableTokens(_beneficiaries[i]); + } + } + /** * @notice Used to bulk add vesting schedules for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses - * @param _numberOfTokens number of tokens - * @param _duration vesting duration - * @param _frequency vesting frequency - * @param _startTime vesting start time + * @param _numberOfTokens array of number of tokens + * @param _durations array of vesting duration + * @param _frequencies array of vesting frequency + * @param _startTimes array of vesting start time */ function addScheduleMulti( address[] _beneficiaries, - uint256 _numberOfTokens, - uint256 _duration, - uint256 _frequency, - uint256 _startTime + uint256[] _numberOfTokens, + uint256[] _durations, + uint256[] _frequencies, + uint256[] _startTimes ) external withPerm(ADMIN) { + require( + _beneficiaries.length == _numberOfTokens.length && /*solium-disable-line operator-whitespace*/ + _beneficiaries.length == _durations.length && /*solium-disable-line operator-whitespace*/ + _beneficiaries.length == _frequencies.length && /*solium-disable-line operator-whitespace*/ + _beneficiaries.length == _startTimes.length, + "Arrays sizes mismatch" + ); for (uint256 i = 0; i < _beneficiaries.length; i++) { - _addSchedule(_beneficiaries[i], _numberOfTokens, _duration, _frequency, _startTime); + _addSchedule(_beneficiaries[i], _numberOfTokens[i], _durations[i], _frequencies[i], _startTimes[i]); } } @@ -424,11 +429,12 @@ contract VestingEscrowWallet is IWallet { * @notice Used to bulk add vesting schedules from template for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses * @param _index index of the template - * @param _startTime vesting start time + * @param _startTimes array of vesting start time */ - function addScheduleFromTemplateMulti(address[] _beneficiaries, uint256 _index, uint256 _startTime) external withPerm(ADMIN) { + function addScheduleFromTemplateMulti(address[] _beneficiaries, uint256 _index, uint256[] _startTimes) external withPerm(ADMIN) { + require(_beneficiaries.length == _startTimes.length, "Arrays sizes mismatch"); for (uint256 i = 0; i < _beneficiaries.length; i++) { - _addScheduleFromTemplate(_beneficiaries[i], _index, _startTime); + _addScheduleFromTemplate(_beneficiaries[i], _index, _startTimes[i]); } } @@ -446,25 +452,32 @@ contract VestingEscrowWallet is IWallet { * @notice Used to bulk modify vesting schedules for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses * @param _indexes array of beneficiary's indexes of schedule - * @param _numberOfTokens number of tokens - * @param _duration vesting duration - * @param _frequency vesting frequency - * @param _startTime vesting start time + * @param _numberOfTokens array of number of tokens + * @param _durations array of vesting duration + * @param _frequencies array of vesting frequency + * @param _startTimes array of vesting start time */ function modifyScheduleMulti( address[] _beneficiaries, uint256[] _indexes, - uint256 _numberOfTokens, - uint256 _duration, - uint256 _frequency, - uint256 _startTime + uint256[] _numberOfTokens, + uint256[] _durations, + uint256[] _frequencies, + uint256[] _startTimes ) - external + public withPerm(ADMIN) { - require(_beneficiaries.length == _indexes.length, "Arrays sizes mismatch"); + require( + _beneficiaries.length == _indexes.length && /*solium-disable-line operator-whitespace*/ + _beneficiaries.length == _numberOfTokens.length && /*solium-disable-line operator-whitespace*/ + _beneficiaries.length == _durations.length && /*solium-disable-line operator-whitespace*/ + _beneficiaries.length == _frequencies.length && /*solium-disable-line operator-whitespace*/ + _beneficiaries.length == _startTimes.length, + "Arrays sizes mismatch" + ); for (uint256 i = 0; i < _beneficiaries.length; i++) { - _modifySchedule(_beneficiaries[i], _indexes[i], _numberOfTokens, _duration, _frequency, _startTime); + _modifySchedule(_beneficiaries[i], _indexes[i], _numberOfTokens[i], _durations[i], _frequencies[i], _startTimes[i]); } } @@ -483,6 +496,11 @@ contract VestingEscrowWallet is IWallet { require(now < _startTime, "Date in the past"); } + function _checkSchedule(address _beneficiary, uint256 _index) internal view { + require(_beneficiary != address(0), "Invalid address"); + require(_index < schedules[_beneficiary].length, "Schedule not found"); + } + function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) internal pure { require(_numberOfTokens > 0, "Zero amount"); require(_duration % _frequency == 0, "Duration and frequency mismatch"); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 6c629628e..0c331dda1 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -886,83 +886,95 @@ contract('VestingEscrowWallet', accounts => { describe("Tests for multi operations", async () => { it("Should not be able to add schedules to the beneficiaries -- fail because of permissions check", async () => { + let startTimes = [latestTime() + 100, latestTime() + 100, latestTime() + 100]; await catchRevert( - I_VestingEscrowWallet.addScheduleMulti([account_beneficiary1], 10000, 4, 1, latestTime() + 100, {from: account_beneficiary1}) + I_VestingEscrowWallet.addScheduleMulti(beneficiaries, [10000, 10000, 10000], [4, 4, 4], [1, 1, 1], startTimes, {from: account_beneficiary1}) ); }); + it("Should not be able to add schedules to the beneficiaries -- fail because of arrays sizes mismatch", async () => { + let startTimes = [latestTime() + 100, latestTime() + 100, latestTime() + 100]; + let totalNumberOfTokens = 60000; + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + await catchRevert( + I_VestingEscrowWallet.addScheduleMulti(beneficiaries, [20000, 30000, 10000], [4, 4], [1, 1, 1], startTimes, {from: wallet_admin}) + ); + I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + }); + it("Should add schedules for 3 beneficiaries", async () => { - let numberOfTokens = 30000; - let duration = durationUtil.weeks(4); - let frequency = durationUtil.weeks(1); - let startTime = latestTime() + durationUtil.seconds(100); + let numberOfTokens = [20000, 30000, 10000]; + let durations = [durationUtil.weeks(4), durationUtil.weeks(3), durationUtil.weeks(4)]; + let frequencies = [durationUtil.weeks(2), durationUtil.weeks(1), durationUtil.weeks(1)]; + let startTimes = [latestTime() + durationUtil.days(1), latestTime() + durationUtil.days(2), latestTime() + durationUtil.days(3)]; - let totalNumberOfTokens = numberOfTokens * 3; + let totalNumberOfTokens = 60000; await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); - let tx = await I_VestingEscrowWallet.addScheduleMulti(beneficiaries, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + let tx = await I_VestingEscrowWallet.addScheduleMulti(beneficiaries, numberOfTokens, durations, frequencies, startTimes, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; let beneficiary = beneficiaries[i]; - checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(log, beneficiary, numberOfTokens[i], durations[i], frequencies[i], startTimes[i]); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); + checkSchedule(schedule, numberOfTokens[i], durations[i], frequencies[i], startTimes[i], CREATED); } }); - it("Should not be able modify vesting schedule for 3 beneficiary's addresses", async () => { - let numberOfTokens = 25000; - let duration = durationUtil.seconds(50); - let frequency = durationUtil.seconds(10); + it("Should not be able modify vesting schedule for 3 beneficiary's addresses -- fail because of arrays sizes mismatch", async () => { + let numberOfTokens = [25000, 25000, 25000]; + let durations = [durationUtil.seconds(50), durationUtil.seconds(50), durationUtil.seconds(50)]; + let frequencies = [durationUtil.seconds(10), durationUtil.seconds(10), durationUtil.seconds(10)]; let timeShift = durationUtil.seconds(100); - let startTime = latestTime() + timeShift; + let startTimes = [latestTime() + timeShift, latestTime() + timeShift, latestTime() + timeShift]; let indexes = [0, 0, 0, 0]; await catchRevert( - I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) + I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, durations, frequencies, startTimes, {from: wallet_admin}) ); }); it("Should not be able to modify schedules for the beneficiaries -- fail because of permissions check", async () => { - let numberOfTokens = 25000; - let duration = durationUtil.seconds(50); - let frequency = durationUtil.seconds(10); + let numberOfTokens = [25000, 25000, 25000]; + let durations = [durationUtil.seconds(50), durationUtil.seconds(50), durationUtil.seconds(50)]; + let frequencies = [durationUtil.seconds(10), durationUtil.seconds(10), durationUtil.seconds(10)]; let timeShift = durationUtil.seconds(100); - let startTime = latestTime() + timeShift; + let startTimes = [latestTime() + timeShift, latestTime() + timeShift, latestTime() + timeShift]; let indexes = [0, 0, 0]; await catchRevert( - I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: account_beneficiary1}) + I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, durations, frequencies, startTimes, {from: account_beneficiary1}) ); }); it("Should modify vesting schedule for 3 beneficiary's addresses", async () => { - let numberOfTokens = 25000; - let duration = durationUtil.seconds(50); - let frequency = durationUtil.seconds(10); + let numberOfTokens = [15000, 15000, 15000]; + let durations = [durationUtil.seconds(50), durationUtil.seconds(50), durationUtil.seconds(50)]; + let frequencies = [durationUtil.seconds(10), durationUtil.seconds(10), durationUtil.seconds(10)]; let timeShift = durationUtil.seconds(100); - let startTime = latestTime() + timeShift; + let startTimes = [latestTime() + timeShift, latestTime() + timeShift, latestTime() + timeShift]; let indexes = [0, 0, 0]; - const tx = await I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); - await increaseTime(timeShift + frequency); + const tx = await I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, durations, frequencies, startTimes, {from: wallet_admin}); + await increaseTime(timeShift + frequencies[0]); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; let beneficiary = beneficiaries[i]; - checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(log, beneficiary, numberOfTokens[i], durations[i], frequencies[i], startTimes[i]); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, STARTED); + checkSchedule(schedule, numberOfTokens[i], durations[i], frequencies[i], startTimes[i], STARTED); } let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); @@ -988,10 +1000,10 @@ contract('VestingEscrowWallet', accounts => { let log = tx.logs[i]; let beneficiary = beneficiaries[i]; assert.equal(log.args._beneficiary, beneficiary); - assert.equal(log.args._numberOfTokens.toNumber(), 5000); + assert.equal(log.args._numberOfTokens.toNumber(), 3000); let balance = await I_SecurityToken.balanceOf.call(beneficiary); - assert.equal(balance.toNumber(), 5000); + assert.equal(balance.toNumber(), 3000); await I_SecurityToken.transfer(token_owner, balance, {from: beneficiary}); await I_VestingEscrowWallet.revokeAllSchedules(beneficiary, {from: wallet_admin}); @@ -1003,7 +1015,7 @@ contract('VestingEscrowWallet', accounts => { let numberOfTokens = 18000; let duration = durationUtil.weeks(3); let frequency = durationUtil.weeks(1); - let startTime = latestTime() + durationUtil.seconds(100); + let startTimes = [latestTime() + durationUtil.seconds(100), latestTime() + durationUtil.seconds(100), latestTime() + durationUtil.seconds(100)]; let totalNumberOfTokens = numberOfTokens * 3; await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); @@ -1011,7 +1023,7 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); await catchRevert( - I_VestingEscrowWallet.addScheduleFromTemplateMulti([account_beneficiary1, account_beneficiary2], 0, startTime, {from: account_beneficiary1}) + I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, 0, startTimes, {from: account_beneficiary1}) ); }); @@ -1019,26 +1031,26 @@ contract('VestingEscrowWallet', accounts => { let numberOfTokens = 18000; let duration = durationUtil.weeks(3); let frequency = durationUtil.weeks(1); - let startTime = latestTime() + durationUtil.seconds(100); + let startTimes = [latestTime() + durationUtil.seconds(100), latestTime() + durationUtil.seconds(100), latestTime() + durationUtil.seconds(100)]; let totalNumberOfTokens = numberOfTokens * 3; await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); - let tx = await I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, 0, startTime, {from: wallet_admin}); + let tx = await I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, 0, startTimes, {from: wallet_admin}); await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; let beneficiary = beneficiaries[i]; - checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTimes[i]); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); assert.equal(scheduleCount.toNumber(), 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTimes[i], CREATED); } }); From 0c498615b4c923b3306439164bcf6d405e78161b Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 28 Nov 2018 11:47:45 +0200 Subject: [PATCH 236/582] use msg.sender instead of _treasury --- .../modules/Wallet/VestingEscrowWallet.sol | 24 ++++++------------- .../Wallet/VestingEscrowWalletFactory.sol | 4 ---- test/z_vesting_escrow_wallet.js | 9 ++----- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index a1141977c..52c3e5a8f 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -29,7 +29,6 @@ contract VestingEscrowWallet is IWallet { enum State {CREATED, STARTED, COMPLETED} - address public treasury; uint256 public unassignedTokens; mapping (address => Schedule[]) public schedules; @@ -55,8 +54,8 @@ contract VestingEscrowWallet is IWallet { ); event RevokeAllSchedules(address indexed _beneficiary); event RevokeSchedule(address indexed _beneficiary, uint256 _index); - event DepositTokens(uint256 _numberOfTokens); - event SendToTreasury(uint256 _numberOfTokens); + event DepositTokens(uint256 _numberOfTokens, address _sender); + event SendToTreasury(uint256 _numberOfTokens, address _sender); event SendTokens(address indexed _beneficiary, uint256 _numberOfTokens); event AddTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, uint256 _index); event RemoveTemplate(uint256 _index); @@ -72,20 +71,11 @@ contract VestingEscrowWallet is IWallet { { } - /** - * @notice Function used to initialize the different variables - * @param _treasury Address of the treasury - */ - function configure(address _treasury) public onlyFactory { - require(_treasury != address(0), "Invalid address"); - treasury = _treasury; - } - /** * @notice This function returns the signature of the configure function */ function getInitFunction() public pure returns (bytes4) { - return bytes4(keccak256("configure(address)")); + return bytes4(0); } /** @@ -97,9 +87,9 @@ contract VestingEscrowWallet is IWallet { function _depositTokens(uint256 _numberOfTokens) internal { require(_numberOfTokens > 0, "Should be greater than zero"); - ISecurityToken(securityToken).transferFrom(treasury, this, _numberOfTokens); + ISecurityToken(securityToken).transferFrom(msg.sender, this, _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); - emit DepositTokens(_numberOfTokens); + emit DepositTokens(_numberOfTokens, msg.sender); } /** @@ -108,8 +98,8 @@ contract VestingEscrowWallet is IWallet { function sendToTreasury() external withPerm(ADMIN) { uint256 amount = unassignedTokens; unassignedTokens = 0; - ISecurityToken(securityToken).transfer(treasury, amount); - emit SendToTreasury(amount); + ISecurityToken(securityToken).transfer(msg.sender, amount); + emit SendToTreasury(amount, msg.sender); } /** diff --git a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol index 88db1919d..c58a04192 100644 --- a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol +++ b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol @@ -34,10 +34,6 @@ contract VestingEscrowWalletFactory is ModuleFactory { require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance provided"); } VestingEscrowWallet vestingEscrowWallet = new VestingEscrowWallet(msg.sender, address(polyToken)); - //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == vestingEscrowWallet.getInitFunction(), "Invalid data"); - /*solium-disable-next-line security/no-low-level-calls*/ - require(address(vestingEscrowWallet).call(_data), "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(vestingEscrowWallet), getName(), address(this), msg.sender, setupCost, now); return address(vestingEscrowWallet); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 0c331dda1..8c5d3fba5 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -71,7 +71,7 @@ contract('VestingEscrowWallet', accounts => { // Accounts setup account_polymath = accounts[0]; token_owner = accounts[1]; - wallet_admin = accounts[2]; + wallet_admin = token_owner; account_beneficiary1 = accounts[6]; account_beneficiary2 = accounts[7]; @@ -173,13 +173,8 @@ contract('VestingEscrowWallet', accounts => { }); it("Should successfully attach the VestingEscrowWallet with the security token", async () => { - let bytesData = encodeModuleCall( - ["address"], - [token_owner] - ); - await I_SecurityToken.changeGranularity(1, {from: token_owner}); - const tx = await I_SecurityToken.addModule(I_VestingEscrowWalletFactory.address, bytesData, 0, 0, { from: token_owner }); + const tx = await I_SecurityToken.addModule(I_VestingEscrowWalletFactory.address, "", 0, 0, { from: token_owner }); assert.equal(tx.logs[2].args._types[0].toNumber(), 6, "VestingEscrowWallet doesn't get deployed"); assert.equal( From 125a199649cf73e605a2fa311d7708f3fe5f1c15 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 28 Nov 2018 12:35:09 +0200 Subject: [PATCH 237/582] minor fix --- contracts/modules/Wallet/VestingEscrowWalletFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol index c58a04192..d0035da10 100644 --- a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol +++ b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol @@ -29,7 +29,7 @@ contract VestingEscrowWalletFactory is ModuleFactory { * _data Data used for the intialization of the module factory variables * @return address Contract address of the Module */ - function deploy(bytes _data) external returns(address) { + function deploy(bytes /*_data*/) external returns(address) { if (setupCost > 0) { require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance provided"); } From 4854ace6948caf6fd4d6c3c2a09f2ba83fe22498 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 28 Nov 2018 12:35:25 +0200 Subject: [PATCH 238/582] updated permissions_list.md --- docs/permissions_list.md | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/docs/permissions_list.md b/docs/permissions_list.md index b49c95a0e..de3fd2930 100644 --- a/docs/permissions_list.md +++ b/docs/permissions_list.md @@ -271,6 +271,57 @@ removeTransferLimitInPercentageMulti + + Wallet + VestingEscrowWallet + depositTokens() + withPerm(ADMIN) + + + sendToTreasury() + + + pushAvailableTokens() + + + addTemplate() + + + removeTemplate() + + + addSchedule() + + + addScheduleFromTemplate() + + + modifySchedule() + + + revokeSchedule() + + + revokeAllSchedules() + + + trimBeneficiaries() + + + pushAvailableTokensMulti() + + + addScheduleMulti() + + + addScheduleFromTemplateMulti() + + + revokeSchedulesMulti() + + + modifyScheduleMulti() + From f3b58fb883b3204547b9fb6c6e8fd97ca1a1a6a1 Mon Sep 17 00:00:00 2001 From: Satyam Agrawal Date: Tue, 27 Nov 2018 03:48:41 +0530 Subject: [PATCH 239/582] resolve conflicts in changelog --- CHANGELOG.md | 11 ++++++++--- .../ManualApprovalTransferManagerFactory.sol | 2 +- test/j_manual_approval_transfer_manager.js | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db3d8dcde..224ba8304 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,10 +13,15 @@ All notable changes to this project will be documented in this file. * Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. * Removed individual mappings for tier data removed in UDSTSTO. +## Manual Approval TransferManager +* Removed `0x0` check for the `_from` address to `ManualApprovalTransferManager`. This allows for the Issuer/Transfer Agent to approve a one-off mint of tokens that otherwise would not be possible. +* Changed the version of `ManualApprovalTransferManagerFactory` from `1.0.0` to `2.0.1`. + ##Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. + -# v1.5.0 +# v1.5.0 - Release Candidate [__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ @@ -53,13 +58,13 @@ All notable changes to this project will be documented in this file. * All permissions are denied if no permission manager is active. * Generalize the STO varaible names and added them in `ISTO.sol` to use the common standard in all STOs. * Generalize the event when any new token get registered with the polymath ecosystem. `LogNewSecurityToken` should emit _ticker, _name, _securityTokenAddress, _owner, _addedAt, _registrant respectively. #230 -* Change the function name of `withdraPoly` to `withdrawERC20` and make the function generalize to extract tokens from the ST contract. parmeters are contract address and the value need to extract from the securityToken. +* Change the function name of `withdraPoly` to `withdrawERC20` and make the function generalize to extract tokens from the ST contract. parmeters are contract address and the value need to extract from the securityToken. ## Removed * Removed investors list pruning * Remove `swarmHash` from the `registerTicker(), addCustomTicker(), generateSecurityToken(), addCustomSecurityToken()` functions of TickerRegistry.sol and SecurityTokenRegistry.sol. #230 * Remove `Log` prefix from all the event present in the ecosystem. -* Removed `addTagByModuleType` & `removeTagsByModuleType` from MR. +* Removed `addTagByModuleType` & `removeTagsByModuleType` from MR. ====== diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index f634b33e9..9c5513ee7 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -18,7 +18,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + version = "2.0.1"; name = "ManualApprovalTransferManager"; title = "Manual Approval Transfer Manager"; description = "Manage transfers using single approvals / blocking"; diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 0461f287a..5779a1c13 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -541,7 +541,7 @@ contract("ManualApprovalTransferManager", accounts => { "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.", "Wrong Module added" ); - assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "1.0.0"); + assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.0.1"); }); it("Should get the tags of the factory", async () => { From e9f1129161b37b288ae493db1ebfede4d1207f29 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 28 Nov 2018 13:19:20 +0200 Subject: [PATCH 240/582] fixed permissions_list.md --- docs/permissions_list.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/permissions_list.md b/docs/permissions_list.md index de3fd2930..009781c05 100644 --- a/docs/permissions_list.md +++ b/docs/permissions_list.md @@ -270,8 +270,9 @@ removeTransferLimitInPercentageMulti - - + + + Wallet VestingEscrowWallet depositTokens() From ce812a400aaccf6f775c657c9bf2762398b7c227 Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Tue, 27 Nov 2018 09:35:20 -0300 Subject: [PATCH 241/582] resolve conflicts in readme --- CHANGELOG.md | 9 ++++---- README.md | 62 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 224ba8304..f5a59aecf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,11 @@ # Changelog All notable changes to this project will be documented in this file. -# v2.1.0 - Release Candidate +# v2.1.0 - Release Candidate [__2.1.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-09-18__ -# USDTieredSTO 2.0.1 +## USDTieredSTO 2.0.1 * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. * Added `getSTODetails` to USDTSTO. * Added an Array of Tiers that will hold data about every tier in USDTSTO. @@ -15,9 +15,10 @@ All notable changes to this project will be documented in this file. ## Manual Approval TransferManager * Removed `0x0` check for the `_from` address to `ManualApprovalTransferManager`. This allows for the Issuer/Transfer Agent to approve a one-off mint of tokens that otherwise would not be possible. -* Changed the version of `ManualApprovalTransferManagerFactory` from `1.0.0` to `2.0.1`. +* Changed the version of `ManualApprovalTransferManagerFactory` from `1.0.0` to `2.0.1`. +* Deployed 2.0.1 `ManualApprovalTransferManagerFactory` to address 0x6af2afad53cb334e62b90ddbdcf3a086f654c298 -##Changed +## Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. diff --git a/README.md b/README.md index 64ff0d251..540b226da 100644 --- a/README.md +++ b/README.md @@ -204,17 +204,29 @@ node CLI/polymath-cli dividends_manager | Contract | Address | | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -| TickerRegistry: | [0xc31714e6759a1ee26db1d06af1ed276340cd4233](https://etherscan.io/address/0xc31714e6759a1ee26db1d06af1ed276340cd4233) | -| SecurityTokenRegistry: | [0xef58491224958d978facf55d2120c55a24516b98](https://etherscan.io/address/0xef58491224958d978facf55d2120c55a24516b98) | -| ModuleRegistry: | [0x31d85fffd7e38bd42d2ae0409ac149e3ef0fd92c](https://etherscan.io/address/0x31d85fffd7e38bd42d2ae0409ac149e3ef0fd92c) | -| Polymath Registry: | [0x06595656b93ce14834f0d22b7bbda4382d5ab510](https://etherscan.io/address/0x06595656b93ce14834f0d22b7bbda4382d5ab510) | -| CappedSTOFactory: | [0x2aa1b133f464ac08f66c2f702581d014e4603d31](https://etherscan.io/address/0x2aa1b133f464ac08f66c2f702581d014e4603d31) | -| EthDividendsCheckpointFactory: | [0x0da7ed8789348ac40937cf6ae8ff521eee43816c](https://etherscan.io/address/0x0da7ed8789348ac40937cf6ae8ff521eee43816c) | -| ERC20 Dividends Checkpoint Factory: | [0x6950096964b7adae34d5a3d1792fe73afbe9ddbc](https://etherscan.io/address/0x6950096964b7adae34d5a3d1792fe73afbe9ddbc) | -| General Permission Manager Factory: | [0xeba0348e243f2de2f1687060f9c795ac279c66af](https://etherscan.io/address/0xeba0348e243f2de2f1687060f9c795ac279c66af) | -| Count Transfer Manager Factory: | [0xa662a05647a8e713be1bed193c094805d20471ff](https://etherscan.io/address/0xa662a05647a8e713be1bed193c094805d20471ff) | -| Percentage Transfer Manager Factory: | [0x3870ee581a0528d24a6216311fcfa78f95a00593](https://etherscan.io/address/0x3870ee581a0528d24a6216311fcfa78f95a00593) | - +| SecurityTokenRegistry (Proxy): | [0x240f9f86b1465bf1b8eb29bc88cbf65573dfdd97](https://etherscan.io/address/0x240f9f86b1465bf1b8eb29bc88cbf65573dfdd97) | +| ModuleRegistry (Proxy): | [0x4566d68ea96fc2213f2446f0dd0f482146cee96d](https://etherscan.io/address/0x4566d68ea96fc2213f2446f0dd0f482146cee96d) | +| Polymath Registry: | [0xdfabf3e4793cd30affb47ab6fa4cf4eef26bbc27](https://etherscan.io/address/0xdfabf3e4793cd30affb47ab6fa4cf4eef26bbc27) | +| Feature Registry: | [0xa3eacb03622bf1513880892b7270d965f693ffb5](https://etherscan.io/address/0xa3eacb03622bf1513880892b7270d965f693ffb5) | +| ETHOracle: | [0x60055e9a93aae267da5a052e95846fa9469c0e7a](https://etherscan.io/address/0x60055e9a93aae267da5a052e95846fa9469c0e7a) | +| POLYOracle: | [0x52cb4616E191Ff664B0bff247469ce7b74579D1B](https://etherscan.io/address/0x52cb4616E191Ff664B0bff247469ce7b74579D1B) | +| General Transfer Manager Factory: | [0xdc95598ef2bbfdb66d02d5f3eea98ea39fbc8b26](https://etherscan.io/address/0xdc95598ef2bbfdb66d02d5f3eea98ea39fbc8b26) | +| General Permission Manager Factory: | [0xf0aa1856360277c60052d6095c5b787b01388cdd](https://etherscan.io/address/0xf0aa1856360277c60052d6095c5b787b01388cdd) | +| CappedSTOFactory: | [0x77d89663e8819023a87bfe2bc9baaa6922c0e57c](https://etherscan.io/address/0x77d89663e8819023a87bfe2bc9baaa6922c0e57c) | +| USDTieredSTO Factory: | [0x5a3a30bddae1f857a19b1aed93b5cdb3c3da809a](https://etherscan.io/address/0x5a3a30bddae1f857a19b1aed93b5cdb3c3da809a) | +| EthDividendsCheckpointFactory: | [0x968c74c52f15b2de323eca8c677f6c9266bfefd6](https://etherscan.io/address/0x968c74c52f15b2de323eca8c677f6c9266bfefd6) | +| ERC20 Dividends Checkpoint Factory: | [0x82f9f1ab41bacb1433c79492e54bf13bccd7f9ae](https://etherscan.io/address/0x82f9f1ab41bacb1433c79492e54bf13bccd7f9ae) | +| Count Transfer Manager Factory: | [0xd9fd7e34d6e2c47a69e02131cf8554d52c3445d5](https://etherscan.io/address/0xd9fd7e34d6e2c47a69e02131cf8554d52c3445d5) | +| Percentage Transfer Manager Factory: | [0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b](https://etherscan.io/address/0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b) | +| Manual Approval Transfer Manager Factory (2.0.1): | [0x6af2afad53cb334e62b90ddbdcf3a086f654c298](https://etherscan.io/address/0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b) | +New SecurityTokenRegistry (2.0.1): 0x538136ed73011a766bf0a126a27300c3a7a2e6a6 +(fixed bug with getTickersByOwner()) + +New ModuleRegistry (2.0.1): 0xbc18f144ccf87f2d98e6fa0661799fcdc3170119 +(fixed bug with missing transferOwnership function) + +New ManualApprovalTransferManager 0x6af2afad53cb334e62b90ddbdcf3a086f654c298 +(Fixed 0x0 from bug) ## KOVAN @@ -222,17 +234,23 @@ node CLI/polymath-cli dividends_manager | Contract | Address | | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -| TickerRegistry: | [0xc9af1d88fe48c8a6aa8677a29a89b0a6ae78f5a8](https://kovan.etherscan.io/address/0xc9af1d88fe48c8a6aa8677a29a89b0a6ae78f5a8) | -| SecurityTokenRegistry: | [0xced6e4ec2ac5425743bf4edf4d4e476120b8fc72](https://kovan.etherscan.io/address/0xced6e4ec2ac5425743bf4edf4d4e476120b8fc72) | -| ModuleRegistry: | [0x961913dcbe2f36176bf25774337f3277796820eb](https://kovan.etherscan.io/address/0x961913dcbe2f36176bf25774337f3277796820eb) | -| Polymath Registry: | [0x05a6519e49e34239f78167abf293d94dae61b299](https://kovan.etherscan.io/address/0x05a6519e49e34239f78167abf293d94dae61b299) | -| CappedSTOFactory: | [0xde4f3cfb6b214e60c4e69e6dfc95ede3c4e3d709](https://kovan.etherscan.io/address/0xde4f3cfb6b214e60c4e69e6dfc95ede3c4e3d709) | -| EthDividendsCheckpointFactory: | [0x870a07d45b0f4c5653fc29a4cb0697a01e0224b1](https://kovan.etherscan.io/address/0x870a07d45b0f4c5653fc29a4cb0697a01e0224b1) | -| ERC20 Dividends Checkpoint Factory: | [0x7e823f5df6ed1bb6cc005c692febc6aedf3b8889](https://kovan.etherscan.io/address/0x7e823f5df6ed1bb6cc005c692febc6aedf3b8889) | -| General Permission Manager Factory: | [0x6f5fec2934a34d2e2374042cca6505f1c87ef79b](https://kovan.etherscan.io/address/0x6f5fec2934a34d2e2374042cca6505f1c87ef79b) | -| Count Transfer Manager Factory: | [0xb540b6fa752a91c7e7834523172309e543a99a06](https://kovan.etherscan.io/address/0xb540b6fa752a91c7e7834523172309e543a99a06) | -| Percentage Transfer Manager Factory: | [0xfe908f07e6db57aa6bbd8374e59aac86b60374b0](https://kovan.etherscan.io/address/0xfe908f07e6db57aa6bbd8374e59aac86b60374b0) | - +| SecurityTokenRegistry (Proxy): | [0xbefb81114d532bddddc724af20c3516fa75f0afb](https://kovan.etherscan.io/address/0xbefb81114d532bddddc724af20c3516fa75f0afb) | +| ModuleRegistry (Proxy): | [0x0fac8d8cce224eead73c1187df96570aa80a568b](https://kovan.etherscan.io/address/0x0fac8d8cce224eead73c1187df96570aa80a568b) | +| Polymath Registry: | [0x9903e7b5acfe5fa9713771a8d861eb1df8cd7046](https://kovan.etherscan.io/address/0x9903e7b5acfe5fa9713771a8d861eb1df8cd7046) | +| Feature Registry: | [0xa8f85006fdacb3d59ffae564c05433f0c949e911](https://kovan.etherscan.io/address/0xa8f85006fdacb3d59ffae564c05433f0c949e911) | +| ETHOracle: | [0xCE5551FC9d43E9D2CC255139169FC889352405C8](https://kovan.etherscan.io/address/0xCE5551FC9d43E9D2CC255139169FC889352405C8) | +| POLYOracle: | [0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C](https://kovan.etherscan.io/address/0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C) | +| General Transfer Manager Factory: | [0xfe7e2bb6c200d5222c82d0f8fecca5f8fe4ab8ce](https://kovan.etherscan.io/address/0xfe7e2bb6c200d5222c82d0f8fecca5f8fe4ab8ce) | +| General Permission Manager Factory: | [0xde5eaa8d73f43fc5e7badb203f03ecae2b29bd92](https://kovan.etherscan.io/address/0xde5eaa8d73f43fc5e7badb203f03ecae2b29bd92) | +| CappedSTOFactory: | [0xe14d7dd044cc6cfe37548b6791416c59f19bfc0d](https://kovan.etherscan.io/address/0xe14d7dd044cc6cfe37548b6791416c59f19bfc0d) | +| USDTieredSTO Factory: | [0xf9f0bb9f868d411dd9a9511a79d172449e3c15f5](https://kovan.etherscan.io/address/0xf9f0bb9f868d411dd9a9511a79d172449e3c15f5) | +| EthDividendsCheckpointFactory: | [0x2861425ba5abbf50089c473b28f6c40a8ea5262a](https://kovan.etherscan.io/address/0x2861425ba5abbf50089c473b28f6c40a8ea5262a) | +| ERC20 Dividends Checkpoint Factory: | [0xbf9495550417feaacc43f86d2244581b6d688431](https://kovan.etherscan.io/address/0xbf9495550417feaacc43f86d2244581b6d688431) | +| Count Transfer Manager Factory: | [0x3c3c1f40ae2bdca82b90541b2cfbd41caa941c0e](https://kovan.etherscan.io/address/0x3c3c1f40ae2bdca82b90541b2cfbd41caa941c0e) | +| Percentage Transfer Manager Factory: | [0x8cd00c3914b2967a8b79815037f51c76874236b8](https://kovan.etherscan.io/address/0x8cd00c3914b2967a8b79815037f51c76874236b8) | +| Manual Approval Transfer Manager Factory: | [0x9faa79e2ccf0eb49aa6ebde1795ad2e951ce78f8](https://kovan.etherscan.io/address/0x9faa79e2ccf0eb49aa6ebde1795ad2e951ce78f8) | +New ManualApprovalTransferManager 0x9faa79e2ccf0eb49aa6ebde1795ad2e951ce78f8 +(Fixed 0x0 from bug) ## Package version requirements for your machine: From 8a079129bc6a8c50445366c2b7afa59627e9d09e Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Tue, 27 Nov 2018 10:39:45 -0300 Subject: [PATCH 242/582] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 540b226da..9caa44f67 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,8 @@ node CLI/polymath-cli dividends_manager | Count Transfer Manager Factory: | [0xd9fd7e34d6e2c47a69e02131cf8554d52c3445d5](https://etherscan.io/address/0xd9fd7e34d6e2c47a69e02131cf8554d52c3445d5) | | Percentage Transfer Manager Factory: | [0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b](https://etherscan.io/address/0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b) | | Manual Approval Transfer Manager Factory (2.0.1): | [0x6af2afad53cb334e62b90ddbdcf3a086f654c298](https://etherscan.io/address/0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b) | + + New SecurityTokenRegistry (2.0.1): 0x538136ed73011a766bf0a126a27300c3a7a2e6a6 (fixed bug with getTickersByOwner()) @@ -249,6 +251,8 @@ New ManualApprovalTransferManager 0x6af2afad53cb334e62b90ddbdcf3a086f654c298 | Count Transfer Manager Factory: | [0x3c3c1f40ae2bdca82b90541b2cfbd41caa941c0e](https://kovan.etherscan.io/address/0x3c3c1f40ae2bdca82b90541b2cfbd41caa941c0e) | | Percentage Transfer Manager Factory: | [0x8cd00c3914b2967a8b79815037f51c76874236b8](https://kovan.etherscan.io/address/0x8cd00c3914b2967a8b79815037f51c76874236b8) | | Manual Approval Transfer Manager Factory: | [0x9faa79e2ccf0eb49aa6ebde1795ad2e951ce78f8](https://kovan.etherscan.io/address/0x9faa79e2ccf0eb49aa6ebde1795ad2e951ce78f8) | + + New ManualApprovalTransferManager 0x9faa79e2ccf0eb49aa6ebde1795ad2e951ce78f8 (Fixed 0x0 from bug) From b14ed6c802643b5d32c338608fc9ae2ab4009e32 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 28 Nov 2018 12:27:16 +0100 Subject: [PATCH 243/582] WIP --- .../z_fuzz_test_adding_removing_modules_ST.js | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index 577918a74..8a455f3cd 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -80,6 +80,9 @@ contract('GeneralPermissionManager', accounts => { let I_ManualApprovalTransferManagerFactory; let I_ManualApprovalTransferManager; + //Define all modules for test + let + // SecurityToken Details const name = "Team"; const symbol = "sap"; @@ -105,7 +108,7 @@ contract('GeneralPermissionManager', accounts => { let testRepeat = 20; // permission manager fuzz test - let perms = ['ADMIN','WHITELIST', 'FLAGS', 'TRANSFER_APPROVAL']; + let modules = ['CappedSTO','DummySTO', 'USDTieredSTO', 'CountTransferManager', 'ManualApprovalTransferManager', 'PercentageTransferManager']; let totalPerms = perms.length; before(async () => { @@ -244,4 +247,27 @@ contract('GeneralPermissionManager', accounts => { I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); }); }); + + + + describe("adding and removing different modules", async () => { + + it("should pass test for randomly adding and removing modules ", async () => { + + console.log("1"); + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 0; i < testRepeat; i++) { + + // choose a random module + + + + // attach it to the ST + + // remove it from the ST + + }; + }) + }); + }); From cb975a524b3f43f1f3c4d0d4fb964d4d6ceaf849 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 28 Nov 2018 12:00:37 +0000 Subject: [PATCH 244/582] Keep ABI constant --- .../GeneralTransferManager.sol | 66 ++++++++++++------- test/h_general_transfer_manager.js | 36 +++++----- test/helpers/signData.js | 2 +- 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 04028fead..080c8be17 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -35,10 +35,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag address _investor, uint256 _dateAdded, address _addedBy, - uint64 _fromTime, - uint64 _toTime, - uint64 _expiryTime, - uint8 _canBuyFromSTO + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, + bool _canBuyFromSTO ); /** @@ -177,15 +177,21 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag */ function modifyWhitelist( address _investor, - uint64 _fromTime, - uint64 _toTime, - uint64 _expiryTime, - uint8 _canBuyFromSTO + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, + bool _canBuyFromSTO ) public withPerm(WHITELIST) { - _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + uint8 canBuyFromSTO = 0; + if (_canBuyFromSTO) { + canBuyFromSTO = 1; + } + _modifyWhitelist(_investor, uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO); + /*solium-disable-next-line security/no-block-members*/ + emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** @@ -210,8 +216,6 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag investors.push(_investor); } whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO, uint8(1)); - /*solium-disable-next-line security/no-block-members*/ - emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** @@ -224,17 +228,25 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag */ function modifyWhitelistMulti( address[] _investors, - uint64[] _fromTimes, - uint64[] _toTimes, - uint64[] _expiryTimes, - uint8[] _canBuyFromSTO + uint256[] _fromTimes, + uint256[] _toTimes, + uint256[] _expiryTimes, + bool[] _canBuyFromSTO ) public withPerm(WHITELIST) { require(_investors.length == _fromTimes.length, "Mismatched input lengths"); require(_fromTimes.length == _toTimes.length, "Mismatched input lengths"); require(_toTimes.length == _expiryTimes.length, "Mismatched input lengths"); require(_canBuyFromSTO.length == _toTimes.length, "Mismatched input length"); + uint8 canBuyFromSTO; for (uint256 i = 0; i < _investors.length; i++) { - _modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); + if (_canBuyFromSTO[i]) { + canBuyFromSTO = 1; + } else { + canBuyFromSTO = 0; + } + _modifyWhitelist(_investors[i], uint64(_fromTimes[i]), uint64(_toTimes[i]), uint64(_expiryTimes[i]), canBuyFromSTO); + /*solium-disable-next-line security/no-block-members*/ + emit ModifyWhitelist(_investors[i], now, msg.sender, _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); } } @@ -254,21 +266,21 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag */ function modifyWhitelistSigned( address _investor, - uint64 _fromTime, - uint64 _toTime, - uint64 _expiryTime, - uint8 _canBuyFromSTO, - uint64 _validFrom, - uint64 _validTo, + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, + bool _canBuyFromSTO, + uint256 _validFrom, + uint256 _validTo, uint256 _nonce, uint8 _v, bytes32 _r, bytes32 _s ) public { /*solium-disable-next-line security/no-block-members*/ - require(_validFrom <= uint64(now), "ValidFrom is too early"); + require(_validFrom <= now, "ValidFrom is too early"); /*solium-disable-next-line security/no-block-members*/ - require(_validTo >= uint64(now), "ValidTo is too late"); + require(_validTo >= now, "ValidTo is too late"); require(!nonceMap[_investor][_nonce], "Already used signature"); nonceMap[_investor][_nonce] = true; bytes32 hash = keccak256( @@ -278,7 +290,11 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag if (whitelist[_investor].added == uint8(0)) { investors.push(_investor); } - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO, uint8(1)); + uint8 canBuyFromSTO = 0; + if (_canBuyFromSTO) { + canBuyFromSTO = 1; + } + whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); /*solium-disable-next-line security/no-block-members*/ emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 5dbcf5a6c..f8b1ed989 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -188,7 +188,7 @@ contract("GeneralTransferManager", accounts => { [latestTime() + duration.days(30), latestTime() + duration.days(30)], [latestTime() + duration.days(90), latestTime() + duration.days(90)], [latestTime() + duration.years(1), latestTime() + duration.years(1)], - [0, 0], + [false, false], { from: account_issuer, gas: 6000000 @@ -316,7 +316,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -378,7 +378,7 @@ contract("GeneralTransferManager", accounts => { latestTime() + duration.days(10), latestTime() + duration.days(10), latestTime() + duration.days(20), - 1, + true, { from: account_issuer, gas: 6000000 @@ -424,7 +424,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(20), - 1, + true, { from: account_issuer, gas: 6000000 @@ -484,7 +484,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -501,7 +501,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -528,7 +528,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -545,7 +545,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -572,7 +572,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -589,7 +589,7 @@ contract("GeneralTransferManager", accounts => { fromTime, toTime, expiryTime, - 1, + true, validFrom, validTo, nonce, @@ -616,7 +616,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - 1, + true, validFrom, validTo, nonce, @@ -632,7 +632,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - 1, + true, validFrom, validTo, nonce, @@ -672,7 +672,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - 1, + true, validFrom, validTo, nonce, @@ -688,7 +688,7 @@ contract("GeneralTransferManager", accounts => { latestTime(), latestTime() + duration.days(80), expiryTime + duration.days(200), - 1, + true, validFrom, validTo, nonce, @@ -795,7 +795,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [1, 1], + [true, true], { from: account_delegate, gas: 6000000 @@ -835,7 +835,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime], [expiryTime, expiryTime], - [1, 1], + [true, true], { from: account_delegate, gas: 6000000 @@ -855,7 +855,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime], - [1, 1], + [true, true], { from: account_delegate, gas: 6000000 @@ -874,7 +874,7 @@ contract("GeneralTransferManager", accounts => { [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [1, 1], + [true, true], { from: token_owner, gas: 6000000 diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 2e5c1ad61..ea7476cc3 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -6,7 +6,7 @@ const ethUtil = require("ethereumjs-util"); function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce, pk) { let packedData = utils .solidityKeccak256( - ["address", "address", "uint64", "uint64", "uint64", "uint8", "uint64", "uint64", "uint256"], + ["address", "address", "uint256", "uint256", "uint256", "bool", "uint256", "uint256", "uint256"], [tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce] ) .slice(2); From 0f86d9d921f158533d3ca9dcd1f5d5a0c761833d Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 28 Nov 2018 09:47:35 -0300 Subject: [PATCH 245/582] Minor fixes --- CLI/commands/sto_manager.js | 166 +++++++++++++++++----------------- CLI/commands/token_manager.js | 66 +++++++------- 2 files changed, 116 insertions(+), 116 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 9fcfd54dd..d0fd1c3ea 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -39,16 +39,16 @@ async function executeApp() { } options.push('Add new STO module'); - let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Exit'}); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Exit' }); let optionSelected = index != -1 ? options[index] : 'Exit'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Show existing STO information': - let stoToShow = selectExistingSTO(nonArchivedModules, true); + let stoToShow = selectExistingSTO(nonArchivedModules, true); await showSTO(stoToShow.name, stoToShow.module); break; case 'Modify existing STO': - let stoToModify = selectExistingSTO(nonArchivedModules); + let stoToModify = selectExistingSTO(nonArchivedModules); await modifySTO(stoToModify.name, stoToModify.module); break; case 'Add new STO module': @@ -67,7 +67,7 @@ function selectExistingSTO(stoModules, showPaused) { filteredModules = stoModules.filter(m => !m.paused); } let options = filteredModules.map(m => `${m.name} at ${m.address}`); - let index = readlineSync.keyInSelect(options, 'Select a module: ', {cancel: false}); + let index = readlineSync.keyInSelect(options, 'Select a module: ', { cancel: false }); console.log('Selected:', options[index], '\n'); let selectedName = filteredModules[index].name; let stoABI; @@ -81,7 +81,7 @@ function selectExistingSTO(stoModules, showPaused) { } let stoModule = new web3.eth.Contract(stoABI, filteredModules[index].address); - return {name: selectedName, module: stoModule}; + return { name: selectedName, module: stoModule }; } async function showSTO(selectedSTO, currentSTO) { @@ -156,14 +156,14 @@ async function cappedSTO_launch(stoConfig) { return; } else { let transferAction = polyToken.methods.transfer(securityToken._address, transferAmount); - let receipt = await common.sendTransaction(transferAction, {factor: 2}); + let receipt = await common.sendTransaction(transferAction, { factor: 2 }); let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) } } let oneMinuteFromNow = new web3.utils.BN((Math.floor(Date.now() / 1000) + 60)); - let oneMonthFromNow = new web3.utils.BN((Math.floor(Date.now()/1000)+ (30 * 24 * 60 * 60))); + let oneMonthFromNow = new web3.utils.BN((Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60))); let cappedSTOconfig = {}; let useConfigFile = typeof stoConfig !== 'undefined'; @@ -172,7 +172,7 @@ async function cappedSTO_launch(stoConfig) { if (cappedSTOconfig.cap == "") cappedSTOconfig.cap = 500000; cappedSTOconfig.raiseType = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise or leave empty for Ether raise (E): '); - if (cappedSTOconfig.raiseType.toUpperCase() == 'P' ) { + if (cappedSTOconfig.raiseType.toUpperCase() == 'P') { cappedSTOconfig.raiseType = [gbl.constants.FUND_RAISE_TYPES.POLY]; } else { cappedSTOconfig.raiseType = [gbl.constants.FUND_RAISE_TYPES.ETH]; @@ -185,7 +185,7 @@ async function cappedSTO_launch(stoConfig) { if (cappedSTOconfig.wallet == "") cappedSTOconfig.wallet = Issuer.address; cappedSTOconfig.startTime = readlineSync.question('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): '); - + cappedSTOconfig.endTime = readlineSync.question('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): '); } else { cappedSTOconfig = stoConfig; @@ -196,13 +196,13 @@ async function cappedSTO_launch(stoConfig) { let cappedSTOABI = abis.cappedSTO(); let configureFunction = cappedSTOABI.find(o => o.name === 'configure' && o.type === 'function'); - let bytesSTO = web3.eth.abi.encodeFunctionCall( configureFunction, - [ cappedSTOconfig.startTime, - cappedSTOconfig.endTime, - web3.utils.toWei(cappedSTOconfig.cap.toString()), - cappedSTOconfig.rate, - cappedSTOconfig.raiseType, - cappedSTOconfig.wallet ] + let bytesSTO = web3.eth.abi.encodeFunctionCall(configureFunction, + [cappedSTOconfig.startTime, + cappedSTOconfig.endTime, + web3.utils.toWei(cappedSTOconfig.cap.toString()), + cappedSTOconfig.rate, + cappedSTOconfig.raiseType, + cappedSTOconfig.wallet] ); let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, stoFee, 0); @@ -229,7 +229,7 @@ async function cappedSTO_status(currentSTO) { let displayInvestorCount = await currentSTO.methods.investorCount().call(); let displayTokenSymbol = await securityToken.methods.symbol().call(); - let now = Math.floor(Date.now()/1000); + let now = Math.floor(Date.now() / 1000); let timeTitle; let timeRemaining; @@ -270,7 +270,7 @@ async function cappedSTO_status(currentSTO) { function fundingConfigUSDTieredSTO() { let funding = {}; - let selectedFunding = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise,' + chalk.green(` D `) + 'for DAI raise,' + chalk.green(` E `) + 'for Ether raise or any combination of them (i.e.'+ chalk.green(` PED `) + 'for all): ').toUpperCase(); + let selectedFunding = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise,' + chalk.green(` D `) + 'for DAI raise,' + chalk.green(` E `) + 'for Ether raise or any combination of them (i.e.' + chalk.green(` PED `) + 'for all): ').toUpperCase(); funding.raiseType = []; if (selectedFunding.includes('E')) { @@ -293,7 +293,7 @@ function addressesConfigUSDTieredSTO(usdTokenRaise) { let addresses = {}; addresses.wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address", @@ -302,7 +302,7 @@ function addressesConfigUSDTieredSTO(usdTokenRaise) { if (addresses.wallet == "") addresses.wallet = Issuer.address; addresses.reserveWallet = readlineSync.question('Enter the address that will receive remaining tokens in the case the cap is not met (' + Issuer.address + '): ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address", @@ -312,7 +312,7 @@ function addressesConfigUSDTieredSTO(usdTokenRaise) { if (usdTokenRaise) { addresses.usdToken = readlineSync.question('Enter the address of the USD Token or stable coin (' + usdToken.options.address + '): ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address", @@ -321,7 +321,7 @@ function addressesConfigUSDTieredSTO(usdTokenRaise) { if (addresses.usdToken == "") addresses.usdToken = usdToken.options.address; } else { addresses.usdToken = '0x0000000000000000000000000000000000000000'; - } + } return addresses; } @@ -330,13 +330,13 @@ function tiersConfigUSDTieredSTO(polyRaise) { let tiers = {}; let defaultTiers = 3; - tiers.tiers = readlineSync.questionInt(`Enter the number of tiers for the STO? (${defaultTiers}): `, { - limit: function(input) { - return input > 0; + tiers.tiers = parseInt(readlineSync.question(`Enter the number of tiers for the STO? (${defaultTiers}): `, { + limit: function (input) { + return parseInt(input) > 0; }, limitMessage: 'Must be greater than zero', defaultInput: defaultTiers - }); + })); let defaultTokensPerTier = [190000000, 100000000, 200000000]; let defaultRatePerTier = ['0.05', '0.10', '0.15']; @@ -347,33 +347,33 @@ function tiersConfigUSDTieredSTO(polyRaise) { tiers.tokensPerTierDiscountPoly = []; tiers.ratePerTierDiscountPoly = []; for (let i = 0; i < tiers.tiers; i++) { - tiers.tokensPerTier[i] = readlineSync.question(`How many tokens do you plan to sell on tier No. ${i+1}? (${defaultTokensPerTier[i]}): `, { - limit: function(input) { + tiers.tokensPerTier[i] = readlineSync.question(`How many tokens do you plan to sell on tier No. ${i + 1}? (${defaultTokensPerTier[i]}): `, { + limit: function (input) { return parseFloat(input) > 0; }, limitMessage: 'Must be greater than zero', defaultInput: defaultTokensPerTier[i] }); - tiers.ratePerTier[i] = readlineSync.question(`What is the USD per token rate for tier No. ${i+1}? (${defaultRatePerTier[i]}): `, { - limit: function(input) { + tiers.ratePerTier[i] = readlineSync.question(`What is the USD per token rate for tier No. ${i + 1}? (${defaultRatePerTier[i]}): `, { + limit: function (input) { return parseFloat(input) > 0; }, limitMessage: 'Must be greater than zero', defaultInput: defaultRatePerTier[i] }); - if (polyRaise && readlineSync.keyInYNStrict(`Do you plan to have a discounted rate for POLY investments for tier No. ${i+1}? `)) { - tiers.tokensPerTierDiscountPoly[i] = readlineSync.question(`How many of those tokens do you plan to sell at discounted rate on tier No. ${i+1}? (${defaultTokensPerTierDiscountPoly[i]}): `, { - limit: function(input) { + if (polyRaise && readlineSync.keyInYNStrict(`Do you plan to have a discounted rate for POLY investments for tier No. ${i + 1}? `)) { + tiers.tokensPerTierDiscountPoly[i] = readlineSync.question(`How many of those tokens do you plan to sell at discounted rate on tier No. ${i + 1}? (${defaultTokensPerTierDiscountPoly[i]}): `, { + limit: function (input) { return parseFloat(input) < parseFloat(tiers.tokensPerTier[i]); }, limitMessage: 'Must be less than the No. of tokens of the tier', defaultInput: defaultTokensPerTierDiscountPoly[i] }); - tiers.ratePerTierDiscountPoly[i] = readlineSync.question(`What is the discounted rate for tier No. ${i+1}? (${defaultRatePerTierDiscountPoly[i]}): `, { - limit: function(input) { + tiers.ratePerTierDiscountPoly[i] = readlineSync.question(`What is the discounted rate for tier No. ${i + 1}? (${defaultRatePerTierDiscountPoly[i]}): `, { + limit: function (input) { return parseFloat(input) < parseFloat(tiers.ratePerTier[i]); }, limitMessage: 'Must be less than the rate of the tier', @@ -393,7 +393,7 @@ function limitsConfigUSDTieredSTO() { let defaultMinimumInvestment = 5; limits.minimumInvestmentUSD = readlineSync.question(`What is the minimum investment in USD? (${defaultMinimumInvestment}): `, { - limit: function(input) { + limit: function (input) { return parseFloat(input) > 0; }, limitMessage: "Must be greater than zero", @@ -402,7 +402,7 @@ function limitsConfigUSDTieredSTO() { let nonAccreditedLimit = 2500; limits.nonAccreditedLimitUSD = readlineSync.question(`What is the default limit for non accredited investors in USD? (${nonAccreditedLimit}): `, { - limit: function(input) { + limit: function (input) { return parseFloat(input) >= parseFloat(limits.minimumInvestmentUSD); }, limitMessage: "Must be greater than minimum investment", @@ -417,13 +417,13 @@ function timesConfigUSDTieredSTO(stoConfig) { let oneMinuteFromNow = Math.floor(Date.now() / 1000) + 60; if (typeof stoConfig === 'undefined') { - times.startTime = readlineSync.questionInt('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): ', { - limit: function(input) { - return input > Math.floor(Date.now() / 1000); + times.startTime = parseInt(readlineSync.question('Enter the start time for the STO (Unix Epoch time)\n(1 minutes from now = ' + oneMinuteFromNow + ' ): ', { + limit: function (input) { + return parseInt(input) > Math.floor(Date.now() / 1000); }, limitMessage: "Must be a future time", defaultInput: oneMinuteFromNow - }); + })); } else { times.startTime = stoConfig.times.startTime; } @@ -431,13 +431,13 @@ function timesConfigUSDTieredSTO(stoConfig) { let oneMonthFromNow = Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60); if (typeof stoConfig === 'undefined') { - times.endTime = readlineSync.questionInt('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): ', { - limit: function(input) { - return input > times.startTime; + times.endTime = parseInt(readlineSync.question('Enter the end time for the STO (Unix Epoch time)\n(1 month from now = ' + oneMonthFromNow + ' ): ', { + limit: function (input) { + return parseInt(input) > times.startTime; }, limitMessage: "Must be greater than Start Time", defaultInput: oneMonthFromNow - }); + })); } else { times.endTime = stoConfig.times.startTime; } @@ -466,7 +466,7 @@ async function usdTieredSTO_launch(stoConfig) { return; } else { let transferAction = polyToken.methods.transfer(securityToken._address, transferAmount); - let receipt = await common.sendTransaction(transferAction, {factor: 2}); + let receipt = await common.sendTransaction(transferAction, { factor: 2 }); let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) } @@ -481,19 +481,19 @@ async function usdTieredSTO_launch(stoConfig) { let usdTieredSTOABI = abis.usdTieredSTO(); let configureFunction = usdTieredSTOABI.find(o => o.name === 'configure' && o.type === 'function'); - let bytesSTO = web3.eth.abi.encodeFunctionCall( configureFunction, - [ times.startTime, - times.endTime, - tiers.ratePerTier.map(r => web3.utils.toWei(r.toString())), - tiers.ratePerTierDiscountPoly.map(rd => web3.utils.toWei(rd.toString())), - tiers.tokensPerTier.map(t => web3.utils.toWei(t.toString())), - tiers.tokensPerTierDiscountPoly.map(td => web3.utils.toWei(td.toString())), - web3.utils.toWei(limits.nonAccreditedLimitUSD.toString()), - web3.utils.toWei(limits.minimumInvestmentUSD.toString()), - funding.raiseType, - addresses.wallet, - addresses.reserveWallet, - addresses.usdToken ] + let bytesSTO = web3.eth.abi.encodeFunctionCall(configureFunction, + [times.startTime, + times.endTime, + tiers.ratePerTier.map(r => web3.utils.toWei(r.toString())), + tiers.ratePerTierDiscountPoly.map(rd => web3.utils.toWei(rd.toString())), + tiers.tokensPerTier.map(t => web3.utils.toWei(t.toString())), + tiers.tokensPerTierDiscountPoly.map(td => web3.utils.toWei(td.toString())), + web3.utils.toWei(limits.nonAccreditedLimitUSD.toString()), + web3.utils.toWei(limits.minimumInvestmentUSD.toString()), + funding.raiseType, + addresses.wallet, + addresses.reserveWallet, + addresses.usdToken] ); let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, stoFee, 0); @@ -525,7 +525,7 @@ async function usdTieredSTO_status(currentSTO) { let raiseTypes = []; for (const fundType in gbl.constants.FUND_RAISE_TYPES) { if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { - raiseTypes.push(fundType); + raiseTypes.push(fundType); } } @@ -559,14 +559,14 @@ async function usdTieredSTO_status(currentSTO) { } displayTiers += ` - - Tier ${t+1}: + - Tier ${t + 1}: Tokens: ${web3.utils.fromWei(tokensPerTierTotal)} ${displayTokenSymbol} Rate: ${web3.utils.fromWei(ratePerTier)} USD per Token` - + displayDiscountTokens; + + displayDiscountTokens; - displayMintedPerTier += ` - - Tokens minted in Tier ${t+1}: ${web3.utils.fromWei(mintedPerTierTotal)} ${displayTokenSymbol}` - + displayMintedPerTierPerType; + displayMintedPerTier += ` + - Tokens minted in Tier ${t + 1}: ${web3.utils.fromWei(mintedPerTierTotal)} ${displayTokenSymbol}` + + displayMintedPerTierPerType; } let displayFundsRaisedUSD = web3.utils.fromWei(await currentSTO.methods.fundsRaisedUSD().call()); @@ -581,13 +581,13 @@ async function usdTieredSTO_status(currentSTO) { let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); displayWalletBalancePerType += ` Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; - + balance = await getBalance(displayReserveWallet, gbl.constants.FUND_RAISE_TYPES[type]); let reserveWalletBalance = web3.utils.fromWei(balance); let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); displayReserveWalletBalancePerType += ` Balance ${type}:\t\t ${reserveWalletBalance} ${type} (${reserveWalletBalanceUSD} USD)`; - + let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); displayFundsRaisedPerType += ` ${type}:\t\t\t ${fundsRaised} ${type}`; @@ -602,7 +602,7 @@ async function usdTieredSTO_status(currentSTO) { let displayRaiseType = raiseTypes.join(' - '); - let now = Math.floor(Date.now()/1000); + let now = Math.floor(Date.now() / 1000); let timeTitle; let timeRemaining; if (now < displayStartTime) { @@ -622,24 +622,24 @@ async function usdTieredSTO_status(currentSTO) { - End Time: ${new Date(displayEndTime * 1000)} - Raise Type: ${displayRaiseType} - Tiers: ${tiersLength}` - + displayTiers + ` + + displayTiers + ` - Minimum Investment: ${displayMinimumInvestmentUSD} USD - Non Accredited Limit: ${displayNonAccreditedLimitUSD} USD - Wallet: ${displayWallet}` - + displayWalletBalancePerType + ` + + displayWalletBalancePerType + ` - Reserve Wallet: ${displayReserveWallet}` - + displayReserveWalletBalancePerType + ` + + displayReserveWalletBalancePerType + ` --------------------------------------------------------------- - ${timeTitle} ${timeRemaining} - Is Finalized: ${displayIsFinalized} - Tokens Sold: ${displayTokensSold} ${displayTokenSymbol}` - + displayTokensSoldPerType + ` + + displayTokensSoldPerType + ` - Current Tier: ${displayCurrentTier}` - + displayMintedPerTier + ` + + displayMintedPerTier + ` - Investor count: ${displayInvestorCount} - Funds Raised` - + displayFundsRaisedPerType + ` + + displayFundsRaisedPerType + ` USD: ${displayFundsRaisedUSD} USD `); @@ -815,7 +815,7 @@ async function initialize(_tokenSymbol) { tokenSymbol = _tokenSymbol; } let securityTokenAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); - if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { + if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { console.log(chalk.red(`Selected Security Token ${tokenSymbol} does not exist.`)); process.exit(0); } @@ -833,7 +833,7 @@ function welcome() { console.log("Issuer Account: " + Issuer.address + "\n"); } -async function setup(){ +async function setup() { try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -851,25 +851,25 @@ async function setup(){ usdToken.setProvider(web3.currentProvider); } catch (err) { console.log(err) - console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); + console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); process.exit(0); } } async function selectToken() { let result = null; - + let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); let tokenDataArray = await Promise.all(userTokens.map(async function (t) { let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); - return {symbol: tokenData[0], address: t}; + return { symbol: tokenData[0], address: t }; })); let options = tokenDataArray.map(function (t) { return `${t.symbol} - Deployed at ${t.address}`; }); options.push('Enter token symbol manually'); - let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); + let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); switch (options[index]) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); @@ -881,16 +881,16 @@ async function selectToken() { result = tokenDataArray[index].symbol; break; } - + return result; } module.exports = { - executeApp: async function(_tokenSymbol) { + executeApp: async function (_tokenSymbol) { await initialize(_tokenSymbol); return executeApp(); }, - addSTOModule: async function(_tokenSymbol, stoConfig) { + addSTOModule: async function (_tokenSymbol, stoConfig) { await initialize(_tokenSymbol); return addSTOModule(stoConfig) } diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 47361cb12..6faa7ba34 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -17,7 +17,7 @@ let featureRegistry; let securityToken; let allModules; -let tokenSymbol +let tokenSymbol async function setup() { try { @@ -63,7 +63,7 @@ async function displayTokenData() { let displayTransferFrozen = await securityToken.methods.transfersFrozen().call(); let displayMintingFrozen = await securityToken.methods.mintingFrozen().call(); let displayUserTokens = await securityToken.methods.balanceOf(Issuer.address).call(); - + console.log(` *************** Security Token Information **************** - Address: ${securityToken.options.address} @@ -137,7 +137,7 @@ async function selectAction() { } else { options.push('Freeze transfers'); } - + let isMintingFrozen = await securityToken.methods.mintingFrozen().call(); if (!isMintingFrozen) { let isFreezeMintingAllowed = await featureRegistry.methods.getFeatureStatus('freezeMintingAllowed').call(); @@ -147,7 +147,7 @@ async function selectAction() { } options.push('Create a checkpoint', 'List investors') - + let currentCheckpointId = await securityToken.methods.currentCheckpointId().call(); if (currentCheckpointId > 0) { options.push('List investors at checkpoint') @@ -159,7 +159,7 @@ async function selectAction() { options.push('Manage modules', 'Withdraw tokens from contract'); - let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Exit'}); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Exit' }); let selected = index == -1 ? 'Exit' : options[index]; console.log('Selected:', selected); switch (selected) { @@ -187,9 +187,9 @@ async function selectAction() { await listInvestors(); break; case 'List investors at checkpoint': - let checkpointId = readlineSync.questionInt('Enter the id of the checkpoint: ', { + let checkpointId = readlineSync.question('Enter the id of the checkpoint: ', { limit: function (input) { - return input > 0 && input <= currentCheckpointId; + return parseInt(input) > 0 && parseInt(input) <= parseInt(currentCheckpointId); }, limitMessage: `Must be greater than 0 and less than ${currentCheckpointId}` }); @@ -275,22 +275,22 @@ async function listInvestorsAtCheckpoint(checkpointId) { } else { console.log(chalk.yellow(`There are no investors at checkpoint ${checkpointId}`)); } - + } async function mintTokens() { let options = ['Modify whitelist', 'Mint tokens to a single address', `Modify whitelist and mint tokens using data from 'whitelist_data.csv' and 'multi_mint_data.csv'`]; - let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: 'Return'}); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); let selected = index == -1 ? 'Return' : options[index]; console.log('Selected:', selected); switch (selected) { case 'Modify whitelist': let investor = readlineSync.question('Enter the address to whitelist: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" - }); + }); let fromTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); let toTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); let expiryTime = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); @@ -354,7 +354,7 @@ async function withdrawFromContract(erc20address, value) { async function listModuleOptions() { let options = ['Add a module'] - + let unpausedModules = allModules.filter(m => m.paused == false); if (unpausedModules.length > 0) { options.push('Pause a module'); @@ -379,7 +379,7 @@ async function listModuleOptions() { options.push('Remove a module', 'Change module budget'); } - let index = readlineSync.keyInSelect(options, chalk.yellow('What do you want to do?'), {cancel: 'Return'}); + let index = readlineSync.keyInSelect(options, chalk.yellow('What do you want to do?'), { cancel: 'Return' }); let selected = index == -1 ? 'Exit' : options[index]; console.log('Selected:', selected); switch (selected) { @@ -403,14 +403,14 @@ async function listModuleOptions() { break; case 'Change module budget': await changeBudget(allModules); - break; + break; } } // Modules a actions async function addModule() { let options = ['Permission Manager', 'Transfer Manager', 'Security Token Offering', 'Dividends', 'Burn']; - let index = readlineSync.keyInSelect(options, 'What type of module whould you like to add?', {cancel: 'Return'}); + let index = readlineSync.keyInSelect(options, 'What type of module whould you like to add?', { cancel: 'Return' }); switch (options[index]) { case 'Permission Manager': console.log(chalk.red(` @@ -446,7 +446,7 @@ async function pauseModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); let index = readlineSync.keyInSelect(options, 'Which module whould you like to pause?'); if (index != -1) { - console.log("\nSelected:",options[index]); + console.log("\nSelected:", options[index]); let moduleABI; if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { moduleABI = abis.ISTO(); @@ -467,7 +467,7 @@ async function unpauseModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); let index = readlineSync.keyInSelect(options, 'Which module whould you like to pause?'); if (index != -1) { - console.log("\nSelected: ",options[index]); + console.log("\nSelected: ", options[index]); let moduleABI; if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { moduleABI = abis.ISTO(); @@ -488,9 +488,9 @@ async function archiveModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); let index = readlineSync.keyInSelect(options, 'Which module would you like to archive?'); if (index != -1) { - console.log("\nSelected: ",options[index]); + console.log("\nSelected: ", options[index]); let archiveModuleAction = securityToken.methods.archiveModule(modules[index].address); - await common.sendTransaction(archiveModuleAction, {factor: 2}); + await common.sendTransaction(archiveModuleAction, { factor: 2 }); console.log(chalk.green(`${modules[index].name} has been archived successfully!`)); } } @@ -499,9 +499,9 @@ async function unarchiveModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); let index = readlineSync.keyInSelect(options, 'Which module whould you like to unarchive?'); if (index != -1) { - console.log("\nSelected: ",options[index]); + console.log("\nSelected: ", options[index]); let unarchiveModuleAction = securityToken.methods.unarchiveModule(modules[index].address); - await common.sendTransaction(unarchiveModuleAction, {factor: 2}); + await common.sendTransaction(unarchiveModuleAction, { factor: 2 }); console.log(chalk.green(`${modules[index].name} has been unarchived successfully!`)); } } @@ -510,9 +510,9 @@ async function removeModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); let index = readlineSync.keyInSelect(options, 'Which module whould you like to remove?'); if (index != -1) { - console.log("\nSelected: ",options[index]); + console.log("\nSelected: ", options[index]); let removeModuleAction = securityToken.methods.removeModule(modules[index].address); - await common.sendTransaction(removeModuleAction, {factor: 2}); + await common.sendTransaction(removeModuleAction, { factor: 2 }); console.log(chalk.green(`${modules[index].name} has been removed successfully!`)); } } @@ -521,8 +521,8 @@ async function changeBudget() { let options = modules.map(m => `${m.name} (${m.address})`); let index = readlineSync.keyInSelect(options, 'Which module whould you like to remove?'); if (index != -1) { - console.log("\nSelected: ",options[index]); - let increase = 0 == readlineSync.keyInSelect(['Increase', 'Decrease'], `Do you want to increase or decrease budget?`, {cancel: false}); + console.log("\nSelected: ", options[index]); + let increase = 0 == readlineSync.keyInSelect(['Increase', 'Decrease'], `Do you want to increase or decrease budget?`, { cancel: false }); let amount = readlineSync.question(`Enter the amount of POLY to change in allowance`); let changeModuleBudgetAction = securityToken.methods.changeModuleBudget(modules[index].address, web3.utils.toWei(amount), increase); await common.sendTransaction(changeModuleBudgetAction); @@ -532,7 +532,7 @@ async function changeBudget() { // Helpers async function showUserInfo(_user) { - console.log(` + console.log(` ******************** User Information ********************* - Address: ${_user} - POLY balance: ${web3.utils.fromWei(await polyToken.methods.balanceOf(_user).call())} @@ -568,7 +568,7 @@ async function getAllModules() { pausedTemp = await contractTemp.methods.paused().call(); } modules.push(new ModuleInfo(type, nameTemp, details[1], details[2], details[3], pausedTemp)); - } catch(error) { + } catch (error) { console.log(error); console.log(chalk.red(` ************************* @@ -590,7 +590,7 @@ async function initialize(_tokenSymbol) { tokenSymbol = _tokenSymbol; } let securityTokenAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); - if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { + if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { console.log(chalk.red(`Selected Security Token ${tokenSymbol} does not exist.`)); process.exit(0); } @@ -610,18 +610,18 @@ function welcome() { async function selectToken() { let result = null; - + let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); let tokenDataArray = await Promise.all(userTokens.map(async function (t) { let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); - return {symbol: tokenData[0], address: t}; + return { symbol: tokenData[0], address: t }; })); let options = tokenDataArray.map(function (t) { return `${t.symbol} - Deployed at ${t.address}`; }); options.push('Enter token symbol manually'); - let index = readlineSync.keyInSelect(options, 'Select a token:', {cancel: 'Exit'}); + let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); switch (options[index]) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); @@ -633,12 +633,12 @@ async function selectToken() { result = tokenDataArray[index].symbol; break; } - + return result; } module.exports = { - executeApp: async function(_tokenSymbol) { + executeApp: async function (_tokenSymbol) { await initialize(_tokenSymbol) return executeApp(); } From 3379a6f82976fa5ccfe1b2a83c1860e67616488e Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 28 Nov 2018 14:39:31 +0100 Subject: [PATCH 246/582] WIP --- .../z_fuzz_test_adding_removing_modules_ST.js | 58 +++++++++++-------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index 8a455f3cd..f14522857 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -17,11 +17,15 @@ import { encodeModuleCall } from "./helpers/encodeCall"; const SecurityToken = artifacts.require('./SecurityToken.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); + +// modules for test const CountTransferManager = artifacts.require("./CountTransferManager"); -const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); -const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionTM'); const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); +const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); +const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); + + const Web3 = require('web3'); const BigNumber = require('bignumber.js'); @@ -53,10 +57,6 @@ contract('GeneralPermissionManager', accounts => { let I_SecurityTokenRegistryProxy; let P_GeneralPermissionManager; let I_GeneralTransferManagerFactory; - let I_VolumeRestrictionTransferManagerFactory; - let I_PercentageTransferManagerFactory; - let I_PercentageTransferManager; - let I_VolumeRestrictionTransferManager; let I_GeneralPermissionManager; let I_GeneralTransferManager; let I_ModuleRegistryProxy; @@ -70,18 +70,26 @@ contract('GeneralPermissionManager', accounts => { let I_STRProxied; let I_PolyToken; let I_PolymathRegistry; + + + //Define all modules for test let I_CountTransferManagerFactory; let I_CountTransferManager; + let I_SingleTradeVolumeRestrictionManagerFactory; let I_SingleTradeVolumeRestrictionManager; - let I_SingleTradeVolumeRestrictionPercentageManager; - let P_SingleTradeVolumeRestrictionManager; + let P_SingleTradeVolumeRestrictionManagerFactory; + let P_SingleTradeVolumeRestrictionManager; + let I_ManualApprovalTransferManagerFactory; let I_ManualApprovalTransferManager; - //Define all modules for test - let + let I_VolumeRestrictionTransferManagerFactory; + let I_VolumeRestrictionTransferManager; + + let I_PercentageTransferManagerFactory; + let I_PercentageTransferManager; // SecurityToken Details const name = "Team"; @@ -108,8 +116,10 @@ contract('GeneralPermissionManager', accounts => { let testRepeat = 20; // permission manager fuzz test - let modules = ['CappedSTO','DummySTO', 'USDTieredSTO', 'CountTransferManager', 'ManualApprovalTransferManager', 'PercentageTransferManager']; - let totalPerms = perms.length; + // let modules = ['CountTransferManager', 'SingleTradeVolumeRestrictionManager', 'ManualApprovalTransferManager', 'I_VolumeRestrictionTransferManager', 'PercentageTransferManager']; + let modules = ['I_CountTransferManager']; + let totalModules = modules.length; + before(async () => { // Accounts setup @@ -151,15 +161,11 @@ contract('GeneralPermissionManager', accounts => { // Deploy Modules [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - - [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); - - [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); - [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); // Printing all the contract addresses console.log(` @@ -257,16 +263,22 @@ contract('GeneralPermissionManager', accounts => { console.log("1"); // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts for (var i = 0; i < testRepeat; i++) { + + var j = Math.floor(Math.random() * 10); // choose a random module + let randomModule = modules[Math.floor(Math.random() * Math.floor(totalModules))]; + console.log("choosen module "+ randomModule); + // attach it to the ST + let tx = await I_SecurityToken.addModule(randomModule.address, bytesSTO, 0, 0, { from: token_owner }); + console.log("successfully attached module " + randomModule); + // remove it from the ST + tx = await I_SecurityToken.removeModule(randomModule.address, { from: token_owner }); + console.log("successfully removed module " + randomModule); - // attach it to the ST - - // remove it from the ST - - }; + } }) }); From 9335b27e162f9386154e050898186f5e381e3e7e Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 28 Nov 2018 19:55:47 +0530 Subject: [PATCH 247/582] minor fix in readme to reset the MATM --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9caa44f67..8c5ae0a4e 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,7 @@ node CLI/polymath-cli dividends_manager | ERC20 Dividends Checkpoint Factory: | [0x82f9f1ab41bacb1433c79492e54bf13bccd7f9ae](https://etherscan.io/address/0x82f9f1ab41bacb1433c79492e54bf13bccd7f9ae) | | Count Transfer Manager Factory: | [0xd9fd7e34d6e2c47a69e02131cf8554d52c3445d5](https://etherscan.io/address/0xd9fd7e34d6e2c47a69e02131cf8554d52c3445d5) | | Percentage Transfer Manager Factory: | [0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b](https://etherscan.io/address/0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b) | -| Manual Approval Transfer Manager Factory (2.0.1): | [0x6af2afad53cb334e62b90ddbdcf3a086f654c298](https://etherscan.io/address/0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b) | +| Manual Approval Transfer Manager Factory (2.0.1): | [0x6af2afad53cb334e62b90ddbdcf3a086f654c298](https://etherscan.io/address/0x6af2afad53cb334e62b90ddbdcf3a086f654c298) | New SecurityTokenRegistry (2.0.1): 0x538136ed73011a766bf0a126a27300c3a7a2e6a6 From 17f10154cb8058617ccad792302738a827774b4c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 28 Nov 2018 21:37:13 +0530 Subject: [PATCH 248/582] Updated comments --- contracts/modules/STO/CappedSTO.sol | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 0d79d285c..d85fcb3da 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -13,10 +13,11 @@ contract CappedSTO is ISTO, ReentrancyGuard { // Determine whether users can invest on behalf of a beneficiary bool public allowBeneficialInvestments = false; - // How many token units multiplied by 10^18 a buyer gets per wei / base unit of POLY + // How many token units a buyer gets (multiplied by 10^18) per wei / base unit of POLY // If rate is 10^18, buyer will get 1 token unit for every wei / base unit of poly. uint256 public rate; - //How many tokens this STO will be allowed to sell to investors + //How many token base units this STO will be allowed to sell to investors + // 1 full token = 10^decimals_of_token base units uint256 public cap; mapping (address => uint256) public investors; @@ -49,8 +50,8 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @notice Function used to intialize the contract variables * @param _startTime Unix timestamp at which offering get started * @param _endTime Unix timestamp at which offering get ended - * @param _cap Maximum No. of tokens for sale - * @param _rate Token units multiplied by 10^18 a buyer gets per wei / base unit of POLY + * @param _cap Maximum No. of token base units for sale + * @param _rate Token units a buyer gets multiplied by 10^18 per wei / base unit of POLY * @param _fundRaiseTypes Type of currency used to collect the funds * @param _fundsReceiver Ethereum account address to hold the funds */ @@ -154,8 +155,8 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @notice Return the STO details * @return Unixtimestamp at which offering gets start. * @return Unixtimestamp at which offering ends. - * @return Number of tokens this STO will be allowed to sell to investors. - * @return Token units multiplied by 10^18 a buyer gets per wei / base unit of POLY + * @return Number of token base units this STO will be allowed to sell to investors. + * @return Token units a buyer gets(multiplied by 10^18) per wei / base unit of POLY * @return Amount of funds raised * @return Number of individual investors this STO have. * @return Amount of tokens get sold. From dde0a91f847fee0a1ee2213e2b1b7b77e47471f6 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 28 Nov 2018 14:37:51 -0300 Subject: [PATCH 249/582] Allow to add TM modules from token_manager --- CLI/commands/token_manager.js | 6 ++---- CLI/commands/transfer_manager.js | 4 ++++ CLI/polymath-cli.js | 32 ++++++++++++++++---------------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 6faa7ba34..eaa70b09a 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -4,6 +4,7 @@ const chalk = require('chalk'); const whitelist = require('./whitelist'); const multimint = require('./multi_mint'); const stoManager = require('./sto_manager'); +const transferManager = require('./transfer_manager'); const common = require('./common/common_functions'); const gbl = require('./common/global'); @@ -419,10 +420,7 @@ async function addModule() { *********************************`)); break; case 'Transfer Manager': - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************`)); + await transferManager.addTransferManagerModule(tokenSymbol) break; case 'Security Token Offering': await stoManager.addSTOModule(tokenSymbol) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index e4a62891a..083c95e14 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -948,5 +948,9 @@ module.exports = { executeApp: async function (_tokenSymbol) { await initialize(_tokenSymbol); return executeApp(); + }, + addTransferManagerModule: async function (_tokenSymbol) { + await initialize(_tokenSymbol); + return addTransferManagerModule() } } \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index f154b5f8a..79b9c4c70 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -35,7 +35,7 @@ program .option('-d, --details
', 'Off-chain details of the token') .option('-D, --divisible
', 'If token is divisible or not [true]', /^(true|false)/) .description('Wizard-like script that will guide technical users in the creation and deployment of an ST-20 token') - .action(async function(cmd) { + .action(async function (cmd) { await gbl.initialize(program.remoteNode); await st20generator.executeApp(cmd.ticker, cmd.transferOwnership, cmd.tokenName, cmd.details, cmd.divisible); }); @@ -46,7 +46,7 @@ program .option('-t, --securityToken ', 'Selects a ST to manage modules') .option('-l, --launch ', 'Uses configuration file to configure and launch a STO') .description('Wizard-like script that will guide technical users in the creation of an STO') - .action(async function(cmd) { + .action(async function (cmd) { await gbl.initialize(program.remoteNode); if (cmd.launch) { let config = yaml.safeLoad(fs.readFileSync(`${__dirname}/${cmd.launch}`, 'utf8')); @@ -60,7 +60,7 @@ program .command('faucet [beneficiary] [amount]') .alias('f') .description('Poly faucet for local private netwtorks') - .action(async function(beneficiary, amount) { + .action(async function (beneficiary, amount) { await gbl.initialize(program.remoteNode); await faucet.executeApp(beneficiary, amount); }); @@ -69,7 +69,7 @@ program .command('investor_portal [investor] [privateKey] [symbol] [currency] [amount]') .alias('i') .description('Participate in any STO you have been whitelisted for') - .action(async function(investor, privateKey, symbol, currency, amount) { + .action(async function (investor, privateKey, symbol, currency, amount) { await gbl.initialize(program.remoteNode); await investor_portal.executeApp(investor, privateKey, symbol, currency, amount); }); @@ -79,7 +79,7 @@ program .alias('stm') .option('-t, --securityToken ', 'Selects a ST to manage') .description('Manage your Security Tokens, mint tokens, add modules and change config') - .action(async function(cmd) { + .action(async function (cmd) { await gbl.initialize(program.remoteNode); await token_manager.executeApp(cmd.securityToken); }); @@ -88,7 +88,7 @@ program .command('multi_mint [batchSize]') .alias('mi') .description('Distribute tokens to previously whitelisted investors') - .action(async function(tokenSymbol, batchSize) { + .action(async function (tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); await multimint.executeApp(tokenSymbol, batchSize); }); @@ -97,7 +97,7 @@ program .command('transfer ') .alias('t') .description('Transfer ST tokens to another account') - .action(async function(tokenSymbol, transferTo, transferAmount) { + .action(async function (tokenSymbol, transferTo, transferAmount) { await gbl.initialize(program.remoteNode); await transfer.executeApp(tokenSymbol, transferTo, transferAmount); }); @@ -106,7 +106,7 @@ program .command('transfer_ownership ') .alias('to') .description('Transfer Ownership of an own contract to another account') - .action(async function(contractAddress, transferTo) { + .action(async function (contractAddress, transferTo) { await gbl.initialize(program.remoteNode); await transfer_ownership.executeApp(contractAddress, transferTo); }); @@ -115,7 +115,7 @@ program .command('whitelist [batchSize]') .alias('w') .description('Mass-update a whitelist of allowed/known investors') - .action(async function(tokenSymbol, batchSize) { + .action(async function (tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); await whitelist.executeApp(tokenSymbol, batchSize); }); @@ -124,7 +124,7 @@ program .command('dividends_manager [dividendsType]') .alias('dm') .description('Runs dividends_manager') - .action(async function(dividendsType) { + .action(async function (dividendsType) { await gbl.initialize(program.remoteNode); await dividends_manager.executeApp(dividendsType); }); @@ -134,7 +134,7 @@ program .alias('tm') .option('-t, --securityToken ', 'Selects a ST to manage transfer modules') .description('Runs transfer_manager') - .action(async function(cmd) { + .action(async function (cmd) { await gbl.initialize(program.remoteNode); await transfer_manager.executeApp(cmd.securityToken); }); @@ -143,7 +143,7 @@ program .command('contract_manager') .alias('cm') .description('Runs contract_manager') - .action(async function() { + .action(async function () { await gbl.initialize(program.remoteNode); await contract_manager.executeApp(); }); @@ -152,7 +152,7 @@ program .command('accredit [batchSize]') .alias('a') .description('Runs accredit') - .action(async function(tokenSymbol, batchSize) { + .action(async function (tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); await accredit.executeApp(tokenSymbol, batchSize); }); @@ -161,7 +161,7 @@ program .command('nonAccreditedLimit [batchSize]') .alias('nal') .description('Runs changeNonAccreditedLimit') - .action(async function(tokenSymbol, batchSize) { + .action(async function (tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); await changeNonAccreditedLimit.executeApp(tokenSymbol, batchSize); }); @@ -170,7 +170,7 @@ program .command('strMigrator [toStrAddress] [fromTrAddress] [fromStrAddress]') .alias('str') .description('Runs STR Migrator') - .action(async function(toStrAddress, fromTrAddress, fromStrAddress) { + .action(async function (toStrAddress, fromTrAddress, fromStrAddress) { await gbl.initialize(program.remoteNode); await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress); }); @@ -179,7 +179,7 @@ program .command('permission_manager') .alias('pm') .description('Runs permission_manager') - .action(async function() { + .action(async function () { await gbl.initialize(program.remoteNode); await permission_manager.executeApp(); }); From 9105172b8335034261ece564717514317e7d2ac8 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 28 Nov 2018 14:43:00 -0300 Subject: [PATCH 250/582] Whitelist from csv fix --- CLI/commands/transfer_manager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 083c95e14..004bc603a 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -5,6 +5,7 @@ var common = require('./common/common_functions'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); var gbl = require('./common/global'); +var whitelist = require('./whitelist'); // App flow let tokenSymbol; @@ -373,7 +374,7 @@ async function generalTransferManager() { case 'Modify whitelist from CSV': console.log(chalk.yellow(`Data is going to be read from 'data/whitelist_data.csv'. Be sure this file is updated!`)); if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { - shell.exec(`${__dirname}/scripts/script.sh Whitelist ${tokenSymbol} 75 ${network}`); + await whitelist.executeApp(tokenSymbl); } break; /* From 7064effab2fd74eb7a6c5021e263c0d6c49795cb Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 28 Nov 2018 14:44:06 -0300 Subject: [PATCH 251/582] Deleted network variable --- CLI/commands/transfer_manager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 004bc603a..44ae64ca1 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -11,7 +11,6 @@ var whitelist = require('./whitelist'); let tokenSymbol; let securityToken; let securityTokenRegistry; -let network; let currentTransferManager; async function executeApp() { From 09424e0b35f95d8a2fe961adc2b9c4ccfc9e370e Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 28 Nov 2018 15:28:23 -0300 Subject: [PATCH 252/582] CLI - Fix at removing modules --- CLI/commands/token_manager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 6faa7ba34..98d13fd3d 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -372,11 +372,11 @@ async function listModuleOptions() { let archivedModules = allModules.filter(m => m.archived); if (archivedModules.length > 0) { - options.push('Unarchive a module'); + options.push('Unarchive a module', 'Remove a module'); } if (allModules.length > 0) { - options.push('Remove a module', 'Change module budget'); + options.push('Change module budget'); } let index = readlineSync.keyInSelect(options, chalk.yellow('What do you want to do?'), { cancel: 'Return' }); @@ -399,7 +399,7 @@ async function listModuleOptions() { await unarchiveModule(archivedModules); break; case 'Remove a module': - await removeModule(allModules); + await removeModule(archivedModules); break; case 'Change module budget': await changeBudget(allModules); From 51392544d8b5976ffb724e7f7a8d845b7db74d81 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 28 Nov 2018 15:54:34 -0300 Subject: [PATCH 253/582] CLI - Fix on exit at token selection --- CLI/commands/sto_manager.js | 3 ++- CLI/commands/token_manager.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index d0fd1c3ea..d70c0ca81 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -870,7 +870,8 @@ async function selectToken() { options.push('Enter token symbol manually'); let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); - switch (options[index]) { + let selected = index != -1 ? options[index] : 'Exit'; + switch (selected) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); break; diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 98d13fd3d..fe9590f1f 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -622,7 +622,8 @@ async function selectToken() { options.push('Enter token symbol manually'); let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); - switch (options[index]) { + let selected = index != -1 ? options[index] : 'Exit'; + switch (selected) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); break; From 37aafb8acb3e2a265011e54c9d545594c1c1adb4 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 28 Nov 2018 19:31:54 +0000 Subject: [PATCH 254/582] Fixes --- .../GeneralTransferManager.sol | 71 ++++++++++---- .../GeneralTransferManagerFactory.sol | 2 +- .../GeneralTransferManagerStorage.sol | 8 +- test/b_capped_sto.js | 12 +-- test/c_checkpoints.js | 6 +- test/d_count_transfer_manager.js | 8 +- test/e_erc20_dividends.js | 8 +- test/f_ether_dividends.js | 10 +- test/h_general_transfer_manager.js | 92 ++++++++----------- test/i_Issuance.js | 4 +- test/j_manual_approval_transfer_manager.js | 6 +- test/l_percentage_transfer_manager.js | 6 +- test/m_presale_sto.js | 6 +- test/o_security_token.js | 20 ++-- test/p_usd_tiered_sto.js | 12 +-- test/q_usd_tiered_sto_sim.js | 4 +- test/r_concurrent_STO.js | 2 +- test/v_tracked_redemptions.js | 4 +- ...kup_volume_restriction_transfer_manager.js | 6 +- test/x_single_trade_volume_restriction.js | 10 +- test/y_scheduled_checkpoints.js | 6 +- 21 files changed, 164 insertions(+), 139 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 080c8be17..c43531db7 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -24,7 +24,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag // Emit when there is change in the flag variable called signingAddress event ChangeSigningAddress(address _signingAddress); // Emit when investor details get modified related to their whitelisting - event OffsetModified(uint64 _time, uint8 _isForward); + event DefaultsModified(uint64 _defaultFromTime, uint64 _defaultToTime); // _fromTime is the time from which the _investor can send tokens // _toTime is the time from which the _investor can receive tokens @@ -52,10 +52,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag { } - function modifyOffset(uint64 _time, uint8 _isForward) public withPerm(FLAGS) { - offset.time = _time; - offset.isForward = _isForward; - emit OffsetModified(_time, _isForward); + function modifyDefaults(uint64 _defaultFromTime, uint64 _defaultToTime) public withPerm(FLAGS) { + defaults.fromTime = _defaultFromTime; + defaults.toTime = _defaultToTime; + emit DefaultsModified(_defaultFromTime, _defaultToTime); } /** @@ -126,7 +126,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag allowAllBurnTransfers = _allowAllBurnTransfers; emit AllowAllBurnTransfers(_allowAllBurnTransfers); } - + event Times(uint64 _from, uint64 _to); /** * @notice Default implementation of verifyTransfer used by SecurityToken * If the transfer request comes from the STO, it only checks that the investor is in the whitelist @@ -156,13 +156,15 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag if (allowAllWhitelistIssuances && _from == issuanceAddress) { return _onWhitelist(_to) ? Result.VALID : Result.NA; } + (uint64 adjustedFromTime, uint64 adjustedToTime) = _adjustTimes(whitelist[_from].fromTime, whitelist[_to].toTime); + if (_from == issuanceAddress) { - return (_onWhitelist(_to) && _adjustTimes(whitelist[_to].toTime) <= uint64(now)) ? Result.VALID : Result.NA; + return (_onWhitelist(_to) && (adjustedToTime <= uint64(now))) ? Result.VALID : Result.NA; } //Anyone on the whitelist can transfer provided the blocknumber is large enough /*solium-disable-next-line security/no-block-members*/ - return ((_onWhitelist(_from) && _adjustTimes(whitelist[_from].fromTime) <= uint64(now)) && - (_onWhitelist(_to) && _adjustTimes(whitelist[_to].toTime) <= uint64(now))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return ((_onWhitelist(_from) && (adjustedFromTime <= uint64(now))) && + (_onWhitelist(_to) && (adjustedToTime <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -326,14 +328,19 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag return attached; } - function _adjustTimes(uint64 _time) internal view returns(uint64) { - if (offset.isForward != 0) { - require(_time + offset.time > _time); - return _time + offset.time; - } else { - require(_time >= offset.time); - return _time - offset.time; + /** + * @notice Internal function to adjust times using default values + */ + function _adjustTimes(uint64 _fromTime, uint64 _toTime) internal view returns(uint64, uint64) { + uint64 adjustedFromTime = _fromTime; + uint64 adjustedToTime = _toTime; + if (_fromTime == 0) { + adjustedFromTime = defaults.fromTime; + } + if (_toTime == 0) { + adjustedToTime = defaults.toTime; } + return (adjustedFromTime, adjustedToTime); } /** @@ -343,6 +350,38 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag return investors; } + /** + * @dev Returns list of all investors data + */ + function getAllInvestorsData() external view returns(uint256[], uint256[], uint256[], bool[]) { + return _investorsData(investors); + } + + /** + * @dev Returns list of specified investors data + */ + function getInvestorsData(address[] _investors) external view returns(uint256[], uint256[], uint256[], bool[]) { + return _investorsData(_investors); + } + + function _investorsData(address[] _investors) internal view returns(uint256[], uint256[], uint256[], bool[]) { + uint256[] memory fromTimes = new uint256[](_investors.length); + uint256[] memory toTimes = new uint256[](_investors.length); + uint256[] memory expiryTimes = new uint256[](_investors.length); + bool[] memory canBuyFromSTOs = new bool[](_investors.length); + for (uint256 i = 0; i < _investors.length; i++) { + fromTimes[i] = whitelist[_investors[i]].fromTime; + toTimes[i] = whitelist[_investors[i]].toTime; + expiryTimes[i] = whitelist[_investors[i]].expiryTime; + if (whitelist[_investors[i]].canBuyFromSTO == 0) { + canBuyFromSTOs[i] = false; + } else { + canBuyFromSTOs[i] = true; + } + } + return (fromTimes, toTimes, expiryTimes, canBuyFromSTOs); + } + /** * @notice Return the permissions flag that are associated with general trnasfer manager */ diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 4c81be20a..27c894fb2 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -18,7 +18,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); - version = "1.0.0"; + version = "2.0.0"; name = "GeneralTransferManager"; title = "General Transfer Manager"; description = "Manage transfers using a time based whitelist"; diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol index f5c162080..cca7b5dd1 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol @@ -24,13 +24,13 @@ contract GeneralTransferManagerStorage { } // Allows all TimeRestrictions to be offset - struct Offset { - uint64 time; - uint8 isForward; + struct Defaults { + uint64 fromTime; + uint64 toTime; } // Offset to be applied to all timings (except KYC expiry) - Offset public offset; + Defaults public defaults; // List of all addresses that have been added to the GTM at some point address[] public investors; diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index b1365ad3b..5024b0dfc 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -360,7 +360,7 @@ contract("CappedSTO", accounts => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { from: account_issuer }); @@ -443,7 +443,7 @@ contract("CappedSTO", accounts => { fromTime, toTime + duration.days(20), expiryTime, - 1, + true, { from: account_issuer } @@ -565,7 +565,7 @@ contract("CappedSTO", accounts => { it("Should successfully whitelist investor 3", async () => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { from: account_issuer, gas: 500000 }); @@ -733,7 +733,7 @@ contract("CappedSTO", accounts => { "Tokens are not transfered properly" ); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, P_fromTime, P_toTime, P_expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, P_fromTime, P_toTime, P_expiryTime, true, { from: account_issuer, gas: 500000 }); @@ -800,7 +800,7 @@ contract("CappedSTO", accounts => { P_fromTime, P_toTime + duration.days(20), P_expiryTime, - 1, + true, { from: account_issuer, gas: 500000 @@ -997,7 +997,7 @@ contract("CappedSTO", accounts => { await I_PolyToken.getTokens(polyToInvest * Math.pow(10, 18), account_investor3); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, true, { from: account_issuer, gas: 500000 }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 2ba198f83..6a08b6dea 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -149,7 +149,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 0, + false, { from: account_issuer, gas: 6000000 @@ -176,7 +176,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 0, + false, { from: account_issuer, gas: 6000000 @@ -201,7 +201,7 @@ contract("Checkpoints", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 0, + false, { from: account_issuer, gas: 6000000 diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 4e86bdbb6..1a1e7717a 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -200,7 +200,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -230,7 +230,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -257,7 +257,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -282,7 +282,7 @@ contract("CountTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 6a4baeab6..aac008d4a 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -202,7 +202,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -232,7 +232,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -372,7 +372,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(20), - 1, + true, { from: account_issuer, gas: 500000 @@ -434,7 +434,7 @@ contract("ERC20DividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 68c11f72f..694b8611a 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -200,7 +200,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -230,7 +230,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -364,7 +364,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(20), - 1, + true, { from: account_issuer, gas: 500000 @@ -415,7 +415,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 @@ -719,7 +719,7 @@ contract("EtherDividendCheckpoint", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 500000 diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index f8b1ed989..5d019f521 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -197,6 +197,8 @@ contract("GeneralTransferManager", accounts => { assert.equal(tx.logs[0].args._investor, account_affiliates1); assert.equal(tx.logs[1].args._investor, account_affiliates2); assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2]); + console.log(await I_GeneralTransferManager.getAllInvestorsData.call()); + console.log(await I_GeneralTransferManager.getInvestorsData.call([account_affiliates1, account_affiliates2])); }); it("Should whitelist lots of addresses and check gas", async () => { @@ -367,7 +369,7 @@ contract("GeneralTransferManager", accounts => { }); }); - describe("Buy tokens using on-chain whitelist and negative offset", async () => { + describe("Buy tokens using on-chain whitelist and defaults", async () => { // let snap_id; it("Should Buy the tokens", async () => { @@ -375,8 +377,8 @@ contract("GeneralTransferManager", accounts => { // snap_id = await takeSnapshot(); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime() + duration.days(10), - latestTime() + duration.days(10), + 0, + 0, latestTime() + duration.days(20), true, { @@ -391,36 +393,8 @@ contract("GeneralTransferManager", accounts => { "Failed in adding the investor in whitelist" ); - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); - - await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("3", "ether")); - }); - - it("Add an offset and check transfers are disabled", async () => { - let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 0, {from: token_owner}); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("3", "ether")); - tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); - // await revertToSnapshot(snap_id); - }); - - }); - - - describe("Buy tokens using on-chain whitelist and positive offset", async () => { - // let snap_id; - - it("Should Buy the tokens", async () => { - - // Add the Investor in to the whitelist - // snap_id = await takeSnapshot(); - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, + tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, latestTime(), latestTime(), latestTime() + duration.days(20), @@ -433,37 +407,49 @@ contract("GeneralTransferManager", accounts => { assert.equal( tx.logs[0].args._investor.toLowerCase(), - account_investor1.toLowerCase(), + account_investor2.toLowerCase(), "Failed in adding the investor in whitelist" ); // Jump time await increaseTime(5000); - // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); - // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); - // Mint some tokens - console.log(await I_GeneralTransferManager.offset.call()); - await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + // Can transfer tokens + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1}); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); + it("Add a from default and check transfers are disabled then enabled in the future", async () => { + let tx = await I_GeneralTransferManager.modifyDefaults(latestTime() + duration.days(5), 0, {from: token_owner}); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor2}); + await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1})); + await increaseTime(duration.days(5)); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1}); }); - it("Add an offset and check transfers are disabled", async () => { - let tx = await I_GeneralTransferManager.modifyOffset(duration.days(10), 1, {from: token_owner}); - // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); - // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); + it("Add a to default and check transfers are disabled then enabled in the future", async () => { + let tx = await I_GeneralTransferManager.modifyDefaults(0, latestTime() + duration.days(5), {from: token_owner}); + await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor2})); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1}); + await increaseTime(duration.days(5)); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("2", "ether"), {from: account_investor2}); + // revert changes + await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + 0, + 0, + 0, + false, + { + from: account_issuer, + gas: 6000000 + } + ); + await I_GeneralTransferManager.modifyDefaults(0, 0, {from: token_owner}); + }); - await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1})); - await increaseTime(duration.days(10)); - // console.log("vT1: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call(account_investor1, account_investor1, web3.utils.toWei("1", "ether"), "", false))); - // console.log("vT2: " + JSON.stringify(await I_GeneralTransferManager.verifyTransfer.call("0x0000000000000000000000000000000000000000", account_investor1, web3.utils.toWei("1", "ether"), "", false))); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor1}); - tx = await I_GeneralTransferManager.modifyOffset(0, 0, {from: token_owner}); - // await revertToSnapshot(snap_id); - }); }); diff --git a/test/i_Issuance.js b/test/i_Issuance.js index efcf0db96..ac1fcdd37 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -215,7 +215,7 @@ contract("Issuance", accounts => { fromTime + duration.days(70), toTime + duration.days(90), expiryTime + duration.days(50), - 1, + true, { from: account_polymath } @@ -271,7 +271,7 @@ contract("Issuance", accounts => { }); it("should add the investor into the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { from: account_delegate, gas: 7000000 }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index c817f5c44..0461f287a 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -171,7 +171,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -201,7 +201,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -290,7 +290,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index 530b202c8..e122bdea2 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -192,7 +192,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -222,7 +222,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -287,7 +287,7 @@ contract("PercentageTransferManager", accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index 35a348c30..a89932dc4 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -236,7 +236,7 @@ contract("PreSaleSTO", accounts => { expiryTime = toTime + duration.days(100); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { from: account_issuer, gas: 6000000 }); @@ -277,7 +277,7 @@ contract("PreSaleSTO", accounts => { expiryTime = toTime + duration.days(100); // Add the Investor in to the whitelist - let tx1 = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { + let tx1 = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { from: account_issuer, gas: 6000000 }); @@ -285,7 +285,7 @@ contract("PreSaleSTO", accounts => { assert.equal(tx1.logs[0].args._investor, account_investor2, "Failed in adding the investor in whitelist"); // Add the Investor in to the whitelist - let tx2 = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { + let tx2 = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { from: account_issuer, gas: 6000000 }); diff --git a/test/o_security_token.js b/test/o_security_token.js index 7d2722a20..52521181e 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -193,7 +193,7 @@ contract("SecurityToken", accounts => { let toTime = fromTime + duration.days(100); let expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 6000000 }); @@ -212,7 +212,7 @@ contract("SecurityToken", accounts => { let toTime = fromTime + duration.days(100); let expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 6000000 }); @@ -517,7 +517,7 @@ contract("SecurityToken", accounts => { toTime = fromTime + duration.days(100); expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 6000000 }); @@ -614,7 +614,7 @@ contract("SecurityToken", accounts => { }); it("Should transfer from whitelist investor1 to whitelist investor 2", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 500000 }); @@ -636,7 +636,7 @@ contract("SecurityToken", accounts => { it("Should transferFrom from one investor to other", async () => { await I_SecurityToken.approve(account_investor1, 2 * Math.pow(10, 18), { from: account_investor2 }); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { from: token_owner, gas: 500000 }); @@ -682,7 +682,7 @@ contract("SecurityToken", accounts => { }); it("Should add the investor in the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, true, { from: account_delegate, gas: 6000000 }); @@ -722,7 +722,7 @@ contract("SecurityToken", accounts => { }); it("Should remove investor from the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, 0, 0, 0, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, 0, 0, 0, true, { from: account_delegate, gas: 6000000 }); @@ -751,7 +751,7 @@ contract("SecurityToken", accounts => { }); it("Should fail in buying to tokens", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, true, { from: account_delegate, gas: 6000000 }); @@ -939,7 +939,7 @@ contract("SecurityToken", accounts => { latestTime(), latestTime() + duration.seconds(2), latestTime() + duration.days(50), - 1, + true, { from: account_delegate, gas: 6000000 @@ -982,7 +982,7 @@ contract("SecurityToken", accounts => { latestTime(), latestTime() + duration.seconds(2), latestTime() + duration.days(50), - 1, + true, { from: account_delegate, gas: 6000000 diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 8a274942a..1bec3697f 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1005,7 +1005,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1105,7 +1105,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1160,7 +1160,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1230,7 +1230,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1285,7 +1285,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime(); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER }); @@ -1353,7 +1353,7 @@ contract("USDTieredSTO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let whitelisted = 1; + let whitelisted = true; const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { from: ISSUER diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 31929ade5..b287cb201 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -353,13 +353,13 @@ contract("USDTieredSTO Sim", accounts => { let fromTime = latestTime() + duration.days(15); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = 1; + let canBuyFromSTO = true; await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, 0, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, { from: ISSUER }); await increaseTime(duration.days(3)); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 36761308e..60cdd14f9 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -159,7 +159,7 @@ contract("Concurrent STO", accounts => { let fromTime = latestTime(); let toTime = latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); - let canBuyFromSTO = 1; + let canBuyFromSTO = true; let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, canBuyFromSTO, { from: account_issuer, diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index eacddd87e..2d5ae8c6c 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -190,7 +190,7 @@ contract("TrackedRedemption", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 @@ -220,7 +220,7 @@ contract("TrackedRedemption", accounts => { latestTime(), latestTime(), latestTime() + duration.days(30), - 1, + true, { from: account_issuer, gas: 500000 diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index 7646fb031..358e5b702 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -165,7 +165,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer }); @@ -192,7 +192,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer }); @@ -249,7 +249,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer }); diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index 25243a638..99fe5cb9e 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -165,7 +165,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer }); @@ -193,7 +193,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer }); @@ -542,7 +542,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer } ); @@ -552,7 +552,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer } ); @@ -562,7 +562,7 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, { + true, { from: account_issuer } ); diff --git a/test/y_scheduled_checkpoints.js b/test/y_scheduled_checkpoints.js index 864c6b9a1..5fcc03a74 100644 --- a/test/y_scheduled_checkpoints.js +++ b/test/y_scheduled_checkpoints.js @@ -192,7 +192,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -235,7 +235,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 @@ -270,7 +270,7 @@ contract('ScheduledCheckpoint', accounts => { latestTime(), latestTime(), latestTime() + duration.days(10), - 1, + true, { from: account_issuer, gas: 6000000 From 81054dcf0fef34fdb6df6db2bf7c8e4291a88bae Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 28 Nov 2018 16:39:15 -0300 Subject: [PATCH 255/582] CLI - Support for not integer rates on CappedSTO --- CLI/commands/investor_portal.js | 93 ++++++++++++++++----------------- CLI/commands/sto_manager.js | 6 +-- 2 files changed, 48 insertions(+), 51 deletions(-) diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 1ced21ce0..cdfa66828 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -9,8 +9,6 @@ var gbl = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); -const STO_KEY = 3; - let securityTokenRegistry; let securityToken; let selectedSTO; @@ -50,7 +48,7 @@ async function executeApp(investorAddress, investorPrivKey, symbol, currency, am } } if (investorAddress != "") { - User = { address: investorAddress, privateKey: investorPrivKey}; + User = { address: investorAddress, privateKey: investorPrivKey }; } else { User = Issuer; } @@ -111,7 +109,7 @@ async function inputSymbol(symbol) { if (STSymbol == "") process.exit(); STAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(STSymbol).call(); - if (STAddress == "0x0000000000000000000000000000000000000000"){ + if (STAddress == "0x0000000000000000000000000000000000000000") { console.log(`Token symbol provided is not a registered Security Token. Please enter another symbol.`); } else { let securityTokenABI = abis.securityToken(); @@ -123,12 +121,12 @@ async function inputSymbol(symbol) { let generalTransferManagerABI = abis.generalTransferManager(); generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, gtmModule[0]); - let stoModules = await securityToken.methods.getModulesByType(STO_KEY).call(); + let stoModules = await securityToken.methods.getModulesByType(gbl.constants.MODULES_TYPES.STO).call(); if (stoModules.length == 0) { console.log(chalk.red(`There is no STO module attached to the ${STSymbol.toUpperCase()} Token. No further actions can be taken.`)); process.exit(0); } else { - STOAddress = stoModules[0]; + STOAddress = stoModules[0]; let stoModuleData = await securityToken.methods.getModule(STOAddress).call(); selectedSTO = web3.utils.toAscii(stoModuleData[0]).replace(/\u0000/g, ''); let interfaceSTOABI = abis.stoInterface(); @@ -187,19 +185,19 @@ async function showCappedSTOInfo() { } } - let now = Math.floor(Date.now()/1000); + let now = Math.floor(Date.now() / 1000); - await generalTransferManager.methods.whitelist(User.address).call({}, function(error, result){ + await generalTransferManager.methods.whitelist(User.address).call({}, function (error, result) { displayCanBuy = result.canBuyFromSTO; displayValidKYC = parseInt(result.expiryTime) > now; }); let timeTitle; let timeRemaining; - if(now < displayStartTime){ + if (now < displayStartTime) { timeTitle = "STO starts in: "; timeRemaining = displayStartTime - now; - }else{ + } else { timeTitle = "Time remaining:"; timeRemaining = displayEndTime - now; } @@ -213,7 +211,7 @@ async function showCappedSTOInfo() { - Start Time: ${new Date(displayStartTime * 1000)} - End Time: ${new Date(displayEndTime * 1000)} - Raise Type: ${displayRaiseType} - - Rate: 1 ${displayRaiseType} = ${displayRate} ${STSymbol.toUpperCase()} + - Rate: 1 ${displayRaiseType} = ${web3.utils.fromWei(displayRate)} ${STSymbol.toUpperCase()} --------------------------------------------------------------- - ${timeTitle} ${timeRemaining} - Funds raised: ${web3.utils.fromWei(displayFundsRaised)} ${displayRaiseType} @@ -222,7 +220,7 @@ async function showCappedSTOInfo() { - Investor count: ${displayInvestorCount} `); - if(!displayCanBuy) { + if (!displayCanBuy) { console.log(chalk.red(`Your address is not approved to participate in this token sale.\n`)); process.exit(0); } else if (!displayValidKYC) { @@ -237,8 +235,7 @@ async function showCappedSTOInfo() { } } -async function showUserInfoForUSDTieredSTO() -{ +async function showUserInfoForUSDTieredSTO() { for (const fundType in gbl.constants.FUND_RAISE_TYPES) { if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { let displayInvestorInvested = web3.utils.fromWei(await currentSTO.methods.investorInvested(User.address, gbl.constants.FUND_RAISE_TYPES[fundType]).call()); @@ -249,15 +246,15 @@ async function showUserInfoForUSDTieredSTO() let displayInvestorInvestedUSD = web3.utils.fromWei(await currentSTO.methods.investorInvestedUSD(User.address).call()); console.log(` - Invested in USD: ${displayInvestorInvestedUSD} USD`); - await generalTransferManager.methods.whitelist(User.address).call({}, function(error, result){ + await generalTransferManager.methods.whitelist(User.address).call({}, function (error, result) { displayCanBuy = result.canBuyFromSTO; - displayValidKYC = parseInt(result.expiryTime) > Math.floor(Date.now()/1000); + displayValidKYC = parseInt(result.expiryTime) > Math.floor(Date.now() / 1000); }); - console.log(` - Whitelisted: ${(displayCanBuy)? 'YES' : 'NO'}`); - console.log(` - Valid KYC: ${(displayValidKYC)? 'YES' : 'NO'}`); + console.log(` - Whitelisted: ${(displayCanBuy) ? 'YES' : 'NO'}`); + console.log(` - Valid KYC: ${(displayValidKYC) ? 'YES' : 'NO'}`); let displayIsUserAccredited = await currentSTO.methods.accredited(User.address).call(); - console.log(` - Accredited: ${(displayIsUserAccredited)? "YES" : "NO"}`) + console.log(` - Accredited: ${(displayIsUserAccredited) ? "YES" : "NO"}`) if (!await currentSTO.methods.accredited(User.address).call()) { let displayOverrideNonAccreditedLimitUSD = web3.utils.fromWei(await currentSTO.methods.nonAccreditedLimitUSDOverride(User.address).call()) @@ -310,7 +307,7 @@ async function showUSDTieredSTOInfo() { displayDiscountMinted = `(${web3.utils.fromWei(mintedPerTierDiscountPoly)} ${displayTokenSymbol} at discounted rate)`; } - + let mintedPerTier = mintedPerTierPerRaiseType[gbl.constants.FUND_RAISE_TYPES[type]]; displayMintedPerTierPerType += ` @@ -318,14 +315,14 @@ async function showUSDTieredSTOInfo() { } displayTiers += ` - - Tier ${t+1}: + - Tier ${t + 1}: Tokens: ${web3.utils.fromWei(tokensPerTierTotal)} ${displayTokenSymbol} Rate: ${web3.utils.fromWei(ratePerTier)} USD per Token` - + displayDiscountTokens; + + displayDiscountTokens; - displayMintedPerTier += ` - - Tokens minted in Tier ${t+1}: ${web3.utils.fromWei(mintedPerTierTotal)} ${displayTokenSymbol}` - + displayMintedPerTierPerType; + displayMintedPerTier += ` + - Tokens minted in Tier ${t + 1}: ${web3.utils.fromWei(mintedPerTierTotal)} ${displayTokenSymbol}` + + displayMintedPerTierPerType; } let displayFundsRaisedUSD = web3.utils.fromWei(await currentSTO.methods.fundsRaisedUSD().call()); @@ -347,7 +344,7 @@ async function showUSDTieredSTOInfo() { let displayRaiseType = raiseTypes.join(' - '); - let now = Math.floor(Date.now()/1000); + let now = Math.floor(Date.now() / 1000); let timeTitle; let timeRemaining; if (now < displayStartTime) { @@ -366,18 +363,18 @@ async function showUSDTieredSTOInfo() { - End Time: ${new Date(displayEndTime * 1000)} - Raise Type: ${displayRaiseType} - Tiers: ${tiersLength}` - + displayTiers + ` + + displayTiers + ` - Minimum Investment: ${displayMinimumInvestmentUSD} USD - Default NonAccredited Limit: ${displayNonAccreditedLimitUSD} USD ----------------------------------------------------------------------- - ${timeTitle} ${timeRemaining} - Tokens Sold: ${displayTokensSold} ${displayTokenSymbol}` - + displayTokensSoldPerType + ` + + displayTokensSoldPerType + ` - Current Tier: ${displayCurrentTier}` - + displayMintedPerTier + ` + + displayMintedPerTier + ` - Investor count: ${displayInvestorCount} - Funds Raised` - + displayFundsRaisedPerType + ` + + displayFundsRaisedPerType + ` USD: ${displayFundsRaisedUSD} USD `); @@ -411,7 +408,7 @@ async function investCappedSTO(currency, amount) { } if (amt == "") process.exit(); - let rate = await currentSTO.methods.rate().call(); + let rate = web3.utils.fromWei(await currentSTO.methods.rate().call()); let cost = new BigNumber(amt).div(rate); console.log(`This investment will cost ${cost} ${raiseTypes[0]}`); @@ -422,11 +419,11 @@ async function investCappedSTO(currency, amount) { let allowance = await polyToken.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { let approveAction = polyToken.methods.approve(STOAddress, costWei); - await common.sendTransaction(approveAction, {from: User}); + await common.sendTransaction(approveAction, { from: User }); } let actionBuyTokensWithPoly = currentSTO.methods.buyTokensWithPoly(costWei); - let receipt = await common.sendTransaction(actionBuyTokensWithPoly, {from: User}); - logTokensPurchasedCappedSTO(receipt); + let receipt = await common.sendTransaction(actionBuyTokensWithPoly, { from: User }); + logTokensPurchasedCappedSTO(receipt, 'POLY'); } else { console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} POLY but have ${userBalance} POLY.`)); console.log(chalk.red(`Please purchase a smaller amount of tokens or access the POLY faucet to get the POLY to complete this txn.`)); @@ -434,8 +431,8 @@ async function investCappedSTO(currency, amount) { } } else { let actionBuyTokens = currentSTO.methods.buyTokens(User.address); - let receipt = await common.sendTransaction(actionBuyTokens, {from: User, value: costWei}); - logTokensPurchasedCappedSTO(receipt); + let receipt = await common.sendTransaction(actionBuyTokens, { from: User, value: costWei }); + logTokensPurchasedCappedSTO(receipt, 'ETH'); } await showTokenInfo(); } @@ -456,7 +453,7 @@ async function investUsdTieredSTO(currency, amount) { console.log(chalk.green(` Current ${type} price:\t\t ${displayPrice} USD`)); } if (raiseTypes.length > 1) { - let index = readlineSync.keyInSelect(raiseTypes, 'Choose one of the allowed raise types: ', {cancel: false}); + let index = readlineSync.keyInSelect(raiseTypes, 'Choose one of the allowed raise types: ', { cancel: false }); raiseType = raiseTypes[index]; } else { raiseType = raiseTypes[0]; @@ -470,7 +467,7 @@ async function investUsdTieredSTO(currency, amount) { let minimumInvestmentUSD = await currentSTO.methods.minimumInvestmentUSD().call(); let minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(gbl.constants.FUND_RAISE_TYPES[raiseType], minimumInvestmentUSD).call(); cost = readlineSync.question(chalk.yellow(`Enter the amount of ${raiseType} you would like to invest or press 'Enter' to exit: `), { - limit: function(input) { + limit: function (input) { return investorInvestedUSD != 0 || parseInt(input) > parseInt(web3.utils.fromWei(minimumInvestmentRaiseType)); }, limitMessage: `Amount must be greater than minimum investment (${web3.utils.fromWei(minimumInvestmentRaiseType)} ${raiseType} = ${web3.utils.fromWei(minimumInvestmentUSD)} USD)` @@ -496,10 +493,10 @@ async function investUsdTieredSTO(currency, amount) { let allowance = await polyToken.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { let approveAction = polyToken.methods.approve(STOAddress, costWei); - await common.sendTransaction(approveAction, {from: User}); + await common.sendTransaction(approveAction, { from: User }); } let actionBuyWithPoly = currentSTO.methods.buyWithPOLYRateLimited(User.address, costWei, minTokenToBuy); - let receipt = await common.sendTransaction(actionBuyWithPoly, {from: User, factor: 2}); + let receipt = await common.sendTransaction(actionBuyWithPoly, { from: User, factor: 2 }); logTokensPurchasedUSDTieredSTO(receipt); } else { console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} POLY but have ${userBalance} POLY.`)); @@ -512,19 +509,19 @@ async function investUsdTieredSTO(currency, amount) { let allowance = await usdToken.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { let approveAction = usdToken.methods.approve(STOAddress, costWei); - await common.sendTransaction(approveAction, {from: User}); + await common.sendTransaction(approveAction, { from: User }); } let actionBuyWithUSD = currentSTO.methods.buyWithUSDRateLimited(User.address, costWei, minTokenToBuy); - let receipt = await common.sendTransaction(actionBuyWithUSD, {from: User, factor: 1.5}); + let receipt = await common.sendTransaction(actionBuyWithUSD, { from: User, factor: 1.5 }); logTokensPurchasedUSDTieredSTO(receipt); } else { console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} DAI but have ${userBalance} DAI.`)); console.log(chalk.red(`Please purchase a smaller amount of tokens.`)); process.exit(); - } + } } else { let actionBuyWithETH = currentSTO.methods.buyWithETHRateLimited(User.address, minTokenToBuy); - let receipt = await common.sendTransaction(actionBuyWithETH, {from: User, value: costWei}); + let receipt = await common.sendTransaction(actionBuyWithETH, { from: User, value: costWei }); logTokensPurchasedUSDTieredSTO(receipt); } @@ -554,7 +551,7 @@ function logTokensPurchasedUSDTieredSTO(receipt) { }; } -function logTokensPurchasedCappedSTO(receipt) { +function logTokensPurchasedCappedSTO(receipt, displayRaiseType) { console.log(chalk.green(`Congratulations! The token purchase was successfully completed.`)); let events = common.getMultipleEventsFromLogs(currentSTO._jsonInterface, receipt.logs, 'TokenPurchase'); for (event of events) { @@ -567,7 +564,7 @@ function logTokensPurchasedCappedSTO(receipt) { } module.exports = { - executeApp: async function(investorAddress, investorPrivKey, symbol, currency, amount) { - return executeApp(investorAddress, investorPrivKey, symbol, currency, amount); - } + executeApp: async function (investorAddress, investorPrivKey, symbol, currency, amount) { + return executeApp(investorAddress, investorPrivKey, symbol, currency, amount); + } } diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index d70c0ca81..e9b44c907 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -200,7 +200,7 @@ async function cappedSTO_launch(stoConfig) { [cappedSTOconfig.startTime, cappedSTOconfig.endTime, web3.utils.toWei(cappedSTOconfig.cap.toString()), - cappedSTOconfig.rate, + web3.utils.toWei(cappedSTOconfig.rate.toString()), cappedSTOconfig.raiseType, cappedSTOconfig.wallet] ); @@ -219,7 +219,7 @@ async function cappedSTO_launch(stoConfig) { async function cappedSTO_status(currentSTO) { let displayStartTime = await currentSTO.methods.startTime().call(); let displayEndTime = await currentSTO.methods.endTime().call(); - let displayRate = await currentSTO.methods.rate().call(); + let displayRate = new web3.utils.BN(await currentSTO.methods.rate().call()); let displayCap = new web3.utils.BN(await currentSTO.methods.cap().call()); let displayWallet = await currentSTO.methods.wallet().call(); let displayRaiseType = await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.ETH).call() ? 'ETH' : 'POLY'; @@ -250,7 +250,7 @@ async function cappedSTO_status(currentSTO) { - Start Time: ${new Date(displayStartTime * 1000)} - End Time: ${new Date(displayEndTime * 1000)} - Raise Type: ${displayRaiseType} - - Rate: 1 ${displayRaiseType} = ${displayRate} ${displayTokenSymbol.toUpperCase()} + - Rate: 1 ${displayRaiseType} = ${web3.utils.fromWei(displayRate)} ${displayTokenSymbol.toUpperCase()} - Wallet: ${displayWallet} - Wallet Balance: ${displayWalletBalance} ${displayRaiseType} ----------------------------------------------- From 145fe5bfe51fded32140e3eea221c2f01278860c Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 28 Nov 2018 16:42:02 -0300 Subject: [PATCH 256/582] CLI - Minor fix --- CLI/commands/transfer_manager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 44ae64ca1..3b65df2e8 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -929,7 +929,8 @@ async function selectToken() { options.push('Enter token symbol manually'); let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); - switch (options[index]) { + let selected = index != -1 ? options[index] : 'Exit'; + switch (selected) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); break; From 29886635ffe51e43803b337a41eb10f463e3e7ce Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 28 Nov 2018 20:03:50 +0000 Subject: [PATCH 257/582] Update change log --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e19e93ce..4b0a145fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,8 @@ All notable changes to this project will be documented in this file. * Removed individual mappings for tier data removed in UDSTSTO. # GeneralTransferManager -* Add an Offset that can be used to move all from & to dates forwards or backwards by a fixed offset. +* `getInvestors`, `getAllInvestorsData`, `getInvestorsData` added to GTM to allow easy data queries. +* `modifyDefaults(uint64 _defaultFromTime, uint64 _defaultToTime)` added which sets a default timestamp used when `fromTime` or `toTime` are 0 * Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`) * Fix for when `allowAllWhitelistIssuances` is FALSE * Make GTM a Proxy based implementation to reduce deployment gas costs From dc5657b3b8dc1acbce06adbc882917ce1496fed5 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 29 Nov 2018 12:04:55 +0100 Subject: [PATCH 258/582] fixing audit change request from Mudit --- .../modules/TransferManager/CountTransferManager.sol | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index b54870251..86a537ebe 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -26,12 +26,14 @@ contract CountTransferManager is ITransferManager { } /** @notice Used to verify the transfer transaction and prevent a transfer if it passes the allowed amount of token holders + * @param _from Address of the sender * @param _to Address of the receiver + * @param _amount Amount to send */ function verifyTransfer( - address /* _from */, + address _from, address _to, - uint256 /* _amount */, + uint256 _amount, bytes /* _data */, bool /* _isTransfer */ ) @@ -41,7 +43,7 @@ contract CountTransferManager is ITransferManager { if (!paused) { if (maxHolderCount < ISecurityToken(securityToken).getInvestorCount()) { // Allow transfers to existing maxHolders - if (ISecurityToken(securityToken).balanceOf(_to) != 0) { + if (ISecurityToken(securityToken).balanceOf(_to) != 0 || ISecurityToken(securityToken).balanceOf(_from) == _amount) { return Result.NA; } return Result.INVALID; From 4eb3a5a160768304d91dcadc3ae1f20fdfe2b166 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 29 Nov 2018 18:47:10 +0530 Subject: [PATCH 259/582] redesign the lockup module --- .../TransferManager/LockUpTransferManager.sol | 455 ------------ .../TransferManager/LockUpTransferManager.sol | 651 ++++++++++++++++++ .../LockUpTransferManagerFactory.sol | 2 +- 3 files changed, 652 insertions(+), 456 deletions(-) delete mode 100644 contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol create mode 100644 contracts/modules/TransferManager/LockUpTransferManager.sol rename contracts/modules/{Experimental => }/TransferManager/LockUpTransferManagerFactory.sol (98%) diff --git a/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol deleted file mode 100644 index f1a8dddea..000000000 --- a/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol +++ /dev/null @@ -1,455 +0,0 @@ -pragma solidity ^0.4.24; - -import "./../../TransferManager/ITransferManager.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -contract LockUpTransferManager is ITransferManager { - - using SafeMath for uint256; - - // permission definition - bytes32 public constant ADMIN = "ADMIN"; - - // a per-user lockup - struct LockUp { - uint256 lockupAmount; // Amount to be locked - uint256 startTime; // when this lockup starts (seconds) - uint256 lockUpPeriodSeconds; // total period of lockup (seconds) - uint256 releaseFrequencySeconds; // how often to release a tranche of tokens (seconds) - } - - // maps user addresses to an array of lockups for that user - mapping (address => LockUp[]) internal lockUps; - - event AddNewLockUp( - address indexed userAddress, - uint256 lockupAmount, - uint256 startTime, - uint256 lockUpPeriodSeconds, - uint256 releaseFrequencySeconds, - uint256 indexed lockupIndex - ); - - event RemoveLockUp( - address indexed userAddress, - uint256 indexed lockupIndex - ); - - event ModifyLockUp( - address indexed userAddress, - uint256 lockupAmount, - uint256 startTime, - uint256 lockUpPeriodSeconds, - uint256 releaseFrequencySeconds, - uint256 indexed lockupIndex - ); - - event ChangeLockupIndex( - address indexed _userAddress, - uint256 indexed _oldLockupIndex, - uint256 indexed _newLockupIndex, - uint256 _timestamp - ); - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) - public - Module(_securityToken, _polyAddress) - { - } - - /** @notice Used to verify the transfer transaction and prevent locked up tokens from being transferred - * @param _from Address of the sender - * @param _amount The amount of tokens to transfer - */ - function verifyTransfer(address _from, address /* _to*/, uint256 _amount, bytes /* _data */, bool /*_isTransfer*/) public returns(Result) { - // only attempt to verify the transfer if the token is unpaused, this isn't a mint txn, and there exists a lockup for this user - if (!paused && _from != address(0) && lockUps[_from].length != 0) { - // check if this transfer is valid - return _checkIfValidTransfer(_from, _amount); - } - return Result.NA; - } - - /** - * @notice Lets the admin create a volume restriction lockup for a given address. - * @param _userAddress Address of the user whose tokens should be locked up - * @param _lockupAmount Amount of tokens that need to lock. - * @param _startTime When this lockup starts (seconds) - * @param _lockUpPeriodSeconds Total period of lockup (seconds) - * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) - */ - function addLockUp( - address _userAddress, - uint256 _lockupAmount, - uint256 _startTime, - uint256 _lockUpPeriodSeconds, - uint256 _releaseFrequencySeconds - ) - external - withPerm(ADMIN) - { - _addLockUp( - _userAddress, - _lockupAmount, - _startTime, - _lockUpPeriodSeconds, - _releaseFrequencySeconds - ); - } - - /** - * @notice Lets the admin create multiple volume restriction lockups for multiple given addresses. - * @param _userAddresses Array of address of the user whose tokens should be locked up - * @param _lockupAmounts Array of the amounts that need to be locked for the different addresses. - * @param _startTimes Array of When this lockup starts (seconds) - * @param _lockUpPeriodsSeconds Array of total periods of lockup (seconds) - * @param _releaseFrequenciesSeconds Array of how often to release a tranche of tokens (seconds) - */ - function addLockUpMulti( - address[] _userAddresses, - uint256[] _lockupAmounts, - uint256[] _startTimes, - uint256[] _lockUpPeriodsSeconds, - uint256[] _releaseFrequenciesSeconds - ) - external - withPerm(ADMIN) - { - require( - _userAddresses.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _lockupAmounts.length, - "Input array length mismatch" - ); - - for (uint256 i = 0; i < _userAddresses.length; i++) { - _addLockUp(_userAddresses[i], _lockupAmounts[i], _startTimes[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i]); - } - - } - - /** - * @notice Lets the admin remove a user's lock up - * @param _userAddress Address of the user whose tokens are locked up - * @param _lockupIndex Index of the lockup need to be removed. - */ - function removeLockUp(address _userAddress, uint256 _lockupIndex) external withPerm(ADMIN) { - _removeLockUp(_userAddress, _lockupIndex); - } - - /** - * @notice Use to remove the lockup for multiple users - * @param _userAddresses Array of addresses of the user whose tokens are locked up - * @param _lockupIndexes Array of the indexes to the lockup that needs to be removed. - */ - function removeLockUpMulti(address[] _userAddresses, uint256[] _lockupIndexes) external withPerm(ADMIN) { - require(_userAddresses.length == _lockupIndexes.length, "Array length mismatch"); - for (uint256 i = 0; i < _userAddresses.length; i++) { - _removeLockUp(_userAddresses[i], _lockupIndexes[i]); - } - } - - /** - * @notice Lets the admin modify a volume restriction lockup for a given address. - * @param _userAddress Address of the user whose tokens should be locked up - * @param _lockupAmount Amount of tokens that needs to be locked - * @param _startTime When this lockup starts (seconds) - * @param _lockUpPeriodSeconds Total period of lockup (seconds) - * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) - * @param _lockupIndex Index of the lockup that needs to be modified. - */ - function modifyLockUp( - address _userAddress, - uint256 _lockupAmount, - uint256 _startTime, - uint256 _lockUpPeriodSeconds, - uint256 _releaseFrequencySeconds, - uint256 _lockupIndex - ) - external - withPerm(ADMIN) - { - _modifyLockUp( - _userAddress, - _lockupAmount, - _startTime, - _lockUpPeriodSeconds, - _releaseFrequencySeconds, - _lockupIndex - ); - } - - /** - * @notice Lets the admin modify a volume restriction lockup for a multiple address. - * @param _userAddresses Array of address of the user whose tokens should be locked up - * @param _lockupAmounts Array of the amount of tokens that needs to be locked for the respective addresses. - * @param _startTimes Array of the start time of the lockups (seconds) - * @param _lockUpPeriodsSeconds Array of unix timestamp for the list of lockups (seconds). - * @param _releaseFrequenciesSeconds How often to release a tranche of tokens (seconds) - * @param _lockupIndexes Array of the lockup indexes that needs to be modified - */ - function modifyLockUpMulti( - address[] _userAddresses, - uint256[] _lockupAmounts, - uint256[] _startTimes, - uint256[] _lockUpPeriodsSeconds, - uint256[] _releaseFrequenciesSeconds, - uint256[] _lockupIndexes - ) - public - withPerm(ADMIN) - { - require( - _userAddresses.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _lockupAmounts.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _lockupIndexes.length, - "Input array length mismatch" - ); - for (uint256 i = 0; i < _userAddresses.length; i++) { - _modifyLockUp( - _userAddresses[i], - _lockupAmounts[i], - _startTimes[i], - _lockUpPeriodsSeconds[i], - _releaseFrequenciesSeconds[i], - _lockupIndexes[i] - ); - } - } - - /** - * @notice Get the length of the lockups array for a specific user address - * @param _userAddress Address of the user whose tokens should be locked up - */ - function getLockUpsLength(address _userAddress) public view returns (uint256) { - return lockUps[_userAddress].length; - } - - /** - * @notice Get a specific element in a user's lockups array given the user's address and the element index - * @param _userAddress Address of the user whose tokens should be locked up - * @param _lockUpIndex The index of the LockUp to edit for the given userAddress - */ - function getLockUp(address _userAddress, uint256 _lockUpIndex) public view returns ( - uint256 lockupAmount, - uint256 startTime, - uint256 lockUpPeriodSeconds, - uint256 releaseFrequencySeconds, - uint256 unlockedAmount - ) { - require(lockUps[_userAddress].length > _lockUpIndex, "Invalid index"); - LockUp[] memory userLockup = lockUps[_userAddress]; - return ( - userLockup[_lockUpIndex].lockupAmount, - userLockup[_lockUpIndex].startTime, - userLockup[_lockUpIndex].lockUpPeriodSeconds, - userLockup[_lockUpIndex].releaseFrequencySeconds, - _getUnlockedAmountForLockup(userLockup, _lockUpIndex) - ); - } - - /** - * @notice Use to get the total locked tokens for a given user - * @param _userAddress Address of the user - * @return uint256 Total locked tokens amount - */ - function getLockedTokenToUser(address _userAddress) public view returns(uint256) { - require(_userAddress != address(0), "Invalid address"); - LockUp[] memory userLockup = lockUps[_userAddress]; - uint256 totalRemainingLockedAmount = 0; - - for (uint256 i = 0; i < userLockup.length; i++) { - // Find out the remaining locked amount for a given lockup - uint256 remainingLockedAmount = userLockup[i].lockupAmount.sub(_getUnlockedAmountForLockup(userLockup, i)); - // aggregating all the remaining locked amount for all the lockups for a given address - totalRemainingLockedAmount = totalRemainingLockedAmount.add(remainingLockedAmount); - } - return totalRemainingLockedAmount; - } - - /** - * @notice Checks whether the transfer is allowed - * @param _userAddress Address of the user whose lock ups should be checked - * @param _amount Amount of tokens that need to transact - */ - function _checkIfValidTransfer(address _userAddress, uint256 _amount) internal view returns (Result) { - uint256 totalRemainingLockedAmount = getLockedTokenToUser(_userAddress); - // Present balance of the user - uint256 currentBalance = ISecurityToken(securityToken).balanceOf(_userAddress); - if ((currentBalance.sub(_amount)) >= totalRemainingLockedAmount) { - return Result.NA; - } - return Result.INVALID; - } - - /** - * @notice Provide the unlock amount for the given lockup for a particular user - */ - function _getUnlockedAmountForLockup(LockUp[] userLockup, uint256 _lockupIndex) internal view returns (uint256) { - /*solium-disable-next-line security/no-block-members*/ - if (userLockup[_lockupIndex].startTime > now) { - return 0; - } else if (userLockup[_lockupIndex].startTime.add(userLockup[_lockupIndex].lockUpPeriodSeconds) <= now) { - return userLockup[_lockupIndex].lockupAmount; - } else { - // Calculate the no. of periods for a lockup - uint256 noOfPeriods = (userLockup[_lockupIndex].lockUpPeriodSeconds).div(userLockup[_lockupIndex].releaseFrequencySeconds); - // Calculate the transaction time lies in which period - /*solium-disable-next-line security/no-block-members*/ - uint256 elapsedPeriod = (now.sub(userLockup[_lockupIndex].startTime)).div(userLockup[_lockupIndex].releaseFrequencySeconds); - // Calculate the allowed unlocked amount per period - uint256 amountPerPeriod = (userLockup[_lockupIndex].lockupAmount).div(noOfPeriods); - // Find out the unlocked amount for a given lockup - uint256 unLockedAmount = elapsedPeriod.mul(amountPerPeriod); - return unLockedAmount; - } - - } - - function _modifyLockUp( - address _userAddress, - uint256 _lockupAmount, - uint256 _startTime, - uint256 _lockUpPeriodSeconds, - uint256 _releaseFrequencySeconds, - uint256 _lockupIndex - ) - internal - { - require(lockUps[_userAddress].length > _lockupIndex, "Invalid index"); - - // Get the lockup from the master list and edit it - LockUp[] storage userLockup = lockUps[_userAddress]; - // If _startTime is equal to the previous startTime then it only allow to modify - // when there is no tokens gets unlocked from the lockup - if (_startTime == userLockup[_lockupIndex].startTime) { - require(_getUnlockedAmountForLockup(userLockup, _lockupIndex) == uint256(0)); - } else { - /*solium-disable-next-line security/no-block-members*/ - require(_startTime >= now, "start time is in past"); - } - _checkLockUpParams( - _userAddress, - _lockupAmount, - _lockUpPeriodSeconds, - _releaseFrequencySeconds - ); - - userLockup[_lockupIndex] = LockUp( - _lockupAmount, - _startTime, - _lockUpPeriodSeconds, - _releaseFrequencySeconds - ); - - emit ModifyLockUp( - _userAddress, - _lockupAmount, - _startTime, - _lockUpPeriodSeconds, - _releaseFrequencySeconds, - _lockupIndex - ); - } - - function _removeLockUp(address _userAddress, uint256 _lockupIndex) internal { - require(lockUps[_userAddress].length > _lockupIndex, "Invalid index"); - LockUp[] storage userLockup = lockUps[_userAddress]; - - emit RemoveLockUp( - _userAddress, - _lockupIndex - ); - - if (_lockupIndex != userLockup.length - 1) { - // move the last element in the array into the index that is desired to be removed. - userLockup[_lockupIndex] = userLockup[userLockup.length - 1]; - /*solium-disable-next-line security/no-block-members*/ - emit ChangeLockupIndex(_userAddress, userLockup.length - 1, _lockupIndex, now); - } - userLockup.length--; - } - - function _addLockUp( - address _userAddress, - uint256 _lockupAmount, - uint256 _startTime, - uint256 _lockUpPeriodSeconds, - uint256 _releaseFrequencySeconds - ) - internal - { - /*solium-disable-next-line security/no-block-members*/ - require(_startTime >= now, "start time is in past"); - _checkLockUpParams(_userAddress, _lockupAmount, _lockUpPeriodSeconds, _releaseFrequencySeconds); - - lockUps[_userAddress].push(LockUp(_lockupAmount, _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds)); - - emit AddNewLockUp( - _userAddress, - _lockupAmount, - _startTime, - _lockUpPeriodSeconds, - _releaseFrequencySeconds, - lockUps[_userAddress].length -1 - ); - } - - /** - * @notice Parameter checking function for creating or editing a lockup. This function will cause an exception if any of the parameters are bad. - * @param _userAddress Address whom lockup is being applied - * @param _lockupAmount Amount that needs to be locked - * @param _lockUpPeriodSeconds Total period of lockup (seconds) - * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) - */ - function _checkLockUpParams( - address _userAddress, - uint256 _lockupAmount, - uint256 _lockUpPeriodSeconds, - uint256 _releaseFrequencySeconds - ) - internal - view - { - require(_userAddress != address(0), "Invalid address"); - require(_lockUpPeriodSeconds != 0, "lockUpPeriodSeconds cannot be zero"); - require(_releaseFrequencySeconds != 0, "releaseFrequencySeconds cannot be zero"); - require(_lockupAmount != 0, "lockupAmount cannot be zero"); - - // check that the total amount to be released isn't too granular - require( - _lockupAmount % ISecurityToken(securityToken).granularity() == 0, - "The total amount to be released is more granular than allowed by the token" - ); - - // check that releaseFrequencySeconds evenly divides lockUpPeriodSeconds - require( - _lockUpPeriodSeconds % _releaseFrequencySeconds == 0, - "lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds" - ); - } - - /** - * @notice This function returns the signature of configure function - */ - function getInitFunction() public pure returns (bytes4) { - return bytes4(0); - } - - /** - * @notice Returns the permissions flag that are associated with Percentage transfer Manager - */ - function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](1); - allPermissions[0] = ADMIN; - return allPermissions; - } -} diff --git a/contracts/modules/TransferManager/LockUpTransferManager.sol b/contracts/modules/TransferManager/LockUpTransferManager.sol new file mode 100644 index 000000000..b2b940b3d --- /dev/null +++ b/contracts/modules/TransferManager/LockUpTransferManager.sol @@ -0,0 +1,651 @@ +pragma solidity ^0.4.24; + +import "./TransferManager/ITransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +contract LockUpTransferManager is ITransferManager { + + using SafeMath for uint256; + + // permission definition + bytes32 public constant ADMIN = "ADMIN"; + + // a per-user lockup + struct LockUp { + uint256 lockupAmount; // Amount to be locked + uint256 startTime; // when this lockup starts (seconds) + uint256 lockUpPeriodSeconds; // total period of lockup (seconds) + uint256 releaseFrequencySeconds; // how often to release a tranche of tokens (seconds) + } + + // mapping use to store the lockup details corresponds to lockup name + mapping (bytes32 => LockUp) public lockups; + // mapping user addresses to an array of lockups name for that user + mapping (address => bytes32[]) internal userToLockups; + // get list of the addresses for a particular lockupName + mapping (bytes32 => address[]) internal lockupToUsers; + // holds lockup index corresponds to user address. userAddress => lockupName => lockupIndex + mapping (address => mapping(bytes32 => uint256)) internal userToLockupIndex; + // holds the user address index corresponds to the lockup. lockupName => userAddress => userIndex + mapping (bytes32 => mapping(address => uint256)) internal lockupToUserIndex; + + bytes32[] lockupArray; + + event AddNewLockUpToUser( + address indexed userAddress, + bytes32 indexed lockupName + ); + + event RemoveLockUpFromUser( + address indexed userAddress, + bytes32 indexed lockupName + ); + + event ModifyLockUpType( + uint256 lockupAmount, + uint256 startTime, + uint256 lockUpPeriodSeconds, + uint256 releaseFrequencySeconds, + bytes32 indexed lockupName + ); + + event AddNewLockUpType( + bytes32 indexed lockupName, + uint256 lockupAmount, + uint256 startTime, + uint256 lockUpPeriodSeconds, + uint256 releaseFrequencySeconds + ); + + event RemoveLockUpType(bytes32 indexed lockupName); + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { + } + + /** @notice Used to verify the transfer transaction and prevent locked up tokens from being transferred + * @param _from Address of the sender + * @param _amount The amount of tokens to transfer + */ + function verifyTransfer(address _from, address /* _to*/, uint256 _amount, bytes /* _data */, bool /*_isTransfer*/) public returns(Result) { + // only attempt to verify the transfer if the token is unpaused, this isn't a mint txn, and there exists a lockup for this user + if (!paused && _from != address(0) && userToLockups[_from].length != 0) { + // check if this transfer is valid + return _checkIfValidTransfer(_from, _amount); + } + return Result.NA; + } + + /** + * @notice Use to add the new lockup type + * @param _lockupAmount Amount of tokens that need to lock. + * @param _startTime When this lockup starts (seconds) + * @param _lockUpPeriodSeconds Total period of lockup (seconds) + * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) + * @param _lockupName Name of the lockup + */ + function addNewLockUpType( + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + public + withPerm(ADMIN) + { + _addNewLockUpType( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + } + + /** + * @notice Use to add the new lockup type + * @param _lockupAmounts Array of amount of tokens that need to lock. + * @param _startTimes Array of startTimes when this lockup starts (seconds) + * @param _lockUpPeriodsSeconds Array of total period of lockup (seconds) + * @param _releaseFrequenciesSeconds Array of how often to release a tranche of tokens (seconds) + * @param _lockupNames Array of names of the lockup + */ + function addNewLockUpTypeMulti( + uint256[] _lockupAmounts, + uint256[] _startTimes, + uint256[] _lockUpPeriodsSeconds, + uint256[] _releaseFrequenciesSeconds, + bytes32[] _lockupNames + ) + external + withPerm(ADMIN) + { + require( + _lockupNames.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _lockupAmounts.length, + "Input array length mismatch" + ); + for (uint256 i = 0; i < _lockupNames.length; i++) { + _addNewLockUpType( + _lockupAmounts[i], + _startTimes[i], + _lockUpPeriodsSeconds[i], + _releaseFrequenciesSeconds[i], + _lockupNames[i] + ); + } + } + + /** + * @notice Add the lockup to a user + * @param _userAddress Address of the user + * @param _lockupName Name of the lockup + */ + function addLockUpByName( + address _userAddress, + bytes32 _lockupName + ) + public + withPerm(ADMIN) + { + _addLockUpByName(_userAddress, _lockupName); + } + + /** + * @notice Add the lockup to a user + * @param _userAddresses Address of the user + * @param _lockupNames Name of the lockup + */ + function addLockUpByNameMulti( + address[] _userAddresses, + bytes32[] _lockupNames + ) + external + withPerm(ADMIN) + { + require(_userAddresses.length == _lockupNames.length, "Length mismatch"); + for (uint256 i = 0; i < _userAddresses.length; i++) { + _addLockUpByName(_userAddresses[i], _lockupNames[i]); + } + } + + /** + * @notice Lets the admin create a volume restriction lockup for a given address. + * @param _userAddress Address of the user whose tokens should be locked up + * @param _lockupAmount Amount of tokens that need to lock. + * @param _startTime When this lockup starts (seconds) + * @param _lockUpPeriodSeconds Total period of lockup (seconds) + * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) + * @param _lockupName Name of the lockup + */ + function addNewLockUpToUser( + address _userAddress, + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + external + withPerm(ADMIN) + { + _addNewLockUpToUser( + _userAddress, + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + } + + /** + * @notice Lets the admin create multiple volume restriction lockups for multiple given addresses. + * @param _userAddresses Array of address of the user whose tokens should be locked up + * @param _lockupAmounts Array of the amounts that need to be locked for the different addresses. + * @param _startTimes Array of When this lockup starts (seconds) + * @param _lockUpPeriodsSeconds Array of total periods of lockup (seconds) + * @param _releaseFrequenciesSeconds Array of how often to release a tranche of tokens (seconds) + * @param _lockupNames Array of names of the lockup + */ + function addNewLockUpToUserMulti( + address[] _userAddresses, + uint256[] _lockupAmounts, + uint256[] _startTimes, + uint256[] _lockUpPeriodsSeconds, + uint256[] _releaseFrequenciesSeconds, + bytes32[] _lockupNames + ) + public + withPerm(ADMIN) + { + require( + _userAddresses.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _lockupAmounts.length && + _userAddresses.length == _lockupNames.length, + "Input array length mismatch" + ); + for (uint256 i = 0; i < _userAddresses.length; i++) { + _addNewLockUpToUser(_userAddresses[i], _lockupAmounts[i], _startTimes[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i], _lockupNames[i]); + } + } + + /** + * @notice Lets the admin remove a user's lock up + * @param _userAddress Address of the user whose tokens are locked up + * @param _lockupName Name of the lockup need to be removed. + */ + function removeLockUpFromUser(address _userAddress, bytes32 _lockupName) external withPerm(ADMIN) { + _removeLockUpFromUser(_userAddress, _lockupName); + } + + /** + * @notice Used to remove the lockup type + * @param _lockupName Name of the lockup + */ + function removeLockupType(bytes32 _lockupName) external withPerm(ADMIN) { + _removeLockupType(_lockupName); + } + + /** + * @notice Used to remove the multiple lockup type + * @param _lockupNames Array of the lockup names. + */ + function removeLockupTypeMulti(bytes32[] _lockupNames) external withPerm(ADMIN) { + for (uint256 i = 0; i < _lockupNames.length; i++) { + _removeLockupType(_lockupNames[i]); + } + } + + /** + * @notice Use to remove the lockup for multiple users + * @param _userAddresses Array of addresses of the user whose tokens are locked up + * @param _lockupNames Array of the names of the lockup that needs to be removed. + */ + function removeLockUpFromUserMulti(address[] _userAddresses, bytes32[] _lockupNames) external withPerm(ADMIN) { + require(_userAddresses.length == _lockupNames.length, "Array length mismatch"); + for (uint256 i = 0; i < _userAddresses.length; i++) { + _removeLockUpFromUser(_userAddresses[i], _lockupNames[i]); + } + } + + /** + * @notice Lets the admin modify a lockup. + * @param _lockupAmount Amount of tokens that needs to be locked + * @param _startTime When this lockup starts (seconds) + * @param _lockUpPeriodSeconds Total period of lockup (seconds) + * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) + * @param _lockupName name of the lockup that needs to be modified. + */ + function modifyLockUpType( + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + external + withPerm(ADMIN) + { + _modifyLockUpType( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + } + + /** + * @notice Lets the admin modify a volume restriction lockup for a multiple address. + * @param _lockupAmounts Array of the amount of tokens that needs to be locked for the respective addresses. + * @param _startTimes Array of the start time of the lockups (seconds) + * @param _lockUpPeriodsSeconds Array of unix timestamp for the list of lockups (seconds). + * @param _releaseFrequenciesSeconds How often to release a tranche of tokens (seconds) + * @param _lockupNames Array of the lockup names that needs to be modified + */ + function modifyLockUpTypeMulti( + uint256[] _lockupAmounts, + uint256[] _startTimes, + uint256[] _lockUpPeriodsSeconds, + uint256[] _releaseFrequenciesSeconds, + bytes32[] _lockupNames + ) + public + withPerm(ADMIN) + { + require( + _lockupNames.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _lockupAmounts.length, + "Input array length mismatch" + ); + for (uint256 i = 0; i < _lockupNames.length; i++) { + _modifyLockUpType( + _lockupAmounts[i], + _startTimes[i], + _lockUpPeriodsSeconds[i], + _releaseFrequenciesSeconds[i], + _lockupNames[i] + ); + } + } + + /** + * @notice Get the length of the lockups array for a specific user address + * @param _userAddress Address of the user whose tokens should be locked up + */ + function getLockUpsLength(address _userAddress) public view returns (uint256) { + return userToLockups[_userAddress].length; + } + + /** + * @notice Get a specific element in a user's lockups array given the user's address and the element index + * @param _userAddress Address of the user whose tokens should be locked up + * @param _lockupName The name of the lockup + */ + function getLockUp(address _userAddress, bytes32 _lockupName) public view returns ( + uint256 lockupAmount, + uint256 startTime, + uint256 lockUpPeriodSeconds, + uint256 releaseFrequencySeconds, + uint256 unlockedAmount + ) { + require( + userToLockups[_userAddress][userToLockupIndex[_userAddress][_lockupName]] == _lockupName, + "User not assosicated with given lockup" + ); + bytes32[] memory userLockupNames = userToLockups[_userAddress]; + return ( + lockups[_lockupName].lockupAmount, + lockups[_lockupName].startTime, + lockups[_lockupName].lockUpPeriodSeconds, + lockups[_lockupName].releaseFrequencySeconds, + _getUnlockedAmountForLockup(_lockupName) + ); + } + + /** + * @notice get the list of the users of a lockup type + * @param _lockupName Name of the lockup type + * @return address List of users associated with the blacklist + */ + function getListOfAddresses(bytes32 _lockupName) external view returns(address[]) { + require(lockups[_lockupName].startTime != 0, "Blacklist type doesn't exist"); + return lockupToUsers[_lockupName]; + } + + /** + * @notice get the list of lockups names + * @return bytes32 Array of lockups names + */ + function getAllLockups() external view returns(bytes32[]) { + return lockupArray; + } + + /** + * @notice get the list of the lockups for a given user + * @param _user Address of the user + * @return bytes32 List of lockups names associated with the given address + */ + function getLockupsNamesToUser(address _user) external view returns(bytes32[]) { + return userToLockups[_user]; + } + + /** + * @notice Use to get the total locked tokens for a given user + * @param _userAddress Address of the user + * @return uint256 Total locked tokens amount + */ + function getLockedTokenToUser(address _userAddress) public view returns(uint256) { + require(_userAddress != address(0), "Invalid address"); + bytes32[] memory userLockupNames = userToLockups[_userAddress]; + uint256 totalRemainingLockedAmount = 0; + + for (uint256 i = 0; i < userLockupNames.length; i++) { + // Find out the remaining locked amount for a given lockup + uint256 remainingLockedAmount = lockups[userLockupNames[i]].lockupAmount.sub(_getUnlockedAmountForLockup(userLockupNames[i])); + // aggregating all the remaining locked amount for all the lockups for a given address + totalRemainingLockedAmount = totalRemainingLockedAmount.add(remainingLockedAmount); + } + return totalRemainingLockedAmount; + } + + /** + * @notice Checks whether the transfer is allowed + * @param _userAddress Address of the user whose lock ups should be checked + * @param _amount Amount of tokens that need to transact + */ + function _checkIfValidTransfer(address _userAddress, uint256 _amount) internal view returns (Result) { + uint256 totalRemainingLockedAmount = getLockedTokenToUser(_userAddress); + // Present balance of the user + uint256 currentBalance = ISecurityToken(securityToken).balanceOf(_userAddress); + if ((currentBalance.sub(_amount)) >= totalRemainingLockedAmount) { + return Result.NA; + } + return Result.INVALID; + } + + /** + * @notice Provide the unlock amount for the given lockup for a particular user + */ + function _getUnlockedAmountForLockup(bytes32 _lockupName) internal view returns (uint256) { + /*solium-disable-next-line security/no-block-members*/ + if (lockups[_lockupName].startTime > now) { + return 0; + } else if (lockups[_lockupName].startTime.add(lockups[_lockupName].lockUpPeriodSeconds) <= now) { + return lockups[_lockupName].lockupAmount; + } else { + // Calculate the no. of periods for a lockup + uint256 noOfPeriods = (lockups[_lockupName].lockUpPeriodSeconds).div(lockups[_lockupName].releaseFrequencySeconds); + // Calculate the transaction time lies in which period + /*solium-disable-next-line security/no-block-members*/ + uint256 elapsedPeriod = (now.sub(lockups[_lockupName].startTime)).div(lockups[_lockupName].releaseFrequencySeconds); + // Calculate the allowed unlocked amount per period + uint256 amountPerPeriod = (lockups[_lockupName].lockupAmount).div(noOfPeriods); + // Find out the unlocked amount for a given lockup + uint256 unLockedAmount = elapsedPeriod.mul(amountPerPeriod); + return unLockedAmount; + } + } + + function _removeLockupType(bytes32 _lockupName) internal { + require(lockups[_lockupName].startTime != 0, "Lockup type doesn’t exist"); + require(lockupToUsers[_lockupName].length == 0, "Users are associated with the lockup"); + // delete lockup type + delete(lockups[_lockupName]); + uint256 i = 0; + for (i = 0; i < lockupArray.length; i++) { + if (lockupArray[i] == _lockupName) { + break; + } + } + if (i != lockupArray.length -1) { + lockupArray[i] = lockupArray[lockupArray.length -1]; + } + lockupArray.length--; + emit RemoveLockUpType(_lockupName); + } + + function _modifyLockUpType( + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + internal + { + /*solium-disable-next-line security/no-block-members*/ + require(lockups[_lockupName].startTime > now, "Not allowed to modify"); + require(_startTime >= now, "Past time is not allowed"); + + _checkLockUpParams( + _lockupAmount, + _lockUpPeriodSeconds, + _releaseFrequencySeconds + ); + + lockups[_lockupName] = LockUp( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds + ); + + emit ModifyLockUpType( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + } + + function _removeLockUpFromUser(address _userAddress, bytes32 _lockupName) internal { + require(_userAddress != address(0), "Invalid address"); + require(_lockupName != bytes32(0), "Invalid lockup name"); + require( + userToLockups[_userAddress][userToLockupIndex[_userAddress][_lockupName]] == _lockupName, + "User not assosicated with given lockup" + ); + + // delete the user from the lockup type + uint256 _lockupIndex = lockupToUserIndex[_lockupName][_userAddress]; + uint256 _len = lockupToUsers[_lockupName].length; + if ( _lockupIndex != _len) { + lockupToUsers[_lockupName][_lockupIndex] = lockupToUsers[_lockupName][_len - 1]; + lockupToUserIndex[_lockupName][lockupToUsers[_lockupName][_lockupIndex]] = _lockupIndex; + } + lockupToUsers[_lockupName].length--; + // delete the user index from the lockup + delete(lockupToUserIndex[_lockupName][_userAddress]); + // delete the lockup from the user + uint256 _userIndex = userToLockupIndex[_userAddress][_lockupName]; + _len = userToLockups[_userAddress].length; + if ( _userIndex != _len) { + userToLockups[_userAddress][_userIndex] = userToLockups[_userAddress][_len - 1]; + userToLockupIndex[_userAddress][userToLockups[_userAddress][_userIndex]] = _userIndex; + } + userToLockups[_userAddress].length--; + // delete the lockup index from the user + delete(userToLockupIndex[_userAddress][_lockupName]); + emit RemoveLockUpFromUser(_userAddress, _lockupName); + } + + function _addNewLockUpToUser( + address _userAddress, + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + internal + { + require(_userAddress != address(0), "Invalid address"); + _addNewLockUpType( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + _addLockUpByName(_userAddress, _lockupName); + } + + function _addLockUpByName( + address _userAddress, + bytes32 _lockupName + ) + internal + { + require(_userAddress != address(0), "Invalid address"); + require(lockups[_lockupName].startTime >= now, "Lockup expired"); + + userToLockupIndex[_userAddress][_lockupName] = userToLockups[_userAddress].length; + lockupToUserIndex[_lockupName][_userAddress] = lockupToUsers[_lockupName].length; + userToLockups[_userAddress].push(_lockupName); + lockupToUsers[_lockupName].push(_userAddress); + emit AddNewLockUpToUser(_userAddress, _lockupName); + } + + function _addNewLockUpType( + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + internal + { + require(lockups[_lockupName].lockupAmount == 0, "Already exist"); + /*solium-disable-next-line security/no-block-members*/ + require(_startTime >= now, "Past time not allowed"); + _checkLockUpParams(_lockupAmount, _lockUpPeriodSeconds, _releaseFrequencySeconds); + lockups[_lockupName] = LockUp(_lockupAmount, _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds); + lockupArray.push(_lockupName); + emit AddNewLockUpType(_lockupName, _lockupAmount, _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds); + } + + /** + * @notice Parameter checking function for creating or editing a lockup. + * This function will cause an exception if any of the parameters are bad. + * @param _lockupAmount Amount that needs to be locked + * @param _lockUpPeriodSeconds Total period of lockup (seconds) + * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) + */ + function _checkLockUpParams( + uint256 _lockupAmount, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds + ) + internal + view + { + require(_lockUpPeriodSeconds != 0, "lockUpPeriodSeconds cannot be zero"); + require(_releaseFrequencySeconds != 0, "releaseFrequencySeconds cannot be zero"); + require(_lockupAmount != 0, "lockupAmount cannot be zero"); + + // check that the total amount to be released isn't too granular + require( + _lockupAmount % ISecurityToken(securityToken).granularity() == 0, + "The total amount to be released is more granular than allowed by the token" + ); + + // check that releaseFrequencySeconds evenly divides lockUpPeriodSeconds + require( + _lockUpPeriodSeconds % _releaseFrequencySeconds == 0, + "lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds" + ); + } + + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(0); + } + + /** + * @notice Returns the permissions flag that are associated with Percentage transfer Manager + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; + } +} diff --git a/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol b/contracts/modules/TransferManager/LockUpTransferManagerFactory.sol similarity index 98% rename from contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol rename to contracts/modules/TransferManager/LockUpTransferManagerFactory.sol index 2a79e2528..78f2585d8 100644 --- a/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/LockUpTransferManagerFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./../../ModuleFactory.sol"; +import "../ModuleFactory.sol"; import "./LockUpTransferManager.sol"; /** From ffdf4e9ee1360a114f7172f16b8c23a5a3fce5df Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 29 Nov 2018 18:55:07 +0530 Subject: [PATCH 260/582] Update script fetch correct solc version --- scripts/docs.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/docs.sh b/scripts/docs.sh index db7aba417..205a6ceae 100755 --- a/scripts/docs.sh +++ b/scripts/docs.sh @@ -32,12 +32,20 @@ create_docs() { cd $WEBSITE_DIRECTORY fi + echo "Fetching solc binary" + curl -L -o solidity-ubuntu-trusty.zip https://github.com/ethereum/solidity/releases/download/v0.4.24/solidity-ubuntu-trusty.zip + unzip solidity-ubuntu-trusty.zip + CWD=$(pwd) + OLD_SOLC_PATH=$SOLC_PATH + export SOLC_PATH=$CWD/solc echo "Generating the API documentation in branch $latestTag" # Command to generate the documentation using the solidity-docgen migrate=$(SOLC_ARGS="openzeppelin-solidity="$CORE_ROUTE"/node_modules/openzeppelin-solidity" \ solidity-docgen -x external/oraclizeAPI.sol,mocks/MockPolyOracle.sol,oracles/PolyOracle.sol $CORE_ROUTE $CORE_ROUTE/contracts $CORE_ROUTE/polymath-developer-portal/) + export SOLC_PATH=$OLD_SOLC_PATH + echo "Successfully docs are generated..." echo "Installing npm dependencies..." From 63c6ddcb16d28d135b727fbee9e379b1a802c5c7 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Thu, 29 Nov 2018 10:26:24 -0300 Subject: [PATCH 261/582] moving multi mint to token manager --- CLI/commands/multi_mint.js | 197 ---------------------------------- CLI/commands/token_manager.js | 192 ++++++++++++++++++++++++++++++++- 2 files changed, 190 insertions(+), 199 deletions(-) delete mode 100644 CLI/commands/multi_mint.js diff --git a/CLI/commands/multi_mint.js b/CLI/commands/multi_mint.js deleted file mode 100644 index 3147b2754..000000000 --- a/CLI/commands/multi_mint.js +++ /dev/null @@ -1,197 +0,0 @@ -var common = require('./common/common_functions'); -var csv_shared = require('./common/csv_shared'); -var abis = require('./helpers/contract_abis'); -var BigNumber = require('bignumber.js'); - -let distribData = new Array(); -let fullFileData = new Array(); -let badData = new Array(); -let affiliatesFailedArray = new Array(); -let affiliatesKYCInvalidArray = new Array(); - -let securityToken; -let tokenDivisible; - -async function startScript(tokenSymbol, batchSize) { - securityToken = await csv_shared.start(tokenSymbol, batchSize); - - let result_processing = await csv_shared.read('./CLI/data/multi_mint_data.csv', multimint_processing); - distribData = result_processing.distribData; - fullFileData = result_processing.fullFileData; - badData = result_processing.badData; - - tokenDivisible = await securityToken.methods.granularity().call() == 1; - - await saveInBlockchain(); - await finalResults(); -} - -function multimint_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let validToken = isValidToken(csv_line[1]); - - if (isAddress && - validToken) { - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), validToken)] - } else { - return [false, new Array(csv_line[0], csv_line[1])] - } -} - -function isValidToken(token) { - var tokenAmount = parseFloat(token); - if (tokenDivisible) { - return tokenAmount - } else { - if ((tokenAmount % 1 == 0)) { - return tokenAmount; - } - return false - } -} - -async function saveInBlockchain() { - let gtmModules = await securityToken.methods.getModulesByType(3).call(); - - if (gtmModules.length > 0) { - console.log("Minting of tokens is only allowed before the STO get attached"); - process.exit(0); - } - - console.log(` - ----------------------------------------- - ----- Mint the tokens to affiliates ----- - ----------------------------------------- - `); - - for (let i = 0; i < distribData.length; i++) { - try { - let affiliatesVerifiedArray = [], tokensVerifiedArray = []; - - // Splitting the user arrays to be organized by input - for (let j = 0; j < distribData[i].length; j++) { - let investorAccount = distribData[i][j][0]; - let tokenAmount = web3.utils.toWei((distribData[i][j][1]).toString(), "ether"); - let verifiedTransaction = await securityToken.methods.verifyTransfer("0x0000000000000000000000000000000000000000", investorAccount, tokenAmount, web3.utils.fromAscii('')).call(); - if (verifiedTransaction) { - affiliatesVerifiedArray.push(investorAccount); - tokensVerifiedArray.push(tokenAmount); - } else { - let gtmModule = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); - let generalTransferManager = new web3.eth.Contract(abis.generalTransferManager(), gtmModule[0]); - let validKYC = (await generalTransferManager.methods.whitelist(Issuer.address).call()).expiryTime > Math.floor(Date.now()/1000); - if (validKYC) { - affiliatesFailedArray.push(investorAccount); - } else { - affiliatesKYCInvalidArray.push(investorAccount); - } - } - } - - let mintMultiAction = await securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); - let tx = await common.sendTransaction(mintMultiAction); - console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Multi Mint transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - - } catch (err) { - console.log("ERROR", err) - process.exit(0) - } - } - - return; -} - -async function finalResults() { - let totalInvestors = 0; - let updatedInvestors = 0; - let investorObjectLookup = {}; - let investorData_Events = new Array(); - - let event_data = await securityToken.getPastEvents('Minted', {fromBlock: 0, toBlock: 'latest'}, () => {}); - - for (var i = 0; i < event_data.length; i++) { - let combineArray = []; - - let investorAddress_Event = event_data[i].returnValues._to; - let amount_Event = event_data[i].returnValues._value; - let blockNumber = event_data[i].blockNumber; - - combineArray.push(investorAddress_Event); - combineArray.push(amount_Event); - combineArray.push(blockNumber); - - investorData_Events.push(combineArray) - - // We have already recorded it, so this is an update to our object - if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { - // The block number form the event we are checking is bigger, so we gotta replace it - if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { - investorObjectLookup[investorAddress_Event] = {amount: amount_Event, recordedBlockNumber: blockNumber}; - updatedInvestors += 1; - } - } else { - investorObjectLookup[investorAddress_Event] = {amount: amount_Event, recordedBlockNumber: blockNumber}; - totalInvestors += 1; - } - } - - let investorAddress_Events = Object.keys(investorObjectLookup) - - console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); - console.log(`A total of ${totalInvestors} affiliated investors get the token\n`); - console.log(`This script in total sent ${fullFileData.length - badData.length - affiliatesFailedArray.length - affiliatesKYCInvalidArray.length} new investors and updated investors to the blockchain.\n`); - console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); - console.log(`There were ${affiliatesKYCInvalidArray.length} accounts with invalid KYC.\n`); - console.log(`There were ${affiliatesFailedArray.length} accounts that didn't get sent to the blockchain as they would fail.\n`); - console.log("************************************************************************************************"); - console.log("OBJECT WITH EVERY USER AND THEIR MINTED TOKEN: \n\n", investorObjectLookup) - console.log("************************************************************************************************"); - console.log("LIST OF ALL INVESTORS WHO GOT THE MINTED TOKENS: \n\n", investorAddress_Events) - - let missingDistribs = [], failedVerificationDistribs = [], invalidKYCDistribs = []; - for (let l = 0; l < fullFileData.length; l++) { - if (affiliatesKYCInvalidArray.includes(fullFileData[l][0])) { - invalidKYCDistribs.push(fullFileData[l]); - } else if (affiliatesFailedArray.includes(fullFileData[l][0])) { - failedVerificationDistribs.push(fullFileData[l]); - } else if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { - missingDistribs.push(fullFileData[l]); - } - } - - if (invalidKYCDistribs.length > 0) { - console.log("**************************************************************************************************************************"); - console.log("The following data arrays have an invalid KYC. Please review if these accounts are whitelisted and their KYC is not expired\n"); - console.log(invalidKYCDistribs); - console.log("**************************************************************************************************************************"); - } - if (failedVerificationDistribs.length > 0) { - console.log("*********************************************************************************************************"); - console.log("-- The following data arrays failed at verifyTransfer. Please review if these accounts are whitelisted --\n"); - console.log(failedVerificationDistribs); - console.log("*********************************************************************************************************"); - } - if (missingDistribs.length > 0) { - console.log("******************************************************************************************"); - console.log("-- No Minted event was found for the following data arrays. Please review them manually --\n"); - console.log(missingDistribs); - console.log("******************************************************************************************"); - } - if (missingDistribs.length == 0 && - failedVerificationDistribs.length == 0 && - invalidKYCDistribs.length == 0) { - console.log("\n**************************************************************************************************************************"); - console.log("All accounts passed through from the CSV were successfully get the tokens, because we were able to read them all from events"); - console.log("****************************************************************************************************************************"); - } - -} - -module.exports = { - executeApp: async (tokenSymbol, batchSize) => { - return startScript(tokenSymbol, batchSize); - } -} \ No newline at end of file diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 6faa7ba34..0bbdad729 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -2,10 +2,11 @@ const readlineSync = require('readline-sync'); const chalk = require('chalk'); const whitelist = require('./whitelist'); -const multimint = require('./multi_mint'); const stoManager = require('./sto_manager'); const common = require('./common/common_functions'); const gbl = require('./common/global'); +const csv_shared = require('./common/csv_shared'); +const BigNumber = require('bignumber.js'); // Load contract artifacts const contracts = require('./helpers/contract_addresses'); @@ -15,10 +16,19 @@ let securityTokenRegistry; let polyToken; let featureRegistry; let securityToken; +let tokenDivisible; let allModules; let tokenSymbol +/* CSV data control */ +let distribData = new Array(); +let fullFileData = new Array(); +let badData = new Array(); +let affiliatesFailedArray = new Array(); +let affiliatesKYCInvalidArray = new Array(); +/* End CSV data control */ + async function setup() { try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); @@ -340,11 +350,189 @@ async function multi_mint_tokens() { console.log(chalk.green(`\nCongratulations! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); - await multimint.executeApp(tokenSymbol, 75); + await startCSV(tokenSymbol, 75) console.log(chalk.green(`\nCongratulations! Tokens get successfully Minted and transferred to token holders`)); } /// +async function startCSV(tokenSymbol, batchSize) { + securityToken = await csv_shared.start(tokenSymbol, batchSize); + + let result_processing = await csv_shared.read('./CLI/data/multi_mint_data.csv', multimint_processing); + distribData = result_processing.distribData; + fullFileData = result_processing.fullFileData; + badData = result_processing.badData; + + tokenDivisible = await securityToken.methods.granularity().call() == 1; + + await saveInBlockchain(); + await finalResults(); +} + +function multimint_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let validToken = isValidToken(csv_line[1]); + + if (isAddress && + validToken) { + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), validToken)] + } else { + return [false, new Array(csv_line[0], csv_line[1])] + } +} + +function isValidToken(token) { + var tokenAmount = parseFloat(token); + if (tokenDivisible) { + return tokenAmount + } else { + if ((tokenAmount % 1 == 0)) { + return tokenAmount; + } + return false + } +} + +async function saveInBlockchain() { + let gtmModules = await securityToken.methods.getModulesByType(3).call(); + + if (gtmModules.length > 0) { + console.log("Minting of tokens is only allowed before the STO get attached"); + process.exit(0); + } + + console.log(` + ----------------------------------------- + ----- Mint the tokens to affiliates ----- + ----------------------------------------- + `); + + for (let i = 0; i < distribData.length; i++) { + try { + let affiliatesVerifiedArray = [], tokensVerifiedArray = []; + + // Splitting the user arrays to be organized by input + for (let j = 0; j < distribData[i].length; j++) { + let investorAccount = distribData[i][j][0]; + let tokenAmount = web3.utils.toWei((distribData[i][j][1]).toString(), "ether"); + let verifiedTransaction = await securityToken.methods.verifyTransfer("0x0000000000000000000000000000000000000000", investorAccount, tokenAmount, web3.utils.fromAscii('')).call(); + if (verifiedTransaction) { + affiliatesVerifiedArray.push(investorAccount); + tokensVerifiedArray.push(tokenAmount); + } else { + let gtmModule = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + let generalTransferManager = new web3.eth.Contract(abis.generalTransferManager(), gtmModule[0]); + let validKYC = (await generalTransferManager.methods.whitelist(Issuer.address).call()).expiryTime > Math.floor(Date.now()/1000); + if (validKYC) { + affiliatesFailedArray.push(investorAccount); + } else { + affiliatesKYCInvalidArray.push(investorAccount); + } + } + } + + let mintMultiAction = await securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); + let tx = await common.sendTransaction(mintMultiAction); + console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); + console.log("Multi Mint transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); + + } catch (err) { + console.log("ERROR", err) + process.exit(0) + } + } + + return; +} + +async function finalResults() { + let totalInvestors = 0; + let updatedInvestors = 0; + let investorObjectLookup = {}; + let investorData_Events = new Array(); + + let event_data = await securityToken.getPastEvents('Minted', {fromBlock: 0, toBlock: 'latest'}, () => {}); + + for (var i = 0; i < event_data.length; i++) { + let combineArray = []; + + let investorAddress_Event = event_data[i].returnValues._to; + let amount_Event = event_data[i].returnValues._value; + let blockNumber = event_data[i].blockNumber; + + combineArray.push(investorAddress_Event); + combineArray.push(amount_Event); + combineArray.push(blockNumber); + + investorData_Events.push(combineArray) + + // We have already recorded it, so this is an update to our object + if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { + // The block number form the event we are checking is bigger, so we gotta replace it + if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { + investorObjectLookup[investorAddress_Event] = {amount: amount_Event, recordedBlockNumber: blockNumber}; + updatedInvestors += 1; + } + } else { + investorObjectLookup[investorAddress_Event] = {amount: amount_Event, recordedBlockNumber: blockNumber}; + totalInvestors += 1; + } + } + + let investorAddress_Events = Object.keys(investorObjectLookup) + + console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); + console.log(`A total of ${totalInvestors} affiliated investors get the token\n`); + console.log(`This script in total sent ${fullFileData.length - badData.length - affiliatesFailedArray.length - affiliatesKYCInvalidArray.length} new investors and updated investors to the blockchain.\n`); + console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); + console.log(`There were ${affiliatesKYCInvalidArray.length} accounts with invalid KYC.\n`); + console.log(`There were ${affiliatesFailedArray.length} accounts that didn't get sent to the blockchain as they would fail.\n`); + console.log("************************************************************************************************"); + console.log("OBJECT WITH EVERY USER AND THEIR MINTED TOKEN: \n\n", investorObjectLookup) + console.log("************************************************************************************************"); + console.log("LIST OF ALL INVESTORS WHO GOT THE MINTED TOKENS: \n\n", investorAddress_Events) + + let missingDistribs = [], failedVerificationDistribs = [], invalidKYCDistribs = []; + for (let l = 0; l < fullFileData.length; l++) { + if (affiliatesKYCInvalidArray.includes(fullFileData[l][0])) { + invalidKYCDistribs.push(fullFileData[l]); + } else if (affiliatesFailedArray.includes(fullFileData[l][0])) { + failedVerificationDistribs.push(fullFileData[l]); + } else if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { + missingDistribs.push(fullFileData[l]); + } + } + + if (invalidKYCDistribs.length > 0) { + console.log("**************************************************************************************************************************"); + console.log("The following data arrays have an invalid KYC. Please review if these accounts are whitelisted and their KYC is not expired\n"); + console.log(invalidKYCDistribs); + console.log("**************************************************************************************************************************"); + } + if (failedVerificationDistribs.length > 0) { + console.log("*********************************************************************************************************"); + console.log("-- The following data arrays failed at verifyTransfer. Please review if these accounts are whitelisted --\n"); + console.log(failedVerificationDistribs); + console.log("*********************************************************************************************************"); + } + if (missingDistribs.length > 0) { + console.log("******************************************************************************************"); + console.log("-- No Minted event was found for the following data arrays. Please review them manually --\n"); + console.log(missingDistribs); + console.log("******************************************************************************************"); + } + if (missingDistribs.length == 0 && + failedVerificationDistribs.length == 0 && + invalidKYCDistribs.length == 0) { + console.log("\n**************************************************************************************************************************"); + console.log("All accounts passed through from the CSV were successfully get the tokens, because we were able to read them all from events"); + console.log("****************************************************************************************************************************"); + } + +} + async function withdrawFromContract(erc20address, value) { let withdrawAction = securityToken.methods.withdrawERC20(erc20address, value); await common.sendTransaction(withdrawAction); From 434346c45782efc5a16a68de4833bdb73aed3415 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 29 Nov 2018 19:14:32 +0530 Subject: [PATCH 262/582] minor fix --- contracts/modules/TransferManager/BlacklistTransferManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index e4142874f..70087ae98 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -221,7 +221,7 @@ contract BlacklistTransferManager is ITransferManager { * @param _blacklistName Name of the blacklist */ function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { - require(blacklists[_blacklistName].startTime >= now, "Blacklist type doesn't exist"); + require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); uint256 investorIndex = investorToBlacklist[_investor].length; // Add blacklist index to the investor From a6a97e2fc8279b7d9f3a87feee63243304c0f5ee Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 29 Nov 2018 20:03:06 +0530 Subject: [PATCH 263/582] unification of blacklist name --- .../BlacklistTransferManager.sol | 88 +++++++++---------- test/z_blacklist_transfer_manager.js | 14 +-- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 70087ae98..3b0812cd7 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -38,7 +38,7 @@ contract BlacklistTransferManager is ITransferManager { event AddBlacklistType( uint256 _startTime, uint256 _endTime, - bytes32 _name, + bytes32 _blacklistName, uint256 _repeatPeriodTime ); @@ -46,13 +46,13 @@ contract BlacklistTransferManager is ITransferManager { event ModifyBlacklistType( uint256 _startTime, uint256 _endTime, - bytes32 _name, + bytes32 _blacklistName, uint256 _repeatPeriodTime ); // Emit when the added blacklist type is deleted event DeleteBlacklistType( - bytes32 _name + bytes32 _blacklistName ); // Emit when new investor is added to the blacklist type @@ -64,7 +64,7 @@ contract BlacklistTransferManager is ITransferManager { // Emit when investor is deleted from the blacklist type event DeleteInvestorFromBlacklist( address indexed _investor, - bytes32 _blacklist + bytes32 _blacklistName ); @@ -126,32 +126,32 @@ contract BlacklistTransferManager is ITransferManager { * @notice Used to add the blacklist type * @param _startTime Start date of the blacklist type * @param _endTime End date of the blacklist type - * @param _name Name of the blacklist type + * @param _blacklistName Name of the blacklist type * @param _repeatPeriodTime Repeat period of the blacklist type */ - function addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) public withPerm(ADMIN) { - _addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); + function addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName, uint256 _repeatPeriodTime) public withPerm(ADMIN) { + _addBlacklistType(_startTime, _endTime, _blacklistName, _repeatPeriodTime); } /** * @notice Used to add the multiple blacklist type * @param _startTimes Start date of the blacklist type * @param _endTimes End date of the blacklist type - * @param _names Name of the blacklist type + * @param _blacklistNames Name of the blacklist type * @param _repeatPeriodTimes Repeat period of the blacklist type */ - function addBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _names, uint256[] _repeatPeriodTimes) external withPerm(ADMIN) { - require (_startTimes.length == _endTimes.length && _endTimes.length == _names.length && _names.length == _repeatPeriodTimes.length, "Input array's length mismatch"); + function addBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _blacklistNames, uint256[] _repeatPeriodTimes) external withPerm(ADMIN) { + require (_startTimes.length == _endTimes.length && _endTimes.length == _blacklistNames.length && _blacklistNames.length == _repeatPeriodTimes.length, "Input array's length mismatch"); for (uint256 i = 0; i < _startTimes.length; i++){ - _addBlacklistType(_startTimes[i], _endTimes[i], _names[i], _repeatPeriodTimes[i]); + _addBlacklistType(_startTimes[i], _endTimes[i], _blacklistNames[i], _repeatPeriodTimes[i]); } } /** * @notice Internal function */ - function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _name) internal view { - require(_name != bytes32(0), "Invalid blacklist name"); + function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName) internal view { + require(_blacklistName != bytes32(0), "Invalid blacklist name"); require(_startTime >= now && _startTime < _endTime, "Invalid start or end date"); } @@ -159,42 +159,42 @@ contract BlacklistTransferManager is ITransferManager { * @notice Used to modify the details of a given blacklist type * @param _startTime Start date of the blacklist type * @param _endTime End date of the blacklist type - * @param _name Name of the blacklist type + * @param _blacklistName Name of the blacklist type * @param _repeatPeriodTime Repeat period of the blacklist type */ - function modifyBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) public withPerm(ADMIN) { - require(blacklists[_name].endTime != 0, "Blacklist type doesn't exist"); - _validParams(_startTime, _endTime, _name); - blacklists[_name] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); - emit ModifyBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); + function modifyBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName, uint256 _repeatPeriodTime) public withPerm(ADMIN) { + require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); + _validParams(_startTime, _endTime, _blacklistName); + blacklists[_blacklistName] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); + emit ModifyBlacklistType(_startTime, _endTime, _blacklistName, _repeatPeriodTime); } /** * @notice Used to modify the details of a given multpile blacklist types * @param _startTimes Start date of the blacklist type * @param _endTimes End date of the blacklist type - * @param _names Name of the blacklist type + * @param _blacklistNames Name of the blacklist type * @param _repeatPeriodTimes Repeat period of the blacklist type */ - function modifyBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _names, uint256[] _repeatPeriodTimes) external withPerm(ADMIN) { - require (_startTimes.length == _endTimes.length && _endTimes.length == _names.length && _names.length == _repeatPeriodTimes.length, "Input array's length mismatch"); + function modifyBlacklistTypeMulti(uint256[] _startTimes, uint256[] _endTimes, bytes32[] _blacklistNames, uint256[] _repeatPeriodTimes) external withPerm(ADMIN) { + require (_startTimes.length == _endTimes.length && _endTimes.length == _blacklistNames.length && _blacklistNames.length == _repeatPeriodTimes.length, "Input array's length mismatch"); for (uint256 i = 0; i < _startTimes.length; i++){ - modifyBlacklistType(_startTimes[i], _endTimes[i], _names[i], _repeatPeriodTimes[i]); + modifyBlacklistType(_startTimes[i], _endTimes[i], _blacklistNames[i], _repeatPeriodTimes[i]); } } /** * @notice Used to delete the blacklist type - * @param _name Name of the blacklist type + * @param _blacklistName Name of the blacklist type */ - function deleteBlacklistType(bytes32 _name) public withPerm(ADMIN) { - require(blacklists[_name].endTime != 0, "Blacklist type doesn’t exist"); - require(blacklistToInvestor[_name].length == 0, "Investors are associated with the blacklist"); + function deleteBlacklistType(bytes32 _blacklistName) public withPerm(ADMIN) { + require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn’t exist"); + require(blacklistToInvestor[_blacklistName].length == 0, "Investors are associated with the blacklist"); // delete blacklist type - delete(blacklists[_name]); + delete(blacklists[_blacklistName]); uint256 i = 0; for (i = 0; i < allBlacklists.length; i++) { - if (allBlacklists[i] == _name) { + if (allBlacklists[i] == _blacklistName) { break; } } @@ -202,16 +202,16 @@ contract BlacklistTransferManager is ITransferManager { allBlacklists[i] = allBlacklists[allBlacklists.length -1]; } allBlacklists.length--; - emit DeleteBlacklistType(_name); + emit DeleteBlacklistType(_blacklistName); } /** * @notice Used to delete the multiple blacklist type - * @param _names Name of the blacklist type + * @param _blacklistNames Name of the blacklist type */ - function deleteBlacklistTypeMulti(bytes32[] _names) external withPerm(ADMIN) { - for(uint256 i = 0; i < _names.length; i++){ - deleteBlacklistType(_names[i]); + function deleteBlacklistTypeMulti(bytes32[] _blacklistNames) external withPerm(ADMIN) { + for(uint256 i = 0; i < _blacklistNames.length; i++){ + deleteBlacklistType(_blacklistNames[i]); } } @@ -261,13 +261,13 @@ contract BlacklistTransferManager is ITransferManager { * @notice Used to assign the new blacklist type to the investor * @param _startTime Start date of the blacklist type * @param _endTime End date of the blacklist type - * @param _name Name of the blacklist type + * @param _blacklistName Name of the blacklist type * @param _repeatPeriodTime Repeat period of the blacklist type * @param _investor Address of the investor */ - function addInvestorToNewBlacklist(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime, address _investor) external withPerm(ADMIN){ - _addBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); - addInvestorToBlacklist(_investor, _name); + function addInvestorToNewBlacklist(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName, uint256 _repeatPeriodTime, address _investor) external withPerm(ADMIN){ + _addBlacklistType(_startTime, _endTime, _blacklistName, _repeatPeriodTime); + addInvestorToBlacklist(_investor, _blacklistName); } /** @@ -336,12 +336,12 @@ contract BlacklistTransferManager is ITransferManager { } } - function _addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _name, uint256 _repeatPeriodTime) internal { - require(blacklists[_name].endTime == 0, "Blacklist type already exist"); - _validParams(_startTime, _endTime, _name); - blacklists[_name] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); - allBlacklists.push(_name); - emit AddBlacklistType(_startTime, _endTime, _name, _repeatPeriodTime); + function _addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName, uint256 _repeatPeriodTime) internal { + require(blacklists[_blacklistName].endTime == 0, "Blacklist type already exist"); + _validParams(_startTime, _endTime, _blacklistName); + blacklists[_blacklistName] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); + allBlacklists.push(_blacklistName); + emit AddBlacklistType(_startTime, _endTime, _blacklistName, _repeatPeriodTime); } /** diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index a3dbee46d..07a5a3eb8 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -335,7 +335,7 @@ contract('BlacklistTransferManager', accounts => { it("Should add the blacklist", async() => { //Add the new blacklist let tx = await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in adding the type in blacklist"); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._blacklistName), "a_blacklist", "Failed in adding the type in blacklist"); }); it("Should fail in adding the blacklist as blacklist type already exist", async() => { @@ -388,7 +388,7 @@ contract('BlacklistTransferManager', accounts => { let event_data = tx.logs; for (var i = 0; i < event_data.length; i++) { - let blacklistName = event_data[i].args._name; + let blacklistName = event_data[i].args._blacklistName; assert.equal(web3.utils.hexToUtf8(blacklistName), name[i], "Failed in adding the blacklist"); } }); @@ -422,7 +422,7 @@ contract('BlacklistTransferManager', accounts => { it("Should modify the blacklist", async() => { //Modify the existing blacklist let tx = await I_BlacklistTransferManager.modifyBlacklistType(latestTime()+2000, latestTime()+3000, "a_blacklist", 20, { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "a_blacklist", "Failed in modifying the startdate of blacklist"); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._blacklistName), "a_blacklist", "Failed in modifying the startdate of blacklist"); }); @@ -477,7 +477,7 @@ contract('BlacklistTransferManager', accounts => { let event_data = tx.logs; for (var i = 0; i < event_data.length; i++) { - let blacklistName = event_data[i].args._name; + let blacklistName = event_data[i].args._blacklistName; assert.equal(web3.utils.hexToUtf8(blacklistName), name[i], "Failed in adding the blacklist"); } }); @@ -677,7 +677,7 @@ contract('BlacklistTransferManager', accounts => { it("Should delete the blacklist type", async() => { await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "b_blacklist", 20, { from: token_owner }); let tx = await I_BlacklistTransferManager.deleteBlacklistType("b_blacklist", { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "b_blacklist", "Failed in deleting the blacklist"); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._blacklistName), "b_blacklist", "Failed in deleting the blacklist"); }); @@ -712,7 +712,7 @@ contract('BlacklistTransferManager', accounts => { let event_data = tx.logs; for (var i = 0; i < event_data.length; i++) { - let blacklistName = event_data[i].args._name; + let blacklistName = event_data[i].args._blacklistName; assert.equal(web3.utils.hexToUtf8(blacklistName), name[i], "Failed in deleting the blacklist"); } @@ -866,7 +866,7 @@ contract('BlacklistTransferManager', accounts => { it("Should add investor and new blacklist type", async() => { let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(latestTime()+1000, latestTime()+3000, "c_blacklist", 20, account_investor3, { from: token_owner }); - assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "c_blacklist", "Failed in adding the blacklist"); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._blacklistName), "c_blacklist", "Failed in adding the blacklist"); assert.equal(tx.logs[1].args._investor, account_investor3, "Failed in adding the investor to blacklist"); }); From 78292847be7ea82085e56ad2df24314f5c32a63c Mon Sep 17 00:00:00 2001 From: shuffledex Date: Thu, 29 Nov 2018 11:37:27 -0300 Subject: [PATCH 264/582] replace multi mint to token manager method in cli menu --- CLI/commands/token_manager.js | 3 +++ CLI/polymath-cli.js | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 0bbdad729..265605b98 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -829,5 +829,8 @@ module.exports = { executeApp: async function (_tokenSymbol) { await initialize(_tokenSymbol) return executeApp(); + }, + startCSV: async function (tokenSymbol, batchSize) { + return startCSV(tokenSymbol, batchSize); } } diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 29bea752d..aff3aa4c5 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -7,7 +7,6 @@ var st20generator = require('./commands/ST20Generator'); var sto_manager = require('./commands/sto_manager'); var transfer = require('./commands/transfer'); var whitelist = require('./commands/whitelist'); -var multimint = require('./commands/multi_mint'); var accredit = require('./commands/accredit'); var changeNonAccreditedLimit = require('./commands/changeNonAccreditedLimit'); var transfer_ownership = require('./commands/transfer_ownership'); @@ -90,7 +89,7 @@ program .description('Distribute tokens to previously whitelisted investors') .action(async function(tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - await multimint.executeApp(tokenSymbol, batchSize); + await token_manager.startCSV(tokenSymbol, batchSize); }); program From 0a3adf2df24122f0180955d329f8682c0068a822 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Thu, 29 Nov 2018 13:45:57 -0300 Subject: [PATCH 265/582] moving accredit to sto manager file --- CLI/commands/accredit.js | 94 ------------------------------------- CLI/commands/sto_manager.js | 92 +++++++++++++++++++++++++++++++++++- CLI/polymath-cli.js | 3 +- 3 files changed, 91 insertions(+), 98 deletions(-) delete mode 100644 CLI/commands/accredit.js diff --git a/CLI/commands/accredit.js b/CLI/commands/accredit.js deleted file mode 100644 index cc550af2e..000000000 --- a/CLI/commands/accredit.js +++ /dev/null @@ -1,94 +0,0 @@ -var common = require('./common/common_functions'); -var csv_shared = require('./common/csv_shared'); -var abis = require('./helpers/contract_abis'); -var BigNumber = require('bignumber.js'); - -let distribData = new Array(); -let fullFileData = new Array(); -let badData = new Array(); - -let securityToken; - -async function startScript(tokenSymbol, batchSize) { - securityToken = await csv_shared.start(tokenSymbol, batchSize); - - let result_processing = await csv_shared.read('./CLI/data/accredited_data.csv', accredit_processing); - distribData = result_processing.distribData; - fullFileData = result_processing.fullFileData; - badData = result_processing.badData; - - await saveInBlockchain(); -}; - -function accredit_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let isAccredited = (typeof JSON.parse(csv_line[1].toLowerCase())) == "boolean" ? JSON.parse(csv_line[1].toLowerCase()) : "not-valid"; - - if (isAddress && - (isAccredited != "not-valid")) { - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), isAccredited)] - } else { - return [false, new Array(csv_line[0], isAccredited)] - } -} - -async function saveInBlockchain() { - let gtmModules; - try { - gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); - } catch (e) { - console.log("Please attach USDTieredSTO module before launch this action.", e) - process.exit(0) - } - - if (!gtmModules.length) { - console.log("Please attach USDTieredSTO module before launch this action.") - process.exit(0) - } - - let usdTieredSTO = new web3.eth.Contract(abis.usdTieredSTO(), gtmModules[0]); - - console.log(` - -------------------------------------------------------- - ----- Sending accreditation changes to blockchain ----- - -------------------------------------------------------- - `); - - for (let i = 0; i < distribData.length; i++) { - try { - - // Splitting the user arrays to be organized by input - for (let i = 0; i < distribData.length; i++) { - try { - let investorArray = [], isAccreditedArray = []; - - for (let j = 0; j < distribData[i].length; j++) { - investorArray.push(distribData[i][j][0]) - isAccreditedArray.push(distribData[i][j][1]) - } - - let changeAccreditedAction = await usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); - let tx = await common.sendTransaction(changeAccreditedAction); - console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Change accredited transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - } catch (err) { - console.log("ERROR:", err); - } - } - - } catch (err) { - console.log("ERROR", err) - process.exit(0) - } - } - - return; -} - -module.exports = { - executeApp: async (tokenSymbol, batchSize) => { - return startScript(tokenSymbol, batchSize); - } -} \ No newline at end of file diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index d0fd1c3ea..974d57de4 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -1,11 +1,12 @@ const readlineSync = require('readline-sync'); const chalk = require('chalk'); -const accredit = require('./accredit'); const changeNonAccreditedLimit = require('./changeNonAccreditedLimit'); const contracts = require('./helpers/contract_addresses'); const abis = require('./helpers/contract_abis'); const common = require('./common/common_functions'); const gbl = require('./common/global'); +const csv_shared = require('./common/csv_shared'); +const BigNumber = require('bignumber.js'); /////////////////// // Crowdsale params @@ -18,6 +19,12 @@ let polyToken; let usdToken; let securityToken; +/* CSV variables */ +let distribData = new Array(); +let fullFileData = new Array(); +let badData = new Array(); +/* End CSV variables */ + async function executeApp() { let exit = false; while (!exit) { @@ -690,7 +697,7 @@ async function usdTieredSTO_configure(currentSTO) { await common.sendTransaction(changeAccreditedAction); break; case 2: - await accredit.executeApp(tokenSymbol, 75); + await startCSV(tokenSymbol, 75); break; case 3: let account = readlineSync.question('Enter the address to change non accredited limit: '); @@ -728,6 +735,84 @@ async function usdTieredSTO_configure(currentSTO) { } } +async function startCSV(tokenSymbol, batchSize) { + securityToken = await csv_shared.start(tokenSymbol, batchSize); + + let result_processing = await csv_shared.read('./CLI/data/accredited_data.csv', accredit_processing); + distribData = result_processing.distribData; + fullFileData = result_processing.fullFileData; + badData = result_processing.badData; + + await saveInBlockchain(); +} + +function accredit_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let isAccredited = (typeof JSON.parse(csv_line[1].toLowerCase())) == "boolean" ? JSON.parse(csv_line[1].toLowerCase()) : "not-valid"; + + if (isAddress && + (isAccredited != "not-valid")) { + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), isAccredited)] + } else { + return [false, new Array(csv_line[0], isAccredited)] + } +} + +async function saveInBlockchain() { + let gtmModules; + try { + gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); + } catch (e) { + console.log("Please attach USDTieredSTO module before launch this action.", e) + process.exit(0) + } + + if (!gtmModules.length) { + console.log("Please attach USDTieredSTO module before launch this action.") + process.exit(0) + } + + let usdTieredSTO = new web3.eth.Contract(abis.usdTieredSTO(), gtmModules[0]); + + console.log(` + -------------------------------------------------------- + ----- Sending accreditation changes to blockchain ----- + -------------------------------------------------------- + `); + + for (let i = 0; i < distribData.length; i++) { + try { + + // Splitting the user arrays to be organized by input + for (let i = 0; i < distribData.length; i++) { + try { + let investorArray = [], isAccreditedArray = []; + + for (let j = 0; j < distribData[i].length; j++) { + investorArray.push(distribData[i][j][0]) + isAccreditedArray.push(distribData[i][j][1]) + } + + let changeAccreditedAction = await usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); + let tx = await common.sendTransaction(changeAccreditedAction); + console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); + console.log("Change accredited transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); + } catch (err) { + console.log("ERROR:", err); + } + } + + } catch (err) { + console.log("ERROR", err) + process.exit(0) + } + } + + return; +} + async function modfifyTimes(currentSTO) { let times = timesConfigUSDTieredSTO(); let modifyTimesAction = currentSTO.methods.modifyTimes(times.startTime, times.endTime); @@ -893,5 +978,8 @@ module.exports = { addSTOModule: async function (_tokenSymbol, stoConfig) { await initialize(_tokenSymbol); return addSTOModule(stoConfig) + }, + startCSV: async function (tokenSymbol, batchSize) { + return startCSV(tokenSymbol, batchSize); } } \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index aff3aa4c5..34d463bb9 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -7,7 +7,6 @@ var st20generator = require('./commands/ST20Generator'); var sto_manager = require('./commands/sto_manager'); var transfer = require('./commands/transfer'); var whitelist = require('./commands/whitelist'); -var accredit = require('./commands/accredit'); var changeNonAccreditedLimit = require('./commands/changeNonAccreditedLimit'); var transfer_ownership = require('./commands/transfer_ownership'); var dividends_manager = require('./commands/dividends_manager'); @@ -152,7 +151,7 @@ program .description('Runs accredit') .action(async function(tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - await accredit.executeApp(tokenSymbol, batchSize); + await sto_manager.startCSV(tokenSymbol, batchSize) }); program From dd62de4ce81ce745376410fc2d650260d82060ab Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 29 Nov 2018 19:36:26 +0200 Subject: [PATCH 266/582] data structure refactoring --- .../modules/Wallet/VestingEscrowWallet.sol | 346 ++++++++++-------- 1 file changed, 201 insertions(+), 145 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 52c3e5a8f..f4af38955 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -14,16 +14,20 @@ contract VestingEscrowWallet is IWallet { bytes32 public constant ADMIN = "ADMIN"; struct Schedule { - uint256 numberOfTokens; + //name of the template + bytes32 templateName; + //tokens that were already claimed uint256 claimedTokens; - uint256 duration; - uint256 frequency; + //start time of the schedule uint256 startTime; } struct Template { + //total amount of tokens uint256 numberOfTokens; + //schedule duration uint256 duration; + //schedule frequency uint256 frequency; } @@ -31,34 +35,49 @@ contract VestingEscrowWallet is IWallet { uint256 public unassignedTokens; - mapping (address => Schedule[]) public schedules; address[] public beneficiaries; - Template[] public templates; + //holds schedules for user + mapping(address => Schedule[]) public schedules; + //holds template names for user + mapping(address => bytes32[]) internal userToTemplates; + //mapping use to store the indexes for different template names for a user + mapping(address => mapping(bytes32 => uint256)) internal templateToScheduleIndex; + + //holds user for template + mapping(bytes32 => address[]) internal templateToUsers; + //mapping use to store the indexes for users for a template + mapping(bytes32 => mapping(address => uint256)) internal templateToUserIndex; + mapping(bytes32 => Template) templates; + bytes32[] public templateNames; + + // Emit when new schedule is added event AddSchedule( address indexed _beneficiary, - uint256 _numberOfTokens, - uint256 _duration, - uint256 _frequency, - uint256 _startTime, - uint256 _index + bytes32 _templateName, + uint256 _startTime ); + // Emit when schedule is modified event ModifySchedule( address indexed _beneficiary, - uint256 _index, - uint256 _numberOfTokens, - uint256 _duration, - uint256 _frequency, + bytes32 _templateName, uint256 _startTime ); + // Emit when all schedules are revoked for user event RevokeAllSchedules(address indexed _beneficiary); - event RevokeSchedule(address indexed _beneficiary, uint256 _index); + // Emit when schedule is revoked + event RevokeSchedule(address indexed _beneficiary, bytes32 _templateName); + // Emit when tokes are deposited to wallet event DepositTokens(uint256 _numberOfTokens, address _sender); + // Emit when all unassigned tokens are sent to treasury event SendToTreasury(uint256 _numberOfTokens, address _sender); + // Emit when is sent tokes to user event SendTokens(address indexed _beneficiary, uint256 _numberOfTokens); - event AddTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, uint256 _index); - event RemoveTemplate(uint256 _index); + // Emit when template is added + event AddTemplate(bytes32 _name, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency); + // Emit when template is removed + event RemoveTemplate(bytes32 _name); /** * @notice Constructor @@ -119,27 +138,43 @@ contract VestingEscrowWallet is IWallet { /** * @notice Add template + * @param _name name of template * @param _numberOfTokens number of tokens * @param _duration vesting duration * @param _frequency vesting frequency */ - function addTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) external withPerm(ADMIN) { + function addTemplate(bytes32 _name, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) external withPerm(ADMIN) { + _addTemplate(_name, _numberOfTokens, _duration, _frequency); + } + + function _addTemplate(bytes32 _name, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) internal { + require(!_isTemplateExists(_name)); _validateTemplate(_numberOfTokens, _duration, _frequency); - templates.push(Template(_numberOfTokens, _duration, _frequency)); - emit AddTemplate(_numberOfTokens, _duration, _frequency, templates.length - 1); + templateNames.push(_name); + templates[_name] = Template(_numberOfTokens, _duration, _frequency); + emit AddTemplate(_name, _numberOfTokens, _duration, _frequency); } /** * @notice Removes template - * @param _index index of the template + * @param _name name of template */ - function removeTemplate(uint256 _index) external withPerm(ADMIN) { - require(_index < templates.length, "Template not found"); - if (_index != templates.length - 1) { - templates[_index] = templates[templates.length - 1]; + function removeTemplate(bytes32 _name) external withPerm(ADMIN) { + require(_isTemplateExists(_name)); + require(!_isTemplateUsed(_name)); + // delete template data + delete templates[_name]; + uint256 i; + for (i = 0; i < templateNames.length; i++) { + if (_name == templateNames[i]) { + break; + } + } + if (i != templateNames.length - 1) { + templateNames[i] = templateNames[templateNames.length - 1]; } - templates.length--; - emit RemoveTemplate(_index); + templateNames.length--; + emit RemoveTemplate(_name); } /** @@ -147,12 +182,21 @@ contract VestingEscrowWallet is IWallet { * @return count of templates */ function getTemplateCount() external view returns(uint256) { - return templates.length; + return templateNames.length; + } + + /** + * @notice get the list of template names + * @return bytes32 Array of template names + */ + function getTemplateNames() external view returns(bytes32[]) { + return templateNames; } /** * @notice Adds vesting schedules for each of beneficiary * @param _beneficiary beneficiary's addresses + * @param _templateName name of the template that will be created * @param _numberOfTokens number of tokens * @param _duration vesting duration * @param _frequency vesting frequency @@ -160,6 +204,7 @@ contract VestingEscrowWallet is IWallet { */ function addSchedule( address _beneficiary, + bytes32 _templateName, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, @@ -168,11 +213,12 @@ contract VestingEscrowWallet is IWallet { public withPerm(ADMIN) { - _addSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); + _addSchedule(_beneficiary, _templateName, _numberOfTokens, _duration, _frequency, _startTime); } function _addSchedule( address _beneficiary, + bytes32 _templateName, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency, @@ -180,102 +226,98 @@ contract VestingEscrowWallet is IWallet { ) internal { - _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); - if (_numberOfTokens > unassignedTokens) { - _depositTokens(_numberOfTokens.sub(unassignedTokens)); - } - unassignedTokens = unassignedTokens.sub(_numberOfTokens); - //add beneficiary to the schedule list only if adding first schedule - if (schedules[_beneficiary].length == 0) { - beneficiaries.push(_beneficiary); - } - schedules[_beneficiary].push(Schedule(_numberOfTokens, 0, _duration, _frequency, _startTime)); - uint256 index = schedules[_beneficiary].length - 1; - emit AddSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime, index); + _addTemplate(_templateName, _numberOfTokens, _duration, _frequency); + _addScheduleFromTemplate(_beneficiary, _templateName, _startTime); } /** * @notice Adds vesting schedules from template for each of beneficiary * @param _beneficiary beneficiary's addresses - * @param _index index of the template + * @param _templateName name of the template * @param _startTime vesting start time */ - function addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) external withPerm(ADMIN) { - _addScheduleFromTemplate(_beneficiary, _index, _startTime); + function addScheduleFromTemplate(address _beneficiary, bytes32 _templateName, uint256 _startTime) external withPerm(ADMIN) { + _addScheduleFromTemplate(_beneficiary, _templateName, _startTime); } - function _addScheduleFromTemplate(address _beneficiary, uint256 _index, uint256 _startTime) internal { - require(_index < templates.length, "Template not found"); - Template memory template = templates[_index]; - _addSchedule(_beneficiary, template.numberOfTokens, template.duration, template.frequency, _startTime); + function _addScheduleFromTemplate(address _beneficiary, bytes32 _templateName, uint256 _startTime) internal { + require(_beneficiary != address(0), "Invalid address"); + require(_isTemplateExists(_templateName)); + uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + require( + schedules[_beneficiary].length == 0 || + schedules[_beneficiary][index].templateName != _templateName, + "Schedule from this template already added" + ); + require(now < _startTime, "Date in the past"); + uint256 numberOfTokens = templates[_templateName].numberOfTokens; + if (numberOfTokens > unassignedTokens) { + _depositTokens(numberOfTokens.sub(unassignedTokens)); + } + unassignedTokens = unassignedTokens.sub(numberOfTokens); + //add beneficiary to the schedule list only if adding first schedule + if (schedules[_beneficiary].length == 0) { + beneficiaries.push(_beneficiary); + } + schedules[_beneficiary].push(Schedule(_templateName, 0, _startTime)); + userToTemplates[_beneficiary].push(_templateName); + templateToScheduleIndex[_beneficiary][_templateName] = schedules[_beneficiary].length - 1; + templateToUsers[_templateName].push(_beneficiary); + templateToUserIndex[_templateName][_beneficiary] = templateToUsers[_templateName].length - 1; + emit AddSchedule(_beneficiary, _templateName, _startTime); } /** * @notice Modifies vesting schedules for each of beneficiary * @param _beneficiary beneficiary's addresses - * @param _index index of schedule - * @param _numberOfTokens number of tokens - * @param _duration vesting duration - * @param _frequency vesting frequency + * @param _templateName name of the template * @param _startTime vesting start time */ - function modifySchedule( - address _beneficiary, - uint256 _index, - uint256 _numberOfTokens, - uint256 _duration, - uint256 _frequency, - uint256 _startTime - ) - public - withPerm(ADMIN) - { - _modifySchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); + function modifySchedule(address _beneficiary, bytes32 _templateName, uint256 _startTime) public withPerm(ADMIN) { + _modifySchedule(_beneficiary, _templateName, _startTime); } - function _modifySchedule( - address _beneficiary, - uint256 _index, - uint256 _numberOfTokens, - uint256 _duration, - uint256 _frequency, - uint256 _startTime - ) - internal - { - _validateSchedule(_beneficiary, _numberOfTokens, _duration, _frequency, _startTime); - _checkSchedule(_beneficiary, _index); - Schedule storage schedule = schedules[_beneficiary][_index]; + function _modifySchedule(address _beneficiary, bytes32 _templateName, uint256 _startTime) internal { + _checkSchedule(_beneficiary, _templateName); + require(now < _startTime, "Date in the past"); + uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + Schedule storage schedule = schedules[_beneficiary][index]; /*solium-disable-next-line security/no-block-members*/ require(now < schedule.startTime, "Schedule started"); - if (_numberOfTokens <= schedule.numberOfTokens) { - unassignedTokens = unassignedTokens.add(schedule.numberOfTokens.sub(_numberOfTokens)); - } else { - if (_numberOfTokens.sub(schedule.numberOfTokens) > unassignedTokens) { - _depositTokens(_numberOfTokens.sub(schedule.numberOfTokens).sub(unassignedTokens)); - } - unassignedTokens = unassignedTokens.sub(_numberOfTokens.sub(schedule.numberOfTokens)); - } - schedules[_beneficiary][_index] = Schedule(_numberOfTokens, 0, _duration, _frequency, _startTime); - emit ModifySchedule(_beneficiary, _index, _numberOfTokens, _duration, _frequency, _startTime); + schedule.startTime = _startTime; + emit ModifySchedule(_beneficiary, _templateName, _startTime); } /** * @notice Revokes beneficiary's schedule * @param _beneficiary beneficiary's address - * @param _index index of the schedule + * @param _templateName name of the template */ - function revokeSchedule(address _beneficiary, uint256 _index) external withPerm(ADMIN) { - _checkSchedule(_beneficiary, _index); - _sendTokens(_beneficiary, _index); + function revokeSchedule(address _beneficiary, bytes32 _templateName) external withPerm(ADMIN) { + _checkSchedule(_beneficiary, _templateName); + uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + _sendTokens(_beneficiary, index); Schedule[] storage userSchedules = schedules[_beneficiary]; - uint256 releasedTokens = _getReleasedTokens(_beneficiary, _index); - unassignedTokens = unassignedTokens.add(userSchedules[_index].numberOfTokens.sub(releasedTokens)); - if (_index != userSchedules.length - 1) { - userSchedules[_index] = userSchedules[userSchedules.length - 1]; + //update unassignedTokens + uint256 releasedTokens = _getReleasedTokens(_beneficiary, index); + unassignedTokens = unassignedTokens.add(templates[_templateName].numberOfTokens.sub(releasedTokens)); + //delete user schedule and relation between user and template + if (index != userSchedules.length - 1) { + userSchedules[index] = userSchedules[userSchedules.length - 1]; + userToTemplates[_beneficiary][index] = userToTemplates[_beneficiary][userToTemplates[_beneficiary].length - 1]; } userSchedules.length--; - emit RevokeSchedule(_beneficiary, _index); + userToTemplates[_beneficiary].length--; + delete templateToScheduleIndex[_beneficiary][_templateName]; + //delete relation between template and user + uint256 templateIndex = templateToUserIndex[_templateName][_beneficiary]; + if (templateIndex != templateToUsers[_templateName].length - 1) { + templateToUsers[_templateName][templateIndex] = templateToUsers[_templateName][templateToUsers[_templateName].length - 1]; + } + templateToUsers[_templateName].length--; + delete templateToUserIndex[_templateName][_beneficiary]; + + emit RevokeSchedule(_beneficiary, _templateName); } /** @@ -292,41 +334,62 @@ contract VestingEscrowWallet is IWallet { Schedule[] storage userSchedules = schedules[_beneficiary]; for (uint256 i = 0; i < userSchedules.length; i++) { uint256 releasedTokens = _getReleasedTokens(_beneficiary, i); - unassignedTokens = unassignedTokens.add(userSchedules[i].numberOfTokens.sub(releasedTokens)); + Template storage template = templates[userSchedules[i].templateName]; + unassignedTokens = unassignedTokens.add(template.numberOfTokens.sub(releasedTokens)); + delete templateToScheduleIndex[_beneficiary][userSchedules[i].templateName]; } userSchedules.length = 0; + delete userToTemplates[_beneficiary]; emit RevokeAllSchedules(_beneficiary); } /** * @notice Returns beneficiary's schedule * @param _beneficiary beneficiary's address - * @param _index index of the schedule + * @param _templateName name of the template * @return beneficiary's schedule */ - function getSchedule(address _beneficiary, uint256 _index) external view returns(uint256, uint256, uint256, uint256, State) { - _checkSchedule(_beneficiary, _index); - Schedule storage schedule = schedules[_beneficiary][_index]; + function getSchedule(address _beneficiary, bytes32 _templateName) external view returns(uint256, uint256, uint256, uint256, State) { + _checkSchedule(_beneficiary, _templateName); + uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + Schedule storage schedule = schedules[_beneficiary][index]; return ( - schedule.numberOfTokens, - schedule.duration, - schedule.frequency, + templates[schedule.templateName].numberOfTokens, + templates[schedule.templateName].duration, + templates[schedule.templateName].frequency, schedule.startTime, - getScheduleState(_beneficiary, _index) + getScheduleState(_beneficiary, _templateName) ); } - function getScheduleState(address _beneficiary, uint256 _index) public view returns(State) { - Schedule memory schedule = schedules[_beneficiary][_index]; + /** + * @notice Returns state of the schedule + * @param _beneficiary beneficiary's address + * @return state of the schedule + */ + function getScheduleState(address _beneficiary, bytes32 _templateName) public view returns(State) { + _checkSchedule(_beneficiary, _templateName); + uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + Schedule memory schedule = schedules[_beneficiary][index]; if (now < schedule.startTime) { return State.CREATED; - } else if (now > schedule.startTime && now < schedule.startTime.add(schedule.duration)) { + } else if (now > schedule.startTime && now < schedule.startTime.add(templates[_templateName].duration)) { return State.STARTED; } else { return State.COMPLETED; } } + /** + * @notice Returns list of template names + * @param _beneficiary beneficiary's address + * @return list of template names + */ + function getTemplateNames(address _beneficiary) external view returns(bytes32[]) { + require(_beneficiary != address(0), "Invalid address"); + return userToTemplates[_beneficiary]; + } + /** * @notice Returns count of beneficiary's schedules * @param _beneficiary beneficiary's address @@ -345,15 +408,16 @@ contract VestingEscrowWallet is IWallet { function _getReleasedTokens(address _beneficiary, uint256 _index) internal view returns(uint256) { Schedule storage schedule = schedules[_beneficiary][_index]; + Template storage template = templates[schedule.templateName]; /*solium-disable-next-line security/no-block-members*/ if (now > schedule.startTime) { - uint256 periodCount = schedule.duration.div(schedule.frequency); + uint256 periodCount = template.duration.div(template.frequency); /*solium-disable-next-line security/no-block-members*/ - uint256 periodNumber = (now.sub(schedule.startTime)).div(schedule.frequency); + uint256 periodNumber = (now.sub(schedule.startTime)).div(template.frequency); if (periodNumber > periodCount) { periodNumber = periodCount; } - return schedule.numberOfTokens.mul(periodNumber).div(periodCount); + return template.numberOfTokens.mul(periodNumber).div(periodCount); } else { return 0; } @@ -388,6 +452,7 @@ contract VestingEscrowWallet is IWallet { /** * @notice Used to bulk add vesting schedules for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses + * @param _templateNames array of the template names * @param _numberOfTokens array of number of tokens * @param _durations array of vesting duration * @param _frequencies array of vesting frequency @@ -395,15 +460,17 @@ contract VestingEscrowWallet is IWallet { */ function addScheduleMulti( address[] _beneficiaries, + bytes32[] _templateNames, uint256[] _numberOfTokens, uint256[] _durations, uint256[] _frequencies, uint256[] _startTimes ) - external + public withPerm(ADMIN) { require( + _beneficiaries.length == _templateNames.length && /*solium-disable-line operator-whitespace*/ _beneficiaries.length == _numberOfTokens.length && /*solium-disable-line operator-whitespace*/ _beneficiaries.length == _durations.length && /*solium-disable-line operator-whitespace*/ _beneficiaries.length == _frequencies.length && /*solium-disable-line operator-whitespace*/ @@ -411,20 +478,20 @@ contract VestingEscrowWallet is IWallet { "Arrays sizes mismatch" ); for (uint256 i = 0; i < _beneficiaries.length; i++) { - _addSchedule(_beneficiaries[i], _numberOfTokens[i], _durations[i], _frequencies[i], _startTimes[i]); + _addSchedule(_beneficiaries[i], _templateNames[i], _numberOfTokens[i], _durations[i], _frequencies[i], _startTimes[i]); } } /** * @notice Used to bulk add vesting schedules from template for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses - * @param _index index of the template + * @param _templateNames array of the template names * @param _startTimes array of vesting start time */ - function addScheduleFromTemplateMulti(address[] _beneficiaries, uint256 _index, uint256[] _startTimes) external withPerm(ADMIN) { - require(_beneficiaries.length == _startTimes.length, "Arrays sizes mismatch"); + function addScheduleFromTemplateMulti(address[] _beneficiaries, bytes32[] _templateNames, uint256[] _startTimes) external withPerm(ADMIN) { + require(_beneficiaries.length == _templateNames.length && _beneficiaries.length == _startTimes.length, "Arrays sizes mismatch"); for (uint256 i = 0; i < _beneficiaries.length; i++) { - _addScheduleFromTemplate(_beneficiaries[i], _index, _startTimes[i]); + _addScheduleFromTemplate(_beneficiaries[i], _templateNames[i], _startTimes[i]); } } @@ -441,54 +508,43 @@ contract VestingEscrowWallet is IWallet { /** * @notice Used to bulk modify vesting schedules for each of beneficiaries * @param _beneficiaries array of beneficiary's addresses - * @param _indexes array of beneficiary's indexes of schedule - * @param _numberOfTokens array of number of tokens - * @param _durations array of vesting duration - * @param _frequencies array of vesting frequency + * @param _templateNames array of the template names * @param _startTimes array of vesting start time */ function modifyScheduleMulti( address[] _beneficiaries, - uint256[] _indexes, - uint256[] _numberOfTokens, - uint256[] _durations, - uint256[] _frequencies, + bytes32[] _templateNames, uint256[] _startTimes ) public withPerm(ADMIN) { require( - _beneficiaries.length == _indexes.length && /*solium-disable-line operator-whitespace*/ - _beneficiaries.length == _numberOfTokens.length && /*solium-disable-line operator-whitespace*/ - _beneficiaries.length == _durations.length && /*solium-disable-line operator-whitespace*/ - _beneficiaries.length == _frequencies.length && /*solium-disable-line operator-whitespace*/ + _beneficiaries.length == _templateNames.length && /*solium-disable-line operator-whitespace*/ _beneficiaries.length == _startTimes.length, "Arrays sizes mismatch" ); for (uint256 i = 0; i < _beneficiaries.length; i++) { - _modifySchedule(_beneficiaries[i], _indexes[i], _numberOfTokens[i], _durations[i], _frequencies[i], _startTimes[i]); + _modifySchedule(_beneficiaries[i], _templateNames[i], _startTimes[i]); } } - function _validateSchedule( - address _beneficiary, - uint256 _numberOfTokens, - uint256 _duration, - uint256 _frequency, - uint256 _startTime - ) - internal - view - { + function _checkSchedule(address _beneficiary, bytes32 _templateName) internal view { require(_beneficiary != address(0), "Invalid address"); - _validateTemplate(_numberOfTokens, _duration, _frequency); - require(now < _startTime, "Date in the past"); + uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + require( + index < schedules[_beneficiary].length && + schedules[_beneficiary][index].templateName == _templateName, + "Schedule not found" + ); } - function _checkSchedule(address _beneficiary, uint256 _index) internal view { - require(_beneficiary != address(0), "Invalid address"); - require(_index < schedules[_beneficiary].length, "Schedule not found"); + function _isTemplateExists(bytes32 _name) internal view returns(bool) { + return templates[_name].numberOfTokens > 0; + } + + function _isTemplateUsed(bytes32 _name) internal view returns(bool) { + return templateToUsers[_name].length > 0; } function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) internal pure { From 4c4c9adb163c4bd424797d207e90aa312795c631 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 29 Nov 2018 20:00:19 +0200 Subject: [PATCH 267/582] refactored revokeSchedule() --- .../modules/Wallet/VestingEscrowWallet.sol | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index f4af38955..454f9afa6 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -297,11 +297,16 @@ contract VestingEscrowWallet is IWallet { _checkSchedule(_beneficiary, _templateName); uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; _sendTokens(_beneficiary, index); - Schedule[] storage userSchedules = schedules[_beneficiary]; - //update unassignedTokens uint256 releasedTokens = _getReleasedTokens(_beneficiary, index); unassignedTokens = unassignedTokens.add(templates[_templateName].numberOfTokens.sub(releasedTokens)); - //delete user schedule and relation between user and template + _deleteUserToTemplates(_beneficiary, _templateName); + _deleteTemplateToUsers(_beneficiary, _templateName); + emit RevokeSchedule(_beneficiary, _templateName); + } + + function _deleteUserToTemplates(address _beneficiary, bytes32 _templateName) internal { + uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + Schedule[] storage userSchedules = schedules[_beneficiary]; if (index != userSchedules.length - 1) { userSchedules[index] = userSchedules[userSchedules.length - 1]; userToTemplates[_beneficiary][index] = userToTemplates[_beneficiary][userToTemplates[_beneficiary].length - 1]; @@ -309,15 +314,16 @@ contract VestingEscrowWallet is IWallet { userSchedules.length--; userToTemplates[_beneficiary].length--; delete templateToScheduleIndex[_beneficiary][_templateName]; - //delete relation between template and user + } + + function _deleteTemplateToUsers(address _beneficiary, bytes32 _templateName) internal { + uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; uint256 templateIndex = templateToUserIndex[_templateName][_beneficiary]; if (templateIndex != templateToUsers[_templateName].length - 1) { templateToUsers[_templateName][templateIndex] = templateToUsers[_templateName][templateToUsers[_templateName].length - 1]; } templateToUsers[_templateName].length--; delete templateToUserIndex[_templateName][_beneficiary]; - - emit RevokeSchedule(_beneficiary, _templateName); } /** @@ -337,8 +343,9 @@ contract VestingEscrowWallet is IWallet { Template storage template = templates[userSchedules[i].templateName]; unassignedTokens = unassignedTokens.add(template.numberOfTokens.sub(releasedTokens)); delete templateToScheduleIndex[_beneficiary][userSchedules[i].templateName]; + _deleteTemplateToUsers(_beneficiary, userSchedules[i].templateName); } - userSchedules.length = 0; + delete schedules[_beneficiary]; delete userToTemplates[_beneficiary]; emit RevokeAllSchedules(_beneficiary); } From de2633d8c382b3cc403b5ae947bc464141719582 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Thu, 29 Nov 2018 15:38:50 -0300 Subject: [PATCH 268/582] moving accreditable and nonAccreditable to STO manager --- CLI/commands/changeNonAccreditedLimit.js | 94 ---------------------- CLI/commands/sto_manager.js | 99 +++++++++++++++++++++--- CLI/polymath-cli.js | 5 +- 3 files changed, 92 insertions(+), 106 deletions(-) delete mode 100644 CLI/commands/changeNonAccreditedLimit.js diff --git a/CLI/commands/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js deleted file mode 100644 index 029f2fc70..000000000 --- a/CLI/commands/changeNonAccreditedLimit.js +++ /dev/null @@ -1,94 +0,0 @@ -var common = require('./common/common_functions'); -var csv_shared = require('./common/csv_shared'); -var abis = require('./helpers/contract_abis'); -var BigNumber = require('bignumber.js'); - -let distribData = new Array(); -let fullFileData = new Array(); -let badData = new Array(); - -let securityToken; - -async function startScript(tokenSymbol, batchSize) { - securityToken = await csv_shared.start(tokenSymbol, batchSize); - - let result_processing = await csv_shared.read('./CLI/data/nonAccreditedLimits_data.csv', nonAccredited_processing); - distribData = result_processing.distribData; - fullFileData = result_processing.fullFileData; - badData = result_processing.badData; - - await saveInBlockchain(); -} - -function nonAccredited_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let isNumber = !isNaN(csv_line[1]); - - if (isAddress && isNumber) { - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), csv_line[1])] - } else { - return [false, new Array(csv_line[0], csv_line[1])] - } -} - -async function saveInBlockchain() { - let gtmModules; - try { - gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); - } catch (e) { - console.log("Please attach USDTieredSTO module before launch this action.", e) - process.exit(0) - } - - if (!gtmModules.length) { - console.log("Please attach USDTieredSTO module before launch this action.") - process.exit(0) - } - - let usdTieredSTO = new web3.eth.Contract(abis.usdTieredSTO(), gtmModules[0]); - - console.log(` - -------------------------------------------------------------- - ----- Sending non accredited limit changes to blockchain ----- - -------------------------------------------------------------- - `); - - for (let i = 0; i < distribData.length; i++) { - try { - - // Splitting the user arrays to be organized by input - for (let i = 0; i < distribData.length; i++) { - try { - let investorArray = [], limitArray = []; - - for (let j = 0; j < distribData[i].length; j++) { - investorArray.push(distribData[i][j][0]); - limitArray.push(web3.utils.toWei(distribData[i][j][1].toString())); - } - - let changeNonAccreditedLimitAction = await usdTieredSTO.methods.changeNonAccreditedLimit(investorArray, limitArray); - let tx = await common.sendTransaction(changeNonAccreditedLimitAction); - console.log(`Batch ${i} - Attempting to change non accredited limits to accounts:\n\n`, investorArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Change accredited transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString()), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - - } catch (err) { - console.log("ERROR:", err); - } - } - - } catch (err) { - console.log("ERROR", err) - process.exit(0) - } - } - - return; -} - -module.exports = { - executeApp: async (tokenSymbol, batchSize) => { - return startScript(tokenSymbol, batchSize); - } -} \ No newline at end of file diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 974d57de4..8cd2baa5e 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -1,6 +1,5 @@ const readlineSync = require('readline-sync'); const chalk = require('chalk'); -const changeNonAccreditedLimit = require('./changeNonAccreditedLimit'); const contracts = require('./helpers/contract_addresses'); const abis = require('./helpers/contract_abis'); const common = require('./common/common_functions'); @@ -697,7 +696,7 @@ async function usdTieredSTO_configure(currentSTO) { await common.sendTransaction(changeAccreditedAction); break; case 2: - await startCSV(tokenSymbol, 75); + await startCSV(tokenSymbol, 75, 'accredited'); break; case 3: let account = readlineSync.question('Enter the address to change non accredited limit: '); @@ -709,7 +708,7 @@ async function usdTieredSTO_configure(currentSTO) { await common.sendTransaction(changeNonAccreditedLimitAction); break; case 4: - await changeNonAccreditedLimit.executeApp(tokenSymbol, 75); + await startCSV(tokenSymbol, 75, 'nonAccredited'); break; case 5: await modfifyTimes(currentSTO); @@ -735,15 +734,41 @@ async function usdTieredSTO_configure(currentSTO) { } } -async function startCSV(tokenSymbol, batchSize) { +async function startCSV(tokenSymbol, batchSize, accreditionType) { + let file, proccessing, saving; + + switch (accreditionType) { + case 'accredited': + file = './CLI/data/accredited_data.csv' + proccessing = accredit_processing + saving = saveInBlockchainAccredited + break; + case 'nonAccredited': + file = './CLI/data/nonAccreditedLimits_data.csv' + proccessing = nonAccredited_processing + saving = saveInBlockchainNonAccredited + break; + } + securityToken = await csv_shared.start(tokenSymbol, batchSize); - let result_processing = await csv_shared.read('./CLI/data/accredited_data.csv', accredit_processing); + let result_processing = await csv_shared.read(file, proccessing); distribData = result_processing.distribData; fullFileData = result_processing.fullFileData; badData = result_processing.badData; - await saveInBlockchain(); + await saving(); +} + +function nonAccredited_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let isNumber = !isNaN(csv_line[1]); + + if (isAddress && isNumber) { + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), csv_line[1])] + } else { + return [false, new Array(csv_line[0], csv_line[1])] + } } function accredit_processing(csv_line) { @@ -758,7 +783,7 @@ function accredit_processing(csv_line) { } } -async function saveInBlockchain() { +async function saveInBlockchainAccredited() { let gtmModules; try { gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); @@ -813,6 +838,62 @@ async function saveInBlockchain() { return; } +async function saveInBlockchainNonAccredited() { + let gtmModules; + try { + gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); + } catch (e) { + console.log("Please attach USDTieredSTO module before launch this action.", e) + process.exit(0) + } + + if (!gtmModules.length) { + console.log("Please attach USDTieredSTO module before launch this action.") + process.exit(0) + } + + let usdTieredSTO = new web3.eth.Contract(abis.usdTieredSTO(), gtmModules[0]); + + console.log(` + -------------------------------------------------------------- + ----- Sending non accredited limit changes to blockchain ----- + -------------------------------------------------------------- + `); + + for (let i = 0; i < distribData.length; i++) { + try { + + // Splitting the user arrays to be organized by input + for (let i = 0; i < distribData.length; i++) { + try { + let investorArray = [], limitArray = []; + + for (let j = 0; j < distribData[i].length; j++) { + investorArray.push(distribData[i][j][0]); + limitArray.push(web3.utils.toWei(distribData[i][j][1].toString())); + } + + let changeNonAccreditedLimitAction = await usdTieredSTO.methods.changeNonAccreditedLimit(investorArray, limitArray); + let tx = await common.sendTransaction(changeNonAccreditedLimitAction); + console.log(`Batch ${i} - Attempting to change non accredited limits to accounts:\n\n`, investorArray, "\n\n"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); + console.log("Change accredited transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString()), "Ether"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); + + } catch (err) { + console.log("ERROR:", err); + } + } + + } catch (err) { + console.log("ERROR", err) + process.exit(0) + } + } + + return; +} + async function modfifyTimes(currentSTO) { let times = timesConfigUSDTieredSTO(); let modifyTimesAction = currentSTO.methods.modifyTimes(times.startTime, times.endTime); @@ -979,7 +1060,7 @@ module.exports = { await initialize(_tokenSymbol); return addSTOModule(stoConfig) }, - startCSV: async function (tokenSymbol, batchSize) { - return startCSV(tokenSymbol, batchSize); + startCSV: async function (tokenSymbol, batchSize, accreditionType) { + return startCSV(tokenSymbol, batchSize, accreditionType); } } \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 34d463bb9..c34a4569d 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -7,7 +7,6 @@ var st20generator = require('./commands/ST20Generator'); var sto_manager = require('./commands/sto_manager'); var transfer = require('./commands/transfer'); var whitelist = require('./commands/whitelist'); -var changeNonAccreditedLimit = require('./commands/changeNonAccreditedLimit'); var transfer_ownership = require('./commands/transfer_ownership'); var dividends_manager = require('./commands/dividends_manager'); var transfer_manager = require('./commands/transfer_manager'); @@ -151,7 +150,7 @@ program .description('Runs accredit') .action(async function(tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - await sto_manager.startCSV(tokenSymbol, batchSize) + await sto_manager.startCSV(tokenSymbol, batchSize, 'accredited') }); program @@ -160,7 +159,7 @@ program .description('Runs changeNonAccreditedLimit') .action(async function(tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - await changeNonAccreditedLimit.executeApp(tokenSymbol, batchSize); + await sto_manager.startCSV(tokenSymbol, batchSize, 'nonAccredited') }); program From 6694a068f55768e107e7691332259f34dd416724 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 29 Nov 2018 15:57:18 -0300 Subject: [PATCH 269/582] Count transfer manager --- CLI/commands/helpers/contract_abis.js | 5 +++ CLI/commands/transfer_manager.js | 47 ++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index f93f18ac7..0b186f590 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -8,6 +8,7 @@ let cappedSTOABI; let usdTieredSTOABI; let generalTransferManagerABI; let manualApprovalTransferManagerABI; +let countTransferManagerABI; let generalPermissionManagerABI; let polyTokenABI; let cappedSTOFactoryABI; @@ -31,6 +32,7 @@ try { usdTieredSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTO.json').toString()).abi; generalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralTransferManager.json').toString()).abi; manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ManualApprovalTransferManager.json').toString()).abi; + countTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/CountTransferManager.json').toString()).abi; generalPermissionManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralPermissionManager.json').toString()).abi; polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; @@ -78,6 +80,9 @@ module.exports = { manualApprovalTransferManager: function () { return manualApprovalTransferManagerABI; }, + countTransferManager: function () { + return countTransferManagerABI; + }, generalPermissionManager: function () { return generalPermissionManagerABI; }, diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 44ae64ca1..4fdd6286a 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -180,7 +180,7 @@ async function configExistingModules(tmModules) { let options = tmModules.map(m => `${m.name} at ${m.address}`); let index = readlineSync.keyInSelect(options, 'Which module do you want to config? ', { cancel: 'Return' }); console.log('Selected:', index != -1 ? options[index] : 'Return', '\n'); - let moduleNameSelected = tmModules[index].name; + let moduleNameSelected = index != -1 ? tmModules[index].name : 'Return'; switch (moduleNameSelected) { case 'GeneralTransferManager': @@ -202,7 +202,9 @@ async function configExistingModules(tmModules) { )); break; case 'CountTransferManager': - //await countTransferManager(); + currentTransferManager = new web3.eth.Contract(abis.countTransferManager(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await countTransferManager(); break; case 'SingleTradeVolumeRestrictionTM': //currentTransferManager = new web3.eth.Contract(abis.singleTradeVolumeRestrictionTM(), tmModules[index].address); @@ -226,8 +228,14 @@ async function configExistingModules(tmModules) { } async function addTransferManagerModule() { - let options = ['GeneralTransferManager', 'ManualApprovalTransferManager'/*, 'PercentageTransferManager', -'CountTransferManager', 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM'*/]; + let options = [ + 'GeneralTransferManager', + 'ManualApprovalTransferManager', + 'CountTransferManager', + //'PercentageTransferManager', + //'SingleTradeVolumeRestrictionTM', + //'LookupVolumeRestrictionTM'*/ + ]; let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', { cancel: 'Return' }); if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { @@ -241,11 +249,9 @@ async function addTransferManagerModule() { )); break; case 'CountTransferManager': - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); + let maxHolderCount = readlineSync.question('Enter the maximum no. of holders the SecurityToken is allowed to have: '); + let configureCountTM = abis.countTransferManager().find(o => o.name === 'configure' && o.type === 'function'); + bytes = web3.eth.abi.encodeFunctionCall(configureCountTM, [maxHolderCount]); break; case 'SingleTradeVolumeRestrictionTM': /* @@ -643,6 +649,29 @@ async function getManualBlocking(_from, _to) { return result; } +async function countTransferManager() { + console.log(chalk.blue(`Count Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + + // Show current data + let displayMaxHolderCount = await currentTransferManager.methods.maxHolderCount().call(); + + console.log(`- Max holder count: ${displayMaxHolderCount}`); + + let options = ['Change max holder count'] + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); + let optionSelected = options[index]; + console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + switch (optionSelected) { + case 'Change max holder count': + let maxHolderCount = readlineSync.question('Enter the maximum no. of holders the SecurityToken is allowed to have: '); + let changeHolderCountAction = currentTransferManager.methods.changeHolderCount(maxHolderCount); + let changeHolderCountReceipt = await common.sendTransaction(changeHolderCountAction); + let changeHolderCountEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeHolderCountReceipt.logs, 'ModifyHolderCount'); + console.log(chalk.green(`Max holder count has been set to ${changeHolderCountEvent._newHolderCount} sucessfully!`)); + break; + } +} + async function singleTradeVolumeRestrictionTM() { console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address}`)); console.log(); From 2c514b39c02fd19ab04209ff3543735782967cec Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 29 Nov 2018 17:15:05 -0300 Subject: [PATCH 270/582] Percentage transfer manager --- CLI/commands/helpers/contract_abis.js | 5 ++ CLI/commands/transfer_manager.js | 113 ++++++++++++++++++++++---- 2 files changed, 102 insertions(+), 16 deletions(-) diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index 0b186f590..8a551b70b 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -9,6 +9,7 @@ let usdTieredSTOABI; let generalTransferManagerABI; let manualApprovalTransferManagerABI; let countTransferManagerABI; +let percentageTransferManagerABI; let generalPermissionManagerABI; let polyTokenABI; let cappedSTOFactoryABI; @@ -33,6 +34,7 @@ try { generalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralTransferManager.json').toString()).abi; manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ManualApprovalTransferManager.json').toString()).abi; countTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/CountTransferManager.json').toString()).abi; + percentageTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/PercentageTransferManager.json').toString()).abi; generalPermissionManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralPermissionManager.json').toString()).abi; polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; @@ -83,6 +85,9 @@ module.exports = { countTransferManager: function () { return countTransferManagerABI; }, + percentageTransferManager: function () { + return percentageTransferManagerABI; + }, generalPermissionManager: function () { return generalPermissionManagerABI; }, diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 4fdd6286a..c3dc7253f 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -193,19 +193,16 @@ async function configExistingModules(tmModules) { currentTransferManager.setProvider(web3.currentProvider); await manualApprovalTransferManager(); break; - case 'PercentageTransferManager': - //await percentageTransferManager(); - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); - break; case 'CountTransferManager': currentTransferManager = new web3.eth.Contract(abis.countTransferManager(), tmModules[index].address); currentTransferManager.setProvider(web3.currentProvider); await countTransferManager(); break; + case 'PercentageTransferManager': + currentTransferManager = new web3.eth.Contract(abis.percentageTransferManager(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await percentageTransferManager(); + break; case 'SingleTradeVolumeRestrictionTM': //currentTransferManager = new web3.eth.Contract(abis.singleTradeVolumeRestrictionTM(), tmModules[index].address); //currentTransferManager.setProvider(web3.currentProvider); @@ -232,7 +229,7 @@ async function addTransferManagerModule() { 'GeneralTransferManager', 'ManualApprovalTransferManager', 'CountTransferManager', - //'PercentageTransferManager', + 'PercentageTransferManager', //'SingleTradeVolumeRestrictionTM', //'LookupVolumeRestrictionTM'*/ ]; @@ -241,18 +238,22 @@ async function addTransferManagerModule() { if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { let bytes = web3.utils.fromAscii('', 16); switch (options[index]) { - case 'PercentageTransferManager': - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); - break; case 'CountTransferManager': let maxHolderCount = readlineSync.question('Enter the maximum no. of holders the SecurityToken is allowed to have: '); let configureCountTM = abis.countTransferManager().find(o => o.name === 'configure' && o.type === 'function'); bytes = web3.eth.abi.encodeFunctionCall(configureCountTM, [maxHolderCount]); break; + case 'PercentageTransferManager': + let maxHolderPercentage = toWeiPercentage(readlineSync.question('Enter the maximum amount of tokens in percentage that an investor can hold: ', { + limit: function (input) { + return (parseInt(input) > 0 && parseInt(input) <= 100); + }, + limitMessage: "Must be greater than 0 and less than 100" + })); + let allowPercentagePrimaryIssuance = readlineSync.keyInYNStrict(`Do you want to ignore transactions which are part of the primary issuance? `); + let configurePercentageTM = abis.percentageTransferManager().find(o => o.name === 'configure' && o.type === 'function'); + bytes = web3.eth.abi.encodeFunctionCall(configurePercentageTM, [maxHolderPercentage, allowPercentagePrimaryIssuance]); + break; case 'SingleTradeVolumeRestrictionTM': /* let isTransferLimitInPercentage = !!readlineSync.keyInSelect(['In tokens', 'In percentage'], 'How do you want to set the transfer limit? ', {cancel: false}); @@ -672,6 +673,86 @@ async function countTransferManager() { } } +async function percentageTransferManager() { + console.log(chalk.blue(`Percentage Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + + // Show current data + let displayMaxHolderPercentage = await currentTransferManager.methods.maxHolderPercentage().call(); + let displayAllowPrimaryIssuance = await currentTransferManager.methods.allowPrimaryIssuance().call(); + + console.log(`- Max holder percentage: ${fromWeiPercentage(displayMaxHolderPercentage)}%`); + console.log(`- Allow primary issuance: ${displayAllowPrimaryIssuance ? `YES` : `NO`}`); + + let options = ['Change max holder percentage', 'Check if investor is whitelisted', 'Modify whitelist', 'Modify whitelist from CSV']; + if (displayAllowPrimaryIssuance) { + options.push('Disallow primary issuance'); + } else { + options.push('Allow primary issuance'); + } + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); + let optionSelected = options[index]; + console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + switch (optionSelected) { + case 'Change max holder percentage': + let maxHolderPercentage = toWeiPercentage(readlineSync.question('Enter the maximum amount of tokens in percentage that an investor can hold: ', { + limit: function (input) { + return (parseInt(input) > 0 && parseInt(input) <= 100); + }, + limitMessage: "Must be greater than 0 and less than 100" + })); + let changeHolderPercentageAction = currentTransferManager.methods.changeHolderPercentage(maxHolderPercentage); + let changeHolderPercentageReceipt = await common.sendTransaction(changeHolderPercentageAction); + let changeHolderPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeHolderPercentageReceipt.logs, 'ModifyHolderPercentage'); + console.log(chalk.green(`Max holder percentage has been set to ${fromWeiPercentage(changeHolderPercentageEvent._newHolderPercentage)} successfully!`)); + break; + case 'Check if investor is whitelisted': + let investorToCheck = readlineSync.question('Enter the address of the investor: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let isWhitelisted = await currentTransferManager.methods.whitelist(investorToCheck).call(); + if (isWhitelisted) { + console.log(chalk.green(`${investorToCheck} is whitelisted!`)); + } else { + console.log(chalk.yellow(`${investorToCheck} is not whitelisted!`)); + } + break; + case 'Modify whitelist': + let valid = !!readlineSync.keyInSelect(['Remove investor from whitelist', 'Add investor to whitelist'], 'How do you want to do? ', { cancel: false }); + let investorToWhitelist = readlineSync.question('Enter the address of the investor: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investorToWhitelist, valid); + let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); + let modifyWhitelistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); + if (modifyWhitelistEvent._valid) { + console.log(chalk.green(`${modifyWhitelistEvent._investor} has been added to the whitelist sucessfully!`)); + } else { + console.log(chalk.green(`${modifyWhitelistEvent._investor} has been removed from the whitelist sucessfully!`)); + } + break; + case 'Modify whitelist from CSV': + break; + case 'Allow primary issuance': + case 'Disallow primary issuance': + let setAllowPrimaryIssuanceAction = currentTransferManager.methods.setAllowPrimaryIssuance(!displayAllowPrimaryIssuance); + let setAllowPrimaryIssuanceReceipt = await common.sendTransaction(setAllowPrimaryIssuanceAction); + let setAllowPrimaryIssuanceEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setAllowPrimaryIssuanceReceipt.logs, 'SetAllowPrimaryIssuance'); + if (setAllowPrimaryIssuanceEvent._allowPrimaryIssuance) { + console.log(chalk.green(`Transactions which are part of the primary issuance will be ignored!`)); + } else { + console.log(chalk.green(`Transactions which are part of the primary issuance will NOT be ignored!`)); + } + break; + + } +} + async function singleTradeVolumeRestrictionTM() { console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address}`)); console.log(); From 11b000e1644581295a0986a7b8bc50bcbddce8e6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 29 Nov 2018 22:57:08 +0200 Subject: [PATCH 271/582] contract size optimization --- contracts/modules/Wallet/VestingEscrowWallet.sol | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 454f9afa6..c1aa7fd49 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -317,7 +317,6 @@ contract VestingEscrowWallet is IWallet { } function _deleteTemplateToUsers(address _beneficiary, bytes32 _templateName) internal { - uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; uint256 templateIndex = templateToUserIndex[_templateName][_beneficiary]; if (templateIndex != templateToUsers[_templateName].length - 1) { templateToUsers[_templateName][templateIndex] = templateToUsers[_templateName][templateToUsers[_templateName].length - 1]; @@ -365,16 +364,11 @@ contract VestingEscrowWallet is IWallet { templates[schedule.templateName].duration, templates[schedule.templateName].frequency, schedule.startTime, - getScheduleState(_beneficiary, _templateName) + _getScheduleState(_beneficiary, _templateName) ); } - /** - * @notice Returns state of the schedule - * @param _beneficiary beneficiary's address - * @return state of the schedule - */ - function getScheduleState(address _beneficiary, bytes32 _templateName) public view returns(State) { + function _getScheduleState(address _beneficiary, bytes32 _templateName) internal view returns(State) { _checkSchedule(_beneficiary, _templateName); uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; Schedule memory schedule = schedules[_beneficiary][index]; From aea6509301ab35b45e5e71a0e7d2a26da5fde89e Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 09:14:59 +0530 Subject: [PATCH 272/582] Added docs generation to CI --- .travis.yml | 2 ++ scripts/docs.sh | 1 + 2 files changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index caddfc523..fdadf2ed6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,10 @@ matrix: before_script: - truffle version - wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js + - wget -O node_modules/solidity-docgen/buffer-size/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js script: - npm run test + - npm run docs notifications: slack: secure: W4FZSabLrzF74f317hutolEHnlq2GBlQxU6b85L5XymrjgLEhlgE16c5Qz7Emoyt6le6PXL+sfG2ujJc3XYys/6hppgrHSAasuJnKCdQNpmMZ9BNyMs6WGkmB3enIf3K/FLXb26AQdwpQdIXuOeJUTf879u+YoiZV0eZH8d3+fsIOyovq9N6X5pKOpDM9iT8gGB4t7fie7xf51s+iUaHxyO9G7jDginZ4rBXHcU7mxCub9z+Z1H8+kCTnPWaF+KKVEXx4Z0nI3+urboD7E4OIP02LwrThQls2CppA3X0EoesTcdvj/HLErY/JvsXIFiFEEHZzB1Wi+k2TiOeLcYwEuHIVij+HPxxlJNX/j8uy01Uk8s4rd+0EhvfdKHJqUKqxH4YN2npcKfHEss7bU3y7dUinXQfYShW5ZewHdvc7pnnxBTfhvmdi64HdNrXAPq+s1rhciH7MmnU+tsm4lhrpr+FBuHzUMA9fOCr7b0SQytZEgWpiUls88gdbh3yG8TjyZxmZJGx09cwEP0q7VoH0UwFh7mIu5XmYdd5tWUhavTiO7YV8cUPn7MvwMsTltB3YBpF/fB26L7ka8zBhCsjm9prW6SVYU/dyO3m91VeZtO/zJFHRDA6Q58JGVW2rgzO39z193qC1EGRXqTie96VwAAtNg8+hRb+bI/CWDVzSPc= diff --git a/scripts/docs.sh b/scripts/docs.sh index 205a6ceae..7f631fd06 100755 --- a/scripts/docs.sh +++ b/scripts/docs.sh @@ -38,6 +38,7 @@ create_docs() { CWD=$(pwd) OLD_SOLC_PATH=$SOLC_PATH export SOLC_PATH=$CWD/solc + curl -o node_modules/solidity-docgen/buffer-size/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js echo "Generating the API documentation in branch $latestTag" # Command to generate the documentation using the solidity-docgen From b3767d6930535f72e98c8c511113638bdb0ce62a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 09:19:03 +0530 Subject: [PATCH 273/582] Path fix --- .travis.yml | 2 +- scripts/docs.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fdadf2ed6..ce5467100 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ matrix: before_script: - truffle version - wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js - - wget -O node_modules/solidity-docgen/buffer-size/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js + - wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js script: - npm run test - npm run docs diff --git a/scripts/docs.sh b/scripts/docs.sh index 7f631fd06..2441f1e09 100755 --- a/scripts/docs.sh +++ b/scripts/docs.sh @@ -38,7 +38,7 @@ create_docs() { CWD=$(pwd) OLD_SOLC_PATH=$SOLC_PATH export SOLC_PATH=$CWD/solc - curl -o node_modules/solidity-docgen/buffer-size/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js + curl -o node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js echo "Generating the API documentation in branch $latestTag" # Command to generate the documentation using the solidity-docgen From 617dd73ee3a4295b244c83aa97ee2fa20ab30164 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 09:48:51 +0530 Subject: [PATCH 274/582] script fix --- scripts/docs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docs.sh b/scripts/docs.sh index 2441f1e09..af7f6e395 100755 --- a/scripts/docs.sh +++ b/scripts/docs.sh @@ -38,7 +38,7 @@ create_docs() { CWD=$(pwd) OLD_SOLC_PATH=$SOLC_PATH export SOLC_PATH=$CWD/solc - curl -o node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js + echo "Generating the API documentation in branch $latestTag" # Command to generate the documentation using the solidity-docgen From 89f5351aae258db657297c0535d4df3f9c90a18e Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 10:19:31 +0530 Subject: [PATCH 275/582] Testing travis --- .travis.yml | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index ce5467100..d2b49fea8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,13 +6,21 @@ cache: - node_modules matrix: fast_finish: true -before_script: - - truffle version - - wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js - - wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js -script: - - npm run test - - npm run docs + allow_failures: + - env: 'TASK=docs' +jobs: + include: + - stage: Tests and Coverage + install: yarn install + after_install: wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js + before_script: truffle version + script: npm run test + - stage: docs + env: 'TASK=docs' + before_install: sudo apt-get -y install build-essential libboost-all-dev libz3-dev + install: yarn install + after_install: wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js + script: npm run docs notifications: slack: secure: W4FZSabLrzF74f317hutolEHnlq2GBlQxU6b85L5XymrjgLEhlgE16c5Qz7Emoyt6le6PXL+sfG2ujJc3XYys/6hppgrHSAasuJnKCdQNpmMZ9BNyMs6WGkmB3enIf3K/FLXb26AQdwpQdIXuOeJUTf879u+YoiZV0eZH8d3+fsIOyovq9N6X5pKOpDM9iT8gGB4t7fie7xf51s+iUaHxyO9G7jDginZ4rBXHcU7mxCub9z+Z1H8+kCTnPWaF+KKVEXx4Z0nI3+urboD7E4OIP02LwrThQls2CppA3X0EoesTcdvj/HLErY/JvsXIFiFEEHZzB1Wi+k2TiOeLcYwEuHIVij+HPxxlJNX/j8uy01Uk8s4rd+0EhvfdKHJqUKqxH4YN2npcKfHEss7bU3y7dUinXQfYShW5ZewHdvc7pnnxBTfhvmdi64HdNrXAPq+s1rhciH7MmnU+tsm4lhrpr+FBuHzUMA9fOCr7b0SQytZEgWpiUls88gdbh3yG8TjyZxmZJGx09cwEP0q7VoH0UwFh7mIu5XmYdd5tWUhavTiO7YV8cUPn7MvwMsTltB3YBpF/fB26L7ka8zBhCsjm9prW6SVYU/dyO3m91VeZtO/zJFHRDA6Q58JGVW2rgzO39z193qC1EGRXqTie96VwAAtNg8+hRb+bI/CWDVzSPc= From 29b3ba68718e6bcbe0b7f2fb470fafc6cc8be010 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 10:38:42 +0530 Subject: [PATCH 276/582] Testing travis --- .travis.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index d2b49fea8..93e7cf768 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,17 +10,18 @@ matrix: - env: 'TASK=docs' jobs: include: + - stage: Docs + env: 'TASK=docs' + before_install: sudo add-apt-repository universe + install: yarn install + after_install: sudo apt-get -y install build-essential libboost-all-dev libz3-dev + before_script: wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js + script: npm run docs - stage: Tests and Coverage install: yarn install after_install: wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js before_script: truffle version script: npm run test - - stage: docs - env: 'TASK=docs' - before_install: sudo apt-get -y install build-essential libboost-all-dev libz3-dev - install: yarn install - after_install: wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js - script: npm run docs notifications: slack: secure: W4FZSabLrzF74f317hutolEHnlq2GBlQxU6b85L5XymrjgLEhlgE16c5Qz7Emoyt6le6PXL+sfG2ujJc3XYys/6hppgrHSAasuJnKCdQNpmMZ9BNyMs6WGkmB3enIf3K/FLXb26AQdwpQdIXuOeJUTf879u+YoiZV0eZH8d3+fsIOyovq9N6X5pKOpDM9iT8gGB4t7fie7xf51s+iUaHxyO9G7jDginZ4rBXHcU7mxCub9z+Z1H8+kCTnPWaF+KKVEXx4Z0nI3+urboD7E4OIP02LwrThQls2CppA3X0EoesTcdvj/HLErY/JvsXIFiFEEHZzB1Wi+k2TiOeLcYwEuHIVij+HPxxlJNX/j8uy01Uk8s4rd+0EhvfdKHJqUKqxH4YN2npcKfHEss7bU3y7dUinXQfYShW5ZewHdvc7pnnxBTfhvmdi64HdNrXAPq+s1rhciH7MmnU+tsm4lhrpr+FBuHzUMA9fOCr7b0SQytZEgWpiUls88gdbh3yG8TjyZxmZJGx09cwEP0q7VoH0UwFh7mIu5XmYdd5tWUhavTiO7YV8cUPn7MvwMsTltB3YBpF/fB26L7ka8zBhCsjm9prW6SVYU/dyO3m91VeZtO/zJFHRDA6Q58JGVW2rgzO39z193qC1EGRXqTie96VwAAtNg8+hRb+bI/CWDVzSPc= From c2411dd89d2146b2ff605444813b4544ea52a256 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 10:42:04 +0530 Subject: [PATCH 277/582] Testing travis --- .travis.yml | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 93e7cf768..07104c831 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,24 +4,19 @@ node_js: cache: directories: - node_modules +before_install: + - sudo add-apt-repository ppa:ethereum/ethereum + - sudo apt-get -y update + - sudo apt-get -y install solc matrix: fast_finish: true - allow_failures: - - env: 'TASK=docs' -jobs: - include: - - stage: Docs - env: 'TASK=docs' - before_install: sudo add-apt-repository universe - install: yarn install - after_install: sudo apt-get -y install build-essential libboost-all-dev libz3-dev - before_script: wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js - script: npm run docs - - stage: Tests and Coverage - install: yarn install - after_install: wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js - before_script: truffle version - script: npm run test +before_script: + - truffle version + - wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js + - wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js +script: + - npm run docs + - npm run test notifications: slack: secure: W4FZSabLrzF74f317hutolEHnlq2GBlQxU6b85L5XymrjgLEhlgE16c5Qz7Emoyt6le6PXL+sfG2ujJc3XYys/6hppgrHSAasuJnKCdQNpmMZ9BNyMs6WGkmB3enIf3K/FLXb26AQdwpQdIXuOeJUTf879u+YoiZV0eZH8d3+fsIOyovq9N6X5pKOpDM9iT8gGB4t7fie7xf51s+iUaHxyO9G7jDginZ4rBXHcU7mxCub9z+Z1H8+kCTnPWaF+KKVEXx4Z0nI3+urboD7E4OIP02LwrThQls2CppA3X0EoesTcdvj/HLErY/JvsXIFiFEEHZzB1Wi+k2TiOeLcYwEuHIVij+HPxxlJNX/j8uy01Uk8s4rd+0EhvfdKHJqUKqxH4YN2npcKfHEss7bU3y7dUinXQfYShW5ZewHdvc7pnnxBTfhvmdi64HdNrXAPq+s1rhciH7MmnU+tsm4lhrpr+FBuHzUMA9fOCr7b0SQytZEgWpiUls88gdbh3yG8TjyZxmZJGx09cwEP0q7VoH0UwFh7mIu5XmYdd5tWUhavTiO7YV8cUPn7MvwMsTltB3YBpF/fB26L7ka8zBhCsjm9prW6SVYU/dyO3m91VeZtO/zJFHRDA6Q58JGVW2rgzO39z193qC1EGRXqTie96VwAAtNg8+hRb+bI/CWDVzSPc= From b7b3e367ac695a7ff98a6a11cd241ba1fc9a2440 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 10:44:02 +0530 Subject: [PATCH 278/582] Testing travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 07104c831..f968febbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ cache: directories: - node_modules before_install: - - sudo add-apt-repository ppa:ethereum/ethereum + - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum - sudo apt-get -y update - sudo apt-get -y install solc matrix: From 3469a7d3db3d0ea3157374d927cf08dd1c40dfc1 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 30 Nov 2018 10:48:20 +0530 Subject: [PATCH 279/582] test case improvement --- .../TransferManager/LockUpTransferManager.sol | 3 +- test/w_lockup_transfer_manager.js | 209 +++++++++++++----- 2 files changed, 158 insertions(+), 54 deletions(-) diff --git a/contracts/modules/TransferManager/LockUpTransferManager.sol b/contracts/modules/TransferManager/LockUpTransferManager.sol index b2b940b3d..cb2c4f156 100644 --- a/contracts/modules/TransferManager/LockUpTransferManager.sol +++ b/contracts/modules/TransferManager/LockUpTransferManager.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./TransferManager/ITransferManager.sol"; +import "./ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; contract LockUpTransferManager is ITransferManager { @@ -592,6 +592,7 @@ contract LockUpTransferManager is ITransferManager { ) internal { + require(_lockupName != bytes32(0), "Invalid name"); require(lockups[_lockupName].lockupAmount == 0, "Already exist"); /*solium-disable-next-line security/no-block-members*/ require(_startTime >= now, "Past time not allowed"); diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js index 86031e94b..eb7a76cd6 100644 --- a/test/w_lockup_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -370,12 +370,13 @@ contract('LockUpTransferManager', accounts => { // create a lockup // this will generate an exception because the lockupAmount is zero await catchRevert( - I_LockUpTransferManager.addLockUp( + I_LockUpTransferManager.addNewLockUpToUser( account_investor2, 0, latestTime() + + duration.seconds(1), duration.seconds(400000), duration.seconds(100000), + "a_lockup", { from: token_owner } @@ -387,12 +388,13 @@ contract('LockUpTransferManager', accounts => { // create a lockup // this will generate an exception because the releaseFrequencySeconds is zero await catchRevert( - I_LockUpTransferManager.addLockUp( + I_LockUpTransferManager.addNewLockUpToUser( account_investor2, web3.utils.toWei('1', 'ether'), latestTime() + duration.seconds(1), duration.seconds(400000), 0, + "a_lockup", { from: token_owner } @@ -404,12 +406,13 @@ contract('LockUpTransferManager', accounts => { // create a lockup // this will generate an exception because the lockUpPeriodSeconds is zero await catchRevert( - I_LockUpTransferManager.addLockUp( + I_LockUpTransferManager.addNewLockUpToUser( account_investor2, web3.utils.toWei('1', 'ether'), latestTime() + duration.seconds(1), 0, duration.seconds(100000), + "a_lockup", { from: token_owner } @@ -422,12 +425,13 @@ contract('LockUpTransferManager', accounts => { // create a lockup // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens await catchRevert( - I_LockUpTransferManager.addLockUp( + I_LockUpTransferManager.addNewLockUpToUser( account_investor2, web3.utils.toWei('0.5', 'ether'), latestTime() + + duration.seconds(1), duration.seconds(400000), duration.seconds(100000), + "a_lockup", { from: token_owner } @@ -435,35 +439,82 @@ contract('LockUpTransferManager', accounts => { ); }); + it("Should add the lockup type -- fail because of bad owner", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpType( + web3.utils.toWei('12', 'ether'), + latestTime() + duration.days(1), + 60, + 20, + "a_lockup", + { + from: account_investor1 + } + ) + ); + }) + + it("Should add the new lockup type", async() => { + let tx = await I_LockUpTransferManager.addNewLockUpType( + web3.utils.toWei('12', 'ether'), + latestTime() + duration.days(1), + 60, + 20, + "a_lockup", + { + from: token_owner + } + ); + assert.equal((tx.logs[0].args.lockupAmount).toNumber(), web3.utils.toWei('12', 'ether')); + }); + + it("Should fail to add the creation of the lockup where lockupName is already exists", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUser( + account_investor1, + web3.utils.toWei('5', 'ether'), + latestTime() + duration.seconds(1), + duration.seconds(400000), + duration.seconds(100000), + "a_lockup", + { + from: token_owner + } + ) + ); + }) + it("Should allow the creation of a lockup where the lockup amount is divisible" , async() => { // create a lockup - let tx = await I_LockUpVolumeRestrictionTM_div.addLockUp( + let tx = await I_LockUpVolumeRestrictionTM_div.addNewLockUpToUser( account_investor1, web3.utils.toWei('0.5', 'ether'), latestTime() + duration.seconds(1), duration.seconds(400000), duration.seconds(100000), + "a_lockup", { from: token_owner } ); - assert.equal(tx.logs[0].args.userAddress, account_investor1); + assert.equal(tx.logs[1].args.userAddress, account_investor1); assert.equal((tx.logs[0].args.lockupAmount).toNumber(), web3.utils.toWei('0.5', 'ether')); }); it("Should allow the creation of a lockup where the lockup amount is prime no", async() => { // create a lockup - let tx = await I_LockUpVolumeRestrictionTM_div.addLockUp( + let tx = await I_LockUpVolumeRestrictionTM_div.addNewLockUpToUser( account_investor1, web3.utils.toWei('64951', 'ether'), latestTime() + duration.seconds(1), duration.seconds(400000), duration.seconds(100000), + "b_lockup", { from: token_owner } ); - assert.equal(tx.logs[0].args.userAddress, account_investor1); + assert.equal(tx.logs[1].args.userAddress, account_investor1); assert.equal((tx.logs[0].args.lockupAmount).toNumber(), web3.utils.toWei('64951', 'ether')); }); @@ -477,12 +528,13 @@ contract('LockUpTransferManager', accounts => { // over 17 seconds total, with 4 periods. // this will generate an exception because 17 is not evenly divisble by 4. await catchRevert( - I_LockUpTransferManager.addLockUp( + I_LockUpTransferManager.addNewLockUpToUser( account_investor2, web3.utils.toWei('4', 'ether'), latestTime(), 17, 4, + "b_lockup", { from: token_owner } @@ -496,18 +548,19 @@ contract('LockUpTransferManager', accounts => { console.log("balance", balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); // create a lockup for their entire balance // over 12 seconds total, with 3 periods of 20 seconds each. - await I_LockUpTransferManager.addLockUp( + await I_LockUpTransferManager.addNewLockUpToUser( account_investor2, balance, latestTime() + duration.seconds(1), 60, 20, + "b_lockup", { from: token_owner } ); await increaseTime(2); - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) @@ -517,7 +570,7 @@ contract('LockUpTransferManager', accounts => { it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { // wait 20 seconds await increaseTime(duration.seconds(20)); - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }) @@ -525,13 +578,13 @@ contract('LockUpTransferManager', accounts => { }); it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); }); it("Should again transfer of tokens in a lockup if a period has passed", async() => { - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); }); @@ -540,7 +593,7 @@ contract('LockUpTransferManager', accounts => { // wait 20 more seconds + 1 to get rid of same block time await increaseTime(duration.seconds(21)); - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, 0); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); }); @@ -580,12 +633,13 @@ contract('LockUpTransferManager', accounts => { it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_LockUpTransferManager.addLockUpMulti( + I_LockUpTransferManager.addNewLockUpToUserMulti( [account_investor3], [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], [60, 45], [20, 15], + ["c_lockup", "d_lockup"], { from: token_owner } @@ -595,12 +649,13 @@ contract('LockUpTransferManager', accounts => { it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_LockUpTransferManager.addLockUpMulti( + I_LockUpTransferManager.addNewLockUpToUserMulti( [account_investor3, account_investor3], [], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], [60, 45], [20, 15], + ["c_lockup", "d_lockup"], { from: token_owner } @@ -610,12 +665,13 @@ contract('LockUpTransferManager', accounts => { it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_LockUpTransferManager.addLockUpMulti( + I_LockUpTransferManager.addNewLockUpToUserMulti( [account_investor3, account_investor3], [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], [60, 45, 50], [20, 15], + ["c_lockup", "d_lockup"], { from: token_owner } @@ -625,12 +681,13 @@ contract('LockUpTransferManager', accounts => { it("Should fail to add the multiple lockups -- because array length mismatch", async() => { await catchRevert( - I_LockUpTransferManager.addLockUpMulti( + I_LockUpTransferManager.addNewLockUpToUserMulti( [account_investor3, account_investor3], [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], [60, 45, 50], [20, 15, 10], + ["c_lockup", "d_lockup"], { from: token_owner } @@ -638,21 +695,38 @@ contract('LockUpTransferManager', accounts => { ); }) + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUserMulti( + [account_investor3, account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45], + [20, 15], + ["c_lockup"], + { + from: token_owner + } + ) + ); + }); + it("Should add the multiple lockup to a address", async() => { - await I_LockUpTransferManager.addLockUpMulti( + await I_LockUpTransferManager.addNewLockUpToUserMulti( [account_investor3, account_investor3], [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], [60, 45], [20, 15], + ["c_lockup", "d_lockup"], { from: token_owner } ); await increaseTime(1); - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor3, 0); - let tx2 = await I_LockUpTransferManager.getLockUp.call(account_investor3, 1); + let tx = await I_LockUpTransferManager.getLockUp.call(account_investor3, "c_lockup"); + let tx2 = await I_LockUpTransferManager.getLockUp.call(account_investor3, "d_lockup"); console.log("Total Amount get unlocked:", (tx[4].toNumber()) + (tx2[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor3 }) @@ -693,9 +767,9 @@ contract('LockUpTransferManager', accounts => { it("Should remove multiple lockup --failed because of bad owner", async() => { await catchRevert( - I_LockUpTransferManager.removeLockUpMulti( + I_LockUpTransferManager.removeLockUpFromUserMulti( [account_investor3, account_investor3], - [0,1], + ["c_lockup", "d_lockup"], { from: account_polymath } @@ -703,11 +777,11 @@ contract('LockUpTransferManager', accounts => { ); }); - it("Should remove the multiple lockup -- failed because of invalid index", async() => { + it("Should remove the multiple lockup -- failed because of invalid lockupname", async() => { await catchRevert( - I_LockUpTransferManager.removeLockUpMulti( + I_LockUpTransferManager.removeLockUpFromUserMulti( [account_investor3, account_investor3], - [0,3], + ["c_lockup", "e_lockup"], { from: account_polymath } @@ -716,9 +790,9 @@ contract('LockUpTransferManager', accounts => { }) it("Should remove the multiple lockup", async() => { - await I_LockUpTransferManager.removeLockUpMulti( + await I_LockUpTransferManager.removeLockUpFromUserMulti( [account_investor3, account_investor3], - [1,0], + ["d_lockup", "c_lockup"], { from: token_owner } @@ -730,26 +804,26 @@ contract('LockUpTransferManager', accounts => { it("Should fail to modify the lockup -- because of bad owner", async() => { await I_SecurityToken.mint(account_investor3, web3.utils.toWei("9"), {from: token_owner}); - let tx = await I_LockUpTransferManager.addLockUp( + let tx = await I_LockUpTransferManager.addNewLockUpToUser( account_investor3, web3.utils.toWei("9"), latestTime() + duration.minutes(5), 60, 20, + "z_lockup", { from: token_owner } ); - temp = (tx.logs[0].args.lockupIndex).toNumber(); + await catchRevert( // edit the lockup - I_LockUpTransferManager.modifyLockUp( - account_investor3, + I_LockUpTransferManager.modifyLockUpType( web3.utils.toWei("9"), latestTime() + duration.seconds(1), 60, 20, - (tx.logs[0].args.lockupIndex).toNumber(), + "z_lockup", { from: account_polymath } @@ -760,13 +834,12 @@ contract('LockUpTransferManager', accounts => { it("Modify the lockup when startTime is in past -- failed because startTime is in the past", async() => { await catchRevert( // edit the lockup - I_LockUpTransferManager.modifyLockUp( - account_investor3, + I_LockUpTransferManager.modifyLockUpType( web3.utils.toWei("9"), latestTime() - duration.seconds(50), 60, 20, - temp, + "z_lockup", { from: token_owner } @@ -777,13 +850,12 @@ contract('LockUpTransferManager', accounts => { it("Modify the lockup when startTime is in past -- failed because of invalid index", async() => { await catchRevert( // edit the lockup - I_LockUpTransferManager.modifyLockUp( - account_investor3, + I_LockUpTransferManager.modifyLockUpType( web3.utils.toWei("9"), latestTime() + duration.seconds(50), 60, 20, - 6, + "m_lockup", { from: token_owner } @@ -793,13 +865,12 @@ contract('LockUpTransferManager', accounts => { it("should successfully modify the lockup", async() => { // edit the lockup - await I_LockUpTransferManager.modifyLockUp( - account_investor3, + await I_LockUpTransferManager.modifyLockUpType( web3.utils.toWei("9"), latestTime() + duration.seconds(50), 60, 20, - temp, + "z_lockup", { from: token_owner } @@ -815,12 +886,13 @@ contract('LockUpTransferManager', accounts => { // create a lockup for their entire balance // over 16 seconds total, with 4 periods of 4 seconds each. - await I_LockUpTransferManager.addLockUp( + await I_LockUpTransferManager.addNewLockUpToUser( account_investor1, balance, latestTime() + duration.minutes(5), 60, 20, + "f_lockup", { from: token_owner } @@ -834,7 +906,7 @@ contract('LockUpTransferManager', accounts => { let lockUpCount = await I_LockUpTransferManager.getLockUpsLength(account_investor1); assert.equal(lockUpCount, 1) - let lockUp = await I_LockUpTransferManager.getLockUp(account_investor1, 0); + let lockUp = await I_LockUpTransferManager.getLockUp(account_investor1, "f_lockup"); console.log(lockUp); // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount assert.equal( @@ -847,13 +919,12 @@ contract('LockUpTransferManager', accounts => { // edit the lockup temp = latestTime() + duration.seconds(1); - await I_LockUpTransferManager.modifyLockUp( - account_investor1, + await I_LockUpTransferManager.modifyLockUpType( balance, temp, 60, 20, - 0, + "f_lockup", { from: token_owner } @@ -874,17 +945,16 @@ contract('LockUpTransferManager', accounts => { it("Modify the lockup during the lockup periods --fail because already tokens get unlocked", async() => { let balance = await I_SecurityToken.balanceOf(account_investor1) - let lockUp = await I_LockUpTransferManager.getLockUp(account_investor1, 0); + let lockUp = await I_LockUpTransferManager.getLockUp(account_investor1, "f_lockup"); console.log(lockUp[4].dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); // edit the lockup await catchRevert( - I_LockUpTransferManager.modifyLockUp( - account_investor1, + I_LockUpTransferManager.modifyLockUpType( balance, temp, 90, 30, - 0, + "f_lockup", { from: token_owner } @@ -892,7 +962,34 @@ contract('LockUpTransferManager', accounts => { ); }); - it("Should succesfully get the lockup - fail because array index out of bound", async() => { + it("Should remove the lockup multi", async() => { + await I_LockUpTransferManager.addNewLockUpTypeMulti( + [web3.utils.toWei("10"), web3.utils.toWei("16")], + [latestTime() + duration.days(1), latestTime() + duration.days(1)], + [50000, 50000], + [10000, 10000], + ["k_lockup", "l_lockup"], + { + from: token_owner + } + ); + + // removing the lockup type + let tx = await I_LockUpTransferManager.removeLockupType("k_lockup", {from: token_owner}); + assert.equal(web3.utils.toUtf8(tx.logs[0].args.lockupName), "k_lockup"); + + // attaching the lockup to a user + + await I_LockUpTransferManager.addLockUpByName(account_investor2, "l_lockup", {from: token_owner}); + + // try to delete the lockup but fail + + await catchRevert( + I_LockUpTransferManager.removeLockupType("l_lockup", {from: token_owner}) + ); + }) + + it("Should succesfully get the lockup - fail because no lockup exist for the user of this name", async() => { await catchRevert( I_LockUpTransferManager.getLockUp(account_investor1, 9) ); @@ -903,6 +1000,12 @@ contract('LockUpTransferManager', accounts => { assert.equal(web3.utils.hexToNumber(sig), 0); }); + it("Should get the all lockups added by the issuer till now", async() => { + let tx = await I_LockUpTransferManager.getAllLockups.call(); + for (let i = 0; i < tx.length; i++) { + console.log(web3.utils.toUtf8(tx[i])); + } + }) it("Should get the permission", async() => { let perm = await I_LockUpTransferManager.getPermissions.call(); From af54a213d7456e18a9222e28277deac3a31ab7f8 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 10:51:56 +0530 Subject: [PATCH 280/582] Testing travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index f968febbe..3f1007b26 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,8 @@ before_install: - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum - sudo apt-get -y update - sudo apt-get -y install solc + - sudo apt-get -y install libz3 + - sudo apt-get -y install libz3-dev matrix: fast_finish: true before_script: From 0ec99e492eb703939551fbeb42e58280439528e8 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 11:09:26 +0530 Subject: [PATCH 281/582] Testing travis --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3f1007b26..b2d942c96 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,8 @@ cache: directories: - node_modules before_install: - - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum - - sudo apt-get -y update - - sudo apt-get -y install solc - - sudo apt-get -y install libz3 + - echo -ne '\n' | sudo apt-add-repository -y ppa:hvr/z3 + - sudo apt-get -y update - sudo apt-get -y install libz3-dev matrix: fast_finish: true From 538f7aaaffc9b158dc25e2156a9a9ebdcdccd0f8 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 30 Nov 2018 11:17:20 +0530 Subject: [PATCH 282/582] Testing travis --- .travis.yml | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index b2d942c96..2265b2d88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,19 +4,24 @@ node_js: cache: directories: - node_modules -before_install: - - echo -ne '\n' | sudo apt-add-repository -y ppa:hvr/z3 - - sudo apt-get -y update - - sudo apt-get -y install libz3-dev matrix: fast_finish: true -before_script: - - truffle version - - wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js - - wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js -script: - - npm run docs - - npm run test + allow_failures: + - env: 'TASK=docs' +jobs: + include: + - stage: Tests and Coverage + after_install: wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js + before_script: truffle version + script: npm run test + - stage: Docs + env: 'TASK=docs' + before_install: + - echo -ne '\n' | sudo apt-add-repository -y ppa:hvr/z3 + - sudo apt-get -y update + - sudo apt-get -y install libz3-dev + before_script: wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js + script: npm run docs notifications: slack: - secure: W4FZSabLrzF74f317hutolEHnlq2GBlQxU6b85L5XymrjgLEhlgE16c5Qz7Emoyt6le6PXL+sfG2ujJc3XYys/6hppgrHSAasuJnKCdQNpmMZ9BNyMs6WGkmB3enIf3K/FLXb26AQdwpQdIXuOeJUTf879u+YoiZV0eZH8d3+fsIOyovq9N6X5pKOpDM9iT8gGB4t7fie7xf51s+iUaHxyO9G7jDginZ4rBXHcU7mxCub9z+Z1H8+kCTnPWaF+KKVEXx4Z0nI3+urboD7E4OIP02LwrThQls2CppA3X0EoesTcdvj/HLErY/JvsXIFiFEEHZzB1Wi+k2TiOeLcYwEuHIVij+HPxxlJNX/j8uy01Uk8s4rd+0EhvfdKHJqUKqxH4YN2npcKfHEss7bU3y7dUinXQfYShW5ZewHdvc7pnnxBTfhvmdi64HdNrXAPq+s1rhciH7MmnU+tsm4lhrpr+FBuHzUMA9fOCr7b0SQytZEgWpiUls88gdbh3yG8TjyZxmZJGx09cwEP0q7VoH0UwFh7mIu5XmYdd5tWUhavTiO7YV8cUPn7MvwMsTltB3YBpF/fB26L7ka8zBhCsjm9prW6SVYU/dyO3m91VeZtO/zJFHRDA6Q58JGVW2rgzO39z193qC1EGRXqTie96VwAAtNg8+hRb+bI/CWDVzSPc= + secure: W4FZSabLrzF74f317hutolEHnlq2GBlQxU6b85L5XymrjgLEhlgE16c5Qz7Emoyt6le6PXL+sfG2ujJc3XYys/6hppgrHSAasuJnKCdQNpmMZ9BNyMs6WGkmB3enIf3K/FLXb26AQdwpQdIXuOeJUTf879u+YoiZV0eZH8d3+fsIOyovq9N6X5pKOpDM9iT8gGB4t7fie7xf51s+iUaHxyO9G7jDginZ4rBXHcU7mxCub9z+Z1H8+kCTnPWaF+KKVEXx4Z0nI3+urboD7E4OIP02LwrThQls2CppA3X0EoesTcdvj/HLErY/JvsXIFiFEEHZzB1Wi+k2TiOeLcYwEuHIVij+HPxxlJNX/j8uy01Uk8s4rd+0EhvfdKHJqUKqxH4YN2npcKfHEss7bU3y7dUinXQfYShW5ZewHdvc7pnnxBTfhvmdi64HdNrXAPq+s1rhciH7MmnU+tsm4lhrpr+FBuHzUMA9fOCr7b0SQytZEgWpiUls88gdbh3yG8TjyZxmZJGx09cwEP0q7VoH0UwFh7mIu5XmYdd5tWUhavTiO7YV8cUPn7MvwMsTltB3YBpF/fB26L7ka8zBhCsjm9prW6SVYU/dyO3m91VeZtO/zJFHRDA6Q58JGVW2rgzO39z193qC1EGRXqTie96VwAAtNg8+hRb+bI/CWDVzSPc= \ No newline at end of file From a3f46e53be800887d10d5242e06f6bb3999ca030 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 30 Nov 2018 14:35:22 +0530 Subject: [PATCH 283/582] fixes in the code --- .../modules/Wallet/VestingEscrowWallet.sol | 143 ++++++++++-------- 1 file changed, 84 insertions(+), 59 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index c1aa7fd49..f5049019a 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -1,8 +1,6 @@ pragma solidity ^0.4.24; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "./IWallet.sol"; /** @@ -14,42 +12,48 @@ contract VestingEscrowWallet is IWallet { bytes32 public constant ADMIN = "ADMIN"; struct Schedule { - //name of the template + // Name of the template bytes32 templateName; - //tokens that were already claimed + // Tokens that were already claimed uint256 claimedTokens; - //start time of the schedule + // Start time of the schedule uint256 startTime; } struct Template { - //total amount of tokens + // Total amount of tokens uint256 numberOfTokens; - //schedule duration + // Schedule duration (How long the schedule will last) uint256 duration; - //schedule frequency + // Schedule frequency (It is a cliff time period) uint256 frequency; } + // States used to represent the status of the schedule enum State {CREATED, STARTED, COMPLETED} - + // Number of tokens that are hold by the `this` contract but are unassigned to any schedule uint256 public unassignedTokens; - + // Address of the Treasury wallet. All of the unassigned token will transfer to that address. + address public treasuryWallet; + // List of all beneficiaries who have the schedules running/completed/created address[] public beneficiaries; - //holds schedules for user + // Holds schedules array corresponds to the affiliate/employee address mapping(address => Schedule[]) public schedules; - //holds template names for user + // Holds template names array corresponds to the affiliate/employee address mapping(address => bytes32[]) internal userToTemplates; - //mapping use to store the indexes for different template names for a user - mapping(address => mapping(bytes32 => uint256)) internal templateToScheduleIndex; - - //holds user for template + // Mapping use to store the indexes for different template names for a user. + // affiliate/employee address => template name => index + mapping(address => mapping(bytes32 => uint256)) internal userToTemplateIndex; + // Holds affiliate/employee addresses coressponds to the template name mapping(bytes32 => address[]) internal templateToUsers; - //mapping use to store the indexes for users for a template + // Mapping use to store the indexes for different users for a template. + // template name => affiliate/employee address => index mapping(bytes32 => mapping(address => uint256)) internal templateToUserIndex; - + // Store the template details corresponds to the template name mapping(bytes32 => Template) templates; + + // List of all template names bytes32[] public templateNames; // Emit when new schedule is added @@ -78,6 +82,8 @@ contract VestingEscrowWallet is IWallet { event AddTemplate(bytes32 _name, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency); // Emit when template is removed event RemoveTemplate(bytes32 _name); + // Emit when the treasury wallet gets changed + event TreasuryWalletChanged(address _newWallet, address _oldWallet); /** * @notice Constructor @@ -94,7 +100,26 @@ contract VestingEscrowWallet is IWallet { * @notice This function returns the signature of the configure function */ function getInitFunction() public pure returns (bytes4) { - return bytes4(0); + return bytes4(keccak256("configure(address)")); + } + + /** + * @notice Use to intialize the treasury wallet address + * @param _treasuryWallet Address of the treasury wallet + */ + function configure(address _treasuryWallet) public onlyFactory { + require(_treasuryWallet != address(0), "Invalid address"); + treasuryWallet = _treasuryWallet; + } + + /** + * @notice Use to change the treasury wallet address + * @param _newTreasuryWallet Address of the treasury wallet + */ + function changeTreasuryWallet(address _newTreasuryWallet) public onlyOwner { + require(_newTreasuryWallet != address(0)); + emit TreasuryWalletChanged(_newTreasuryWallet, treasuryWallet); + treasuryWallet = _newTreasuryWallet; } /** @@ -105,8 +130,8 @@ contract VestingEscrowWallet is IWallet { } function _depositTokens(uint256 _numberOfTokens) internal { - require(_numberOfTokens > 0, "Should be greater than zero"); - ISecurityToken(securityToken).transferFrom(msg.sender, this, _numberOfTokens); + require(_numberOfTokens > 0, "Should be > 0"); + ISecurityToken(securityToken).transferFrom(msg.sender, address(this), _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); emit DepositTokens(_numberOfTokens, msg.sender); } @@ -117,7 +142,7 @@ contract VestingEscrowWallet is IWallet { function sendToTreasury() external withPerm(ADMIN) { uint256 amount = unassignedTokens; unassignedTokens = 0; - ISecurityToken(securityToken).transfer(msg.sender, amount); + ISecurityToken(securityToken).transfer(treasuryWallet, amount); emit SendToTreasury(amount, msg.sender); } @@ -132,7 +157,7 @@ contract VestingEscrowWallet is IWallet { /** * @notice Used to withdraw available tokens by beneficiary */ - function withdrawAvailableTokens() external { + function pullAvailableTokens() external { _sendTokens(msg.sender); } @@ -148,7 +173,8 @@ contract VestingEscrowWallet is IWallet { } function _addTemplate(bytes32 _name, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) internal { - require(!_isTemplateExists(_name)); + require(_name != bytes32(0), "Invalid name"); + require(!_isTemplateExists(_name), "Already exists"); _validateTemplate(_numberOfTokens, _duration, _frequency); templateNames.push(_name); templates[_name] = Template(_numberOfTokens, _duration, _frequency); @@ -160,8 +186,8 @@ contract VestingEscrowWallet is IWallet { * @param _name name of template */ function removeTemplate(bytes32 _name) external withPerm(ADMIN) { - require(_isTemplateExists(_name)); - require(!_isTemplateUsed(_name)); + require(_isTemplateExists(_name), "Already exists"); + require(templateToUsers[_name].length == 0); // delete template data delete templates[_name]; uint256 i; @@ -210,7 +236,7 @@ contract VestingEscrowWallet is IWallet { uint256 _frequency, uint256 _startTime ) - public + external withPerm(ADMIN) { _addSchedule(_beneficiary, _templateName, _numberOfTokens, _duration, _frequency, _startTime); @@ -243,13 +269,12 @@ contract VestingEscrowWallet is IWallet { function _addScheduleFromTemplate(address _beneficiary, bytes32 _templateName, uint256 _startTime) internal { require(_beneficiary != address(0), "Invalid address"); require(_isTemplateExists(_templateName)); - uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; require( - schedules[_beneficiary].length == 0 || schedules[_beneficiary][index].templateName != _templateName, - "Schedule from this template already added" + "Already added" ); - require(now < _startTime, "Date in the past"); + require(_startTime >= now, "Date in the past"); uint256 numberOfTokens = templates[_templateName].numberOfTokens; if (numberOfTokens > unassignedTokens) { _depositTokens(numberOfTokens.sub(unassignedTokens)); @@ -261,7 +286,7 @@ contract VestingEscrowWallet is IWallet { } schedules[_beneficiary].push(Schedule(_templateName, 0, _startTime)); userToTemplates[_beneficiary].push(_templateName); - templateToScheduleIndex[_beneficiary][_templateName] = schedules[_beneficiary].length - 1; + userToTemplateIndex[_beneficiary][_templateName] = schedules[_beneficiary].length - 1; templateToUsers[_templateName].push(_beneficiary); templateToUserIndex[_templateName][_beneficiary] = templateToUsers[_templateName].length - 1; emit AddSchedule(_beneficiary, _templateName, _startTime); @@ -279,8 +304,8 @@ contract VestingEscrowWallet is IWallet { function _modifySchedule(address _beneficiary, bytes32 _templateName, uint256 _startTime) internal { _checkSchedule(_beneficiary, _templateName); - require(now < _startTime, "Date in the past"); - uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + require(_startTime > now, "Date in the past"); + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; Schedule storage schedule = schedules[_beneficiary][index]; /*solium-disable-next-line security/no-block-members*/ require(now < schedule.startTime, "Schedule started"); @@ -295,8 +320,8 @@ contract VestingEscrowWallet is IWallet { */ function revokeSchedule(address _beneficiary, bytes32 _templateName) external withPerm(ADMIN) { _checkSchedule(_beneficiary, _templateName); - uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; - _sendTokens(_beneficiary, index); + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; + _sendTokensPerSchedule(_beneficiary, index); uint256 releasedTokens = _getReleasedTokens(_beneficiary, index); unassignedTokens = unassignedTokens.add(templates[_templateName].numberOfTokens.sub(releasedTokens)); _deleteUserToTemplates(_beneficiary, _templateName); @@ -305,21 +330,23 @@ contract VestingEscrowWallet is IWallet { } function _deleteUserToTemplates(address _beneficiary, bytes32 _templateName) internal { - uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; Schedule[] storage userSchedules = schedules[_beneficiary]; if (index != userSchedules.length - 1) { userSchedules[index] = userSchedules[userSchedules.length - 1]; userToTemplates[_beneficiary][index] = userToTemplates[_beneficiary][userToTemplates[_beneficiary].length - 1]; + userToTemplateIndex[_beneficiary][userSchedules[index].templateName] = index; } userSchedules.length--; userToTemplates[_beneficiary].length--; - delete templateToScheduleIndex[_beneficiary][_templateName]; + delete userToTemplateIndex[_beneficiary][_templateName]; } function _deleteTemplateToUsers(address _beneficiary, bytes32 _templateName) internal { uint256 templateIndex = templateToUserIndex[_templateName][_beneficiary]; if (templateIndex != templateToUsers[_templateName].length - 1) { templateToUsers[_templateName][templateIndex] = templateToUsers[_templateName][templateToUsers[_templateName].length - 1]; + templateToUserIndex[_templateName][templateToUsers[_templateName][templateIndex]] = templateIndex; } templateToUsers[_templateName].length--; delete templateToUserIndex[_templateName][_beneficiary]; @@ -339,9 +366,9 @@ contract VestingEscrowWallet is IWallet { Schedule[] storage userSchedules = schedules[_beneficiary]; for (uint256 i = 0; i < userSchedules.length; i++) { uint256 releasedTokens = _getReleasedTokens(_beneficiary, i); - Template storage template = templates[userSchedules[i].templateName]; + Template memory template = templates[userSchedules[i].templateName]; unassignedTokens = unassignedTokens.add(template.numberOfTokens.sub(releasedTokens)); - delete templateToScheduleIndex[_beneficiary][userSchedules[i].templateName]; + delete userToTemplateIndex[_beneficiary][userSchedules[i].templateName]; _deleteTemplateToUsers(_beneficiary, userSchedules[i].templateName); } delete schedules[_beneficiary]; @@ -355,22 +382,23 @@ contract VestingEscrowWallet is IWallet { * @param _templateName name of the template * @return beneficiary's schedule */ - function getSchedule(address _beneficiary, bytes32 _templateName) external view returns(uint256, uint256, uint256, uint256, State) { + function getSchedule(address _beneficiary, bytes32 _templateName) external view returns(uint256, uint256, uint256, uint256, uint256, State) { _checkSchedule(_beneficiary, _templateName); - uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; - Schedule storage schedule = schedules[_beneficiary][index]; + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; + Schedule memory schedule = schedules[_beneficiary][index]; return ( templates[schedule.templateName].numberOfTokens, templates[schedule.templateName].duration, templates[schedule.templateName].frequency, schedule.startTime, + schedule.claimedTokens, _getScheduleState(_beneficiary, _templateName) ); } function _getScheduleState(address _beneficiary, bytes32 _templateName) internal view returns(State) { _checkSchedule(_beneficiary, _templateName); - uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; Schedule memory schedule = schedules[_beneficiary][index]; if (now < schedule.startTime) { return State.CREATED; @@ -402,14 +430,14 @@ contract VestingEscrowWallet is IWallet { } function _getAvailableTokens(address _beneficiary, uint256 _index) internal view returns(uint256) { - Schedule storage schedule = schedules[_beneficiary][_index]; + Schedule memory schedule = schedules[_beneficiary][_index]; uint256 releasedTokens = _getReleasedTokens(_beneficiary, _index); return releasedTokens.sub(schedule.claimedTokens); } function _getReleasedTokens(address _beneficiary, uint256 _index) internal view returns(uint256) { - Schedule storage schedule = schedules[_beneficiary][_index]; - Template storage template = templates[schedule.templateName]; + Schedule memory schedule = schedules[_beneficiary][_index]; + Template memory template = templates[schedule.templateName]; /*solium-disable-next-line security/no-block-members*/ if (now > schedule.startTime) { uint256 periodCount = template.duration.div(template.frequency); @@ -426,11 +454,11 @@ contract VestingEscrowWallet is IWallet { /** * @notice Used to remove beneficiaries without schedules + * TODO: Improve the Trim beneficiary logic -- remain because of size of bytecode hit the limit */ function trimBeneficiaries() external withPerm(ADMIN) { for (uint256 i = 0; i < beneficiaries.length; i++) { if (schedules[beneficiaries[i]].length == 0) { - delete schedules[beneficiaries[i]]; if (i != beneficiaries.length - 1) { beneficiaries[i] = beneficiaries[beneficiaries.length - 1]; } @@ -444,7 +472,6 @@ contract VestingEscrowWallet is IWallet { * @param _beneficiaries array of beneficiary's addresses */ function pushAvailableTokensMulti(address[] _beneficiaries) external withPerm(ADMIN) { - require(_beneficiaries.length > 1, "Array size should be greater than one"); for (uint256 i = 0; i < _beneficiaries.length; i++) { pushAvailableTokens(_beneficiaries[i]); } @@ -532,7 +559,7 @@ contract VestingEscrowWallet is IWallet { function _checkSchedule(address _beneficiary, bytes32 _templateName) internal view { require(_beneficiary != address(0), "Invalid address"); - uint256 index = templateToScheduleIndex[_beneficiary][_templateName]; + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; require( index < schedules[_beneficiary].length && schedules[_beneficiary][index].templateName == _templateName, @@ -544,24 +571,22 @@ contract VestingEscrowWallet is IWallet { return templates[_name].numberOfTokens > 0; } - function _isTemplateUsed(bytes32 _name) internal view returns(bool) { - return templateToUsers[_name].length > 0; - } - - function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) internal pure { + function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) internal view { require(_numberOfTokens > 0, "Zero amount"); - require(_duration % _frequency == 0, "Duration and frequency mismatch"); + require(_duration % _frequency == 0, "Invalid frequency"); uint256 periodCount = _duration.div(_frequency); - require(_numberOfTokens % periodCount == 0, "Tokens and periods mismatch"); + require(_numberOfTokens % periodCount == 0); + uint256 amountPerPeriod = _numberOfTokens.div(periodCount); + require(amountPerPeriod % ISecurityToken(securityToken).granularity() == 0, "Invalid granularity"); } function _sendTokens(address _beneficiary) internal { for (uint256 i = 0; i < schedules[_beneficiary].length; i++) { - _sendTokens(_beneficiary, i); + _sendTokensPerSchedule(_beneficiary, i); } } - function _sendTokens(address _beneficiary, uint256 _index) internal { + function _sendTokensPerSchedule(address _beneficiary, uint256 _index) internal { uint256 amount = _getAvailableTokens(_beneficiary, _index); if (amount > 0) { schedules[_beneficiary][_index].claimedTokens = schedules[_beneficiary][_index].claimedTokens.add(amount); From ae08093b5e4be98e87e707b47b83f15a59365433 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 30 Nov 2018 15:27:53 +0530 Subject: [PATCH 284/582] minor fixes --- .../TransferManager/LockUpTransferManager.sol | 19 +------- test/w_lockup_transfer_manager.js | 43 ------------------- 2 files changed, 2 insertions(+), 60 deletions(-) diff --git a/contracts/modules/TransferManager/LockUpTransferManager.sol b/contracts/modules/TransferManager/LockUpTransferManager.sol index cb2c4f156..1de5a0c14 100644 --- a/contracts/modules/TransferManager/LockUpTransferManager.sol +++ b/contracts/modules/TransferManager/LockUpTransferManager.sol @@ -368,7 +368,6 @@ contract LockUpTransferManager is ITransferManager { userToLockups[_userAddress][userToLockupIndex[_userAddress][_lockupName]] == _lockupName, "User not assosicated with given lockup" ); - bytes32[] memory userLockupNames = userToLockups[_userAddress]; return ( lockups[_lockupName].lockupAmount, lockups[_lockupName].startTime, @@ -454,10 +453,8 @@ contract LockUpTransferManager is ITransferManager { // Calculate the transaction time lies in which period /*solium-disable-next-line security/no-block-members*/ uint256 elapsedPeriod = (now.sub(lockups[_lockupName].startTime)).div(lockups[_lockupName].releaseFrequencySeconds); - // Calculate the allowed unlocked amount per period - uint256 amountPerPeriod = (lockups[_lockupName].lockupAmount).div(noOfPeriods); // Find out the unlocked amount for a given lockup - uint256 unLockedAmount = elapsedPeriod.mul(amountPerPeriod); + uint256 unLockedAmount = (lockups[_lockupName].lockupAmount.mul(elapsedPeriod)).div(noOfPeriods); return unLockedAmount; } } @@ -615,23 +612,11 @@ contract LockUpTransferManager is ITransferManager { uint256 _releaseFrequencySeconds ) internal - view + pure { require(_lockUpPeriodSeconds != 0, "lockUpPeriodSeconds cannot be zero"); require(_releaseFrequencySeconds != 0, "releaseFrequencySeconds cannot be zero"); require(_lockupAmount != 0, "lockupAmount cannot be zero"); - - // check that the total amount to be released isn't too granular - require( - _lockupAmount % ISecurityToken(securityToken).granularity() == 0, - "The total amount to be released is more granular than allowed by the token" - ); - - // check that releaseFrequencySeconds evenly divides lockUpPeriodSeconds - require( - _lockUpPeriodSeconds % _releaseFrequencySeconds == 0, - "lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds" - ); } /** diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js index eb7a76cd6..834ab8cca 100644 --- a/test/w_lockup_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -420,25 +420,6 @@ contract('LockUpTransferManager', accounts => { ); }); - - it("Should prevent the creation of a lockup with bad parameters where the total amount to be released is more granular than allowed by the token", async() => { - // create a lockup - // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens - await catchRevert( - I_LockUpTransferManager.addNewLockUpToUser( - account_investor2, - web3.utils.toWei('0.5', 'ether'), - latestTime() + + duration.seconds(1), - duration.seconds(400000), - duration.seconds(100000), - "a_lockup", - { - from: token_owner - } - ) - ); - }); - it("Should add the lockup type -- fail because of bad owner", async() => { await catchRevert( I_LockUpTransferManager.addNewLockUpType( @@ -518,30 +499,6 @@ contract('LockUpTransferManager', accounts => { assert.equal((tx.logs[0].args.lockupAmount).toNumber(), web3.utils.toWei('64951', 'ether')); }); - it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is not evenly divisible by releaseFrequencySeconds", async() => { - - // balance should be 9000000000000000000 here (9 eth) - let balance = await I_SecurityToken.balanceOf(account_investor2) - - - // create a lockup - // over 17 seconds total, with 4 periods. - // this will generate an exception because 17 is not evenly divisble by 4. - await catchRevert( - I_LockUpTransferManager.addNewLockUpToUser( - account_investor2, - web3.utils.toWei('4', 'ether'), - latestTime(), - 17, - 4, - "b_lockup", - { - from: token_owner - } - ) - ); - }); - it("Should prevent the transfer of tokens in a lockup", async() => { let balance = await I_SecurityToken.balanceOf(account_investor2) From 8b964c5fdb7347d9dd67799c0bdfdced756ff853 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Fri, 30 Nov 2018 09:04:15 -0300 Subject: [PATCH 285/582] whitelist to transfer manager --- CLI/commands/sto_manager.js | 4 +- CLI/commands/token_manager.js | 3 +- CLI/commands/transfer_manager.js | 181 +++++++++++++++++++++++++++++- CLI/commands/whitelist.js | 182 ------------------------------- CLI/polymath-cli.js | 5 +- 5 files changed, 184 insertions(+), 191 deletions(-) delete mode 100644 CLI/commands/whitelist.js diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 8cd2baa5e..898eb8b45 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -708,7 +708,7 @@ async function usdTieredSTO_configure(currentSTO) { await common.sendTransaction(changeNonAccreditedLimitAction); break; case 4: - await startCSV(tokenSymbol, 75, 'nonAccredited'); + await startCSV(tokenSymbol, 75, 'nonAccreditedLimit'); break; case 5: await modfifyTimes(currentSTO); @@ -743,7 +743,7 @@ async function startCSV(tokenSymbol, batchSize, accreditionType) { proccessing = accredit_processing saving = saveInBlockchainAccredited break; - case 'nonAccredited': + case 'nonAccreditedLimit': file = './CLI/data/nonAccreditedLimits_data.csv' proccessing = nonAccredited_processing saving = saveInBlockchainNonAccredited diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index a94c0cc1d..e8556450d 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -1,7 +1,6 @@ // Libraries for terminal prompts const readlineSync = require('readline-sync'); const chalk = require('chalk'); -const whitelist = require('./whitelist'); const stoManager = require('./sto_manager'); const transferManager = require('./transfer_manager'); const common = require('./common/common_functions'); @@ -347,7 +346,7 @@ async function mintToSingleAddress(_investor, _amount) { } async function multi_mint_tokens() { - await whitelist.executeApp(tokenSymbol, 75); + await transferManager.startCSV(tokenSymbol, 75); console.log(chalk.green(`\nCongratulations! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 44ae64ca1..dc5aba389 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -5,13 +5,22 @@ var common = require('./common/common_functions'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); var gbl = require('./common/global'); -var whitelist = require('./whitelist'); +var transferManager = require('./transfer_manager'); +var csv_shared = require('./common/csv_shared'); +var BigNumber = require('bignumber.js'); // App flow let tokenSymbol; let securityToken; let securityTokenRegistry; let currentTransferManager; +let generalTransferManager; + +/* CSV variables */ +let distribData = new Array(); +let fullFileData = new Array(); +let badData = new Array(); +/* End CSV variables */ async function executeApp() { let exit = false; @@ -373,7 +382,7 @@ async function generalTransferManager() { case 'Modify whitelist from CSV': console.log(chalk.yellow(`Data is going to be read from 'data/whitelist_data.csv'. Be sure this file is updated!`)); if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { - await whitelist.executeApp(tokenSymbl); + await transferManager.startCSV(tokenSymbol); } break; /* @@ -468,6 +477,171 @@ async function generalTransferManager() { } } +async function startCSV(tokenSymbol, batchSize) { + securityToken = await csv_shared.start(tokenSymbol, batchSize); + + let result_processing = await csv_shared.read('./CLI/data/whitelist_data.csv', whitelist_processing); + distribData = result_processing.distribData; + fullFileData = result_processing.fullFileData; + badData = result_processing.badData; + + await saveInBlockchain(); + await finalResults(); +}; + +function whitelist_processing(csv_line) { + let isAddress = web3.utils.isAddress(csv_line[0]); + let sellValid = isValidDate(csv_line[1]) + let buyValid = isValidDate(csv_line[2]) + let kycExpiryDate = isValidDate(csv_line[3]) + let canBuyFromSTO = (typeof JSON.parse(csv_line[4].toLowerCase())) == "boolean" ? JSON.parse(csv_line[4].toLowerCase()) : "not-valid"; + + if (isAddress && + sellValid && + buyValid && + kycExpiryDate && + (canBuyFromSTO != "not-valid")) { + return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] + } else { + return [false, new Array(csv_line[0], sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] + } +} + +function isValidDate(date) { + var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(date); + if (matches == null) return false; + var d = matches[2]; + var m = matches[1] - 1; + var y = matches[3]; + var composedDate = new Date(y, m, d); + var timestampDate = composedDate.getTime() + + // For some reason these timestamps are being recorded +4 hours UTC + if (composedDate.getDate() == d && + composedDate.getMonth() == m && + composedDate.getFullYear() == y) { + return timestampDate / 1000 + } else { + return false + } +} + +async function saveInBlockchain() { + let gtmModules; + try { + gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + } catch (e) { + console.log("Please attach General Transfer module before launch this action.", e) + process.exit(0) + } + + generalTransferManager = new web3.eth.Contract(abis.generalTransferManager(), gtmModules[0]); + + console.log(` + ------------------------------------------------------- + ----- Sending buy/sell restrictions to blockchain ----- + ------------------------------------------------------- + `); + + for (let i = 0; i < distribData.length; i++) { + try { + let investorArray = [], fromTimesArray = [], toTimesArray = [], expiryTimeArray = [], canBuyFromSTOArray = []; + + // Splitting the user arrays to be organized by input + for (let j = 0; j < distribData[i].length; j++) { + investorArray.push(distribData[i][j][0]) + fromTimesArray.push(distribData[i][j][1]) + toTimesArray.push(distribData[i][j][2]) + expiryTimeArray.push(distribData[i][j][3]) + canBuyFromSTOArray.push(distribData[i][j][4]) + } + + let modifyWhitelistMultiAction = await generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); + let tx = await common.sendTransaction(modifyWhitelistMultiAction); + console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); + console.log("Whitelist transaxction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); + console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); + + } catch (err) { + console.log("ERROR", err) + process.exit(0) + } + } + + return; +} + +async function finalResults() { + let totalInvestors = 0; + let updatedInvestors = 0; + let investorObjectLookup = {}; + let investorData_Events = new Array(); + let event_data = await generalTransferManager.getPastEvents('ModifyWhitelist', {fromBlock: 0, toBlock: 'latest'}, () => {}); + + for (var i = 0; i < event_data.length; i++) { + let combineArray = []; + + let investorAddress_Event = event_data[i].returnValues._investor + let fromTime_Event = event_data[i].returnValues._fromTime + let toTime_Event = event_data[i].returnValues._toTime + let expiryTime_Event = event_data[i].returnValues._expiryTime + let canBuyFromSTO_Event = event_data[i].returnValues._canBuyFromSTO + let blockNumber = event_data[i].blockNumber + + combineArray.push(investorAddress_Event); + combineArray.push(fromTime_Event); + combineArray.push(toTime_Event); + combineArray.push(expiryTime_Event); + combineArray.push(canBuyFromSTO_Event); + combineArray.push(blockNumber) + + investorData_Events.push(combineArray) + + // We have already recorded it, so this is an update to our object + if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { + // The block number form the event we are checking is bigger, so we gotta replace it + if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { + investorObjectLookup[investorAddress_Event] = {fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber}; + updatedInvestors += 1; + } + } else { + investorObjectLookup[investorAddress_Event] = {fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber}; + totalInvestors += 1; + } + } + + let investorAddress_Events = Object.keys(investorObjectLookup) + + console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); + console.log(`A total of ${totalInvestors} investors have been whitelisted total, all time.\n`); + console.log(`This script in total sent ${fullFileData.length - badData.length} new investors and updated investors to the blockchain.\n`); + console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); + console.log("************************************************************************************************"); + console.log("OBJECT WITH EVERY USER AND THEIR UPDATED TIMES: \n\n", investorObjectLookup) + console.log("************************************************************************************************"); + console.log("LIST OF ALL INVESTORS WHITELISTED: \n\n", investorAddress_Events) + + let missingDistribs = []; + for (let l = 0; l < fullFileData.length; l++) { + if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { + missingDistribs.push(fullFileData[l]) + } + } + + if (missingDistribs.length > 0) { + console.log("************************************************************************************************"); + console.log("-- No LogModifyWhitelist event was found for the following data arrays. Please review them manually --") + console.log(missingDistribs) + console.log("************************************************************************************************"); + } else { + console.log("\n************************************************************************************************"); + console.log("All accounts passed through from the CSV were successfully whitelisted, because we were able to read them all from events") + console.log("************************************************************************************************"); + } + +} + async function manualApprovalTransferManager() { console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address}`), '\n'); @@ -952,5 +1126,8 @@ module.exports = { addTransferManagerModule: async function (_tokenSymbol) { await initialize(_tokenSymbol); return addTransferManagerModule() + }, + startCSV: async function (tokenSymbol, batchSize) { + return startCSV(tokenSymbol, batchSize); } } \ No newline at end of file diff --git a/CLI/commands/whitelist.js b/CLI/commands/whitelist.js deleted file mode 100644 index 7a5767611..000000000 --- a/CLI/commands/whitelist.js +++ /dev/null @@ -1,182 +0,0 @@ -var common = require('./common/common_functions'); -var csv_shared = require('./common/csv_shared'); -var abis = require('./helpers/contract_abis'); -var BigNumber = require('bignumber.js'); - -let distribData = new Array(); -let fullFileData = new Array(); -let badData = new Array(); - -let securityToken; -let generalTransferManager; - -async function startScript(tokenSymbol, batchSize) { - securityToken = await csv_shared.start(tokenSymbol, batchSize); - - let result_processing = await csv_shared.read('./CLI/data/whitelist_data.csv', whitelist_processing); - distribData = result_processing.distribData; - fullFileData = result_processing.fullFileData; - badData = result_processing.badData; - - await saveInBlockchain(); - await finalResults(); -}; - -function whitelist_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let sellValid = isValidDate(csv_line[1]) - let buyValid = isValidDate(csv_line[2]) - let kycExpiryDate = isValidDate(csv_line[3]) - let canBuyFromSTO = (typeof JSON.parse(csv_line[4].toLowerCase())) == "boolean" ? JSON.parse(csv_line[4].toLowerCase()) : "not-valid"; - - if (isAddress && - sellValid && - buyValid && - kycExpiryDate && - (canBuyFromSTO != "not-valid")) { - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] - } else { - return [false, new Array(csv_line[0], sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] - } -} - -function isValidDate(date) { - var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(date); - if (matches == null) return false; - var d = matches[2]; - var m = matches[1] - 1; - var y = matches[3]; - var composedDate = new Date(y, m, d); - var timestampDate = composedDate.getTime() - - // For some reason these timestamps are being recorded +4 hours UTC - if (composedDate.getDate() == d && - composedDate.getMonth() == m && - composedDate.getFullYear() == y) { - return timestampDate / 1000 - } else { - return false - } -} - -async function saveInBlockchain() { - let gtmModules; - try { - gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); - } catch (e) { - console.log("Please attach General Transfer module before launch this action.", e) - process.exit(0) - } - - generalTransferManager = new web3.eth.Contract(abis.generalTransferManager(), gtmModules[0]); - - console.log(` - ------------------------------------------------------- - ----- Sending buy/sell restrictions to blockchain ----- - ------------------------------------------------------- - `); - - for (let i = 0; i < distribData.length; i++) { - try { - let investorArray = [], fromTimesArray = [], toTimesArray = [], expiryTimeArray = [], canBuyFromSTOArray = []; - - // Splitting the user arrays to be organized by input - for (let j = 0; j < distribData[i].length; j++) { - investorArray.push(distribData[i][j][0]) - fromTimesArray.push(distribData[i][j][1]) - toTimesArray.push(distribData[i][j][2]) - expiryTimeArray.push(distribData[i][j][3]) - canBuyFromSTOArray.push(distribData[i][j][4]) - } - - let modifyWhitelistMultiAction = await generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); - let tx = await common.sendTransaction(modifyWhitelistMultiAction); - console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Whitelist transaxction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - - } catch (err) { - console.log("ERROR", err) - process.exit(0) - } - } - - return; -} - -async function finalResults() { - let totalInvestors = 0; - let updatedInvestors = 0; - let investorObjectLookup = {}; - let investorData_Events = new Array(); - let event_data = await generalTransferManager.getPastEvents('ModifyWhitelist', {fromBlock: 0, toBlock: 'latest'}, () => {}); - - for (var i = 0; i < event_data.length; i++) { - let combineArray = []; - - let investorAddress_Event = event_data[i].returnValues._investor - let fromTime_Event = event_data[i].returnValues._fromTime - let toTime_Event = event_data[i].returnValues._toTime - let expiryTime_Event = event_data[i].returnValues._expiryTime - let canBuyFromSTO_Event = event_data[i].returnValues._canBuyFromSTO - let blockNumber = event_data[i].blockNumber - - combineArray.push(investorAddress_Event); - combineArray.push(fromTime_Event); - combineArray.push(toTime_Event); - combineArray.push(expiryTime_Event); - combineArray.push(canBuyFromSTO_Event); - combineArray.push(blockNumber) - - investorData_Events.push(combineArray) - - // We have already recorded it, so this is an update to our object - if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { - // The block number form the event we are checking is bigger, so we gotta replace it - if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { - investorObjectLookup[investorAddress_Event] = {fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber}; - updatedInvestors += 1; - } - } else { - investorObjectLookup[investorAddress_Event] = {fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber}; - totalInvestors += 1; - } - } - - let investorAddress_Events = Object.keys(investorObjectLookup) - - console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); - console.log(`A total of ${totalInvestors} investors have been whitelisted total, all time.\n`); - console.log(`This script in total sent ${fullFileData.length - badData.length} new investors and updated investors to the blockchain.\n`); - console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); - console.log("************************************************************************************************"); - console.log("OBJECT WITH EVERY USER AND THEIR UPDATED TIMES: \n\n", investorObjectLookup) - console.log("************************************************************************************************"); - console.log("LIST OF ALL INVESTORS WHITELISTED: \n\n", investorAddress_Events) - - let missingDistribs = []; - for (let l = 0; l < fullFileData.length; l++) { - if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { - missingDistribs.push(fullFileData[l]) - } - } - - if (missingDistribs.length > 0) { - console.log("************************************************************************************************"); - console.log("-- No LogModifyWhitelist event was found for the following data arrays. Please review them manually --") - console.log(missingDistribs) - console.log("************************************************************************************************"); - } else { - console.log("\n************************************************************************************************"); - console.log("All accounts passed through from the CSV were successfully whitelisted, because we were able to read them all from events") - console.log("************************************************************************************************"); - } - -} - -module.exports = { - executeApp: async (tokenSymbol, batchSize) => { - return startScript(tokenSymbol, batchSize); - } -} \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index b422d5215..3e2494a3f 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -6,7 +6,6 @@ var token_manager = require('./commands/token_manager'); var st20generator = require('./commands/ST20Generator'); var sto_manager = require('./commands/sto_manager'); var transfer = require('./commands/transfer'); -var whitelist = require('./commands/whitelist'); var transfer_ownership = require('./commands/transfer_ownership'); var dividends_manager = require('./commands/dividends_manager'); var transfer_manager = require('./commands/transfer_manager'); @@ -114,7 +113,7 @@ program .description('Mass-update a whitelist of allowed/known investors') .action(async function (tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - await whitelist.executeApp(tokenSymbol, batchSize); + await transfer_manager.startCSV(tokenSymbol, batchSize); }); program @@ -160,7 +159,7 @@ program .description('Runs changeNonAccreditedLimit') .action(async function (tokenSymbol, batchSize) { await gbl.initialize(program.remoteNode); - await sto_manager.startCSV(tokenSymbol, batchSize, 'nonAccredited') + await sto_manager.startCSV(tokenSymbol, batchSize, 'nonAccreditedLimit') }); program From 8ab687e0d3f3398545566a38433b73f14f67f77d Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 30 Nov 2018 13:29:03 +0100 Subject: [PATCH 286/582] added test cases for adding new holders and removing one at the same time when it is already full. --- test/d_count_transfer_manager.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 1a1e7717a..9656c45c9 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -339,6 +339,12 @@ contract("CountTransferManager", accounts => { await catchRevert(I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2", "ether"), { from: account_investor2 })); }); + it("Should be able to transfer to a new token holder if all tokens are transferred and existing holder is removed", async () => { + console.log('acc2 balancce is ' + (await I_SecurityToken.balanceOf(account_investor2)).toNumber()); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4", "ether"), { from: account_investor2 }); + assert((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("4", "ether")); + }); + it("Should be able to consolidate balances", async () => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); }); From 6d12750340ccdd17dbf5af47af573d7025c3a820 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 30 Nov 2018 14:58:32 +0200 Subject: [PATCH 287/582] test fixes - data structure refactoring (not finished) --- .../modules/Wallet/VestingEscrowWallet.sol | 1 + test/z_vesting_escrow_wallet.js | 264 +++++++++--------- 2 files changed, 126 insertions(+), 139 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index f5049019a..c8a05defe 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -271,6 +271,7 @@ contract VestingEscrowWallet is IWallet { require(_isTemplateExists(_templateName)); uint256 index = userToTemplateIndex[_beneficiary][_templateName]; require( + schedules[_beneficiary].length == 0 || schedules[_beneficiary][index].templateName != _templateName, "Already added" ); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 8c5d3fba5..bad3e9e8e 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -71,7 +71,7 @@ contract('VestingEscrowWallet', accounts => { // Accounts setup account_polymath = accounts[0]; token_owner = accounts[1]; - wallet_admin = token_owner; + wallet_admin = accounts[2]; account_beneficiary1 = accounts[6]; account_beneficiary2 = accounts[7]; @@ -173,8 +173,13 @@ contract('VestingEscrowWallet', accounts => { }); it("Should successfully attach the VestingEscrowWallet with the security token", async () => { + let bytesData = encodeModuleCall( + ["address"], + [token_owner] + ); + await I_SecurityToken.changeGranularity(1, {from: token_owner}); - const tx = await I_SecurityToken.addModule(I_VestingEscrowWalletFactory.address, "", 0, 0, { from: token_owner }); + const tx = await I_SecurityToken.addModule(I_VestingEscrowWalletFactory.address, bytesData, 0, 0, { from: token_owner }); assert.equal(tx.logs[2].args._types[0].toNumber(), 6, "VestingEscrowWallet doesn't get deployed"); assert.equal( @@ -317,6 +322,7 @@ contract('VestingEscrowWallet', accounts => { }); it("Should not be able to push available tokens -- fail because of permissions check", async () => { + let templateName = "template-01"; let numberOfTokens = 75000; let duration = durationUtil.seconds(30); let frequency = durationUtil.seconds(10); @@ -324,7 +330,7 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + timeShift; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); - await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency); await catchRevert( @@ -345,20 +351,19 @@ contract('VestingEscrowWallet', accounts => { }); it("Should fail to modify vesting schedule -- fail because schedule already started", async () => { - let numberOfTokens = 75000; - let duration = durationUtil.seconds(30); - let frequency = durationUtil.seconds(10); - let timeShift = durationUtil.seconds(100); + let templateName = "template-01"; let startTime = latestTime() + timeShift; await catchRevert( - I_VestingEscrowWallet.modifySchedule(account_beneficiary3, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) + I_VestingEscrowWallet.modifySchedule(account_beneficiary3, templateName, startTime, {from: wallet_admin}) ); await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should withdraw available tokens to the beneficiary address", async () => { + let templateName = "template-02"; let numberOfTokens = 33000; let duration = durationUtil.seconds(30); let frequency = durationUtil.seconds(10); @@ -366,7 +371,7 @@ contract('VestingEscrowWallet', accounts => { let startTime = latestTime() + timeShift; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); - await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency * 3); const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); @@ -376,27 +381,31 @@ contract('VestingEscrowWallet', accounts => { let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), numberOfTokens); - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary3, 0); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary3, templateName); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, COMPLETED); await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should withdraw available tokens 2 times by 3 schedules to the beneficiary address", async () => { let schedules = [ { + templateName: "template-1-01", numberOfTokens: 100000, duration: durationUtil.minutes(4), frequency: durationUtil.minutes(1) }, { + templateName: "template-1-02", numberOfTokens: 30000, duration: durationUtil.minutes(6), frequency: durationUtil.minutes(1) }, { + templateName: "template-1-03", numberOfTokens: 2000, duration: durationUtil.minutes(10), frequency: durationUtil.minutes(1) @@ -407,11 +416,12 @@ contract('VestingEscrowWallet', accounts => { await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); for (let i = 0; i < schedules.length; i++) { + let templateName = schedules[i].templateName; let numberOfTokens = schedules[i].numberOfTokens; let duration = schedules[i].duration; let frequency = schedules[i].frequency; let startTime = latestTime() + durationUtil.seconds(100); - await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); } let stepCount = 6; await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); @@ -441,6 +451,9 @@ contract('VestingEscrowWallet', accounts => { await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); + for (let i = 0; i < schedules.length; i++) { + await I_VestingEscrowWallet.removeTemplate(schedules[i].templateName, {from: wallet_admin}); + } await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); @@ -450,18 +463,21 @@ contract('VestingEscrowWallet', accounts => { let schedules = [ { + templateName: "template-2-01", numberOfTokens: 100000, duration: durationUtil.years(4), frequency: durationUtil.years(1), startTime: latestTime() + durationUtil.days(1) }, { + templateName: "template-2-02", numberOfTokens: 30000, duration: durationUtil.weeks(6), frequency: durationUtil.weeks(1), startTime: latestTime() + durationUtil.days(2) }, { + templateName: "template-2-03", numberOfTokens: 2000, duration: durationUtil.days(10), frequency: durationUtil.days(2), @@ -471,43 +487,43 @@ contract('VestingEscrowWallet', accounts => { it("Should fail to add vesting schedule to the beneficiary address -- fail because address in invalid", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(0, 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) + I_VestingEscrowWallet.addSchedule(0, "template-2-01", 100000, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to add vesting schedule to the beneficiary address -- fail because start date in the past", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 1, latestTime() - durationUtil.days(1), {from: wallet_admin}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, "template-2-01", 100000, 4, 1, latestTime() - durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to add vesting schedule to the beneficiary address -- fail because number of tokens is 0", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 0, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, "template-2-01", 0, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to add vesting schedule to the beneficiary address -- fail because duration can't be divided entirely by frequency", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 100000, 4, 3, latestTime() + durationUtil.days(1), {from: wallet_admin}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, "template-2-01", 100000, 4, 3, latestTime() + durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to add vesting schedule to the beneficiary address -- fail because number of tokens can't be divided entirely by period count", async () => { await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, 5, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, "template-2-01", 5, 4, 1, latestTime() + durationUtil.days(1), {from: wallet_admin}) ); }); it("Should fail to get vesting schedule -- fail because address is invalid", async () => { await catchRevert( - I_VestingEscrowWallet.getSchedule(0, 0) + I_VestingEscrowWallet.getSchedule(0, "template-2-01") ); }); it("Should fail to get vesting schedule -- fail because schedule not found", async () => { await catchRevert( - I_VestingEscrowWallet.getSchedule(account_beneficiary1, 0) + I_VestingEscrowWallet.getSchedule(account_beneficiary1, "template-2-01") ); }); @@ -518,6 +534,7 @@ contract('VestingEscrowWallet', accounts => { }); it("Should not be able to add schedule -- fail because of permissions check", async () => { + let templateName = schedules[0].templateName; let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; @@ -525,120 +542,93 @@ contract('VestingEscrowWallet', accounts => { await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); await catchRevert( - I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: account_beneficiary1}) + I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: account_beneficiary1}) ); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should add vesting schedule to the beneficiary address", async () => { + let templateName = schedules[0].templateName; let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); - const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); - checkScheduleLog(tx.logs[0], account_beneficiary1, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(tx.logs[0], account_beneficiary1, templateName, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, templateName); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); }); it("Should add vesting schedule without depositing to the beneficiary address", async () => { + let templateName = "template-2-01-2"; let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); - const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); - checkScheduleLog(tx.logs[1], account_beneficiary1, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(tx.logs[1], account_beneficiary1, templateName, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 2); - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 1); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, templateName); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); - await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_admin}); - - - - + await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, templateName, {from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should fail to modify vesting schedule -- fail because schedule not found", async () => { - let numberOfTokens = schedules[0].numberOfTokens; - let duration = schedules[0].duration; - let frequency = schedules[0].frequency; + let templateName = "template-2-03"; let startTime = schedules[0].startTime; await catchRevert( - I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 2, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}) + I_VestingEscrowWallet.modifySchedule(account_beneficiary1, templateName, startTime, {from: wallet_admin}) ); }); it("Should not be able to modify schedule -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 0, 10000, 4, 1, latestTime() + 100, {from: account_beneficiary1}) + I_VestingEscrowWallet.modifySchedule(account_beneficiary1, "template-2-01", 10000, 4, 1, latestTime() + 100, {from: account_beneficiary1}) ); }); it("Should modify vesting schedule for the beneficiary's address", async () => { - let numberOfTokens = schedules[1].numberOfTokens; - let duration = schedules[1].duration; - let frequency = schedules[1].frequency; + let numberOfTokens = schedules[0].numberOfTokens; + let duration = schedules[0].duration; + let frequency = schedules[0].frequency; let startTime = schedules[1].startTime; - const tx = await I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.modifySchedule(account_beneficiary1, "template-2-01", startTime, {from: wallet_admin}); - checkScheduleLog(tx.logs[0], account_beneficiary1, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(tx.logs[0], account_beneficiary1, templateName, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount.toNumber(), 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, "template-2-01"); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); - let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); - assert.equal(unassignedTokens.toNumber(), schedules[0].numberOfTokens - schedules[1].numberOfTokens); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); - it("Should modify vesting schedule without depositing for the beneficiary's address", async () => { - let numberOfTokens = schedules[0].numberOfTokens + schedules[1].numberOfTokens; - let duration = schedules[0].duration; - let frequency = schedules[0].frequency; - let startTime = schedules[0].startTime; - await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); - const tx = await I_VestingEscrowWallet.modifySchedule(account_beneficiary1, 0, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); - - assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), schedules[0].numberOfTokens); - checkScheduleLog(tx.logs[1], account_beneficiary1, numberOfTokens, duration, frequency, startTime); - - let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); - assert.equal(scheduleCount, 1); - - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); - checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); - - let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); - assert.equal(unassignedTokens.toNumber(), 0); - }); - it("Should not be able to revoke schedule -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: account_beneficiary1}) + I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, "template-2-01", {from: account_beneficiary1}) ); }); it("Should revoke vesting schedule from the beneficiary address", async () => { - const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, "template-2-01", {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); @@ -646,17 +636,19 @@ contract('VestingEscrowWallet', accounts => { let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 0); + + await I_VestingEscrowWallet.removeTemplate("template-2-01", {from: account_beneficiary1}) }); it("Should fail to revoke vesting schedule -- fail because address is invalid", async () => { await catchRevert( - I_VestingEscrowWallet.revokeSchedule(0, 0, {from: wallet_admin}) + I_VestingEscrowWallet.revokeSchedule(0, "template-2-01", {from: wallet_admin}) ); }); it("Should fail to revoke vesting schedule -- fail because schedule not found", async () => { await catchRevert( - I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 1, {from: wallet_admin}) + I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, "template-2-02", {from: wallet_admin}) ); }); @@ -671,13 +663,14 @@ contract('VestingEscrowWallet', accounts => { await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); for (let i = 0; i < schedules.length; i++) { + let templateName = schedules[i].templateName; let numberOfTokens = schedules[i].numberOfTokens; let duration = schedules[i].duration; let frequency = schedules[i].frequency; let startTime = schedules[i].startTime; - const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary2, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary2, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); - checkScheduleLog(tx.logs[0], account_beneficiary2, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(tx.logs[0], account_beneficiary2, templateName, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); assert.equal(scheduleCount, i + 1); @@ -694,17 +687,15 @@ contract('VestingEscrowWallet', accounts => { }); it("Should revoke vesting schedule from the beneficiary address", async () => { - const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, 1, {from: wallet_admin}); + let templateName = schedules[1].templateName; + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, templateName, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); - assert.equal(tx.logs[0].args._index, 1); + assert.equal(tx.logs[0].args._templateName, templateName); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); assert.equal(scheduleCount, 2); - - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, 1); - checkSchedule(schedule, schedules[2].numberOfTokens, schedules[2].duration, schedules[2].frequency, schedules[2].startTime, CREATED); }); it("Should revoke 2 vesting schedules from the beneficiary address", async () => { @@ -720,16 +711,19 @@ contract('VestingEscrowWallet', accounts => { it("Should push available tokens during revoking vesting schedule", async () => { let schedules = [ { + templateName: "template-3-01", numberOfTokens: 100000, duration: durationUtil.minutes(4), frequency: durationUtil.minutes(1) }, { + templateName: "template-3-02", numberOfTokens: 30000, duration: durationUtil.minutes(6), frequency: durationUtil.minutes(1) }, { + templateName: "template-3-03", numberOfTokens: 2000, duration: durationUtil.minutes(10), frequency: durationUtil.minutes(1) @@ -740,16 +734,17 @@ contract('VestingEscrowWallet', accounts => { await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); for (let i = 0; i < schedules.length; i++) { + let templateName = schedules[i].templateName; let numberOfTokens = schedules[i].numberOfTokens; let duration = schedules[i].duration; let frequency = schedules[i].frequency; let startTime = latestTime() + durationUtil.seconds(100); - await I_VestingEscrowWallet.addSchedule(account_beneficiary3, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); } let stepCount = 3; await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); - const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary3, 0, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary3, "template-3-01", {from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), 100000 / 4 * stepCount); @@ -765,6 +760,10 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx2.logs[1].args._beneficiary, account_beneficiary3); assert.equal(tx2.logs[1].args._numberOfTokens.toNumber(), 30000); + for (let i = 0; i < schedules.length; i++) { + await I_VestingEscrowWallet.removeTemplate(schedules[i].templateName, {from: wallet_admin}); + } + balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); assert.equal(balance.toNumber(), totalNumberOfTokens - 100000 / 4); @@ -778,18 +777,21 @@ contract('VestingEscrowWallet', accounts => { let schedules = [ { + templateName: "template-4-01", numberOfTokens: 100000, duration: durationUtil.years(4), frequency: durationUtil.years(1), startTime: latestTime() + durationUtil.days(1) }, { + templateName: "template-4-02", numberOfTokens: 30000, duration: durationUtil.weeks(6), frequency: durationUtil.weeks(1), startTime: latestTime() + durationUtil.days(2) }, { + templateName: "template-4-03", numberOfTokens: 2000, duration: durationUtil.days(10), frequency: durationUtil.days(2), @@ -799,17 +801,19 @@ contract('VestingEscrowWallet', accounts => { it("Should not be able to add template -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.addTemplate(25000, 4, 1, {from: account_beneficiary1}) + I_VestingEscrowWallet.addTemplate("template-4-01", 25000, 4, 1, {from: account_beneficiary1}) ); }); it("Should add 3 Templates", async () => { for (let i = 0; i < schedules.length; i++) { + let templateName = schedules[i].templateName; let numberOfTokens = schedules[i].numberOfTokens; let duration = schedules[i].duration; let frequency = schedules[i].frequency; - const tx = await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.addTemplate(templateName, numberOfTokens, duration, frequency, {from: wallet_admin}); + assert.equal(tx.logs[0].args._name, templateName); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); assert.equal(tx.logs[0].args._duration.toNumber(), duration); assert.equal(tx.logs[0].args._frequency.toNumber(), frequency); @@ -818,39 +822,40 @@ contract('VestingEscrowWallet', accounts => { it("Should not be able to remove template -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.removeTemplate(1, {from: account_beneficiary1}) + I_VestingEscrowWallet.removeTemplate("template-4-02", {from: account_beneficiary1}) ); }); it("Should remove template", async () => { - const tx = await I_VestingEscrowWallet.removeTemplate(1, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.removeTemplate("template-4-02", {from: wallet_admin}); - assert.equal(tx.logs[0].args._index, 1); + assert.equal(tx.logs[0].args._name, removeTemplate); }); it("Should fail to add vesting schedule from template -- fail because template not found", async () => { let startTime = schedules[2].startTime; await catchRevert( - I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_admin}) + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, "template-4-02", startTime, {from: wallet_admin}) ); }); it("Should not be able to add schedule from template -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 0, latestTime(), {from: account_beneficiary1}) + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, "template-4-01", latestTime(), {from: account_beneficiary1}) ); }); it("Should add vesting schedule from template", async () => { + let templateName = schedules[2].templateName; let numberOfTokens = schedules[2].numberOfTokens; let duration = schedules[2].duration; let frequency = schedules[2].frequency; let startTime = schedules[2].startTime; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); - const tx = await I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, 1, startTime, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, templateName, startTime, {from: wallet_admin}); - checkScheduleLog(tx.logs[0], account_beneficiary1, numberOfTokens, duration, frequency, startTime); + checkScheduleLog(tx.logs[0], account_beneficiary1, templateName, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 1); @@ -858,19 +863,19 @@ contract('VestingEscrowWallet', accounts => { let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); - await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, 0, {from: wallet_admin}); + await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, templateName, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should fail to remove template", async () => { await catchRevert( - I_VestingEscrowWallet.removeTemplate(2, {from: wallet_admin}) + I_VestingEscrowWallet.removeTemplate("template-4-02", {from: wallet_admin}) ); }); it("Should remove 2 Templates", async () => { - await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_admin}); - await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate("template-4-01", {from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate("template-4-03", {from: wallet_admin}); let templateCount = await I_VestingEscrowWallet.getTemplateCount.call({from: wallet_admin}); assert.equal(templateCount, 0); @@ -880,10 +885,12 @@ contract('VestingEscrowWallet', accounts => { describe("Tests for multi operations", async () => { + let templateNames = ["template-5-01", "template-5-02", "template-5-03"]; + it("Should not be able to add schedules to the beneficiaries -- fail because of permissions check", async () => { let startTimes = [latestTime() + 100, latestTime() + 100, latestTime() + 100]; await catchRevert( - I_VestingEscrowWallet.addScheduleMulti(beneficiaries, [10000, 10000, 10000], [4, 4, 4], [1, 1, 1], startTimes, {from: account_beneficiary1}) + I_VestingEscrowWallet.addScheduleMulti(beneficiaries, templateNames, [10000, 10000, 10000], [4, 4, 4], [1, 1, 1], startTimes, {from: account_beneficiary1}) ); }); @@ -893,27 +900,28 @@ contract('VestingEscrowWallet', accounts => { await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); await catchRevert( - I_VestingEscrowWallet.addScheduleMulti(beneficiaries, [20000, 30000, 10000], [4, 4], [1, 1, 1], startTimes, {from: wallet_admin}) + I_VestingEscrowWallet.addScheduleMulti(beneficiaries, templateNames, [20000, 30000, 10000], [4, 4], [1, 1, 1], startTimes, {from: wallet_admin}) ); I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should add schedules for 3 beneficiaries", async () => { - let numberOfTokens = [20000, 30000, 10000]; - let durations = [durationUtil.weeks(4), durationUtil.weeks(3), durationUtil.weeks(4)]; - let frequencies = [durationUtil.weeks(2), durationUtil.weeks(1), durationUtil.weeks(1)]; - let startTimes = [latestTime() + durationUtil.days(1), latestTime() + durationUtil.days(2), latestTime() + durationUtil.days(3)]; + let numberOfTokens = [15000, 15000, 15000]; + let durations = [durationUtil.seconds(50), durationUtil.seconds(50), durationUtil.seconds(50)]; + let frequencies = [durationUtil.seconds(10), durationUtil.seconds(10), durationUtil.seconds(10)]; + let timeShift = durationUtil.seconds(100); + let startTimes = [latestTime() + timeShift, latestTime() + timeShift, latestTime() + timeShift]; let totalNumberOfTokens = 60000; await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); - let tx = await I_VestingEscrowWallet.addScheduleMulti(beneficiaries, numberOfTokens, durations, frequencies, startTimes, {from: wallet_admin}); + let tx = await I_VestingEscrowWallet.addScheduleMulti(beneficiaries, templateNames, numberOfTokens, durations, frequencies, startTimes, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; let beneficiary = beneficiaries[i]; - checkScheduleLog(log, beneficiary, numberOfTokens[i], durations[i], frequencies[i], startTimes[i]); + checkScheduleLog(log, beneficiary, templateNames[i], startTimes[i]); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); assert.equal(scheduleCount, 1); @@ -924,28 +932,20 @@ contract('VestingEscrowWallet', accounts => { }); it("Should not be able modify vesting schedule for 3 beneficiary's addresses -- fail because of arrays sizes mismatch", async () => { - let numberOfTokens = [25000, 25000, 25000]; - let durations = [durationUtil.seconds(50), durationUtil.seconds(50), durationUtil.seconds(50)]; - let frequencies = [durationUtil.seconds(10), durationUtil.seconds(10), durationUtil.seconds(10)]; let timeShift = durationUtil.seconds(100); let startTimes = [latestTime() + timeShift, latestTime() + timeShift, latestTime() + timeShift]; - let indexes = [0, 0, 0, 0]; await catchRevert( - I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, durations, frequencies, startTimes, {from: wallet_admin}) + I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, ["template-5-01"], startTimes, {from: wallet_admin}) ); }); it("Should not be able to modify schedules for the beneficiaries -- fail because of permissions check", async () => { - let numberOfTokens = [25000, 25000, 25000]; - let durations = [durationUtil.seconds(50), durationUtil.seconds(50), durationUtil.seconds(50)]; - let frequencies = [durationUtil.seconds(10), durationUtil.seconds(10), durationUtil.seconds(10)]; let timeShift = durationUtil.seconds(100); let startTimes = [latestTime() + timeShift, latestTime() + timeShift, latestTime() + timeShift]; - let indexes = [0, 0, 0]; await catchRevert( - I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, durations, frequencies, startTimes, {from: account_beneficiary1}) + I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, templateNames, startTimes, {from: account_beneficiary1}) ); }); @@ -956,24 +956,20 @@ contract('VestingEscrowWallet', accounts => { let timeShift = durationUtil.seconds(100); let startTimes = [latestTime() + timeShift, latestTime() + timeShift, latestTime() + timeShift]; - let indexes = [0, 0, 0]; - const tx = await I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, indexes, numberOfTokens, durations, frequencies, startTimes, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, templateNames, startTimes, {from: wallet_admin}); await increaseTime(timeShift + frequencies[0]); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; let beneficiary = beneficiaries[i]; - checkScheduleLog(log, beneficiary, numberOfTokens[i], durations[i], frequencies[i], startTimes[i]); + checkScheduleLog(log, beneficiary, templateNames[i], startTimes[i]); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); assert.equal(scheduleCount, 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); + let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, templateNames[i]); checkSchedule(schedule, numberOfTokens[i], durations[i], frequencies[i], startTimes[i], STARTED); } - - let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); - assert.equal(unassignedTokens.toNumber(), 5000 * beneficiaries.length); }); it("Should not be able to send available tokens to the beneficiaries addresses -- fail because of array size", async () => { @@ -1002,11 +998,13 @@ contract('VestingEscrowWallet', accounts => { await I_SecurityToken.transfer(token_owner, balance, {from: beneficiary}); await I_VestingEscrowWallet.revokeAllSchedules(beneficiary, {from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate(templateNames[i], {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); } }); it("Should not be able to add schedules from template to the beneficiaries -- fail because of permissions check", async () => { + let templateName = "template-5-01"; let numberOfTokens = 18000; let duration = durationUtil.weeks(3); let frequency = durationUtil.weeks(1); @@ -1015,44 +1013,34 @@ contract('VestingEscrowWallet', accounts => { let totalNumberOfTokens = numberOfTokens * 3; await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); - await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); + await I_VestingEscrowWallet.addTemplate(templateName, numberOfTokens, duration, frequency, {from: wallet_admin}); await catchRevert( - I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, 0, startTimes, {from: account_beneficiary1}) + I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, templateName, startTimes, {from: account_beneficiary1}) ); }); it("Should add schedules from template for 3 beneficiaries", async () => { - let numberOfTokens = 18000; - let duration = durationUtil.weeks(3); - let frequency = durationUtil.weeks(1); - let startTimes = [latestTime() + durationUtil.seconds(100), latestTime() + durationUtil.seconds(100), latestTime() + durationUtil.seconds(100)]; - - let totalNumberOfTokens = numberOfTokens * 3; - await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); - await I_VestingEscrowWallet.addTemplate(numberOfTokens, duration, frequency, {from: wallet_admin}); - - let tx = await I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, 0, startTimes, {from: wallet_admin}); - await I_VestingEscrowWallet.removeTemplate(0, {from: wallet_admin}); + let templateName = "template-5-01"; + let tx = await I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, [templateName, templateName, templateName], startTimes, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; let beneficiary = beneficiaries[i]; - checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTimes[i]); + checkScheduleLog(log, beneficiary, templateName, startTimes[i]); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); assert.equal(scheduleCount.toNumber(), 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); + let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, templateName); checkSchedule(schedule, numberOfTokens, duration, frequency, startTimes[i], CREATED); } - + await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}); }); it("Should not be able to revoke schedules of the beneficiaries -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.revokeSchedulesMulti([account_beneficiary1], {from: account_beneficiary1}) + I_VestingEscrowWallet.revokeSchedulesMulti(beneficiaries, {from: account_beneficiary1}) ); }); @@ -1076,11 +1064,9 @@ contract('VestingEscrowWallet', accounts => { }); -function checkScheduleLog(log, beneficiary, numberOfTokens, duration, frequency, startTime) { +function checkScheduleLog(log, beneficiary, templateName, startTime) { assert.equal(log.args._beneficiary, beneficiary); - assert.equal(log.args._numberOfTokens.toNumber(), numberOfTokens); - assert.equal(log.args._duration.toNumber(), duration); - assert.equal(log.args._frequency.toNumber(), frequency); + assert.equal(log.args._templateName, templateName); assert.equal(log.args._startTime.toNumber(), startTime); } @@ -1089,7 +1075,7 @@ function checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, assert.equal(schedule[1].toNumber(), duration); assert.equal(schedule[2].toNumber(), frequency); assert.equal(schedule[3].toNumber(), startTime); - assert.equal(schedule[4].toNumber(), state); + assert.equal(schedule[5].toNumber(), state); } function getTotalNumberOfTokens(schedules) { From 2e220011affc1c5857d572540194160507d17f20 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 30 Nov 2018 19:01:10 +0530 Subject: [PATCH 288/582] contract changes --- .../TransferManager/VolumeRestrictionTM.sol | 252 ++--- .../VolumeRestrictionTM_prev.sol | 932 ++++++++++++++++++ test/y_volume_restriction_tm.js | 529 +++++----- 3 files changed, 1279 insertions(+), 434 deletions(-) create mode 100644 contracts/modules/TransferManager/VolumeRestrictionTM_prev.sol diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 1ccb525be..e3282fd65 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -11,11 +11,13 @@ contract VolumeRestrictionTM is ITransferManager { // permission definition bytes32 public constant ADMIN = "ADMIN"; - enum RestrictionType { Fixed, Variable } + enum RestrictionType { Fixed, Percentage } struct VolumeRestriction { + // If typeOfRestriction is `Percentage` then allowedTokens will be in + // the % (w.r.t to totalSupply) with a multiplier of 10**16 . else it + // will be fixed amount of tokens uint256 allowedTokens; - uint256 allowedPercentageOfTokens; uint256 startTime; uint256 rollingPeriodInDays; uint256 endTime; @@ -23,8 +25,9 @@ contract VolumeRestrictionTM is ITransferManager { } struct BucketDetails { - uint256[] timestamps; + uint256 lastTradedDayTime; uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays + uint256 daysCovered; // No of days covered till (from the startTime of VolumeRestriction) } // Global restriction that applies to all token holders @@ -50,7 +53,6 @@ contract VolumeRestrictionTM is ITransferManager { event AddNewIndividualRestriction( address indexed _holder, uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -60,7 +62,6 @@ contract VolumeRestrictionTM is ITransferManager { event ModifyIndividualRestriction( address indexed _holder, uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -69,7 +70,6 @@ contract VolumeRestrictionTM is ITransferManager { // Emit when the new global restriction is added event AddGlobalRestriction( uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -78,7 +78,6 @@ contract VolumeRestrictionTM is ITransferManager { // Emit when the new daily (global) restriction is added event AddDailyGlobalRestriction( uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -87,7 +86,6 @@ contract VolumeRestrictionTM is ITransferManager { // Emit when global restriction get modified event ModifyGlobalRestriction( uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -96,7 +94,6 @@ contract VolumeRestrictionTM is ITransferManager { // Emit when daily global restriction get modified event ModifyDailyGlobalRestriction( uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -159,16 +156,14 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Use to add the new individual restriction for a given token holder * @param _holder Address of the token holder, whom restriction will be implied * @param _allowedTokens Amount of tokens allowed to be trade for a given address. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. * @param _startTime Unix timestamp at which restriction get into effect * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ function addIndividualRestriction( address _holder, uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -180,7 +175,6 @@ contract VolumeRestrictionTM is ITransferManager { _addIndividualRestriction( _holder, _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -192,16 +186,14 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Use to add the new individual restriction for multiple token holders * @param _holders Array of address of the token holders, whom restriction will be implied * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. - * @param _allowedPercentageOfTokens Array of percentage of tokens w.r.t to totalSupply allowed to transact. * @param _startTimes Array of unix timestamps at which restrictions get into effect * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) * @param _endTimes Array of unix timestamps at which restriction effects will gets end. - * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for variable) + * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ function addIndividualRestrictionMulti( address[] _holders, uint256[] _allowedTokens, - uint256[] _allowedPercentageOfTokens, uint256[] _startTimes, uint256[] _rollingPeriodInDays, uint256[] _endTimes, @@ -210,13 +202,12 @@ contract VolumeRestrictionTM is ITransferManager { public withPerm(ADMIN) { - _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + _checkLengthOfArray(_allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); require(_holders.length == _allowedTokens.length, "Length mismatch"); for (uint256 i = 0; i < _holders.length; i++) { _addIndividualRestriction( _holders[i], _allowedTokens[i], - _allowedPercentageOfTokens[i], _startTimes[i], _rollingPeriodInDays[i], _endTimes[i], @@ -228,15 +219,13 @@ contract VolumeRestrictionTM is ITransferManager { /** * @notice Use to add the new global restriction for all token holder * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. * @param _startTime Unix timestamp at which restriction get into effect * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ function addGlobalRestriction( uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -249,13 +238,12 @@ contract VolumeRestrictionTM is ITransferManager { globalRestriction.endTime < now, "Not allowed" ); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); if (globalRestriction.endTime != 0) { removeGlobalRestriction(); } globalRestriction = VolumeRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -263,7 +251,6 @@ contract VolumeRestrictionTM is ITransferManager { ); emit AddGlobalRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -274,14 +261,12 @@ contract VolumeRestrictionTM is ITransferManager { /** * @notice Use to add the new global daily restriction for all token holder * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ function addDailyGlobalRestriction( uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _endTime, uint256 _restrictionType @@ -293,10 +278,9 @@ contract VolumeRestrictionTM is ITransferManager { dailyGlobalRestriction.endTime < now, "Not Allowed" ); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); dailyGlobalRestriction = VolumeRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, 1, _endTime, @@ -304,7 +288,6 @@ contract VolumeRestrictionTM is ITransferManager { ); emit AddDailyGlobalRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, 1, _endTime, @@ -335,9 +318,10 @@ contract VolumeRestrictionTM is ITransferManager { */ function removeGlobalRestriction() public withPerm(ADMIN) { require(globalRestriction.endTime != 0); - globalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); - globalBucketDetails.timestamps.length = 0; + globalRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + globalBucketDetails.lastTradedDayTime = 0; globalBucketDetails.sumOfLastPeriod = 0; + globalBucketDetails.daysCovered = 0; emit GlobalRestrictionRemoved(); } @@ -346,7 +330,7 @@ contract VolumeRestrictionTM is ITransferManager { */ function removeDailyGlobalRestriction() external withPerm(ADMIN) { require(dailyGlobalRestriction.endTime != 0); - dailyGlobalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); + dailyGlobalRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); emit DailyGlobalRestrictionRemoved(); } @@ -354,16 +338,14 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Use to modify the existing individual restriction for a given token holder * @param _holder Address of the token holder, whom restriction will be implied * @param _allowedTokens Amount of tokens allowed to be trade for a given address. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. * @param _startTime Unix timestamp at which restriction get into effect * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ function modifyIndividualRestriction( address _holder, uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -375,7 +357,6 @@ contract VolumeRestrictionTM is ITransferManager { _modifyIndividualRestriction( _holder, _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -387,16 +368,14 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Use to modify the existing individual restriction for multiple token holders * @param _holders Array of address of the token holders, whom restriction will be implied * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. - * @param _allowedPercentageOfTokens Array of percentage of tokens w.r.t to totalSupply allowed to transact. * @param _startTimes Array of unix timestamps at which restrictions get into effect * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) * @param _endTimes Array of unix timestamps at which restriction effects will gets end. - * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for variable) + * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ function modifyIndividualRestrictionMulti( address[] _holders, uint256[] _allowedTokens, - uint256[] _allowedPercentageOfTokens, uint256[] _startTimes, uint256[] _rollingPeriodInDays, uint256[] _endTimes, @@ -405,13 +384,12 @@ contract VolumeRestrictionTM is ITransferManager { public withPerm(ADMIN) { - _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + _checkLengthOfArray(_allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); require(_holders.length == _allowedTokens.length, "Length mismatch"); for (uint256 i = 0; i < _holders.length; i++) { _modifyIndividualRestriction( _holders[i], _allowedTokens[i], - _allowedPercentageOfTokens[i], _startTimes[i], _rollingPeriodInDays[i], _endTimes[i], @@ -423,15 +401,13 @@ contract VolumeRestrictionTM is ITransferManager { /** * @notice Use to modify the global restriction for all token holder * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. * @param _startTime Unix timestamp at which restriction get into effect * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ function modifyGlobalRestriction( uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -441,10 +417,9 @@ contract VolumeRestrictionTM is ITransferManager { withPerm(ADMIN) { require(globalRestriction.startTime > now, "Not allowed"); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); globalRestriction = VolumeRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -452,7 +427,6 @@ contract VolumeRestrictionTM is ITransferManager { ); emit ModifyGlobalRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -463,14 +437,12 @@ contract VolumeRestrictionTM is ITransferManager { /** * @notice Use to modify the daily global restriction for all token holder * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ function modifyDailyGlobalRestriction( uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _endTime, uint256 _restrictionType @@ -479,10 +451,9 @@ contract VolumeRestrictionTM is ITransferManager { withPerm(ADMIN) { require(dailyGlobalRestriction.startTime > now, "Not allowed"); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); dailyGlobalRestriction = VolumeRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, 1, _endTime, @@ -490,7 +461,6 @@ contract VolumeRestrictionTM is ITransferManager { ); emit ModifyDailyGlobalRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, 1, _endTime, @@ -502,22 +472,21 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Internal function have a logic to validate the txn amount with global restriction */ function _globalRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { - uint256[] memory timestamps = globalBucketDetails.timestamps; uint256 fromTimestamp; uint256 sumOfLastPeriod = 0; - if (timestamps.length == 0) { + uint256 daysCovered = 0; + if (globalBucketDetails.lastTradedDayTime == 0) { // It will execute when the txn is performed first time after the addition of global restriction fromTimestamp = globalRestriction.startTime; } else { // picking up the preivous timestamp - fromTimestamp = timestamps[timestamps.length -1]; + fromTimestamp = globalBucketDetails.lastTradedDayTime; } // Calculating the difference of days uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); - uint256[] memory passedTimestamps = new uint256[](diffDays); // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod // re-using the local variables to avoid the stack too deep error. - (sumOfLastPeriod, fromTimestamp, passedTimestamps) = _bucketCheck( + (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( fromTimestamp, diffDays, _from, @@ -533,11 +502,10 @@ contract VolumeRestrictionTM is ITransferManager { if(_isTransfer) { // update the global storage _updateGlobalStorage( - passedTimestamps, fromTimestamp, _amount, - diffDays, - sumOfLastPeriod + sumOfLastPeriod, + daysCovered ); } return Result.NA; @@ -549,30 +517,23 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Internal function to update the state variables related to global restriction */ function _updateGlobalStorage( - uint256[] passedTimestamps, uint256 _fromTime, uint256 _amount, - uint256 _diffDays, - uint256 _sumOfLastPeriod + uint256 _sumOfLastPeriod, + uint256 _daysCovered ) internal { - if (_diffDays != 0) { - for (uint256 i = 0; i < passedTimestamps.length; i++) { - // Add the timestamp that is already passed - globalBucketDetails.timestamps.push(passedTimestamps[i]); - } + if (globalBucketDetails.lastTradedDayTime != _fromTime) { + // Assigning the latest transaction timestamp of the day + globalBucketDetails.lastTradedDayTime = _fromTime; + globalBucketDetails.daysCovered = _daysCovered; } - // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) - if (globalBucketDetails.timestamps.length == 0) { - globalBucketDetails.timestamps.push(_fromTime); - } - if(_amount != 0) { + if (_amount != 0) { // updating the sumOfLastPeriod globalBucketDetails.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); - // Re-using the local variable to avoid stack too deep error - _fromTime = globalBucketDetails.timestamps[globalBucketDetails.timestamps.length -1]; + // Increasing the total amount of the day by `_amount` globalBucket[_fromTime] = globalBucket[_fromTime].add(_amount); } } @@ -582,49 +543,49 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _fromTime, uint256 _diffDays, address _from, - BucketDetails _bucketDetails, + BucketDetails memory _bucketDetails, bool _isGlobal, VolumeRestriction _restriction ) internal view - returns (uint256, uint256, uint256[]) + returns (uint256, uint256, uint256) { - uint256[] memory passedTimestamps = new uint256[](_diffDays); - uint256 counter = _bucketDetails.timestamps.length; + uint256 counter = _bucketDetails.daysCovered; uint256 i = 0; - if (_diffDays != 0) { + if (_diffDays >= _restriction.rollingPeriodInDays) { + // If the difference of days is greater than the rollingPeriod then sumOfLastPeriod will always be zero + _bucketDetails.sumOfLastPeriod = 0; + + } else { for (i = 0; i < _diffDays; i++) { - // calculating the timestamp that will used as an index of the next bucket - // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... - // where T1,T2,T3 are timestamps having 24 hrs difference - _fromTime = _fromTime.add(1 days); - - // This condition is to check whether the first rolling period is covered or not - // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting - // the earlier value at that index - if (counter >= _restriction.rollingPeriodInDays) { - if (_isGlobal) { - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. - sub(globalBucket[_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); - } else { - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. - sub(bucket[_from][_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); - } - + // This condition is to check whether the first rolling period is covered or not + // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting + // the earlier value at that index + if (counter >= _restriction.rollingPeriodInDays) { + if (_isGlobal) { + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. + sub(globalBucket[_bucketDetails.lastTradedDayTime.sub((counter.sub(_restriction.rollingPeriodInDays)).mul(1 days))]); + } else { + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. + sub(bucket[_from][_bucketDetails.lastTradedDayTime.sub((counter.sub(_restriction.rollingPeriodInDays)).mul(1 days))]); } + } - // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand - // the alogrithm - //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); - // Storing all those timestamps whose total transacted value is 0 - passedTimestamps[i] = _fromTime; - counter++; + // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand + // the alogrithm + //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); + // Storing all those timestamps whose total transacted value is 0 + counter++; } } - return (_bucketDetails.sumOfLastPeriod, _fromTime, passedTimestamps); + // calculating the timestamp that will used as an index of the next bucket + // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... + // where T1,T2,T3 are timestamps having 24 hrs difference + _fromTime = _fromTime.add(_diffDays.mul(1 days)); + return (_bucketDetails.sumOfLastPeriod, _fromTime, counter.add(_diffDays)); } /** @@ -639,21 +600,22 @@ contract VolumeRestrictionTM is ITransferManager { internal returns(Result) { + uint256 daysCovered; uint256 fromTimestamp; uint256 sumOfLastPeriod = 0; - if (bucketToUser[_from].timestamps.length == 0) { + if (bucketToUser[_from].lastTradedDayTime == 0) { // It will execute when the txn is performed first time after the addition of individual restriction fromTimestamp = individualRestriction[_from].startTime; } else { // Picking up the last timestamp - fromTimestamp = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; + fromTimestamp = bucketToUser[_from].lastTradedDayTime; } // Calculating the difference of days uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); - uint256[] memory passedTimestamps = new uint256[](diffDays); + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod // re-using the local variables to avoid the stack too deep error. - (sumOfLastPeriod, fromTimestamp, passedTimestamps) = _bucketCheck( + (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( fromTimestamp, diffDays, _from, @@ -664,12 +626,11 @@ contract VolumeRestrictionTM is ITransferManager { if (_checkValidAmountToTransact(sumOfLastPeriod, _amount, individualRestriction[_from])) { if (_isTransfer) { _updateIndividualStorage( - passedTimestamps, _from, fromTimestamp, _amount, - diffDays, - sumOfLastPeriod + sumOfLastPeriod, + daysCovered ); } return Result.NA; @@ -707,8 +668,8 @@ contract VolumeRestrictionTM is ITransferManager { returns (bool) { uint256 _allowedAmount = 0; - if (_restriction.typeOfRestriction == RestrictionType.Variable) { - _allowedAmount = (_restriction.allowedPercentageOfTokens.mul(ISecurityToken(securityToken).totalSupply()))/ 10 ** 18; + if (_restriction.typeOfRestriction == RestrictionType.Percentage) { + _allowedAmount = (_restriction.allowedTokens.mul(ISecurityToken(securityToken).totalSupply())) / uint256(10) ** 18; } else { _allowedAmount = _restriction.allowedTokens; } @@ -721,30 +682,23 @@ contract VolumeRestrictionTM is ITransferManager { } function _updateIndividualStorage( - uint256[] passedTimestamps, address _from, uint256 _fromTime, uint256 _amount, - uint256 _diffDays, - uint256 _sumOfLastPeriod + uint256 _sumOfLastPeriod, + uint256 _daysCovered ) internal { - if (_diffDays != 0) { - for (uint256 i = 0; i < passedTimestamps.length; i++) { - // Add the timestamp that is already passed - bucketToUser[_from].timestamps.push(passedTimestamps[i]); - } - } - // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) - if (bucketToUser[_from].timestamps.length == 0) { - bucketToUser[_from].timestamps.push(_fromTime); + if (bucketToUser[_from].lastTradedDayTime != _fromTime) { + // Assigning the latest transaction timestamp of the day + bucketToUser[_from].lastTradedDayTime = _fromTime; + bucketToUser[_from].daysCovered = _daysCovered; } if(_amount != 0) { bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); - // Re-using the local variable to avoid stack too deep error - _fromTime = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; + // Increasing the total amount of the day by `_amount` bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); } @@ -753,16 +707,16 @@ contract VolumeRestrictionTM is ITransferManager { function _removeIndividualRestriction(address _user) internal { require(_user != address(0), "Invalid address"); require(individualRestriction[_user].endTime != 0, "Not present"); - individualRestriction[_user] = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); - bucketToUser[_user].timestamps.length = 0; + individualRestriction[_user] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + bucketToUser[_user].lastTradedDayTime = 0; bucketToUser[_user].sumOfLastPeriod = 0; + bucketToUser[_user].daysCovered = 0; emit IndividualRestrictionRemoved(_user); } function _modifyIndividualRestriction( address _holder, uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -770,12 +724,11 @@ contract VolumeRestrictionTM is ITransferManager { ) internal { - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); require(individualRestriction[_holder].startTime > now, "Not allowed"); individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -784,7 +737,6 @@ contract VolumeRestrictionTM is ITransferManager { emit ModifyIndividualRestriction( _holder, _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -795,7 +747,6 @@ contract VolumeRestrictionTM is ITransferManager { function _addIndividualRestriction( address _holder, uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, @@ -808,14 +759,13 @@ contract VolumeRestrictionTM is ITransferManager { "Already present" ); require(_holder != address(0) && !exemptList[_holder], "Invalid address"); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); if (individualRestriction[_holder].endTime != 0) { _removeIndividualRestriction(_holder); } individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -824,7 +774,6 @@ contract VolumeRestrictionTM is ITransferManager { emit AddNewIndividualRestriction( _holder, _allowedTokens, - _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, @@ -834,7 +783,6 @@ contract VolumeRestrictionTM is ITransferManager { function _checkInputParams( uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, uint256 _startTime, uint256 _rollingPeriodDays, uint256 _endTime, @@ -848,7 +796,7 @@ contract VolumeRestrictionTM is ITransferManager { require(_allowedTokens > 0, "Invalid value"); } else { require( - _allowedPercentageOfTokens > 0 && _allowedPercentageOfTokens <= 100 * 10 ** 16, + _allowedTokens > 0 && _allowedTokens <= 100 * 10 ** 16, "Percentage is not within (0,100]" ); } @@ -860,7 +808,6 @@ contract VolumeRestrictionTM is ITransferManager { function _checkLengthOfArray( uint256[] _allowedTokens, - uint256[] _allowedPercentageOfTokens, uint256[] _startTimes, uint256[] _rollingPeriodInDays, uint256[] _endTimes, @@ -870,8 +817,7 @@ contract VolumeRestrictionTM is ITransferManager { pure { require( - _allowedTokens.length == _allowedPercentageOfTokens.length && - _allowedPercentageOfTokens.length == _startTimes.length && + _allowedTokens.length == _startTimes.length && _startTimes.length == _rollingPeriodInDays.length && _rollingPeriodInDays.length == _endTimes.length && _endTimes.length == _restrictionTypes.length, @@ -882,12 +828,12 @@ contract VolumeRestrictionTM is ITransferManager { /** * @notice Use to get the bucket details for a given address * @param _user Address of the token holder for whom the bucket details has queried - * @return uint256 Array of the timestamps + * @return uint256 lastTradedDayTime * @return uint256 sumOfLastPeriod */ - function getBucketDetailsToUser(address _user) external view returns(uint256[], uint256) { + function getBucketDetailsToUser(address _user) external view returns(uint256, uint256) { return( - bucketToUser[_user].timestamps, + bucketToUser[_user].lastTradedDayTime, bucketToUser[_user].sumOfLastPeriod ); } @@ -903,15 +849,15 @@ contract VolumeRestrictionTM is ITransferManager { /** * @notice Use to get the global bucket details - * @return uint256 Array of timestamps + * @return uint256 lastTradedDayTime * @return uint256 sumOfLastPeriod * @return uint256 Total amount traded on the latest timestamp */ - function getGlobalBucketDetails() external view returns(uint256[], uint256, uint256) { + function getGlobalBucketDetails() external view returns(uint256, uint256, uint256) { return( - globalBucketDetails.timestamps, + globalBucketDetails.lastTradedDayTime, globalBucketDetails.sumOfLastPeriod, - globalBucket[globalBucketDetails.timestamps[globalBucketDetails.timestamps.length - 1]] + globalBucket[globalBucketDetails.lastTradedDayTime] ); } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM_prev.sol b/contracts/modules/TransferManager/VolumeRestrictionTM_prev.sol new file mode 100644 index 000000000..5a42ede3f --- /dev/null +++ b/contracts/modules/TransferManager/VolumeRestrictionTM_prev.sol @@ -0,0 +1,932 @@ +pragma solidity ^0.4.24; + +import "./ITransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../../libraries/BokkyPooBahsDateTimeLibrary.sol"; + +contract VolumeRestrictionTM_prev is ITransferManager { + + using SafeMath for uint256; + + // permission definition + bytes32 public constant ADMIN = "ADMIN"; + + enum RestrictionType { Fixed, Variable } + + struct VolumeRestriction { + uint256 allowedTokens; + uint256 allowedPercentageOfTokens; + uint256 startTime; + uint256 rollingPeriodInDays; + uint256 endTime; + RestrictionType typeOfRestriction; + } + + struct BucketDetails { + uint256[] timestamps; + uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays + } + + // Global restriction that applies to all token holders + VolumeRestriction public globalRestriction; + // Daily global restriction that applies to all token holders (Total ST traded daily is restricted) + VolumeRestriction public dailyGlobalRestriction; + // Variable stores the data matrix for the globa restrictions + BucketDetails internal globalBucketDetails; + // Restriction stored corresponds to a particular token holder + mapping(address => VolumeRestriction) public individualRestriction; + // Storing _from => day's timestamp => total amount transact in a day --individual + mapping(address => mapping(uint256 => uint256)) internal bucket; + // Storing the information that used to validate the transaction + mapping(address => BucketDetails) internal bucketToUser; + // List of wallets that are exempted from all the restrictions applied by the this contract + mapping(address => bool) public exemptList; + // Store the amount of tokens get transacted in a day + mapping(uint256 => uint256) public globalBucket; + + // Emit when the token holder is added/removed from the exemption list + event ChangedExemptWalletList(address indexed _wallet, bool _change); + // Emit when the new individual restriction is added corresponds to new token holders + event AddNewIndividualRestriction( + address indexed _holder, + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when the individual restriction is modified for a given address + event ModifyIndividualRestriction( + address indexed _holder, + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when the new global restriction is added + event AddGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when the new daily (global) restriction is added + event AddDailyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when global restriction get modified + event ModifyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when daily global restriction get modified + event ModifyDailyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when the individual restriction gets removed + event IndividualRestrictionRemoved(address _user); + // Emit when the global restriction gets removed + event GlobalRestrictionRemoved(); + // Emit when the daily global restriction gets removed + event DailyGlobalRestrictionRemoved(); + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { + + } + + /** + * @notice Used to verify the transfer/transferFrom transaction and prevent tranaction + * whose volume of tokens will voilate the maximum volume transfer restriction + * @param _from Address of the sender + * @param _amount The amount of tokens to transfer + * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable + */ + function verifyTransfer(address _from, address /*_to */, uint256 _amount, bytes /*_data*/, bool _isTransfer) public returns (Result) { + // If `_from` is present in the exemptionList or it is `0x0` address then it will not follow the vol restriction + if (!paused && _from != address(0) && !exemptList[_from]) { + // Function must only be called by the associated security token if _isTransfer == true + require(msg.sender == securityToken || !_isTransfer); + // Checking the individual restriction if the `_from` comes in the individual category + if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { + return _individualRestrictionCheck(_from, _amount, _isTransfer); + // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically + } else if (globalRestriction.endTime >= now && globalRestriction.startTime <= now) { + return _globalRestrictionCheck(_from, _amount, _isTransfer); + } + } + return Result.NA; + } + + /** + * @notice Add/Remove wallet address from the exempt list + * @param _wallet Ethereum wallet/contract address that need to be exempted + * @param _change Boolean value used to add (i.e true) or remove (i.e false) from the list + */ + function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { + require(_wallet != address(0), "Invalid address"); + exemptList[_wallet] = _change; + emit ChangedExemptWalletList(_wallet, _change); + } + + /** + * @notice Use to add the new individual restriction for a given token holder + * @param _holder Address of the token holder, whom restriction will be implied + * @param _allowedTokens Amount of tokens allowed to be trade for a given address. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function addIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + _addIndividualRestriction( + _holder, + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + /** + * @notice Use to add the new individual restriction for multiple token holders + * @param _holders Array of address of the token holders, whom restriction will be implied + * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. + * @param _allowedPercentageOfTokens Array of percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTimes Array of unix timestamps at which restrictions get into effect + * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) + * @param _endTimes Array of unix timestamps at which restriction effects will gets end. + * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function addIndividualRestrictionMulti( + address[] _holders, + uint256[] _allowedTokens, + uint256[] _allowedPercentageOfTokens, + uint256[] _startTimes, + uint256[] _rollingPeriodInDays, + uint256[] _endTimes, + uint256[] _restrictionTypes + ) + public + withPerm(ADMIN) + { + _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + require(_holders.length == _allowedTokens.length, "Length mismatch"); + for (uint256 i = 0; i < _holders.length; i++) { + _addIndividualRestriction( + _holders[i], + _allowedTokens[i], + _allowedPercentageOfTokens[i], + _startTimes[i], + _rollingPeriodInDays[i], + _endTimes[i], + _restrictionTypes[i] + ); + } + } + + /** + * @notice Use to add the new global restriction for all token holder + * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function addGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + require( + globalRestriction.endTime < now, + "Not allowed" + ); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + if (globalRestriction.endTime != 0) { + removeGlobalRestriction(); + } + globalRestriction = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddGlobalRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + /** + * @notice Use to add the new global daily restriction for all token holder + * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function addDailyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + require( + dailyGlobalRestriction.endTime < now, + "Not Allowed" + ); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); + dailyGlobalRestriction = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddDailyGlobalRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + 1, + _endTime, + _restrictionType + ); + } + + /** + * @notice use to remove the individual restriction for a given address + * @param _user Address of the user + */ + function removeIndividualRestriction(address _user) external withPerm(ADMIN) { + _removeIndividualRestriction(_user); + } + + /** + * @notice use to remove the individual restriction for a given address + * @param _users Array of address of the user + */ + function removeIndividualRestrictionMulti(address[] _users) external withPerm(ADMIN) { + for (uint256 i = 0; i < _users.length; i++) { + _removeIndividualRestriction(_users[i]); + } + } + + /** + * @notice Use to remove the global restriction + */ + function removeGlobalRestriction() public withPerm(ADMIN) { + require(globalRestriction.endTime != 0); + globalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); + globalBucketDetails.timestamps.length = 0; + globalBucketDetails.sumOfLastPeriod = 0; + emit GlobalRestrictionRemoved(); + } + + /** + * @notice Use to remove the daily global restriction + */ + function removeDailyGlobalRestriction() external withPerm(ADMIN) { + require(dailyGlobalRestriction.endTime != 0); + dailyGlobalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); + emit DailyGlobalRestrictionRemoved(); + } + + /** + * @notice Use to modify the existing individual restriction for a given token holder + * @param _holder Address of the token holder, whom restriction will be implied + * @param _allowedTokens Amount of tokens allowed to be trade for a given address. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function modifyIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + _modifyIndividualRestriction( + _holder, + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + /** + * @notice Use to modify the existing individual restriction for multiple token holders + * @param _holders Array of address of the token holders, whom restriction will be implied + * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. + * @param _allowedPercentageOfTokens Array of percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTimes Array of unix timestamps at which restrictions get into effect + * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) + * @param _endTimes Array of unix timestamps at which restriction effects will gets end. + * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function modifyIndividualRestrictionMulti( + address[] _holders, + uint256[] _allowedTokens, + uint256[] _allowedPercentageOfTokens, + uint256[] _startTimes, + uint256[] _rollingPeriodInDays, + uint256[] _endTimes, + uint256[] _restrictionTypes + ) + public + withPerm(ADMIN) + { + _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + require(_holders.length == _allowedTokens.length, "Length mismatch"); + for (uint256 i = 0; i < _holders.length; i++) { + _modifyIndividualRestriction( + _holders[i], + _allowedTokens[i], + _allowedPercentageOfTokens[i], + _startTimes[i], + _rollingPeriodInDays[i], + _endTimes[i], + _restrictionTypes[i] + ); + } + } + + /** + * @notice Use to modify the global restriction for all token holder + * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function modifyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + require(globalRestriction.startTime > now, "Not allowed"); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + globalRestriction = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyGlobalRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + /** + * @notice Use to modify the daily global restriction for all token holder + * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. + * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) + */ + function modifyDailyGlobalRestriction( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + require(dailyGlobalRestriction.startTime > now, "Not allowed"); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); + dailyGlobalRestriction = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyDailyGlobalRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + 1, + _endTime, + _restrictionType + ); + } + + /** + * @notice Internal function have a logic to validate the txn amount with global restriction + */ + function _globalRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + uint256[] memory timestamps = globalBucketDetails.timestamps; + uint256 fromTimestamp; + uint256 sumOfLastPeriod = 0; + if (timestamps.length == 0) { + // It will execute when the txn is performed first time after the addition of global restriction + fromTimestamp = globalRestriction.startTime; + } else { + // picking up the preivous timestamp + fromTimestamp = timestamps[timestamps.length -1]; + } + // Calculating the difference of days + uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); + uint256[] memory passedTimestamps = new uint256[](diffDays); + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod + // re-using the local variables to avoid the stack too deep error. + (sumOfLastPeriod, fromTimestamp, passedTimestamps) = _bucketCheck( + fromTimestamp, + diffDays, + _from, + globalBucketDetails, + true, + globalRestriction + ); + // Total amout that is transacted uptill now for `fromTimestamp` day + uint256 txSumOfDay = globalBucket[fromTimestamp]; + // Global transaction check + if (_globalTxCheck(sumOfLastPeriod, txSumOfDay, _amount)) { + // allow modification in storage when `_isTransfer` equals true + if(_isTransfer) { + // update the global storage + _updateGlobalStorage( + passedTimestamps, + fromTimestamp, + _amount, + diffDays, + sumOfLastPeriod + ); + } + return Result.NA; + } + return Result.INVALID; + } + + /** + * @notice Internal function to update the state variables related to global restriction + */ + function _updateGlobalStorage( + uint256[] passedTimestamps, + uint256 _fromTime, + uint256 _amount, + uint256 _diffDays, + uint256 _sumOfLastPeriod + ) + internal + { + for (uint256 i = 0; i < passedTimestamps.length; i++) { + // Add the timestamp that is already passed + globalBucketDetails.timestamps.push(passedTimestamps[i]); + } + // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) + if (globalBucketDetails.timestamps.length == 0) { + globalBucketDetails.timestamps.push(_fromTime); + } + if(_amount != 0) { + // updating the sumOfLastPeriod + globalBucketDetails.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + + // Re-using the local variable to avoid stack too deep error + _fromTime = globalBucketDetails.timestamps[globalBucketDetails.timestamps.length -1]; + globalBucket[_fromTime] = globalBucket[_fromTime].add(_amount); + } + } + + /// Internal function for the bucket check + function _bucketCheck( + uint256 _fromTime, + uint256 _diffDays, + address _from, + BucketDetails memory _bucketDetails, + bool _isGlobal, + VolumeRestriction _restriction + ) + internal + view + returns (uint256, uint256, uint256[]) + { + uint256[] memory passedTimestamps = new uint256[](_diffDays); + uint256 counter = _bucketDetails.timestamps.length; + uint256 i = 0; + if (_diffDays != 0) { + for (i = 0; i < _diffDays; i++) { + // calculating the timestamp that will used as an index of the next bucket + // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... + // where T1,T2,T3 are timestamps having 24 hrs difference + _fromTime = _fromTime.add(1 days); + + // This condition is to check whether the first rolling period is covered or not + // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting + // the earlier value at that index + if (counter >= _restriction.rollingPeriodInDays) { + if (_isGlobal) { + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. + sub(globalBucket[_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); + } else { + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. + sub(bucket[_from][_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); + } + + } + + // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand + // the alogrithm + //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); + // Storing all those timestamps whose total transacted value is 0 + passedTimestamps[i] = _fromTime; + counter++; + } + } + return (_bucketDetails.sumOfLastPeriod, _fromTime, passedTimestamps); + } + + /** + * @notice Internal function used to validate the transaction for a given address + * If it validates then it also update the storage corressponds to the individual restriction + */ + function _individualRestrictionCheck( + address _from, + uint256 _amount, + bool _isTransfer + ) + internal + returns(Result) + { + uint256 fromTimestamp; + uint256 sumOfLastPeriod = 0; + if (bucketToUser[_from].timestamps.length == 0) { + // It will execute when the txn is performed first time after the addition of individual restriction + fromTimestamp = individualRestriction[_from].startTime; + } else { + // Picking up the last timestamp + fromTimestamp = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; + } + // Calculating the difference of days + uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); + uint256[] memory passedTimestamps = new uint256[](diffDays); + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod + // re-using the local variables to avoid the stack too deep error. + (sumOfLastPeriod, fromTimestamp, passedTimestamps) = _bucketCheck( + fromTimestamp, + diffDays, + _from, + bucketToUser[_from], + false, + individualRestriction[_from] + ); + if (_checkValidAmountToTransact(sumOfLastPeriod, _amount, individualRestriction[_from])) { + if (_isTransfer) { + _updateIndividualStorage( + passedTimestamps, + _from, + fromTimestamp, + _amount, + diffDays, + sumOfLastPeriod + ); + } + return Result.NA; + } + return Result.INVALID; + } + + + function _globalTxCheck( + uint256 _sumOfLastPeriod, + uint256 _dailyAmount, + uint256 _amount + ) + internal + view + returns(bool) + { + // Checking whether the global day restriction is added or not if yes then calculate + // the total amount get traded on a particular day (~ _fromTime) + if (!_checkValidAmountToTransact(_dailyAmount, _amount, dailyGlobalRestriction) && + now <= dailyGlobalRestriction.endTime && now >= dailyGlobalRestriction.startTime + ) { + return false; + } + return _checkValidAmountToTransact(_sumOfLastPeriod, _amount, globalRestriction); + } + + function _checkValidAmountToTransact( + uint256 _sumOfLastPeriod, + uint256 _amountToTransact, + VolumeRestriction _restriction + ) + internal + view + returns (bool) + { + uint256 _allowedAmount = 0; + if (_restriction.typeOfRestriction == RestrictionType.Variable) { + _allowedAmount = (_restriction.allowedPercentageOfTokens.mul(ISecurityToken(securityToken).totalSupply()))/ uint256(10) ** 18; + } else { + _allowedAmount = _restriction.allowedTokens; + } + // Validation on the amount to transact + if (_allowedAmount >= _sumOfLastPeriod.add(_amountToTransact)) { + return true; + } else { + return false; + } + } + + function _updateIndividualStorage( + uint256[] passedTimestamps, + address _from, + uint256 _fromTime, + uint256 _amount, + uint256 _diffDays, + uint256 _sumOfLastPeriod + ) + internal + { + if (_diffDays != 0) { + for (uint256 i = 0; i < passedTimestamps.length; i++) { + // Add the timestamp that is already passed + bucketToUser[_from].timestamps.push(passedTimestamps[i]); + } + } + // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) + if (bucketToUser[_from].timestamps.length == 0) { + bucketToUser[_from].timestamps.push(_fromTime); + } + if(_amount != 0) { + bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + + // Re-using the local variable to avoid stack too deep error + _fromTime = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; + bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); + } + + } + + function _removeIndividualRestriction(address _user) internal { + require(_user != address(0), "Invalid address"); + require(individualRestriction[_user].endTime != 0, "Not present"); + individualRestriction[_user] = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); + bucketToUser[_user].timestamps.length = 0; + bucketToUser[_user].sumOfLastPeriod = 0; + emit IndividualRestrictionRemoved(_user); + } + + function _modifyIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + internal + { + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + require(individualRestriction[_holder].startTime > now, "Not allowed"); + + individualRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyIndividualRestriction( + _holder, + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + function _addIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + internal + { + require( + individualRestriction[_holder].endTime < now, + "Already present" + ); + require(_holder != address(0) && !exemptList[_holder], "Invalid address"); + _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + + if (individualRestriction[_holder].endTime != 0) { + _removeIndividualRestriction(_holder); + } + individualRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddNewIndividualRestriction( + _holder, + _allowedTokens, + _allowedPercentageOfTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + function _checkInputParams( + uint256 _allowedTokens, + uint256 _allowedPercentageOfTokens, + uint256 _startTime, + uint256 _rollingPeriodDays, + uint256 _endTime, + uint256 _restrictionType + ) + internal + view + { + require(_restrictionType == 0 || _restrictionType == 1, "Invalid type"); + if (_restrictionType == uint256(RestrictionType.Fixed)) { + require(_allowedTokens > 0, "Invalid value"); + } else { + require( + _allowedPercentageOfTokens > 0 && _allowedPercentageOfTokens <= 100 * 10 ** 16, + "Percentage is not within (0,100]" + ); + } + require(_startTime >= now && _endTime > _startTime); + // Maximum limit for the rollingPeriod is 365 days + require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365); + require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays); + } + + function _checkLengthOfArray( + uint256[] _allowedTokens, + uint256[] _allowedPercentageOfTokens, + uint256[] _startTimes, + uint256[] _rollingPeriodInDays, + uint256[] _endTimes, + uint256[] _restrictionTypes + ) + internal + pure + { + require( + _allowedTokens.length == _allowedPercentageOfTokens.length && + _allowedPercentageOfTokens.length == _startTimes.length && + _startTimes.length == _rollingPeriodInDays.length && + _rollingPeriodInDays.length == _endTimes.length && + _endTimes.length == _restrictionTypes.length, + "Array length mismatch" + ); + } + + /** + * @notice Use to get the bucket details for a given address + * @param _user Address of the token holder for whom the bucket details has queried + * @return uint256 Array of the timestamps + * @return uint256 sumOfLastPeriod + */ + function getBucketDetailsToUser(address _user) external view returns(uint256[], uint256) { + return( + bucketToUser[_user].timestamps, + bucketToUser[_user].sumOfLastPeriod + ); + } + + /** + * @notice Use to get the volume of token that being traded at a particular day (`_at` + 24 hours) for a given user + * @param _user Address of the token holder + * @param _at Timestamp + */ + function getTotalTradeByuser(address _user, uint256 _at) external view returns(uint256) { + return bucket[_user][_at]; + } + + /** + * @notice Use to get the global bucket details + * @return uint256 Array of timestamps + * @return uint256 sumOfLastPeriod + * @return uint256 Total amount traded on the latest timestamp + */ + function getGlobalBucketDetails() external view returns(uint256[], uint256, uint256) { + return( + globalBucketDetails.timestamps, + globalBucketDetails.sumOfLastPeriod, + globalBucket[globalBucketDetails.timestamps[globalBucketDetails.timestamps.length - 1]] + ); + } + + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public view returns(bytes4) { + return bytes4(0); + } + + /** + * @notice Returns the permissions flag that are associated with Percentage transfer Manager + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; + } + +} diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 48645f5f4..9c33cb1c7 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -214,7 +214,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("12"), - 0, latestTime() + duration.seconds(2), 3, latestTime() + duration.days(10), @@ -231,7 +230,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("12"), - 0, latestTime() + duration.seconds(2), 3, latestTime() + duration.days(10), @@ -248,7 +246,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, 0, - 0, latestTime() + duration.seconds(2), 3, latestTime() + duration.days(10), @@ -265,7 +262,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, 0, - 0, latestTime() + duration.seconds(2), 3, latestTime() + duration.days(10), @@ -281,7 +277,6 @@ contract('VolumeRestrictionTransferManager', accounts => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, - 0, web3.utils.toWei("10"), latestTime() + duration.seconds(2), 3, @@ -299,7 +294,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("10"), - 0, latestTime() - duration.seconds(5), 3, latestTime() + duration.days(10), @@ -316,7 +310,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("10"), - 0, latestTime() + duration.days(2), 3, latestTime() + duration.days(1), @@ -333,7 +326,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("10"), - 0, latestTime() + duration.days(2), 0, latestTime() + duration.days(10), @@ -350,7 +342,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("10"), - 0, latestTime() + duration.days(2), 366, latestTime() + duration.days(10), @@ -367,7 +358,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("10"), - 0, latestTime() + duration.days(2), 3, latestTime() + duration.days(3), @@ -383,7 +373,6 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("12"), - 0, latestTime() + duration.seconds(2), 3, latestTime() + duration.days(5), @@ -402,7 +391,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [0,0,0], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3,4,5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], @@ -419,7 +407,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [0,0,0], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3,4,5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], @@ -436,7 +423,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10")], - [0,0,0], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3,4,5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], @@ -453,24 +439,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [0,0], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], - [3,4,5], - [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], - [0,0,0], - { - from: token_owner - } - ) - ) - }); - - it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { - await catchRevert( - I_VolumeRestrictionTM.addIndividualRestrictionMulti( - [account_investor2, account_delegate3, account_investor4], - [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [0,0,0], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3,4,5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], @@ -487,7 +455,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [0,0,0], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], @@ -504,7 +471,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [0,0,0], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3, 4, 5], [latestTime() + duration.days(5)], @@ -521,7 +487,6 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [0,0,0], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], @@ -537,7 +502,6 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [0,0,0], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], @@ -546,9 +510,9 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ); - assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 3); - assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3))[3].toNumber(), 4); - assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor4))[3].toNumber(), 5); + assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(), 3); + assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3))[2].toNumber(), 4); + assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor4))[2].toNumber(), 5); }); it("Should remove the restriction multi -- failed because of address is 0", async() => { @@ -588,7 +552,6 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("12"), - 0, latestTime() + duration.seconds(2), 3, latestTime() + duration.days(10), @@ -609,7 +572,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should succesfully transact the tokens just after the starttime", async() => { + it("Should succesfully transact the tokens just after the startTime", async() => { // Check the transfer will be valid or not by calling the verifyTransfer() directly by using _isTransfer = false let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor1, account_investor3, web3.utils.toWei('.3'), "0x0", false); console.log(result); @@ -623,256 +586,260 @@ contract('VolumeRestrictionTransferManager', accounts => { let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); console.log('\n'); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), 0.3); - assert.equal(data[0][i].toNumber(), (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber()) - } console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length -1} + Timestamps array index: ${data[0].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) + .dividedBy(new BigNumber(10).pow(18))} `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 0.3); - assert.equal(data[0].length -1, 0); - tempArray.push(0.3); - }) - - it("Should successfully transact the tokens after 1 and half days", async() => { - await increaseTime(duration.days(1.5)); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor1}); - // Check the balance of the investors - let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); - // Verifying the balances - assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 33.7); - tempArray.push(1); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + assert.equal( + (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), + 0.3 + ); + assert.equal( + data[0].toNumber(), + (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber() + ); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber()} - `); - assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i]); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - } console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length -1} + Days Covered : ${data[0].length -1} `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1.3); - assert.equal(data[0].length -1, 1); - }); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 0.3); + tempArray.push(0.3); + }) - it("Should successfully transact more tokens on the same day (Fuzz test)", async() => { - // Check the balance of the investors - let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - let totalAmountTransacted = 0; - for (let i = 0; i < 10; i++) { - let amount = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); - console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); - totalAmountTransacted += amount; - } + // it("Should successfully transact the tokens after 1 and half days", async() => { + // await increaseTime(duration.days(1.5)); + // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor1}); + // // Check the balance of the investors + // let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); + // // Verifying the balances + // assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 33.7); + // tempArray.push(1); + // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + + // for (let i = 0; i < data[0].length; i++) { + // console.log(` + // Timestamps array index ${i}: ${data[0][i].toNumber()} + // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18)).toNumber()} + // `); + // assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i]); + // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); + // } + // console.log(` + // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + // Last Timestamp Index : ${data[0].length -1} + // `); + // assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1.3); + // assert.equal(data[0].length -1, 1); + // }); + + // it("Should successfully transact more tokens on the same day (Fuzz test)", async() => { + // // Check the balance of the investors + // let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + // let totalAmountTransacted = 0; + // for (let i = 0; i < 10; i++) { + // let amount = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; + // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); + // console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); + // totalAmountTransacted += amount; + // } - // Check the balance of the investors - let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); - // Verifying the balances - assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - tempArray[1] = tempArray[1] + totalAmountTransacted; - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - `); - assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 1.3 + totalAmountTransacted, 0.000001); - assert.equal(data[0].length -1, 1); - }); - - it("Should successfully transfer the tokens after half days-- should increase the day covered by 1", async() => { - let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - await increaseTime(duration.days(.5)); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - tempArray.push(2); - - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); - } + // // Check the balance of the investors + // let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); + // // Verifying the balances + // assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); + // tempArray[1] = tempArray[1] + totalAmountTransacted; + // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + + // for (let i = 0; i < data[0].length; i++) { + // console.log(` + // Timestamps array index ${i}: ${data[0][i].toNumber()} + // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18))} + // `); + // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); + // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + // } + // console.log(` + // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + // Last Timestamp Index : ${data[0].length - 1} + // `); + // assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 1.3 + totalAmountTransacted, 0.000001); + // assert.equal(data[0].length -1, 1); + // }); + + // it("Should successfully transfer the tokens after half days-- should increase the day covered by 1", async() => { + // let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + // await increaseTime(duration.days(.5)); + // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); + // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + // tempArray.push(2); + + // for (let i = 0; i < data[0].length; i++) { + // console.log(` + // Timestamps array index ${i}: ${data[0][i].toNumber()} + // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18))} + // `); + // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); + // } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - `); - assert.equal(data[0].length - 1, 2); - assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), - (oldData[1].plus(new BigNumber(2).times(new BigNumber(10).pow(18)))) - .dividedBy(new BigNumber(10).pow(18)).toNumber()); - }); - - it("Should successfully transfer the tokens in the last day of rolling period", async() => { - // Check the balance of the investors - let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - - let totalAmountTransacted = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(totalAmountTransacted.toString()), {from: account_investor1}); + // console.log(` + // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + // Last Timestamp Index : ${data[0].length - 1} + // `); + // assert.equal(data[0].length - 1, 2); + // assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), + // (oldData[1].plus(new BigNumber(2).times(new BigNumber(10).pow(18)))) + // .dividedBy(new BigNumber(10).pow(18)).toNumber()); + // }); + + // it("Should successfully transfer the tokens in the last day of rolling period", async() => { + // // Check the balance of the investors + // let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + // let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + + // let totalAmountTransacted = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; + // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(totalAmountTransacted.toString()), {from: account_investor1}); - // Check the balance of the investors - let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); - // Verifying the balances - assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - tempArray[2] = tempArray[2] + totalAmountTransacted; - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); - } + // // Check the balance of the investors + // let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); + // // Verifying the balances + // assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); + // tempArray[2] = tempArray[2] + totalAmountTransacted; + // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + // for (let i = 0; i < data[0].length; i++) { + // console.log(` + // Timestamps array index ${i}: ${data[0][i].toNumber()} + // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18))} + // `); + // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); + // } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - `); - assert.equal(data[0].length - 1, 2); - assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), - oldData[1].dividedBy(new BigNumber(10).pow(18)).toNumber() + totalAmountTransacted, 0.001); - }); - - it("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - let minimumAmount = new BigNumber(12).times(new BigNumber(10).pow(18)).minus(data[1]); - let testAmount = minimumAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))) - await catchRevert( - I_SecurityToken.transfer(account_investor3, testAmount, {from: account_investor1}) - ); - }); - - it("Should fail to buy tokens in the new rolling period --failed because amount is more than last two timestamps", async() => { - await increaseTime(duration.days(2)); - await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_investor1}) - ); - }); - - it("Should transfer the tokens in a new rolling period", async() => { - let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - let firstDayAmount; - tempAmount = new BigNumber(0); - for (let i = 0; i < oldData[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${oldData[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - if (i != 2) { - firstDayAmount = await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][0]); - tempAmount = tempAmount.plus(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])); - } - } - - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((oldData[1].toNumber()).toString())} - Last Timestamp Index : ${oldData[0].length -1} - `); - - let currentDayAmount = firstDayAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))); - let tx = await I_SecurityToken.transfer(account_investor3, currentDayAmount, {from: account_investor1}); - tempAmount = tempAmount.minus(currentDayAmount); - tempArray.push(0); - tempArray.push(currentDayAmount.dividedBy(new BigNumber(10).pow(18)).toNumber()); - console.log('\n'); - let newData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - for (let i = 2; i < newData[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${newData[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(newData[0][i].toNumber(), startTime + duration.days(i)) - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((newData[1].toNumber()).toString())} - Last Timestamp Index : ${newData[0].length -1} - `); - }); - - it("Should transfer the more tokens on the same day", async() => { - // Check the balance of the investors - let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - await I_SecurityToken.transfer(account_investor3, tempAmount, {from: account_investor1}); - - // Check the balance of the investors - let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); - // Verifying the balances - assert.closeTo( - (balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), - tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(), - 0.01 - ); - tempArray[tempArray.length -1] = tempArray[tempArray.length -1] + tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - for (let i = 2; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length -1} - `); - let sumOflastperiod = 0; - for (let i = tempArray.length - 1; i >= tempArray.length - 3; i--) { - sumOflastperiod += tempArray[i]; - } - assert.equal(data[0].length - 1, 4); - assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), sumOflastperiod, 0.001); - }); + // console.log(` + // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + // Last Timestamp Index : ${data[0].length - 1} + // `); + // assert.equal(data[0].length - 1, 2); + // assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), + // oldData[1].dividedBy(new BigNumber(10).pow(18)).toNumber() + totalAmountTransacted, 0.001); + // }); + + // it("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { + // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + // let minimumAmount = new BigNumber(12).times(new BigNumber(10).pow(18)).minus(data[1]); + // let testAmount = minimumAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))) + // await catchRevert( + // I_SecurityToken.transfer(account_investor3, testAmount, {from: account_investor1}) + // ); + // }); + + // it("Should fail to buy tokens in the new rolling period --failed because amount is more than last two timestamps", async() => { + // await increaseTime(duration.days(2)); + // await catchRevert( + // I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_investor1}) + // ); + // }); + + // it("Should transfer the tokens in a new rolling period", async() => { + // let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + // let firstDayAmount; + // tempAmount = new BigNumber(0); + // for (let i = 0; i < oldData[0].length; i++) { + // console.log(` + // Timestamps array index ${i}: ${oldData[0][i].toNumber()} + // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])) + // .dividedBy(new BigNumber(10).pow(18))} + // `); + // if (i != 2) { + // firstDayAmount = await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][0]); + // tempAmount = tempAmount.plus(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])); + // } + // } + + // console.log(` + // SumOfLastPeriod : ${web3.utils.fromWei((oldData[1].toNumber()).toString())} + // Last Timestamp Index : ${oldData[0].length -1} + // `); + + // let currentDayAmount = firstDayAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))); + // let tx = await I_SecurityToken.transfer(account_investor3, currentDayAmount, {from: account_investor1}); + // tempAmount = tempAmount.minus(currentDayAmount); + // tempArray.push(0); + // tempArray.push(currentDayAmount.dividedBy(new BigNumber(10).pow(18)).toNumber()); + // console.log('\n'); + // let newData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + // for (let i = 2; i < newData[0].length; i++) { + // console.log(` + // Timestamps array index ${i}: ${newData[0][i].toNumber()} + // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) + // .dividedBy(new BigNumber(10).pow(18))} + // `); + // assert.equal(newData[0][i].toNumber(), startTime + duration.days(i)) + // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) + // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); + // } + // console.log(` + // SumOfLastPeriod : ${web3.utils.fromWei((newData[1].toNumber()).toString())} + // Last Timestamp Index : ${newData[0].length -1} + // `); + // }); + + // it("Should transfer the more tokens on the same day", async() => { + // // Check the balance of the investors + // let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + // await I_SecurityToken.transfer(account_investor3, tempAmount, {from: account_investor1}); + + // // Check the balance of the investors + // let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); + // // Verifying the balances + // assert.closeTo( + // (balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), + // tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(), + // 0.01 + // ); + // tempArray[tempArray.length -1] = tempArray[tempArray.length -1] + tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(); + // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + // for (let i = 2; i < data[0].length; i++) { + // console.log(` + // Timestamps array index ${i}: ${data[0][i].toNumber()} + // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18))} + // `); + // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); + // } + // console.log(` + // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + // Last Timestamp Index : ${data[0].length -1} + // `); + // let sumOflastperiod = 0; + // for (let i = tempArray.length - 1; i >= tempArray.length - 3; i--) { + // sumOflastperiod += tempArray[i]; + // } + // assert.equal(data[0].length - 1, 4); + // assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), sumOflastperiod, 0.001); + // }); }); - describe("Test case for the variable individual restriction", async() => { + describe.skip("Test case for the variable individual restriction", async() => { it("Should add the restriction succesfully", async() => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor2, @@ -1054,7 +1021,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); }); - describe("Add the test cases for global restriction", async() => { + describe.skip("Add the test cases for global restriction", async() => { it("Should successfully add the global restriction", async() => { await I_VolumeRestrictionTM.addGlobalRestriction( @@ -1355,7 +1322,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); }) - describe("Test for the exemptlist", async() => { + describe.skip("Test for the exemptlist", async() => { it("Should add the token holder in the exemption list -- failed because of bad owner", async() => { await catchRevert( @@ -1373,7 +1340,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); }); - describe("Test for modify functions", async() => { + describe.skip("Test for modify functions", async() => { it("Should not able to modify the already started restrictions --global", async() =>{ await catchRevert( From 57c24be626af78bd610021579f8669dd8084932f Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 30 Nov 2018 19:41:19 +0530 Subject: [PATCH 289/582] allow the lockup start could be 0 --- .../TransferManager/LockUpTransferManager.sol | 23 +++++++++++++------ test/w_lockup_transfer_manager.js | 8 +++---- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/contracts/modules/TransferManager/LockUpTransferManager.sol b/contracts/modules/TransferManager/LockUpTransferManager.sol index 1de5a0c14..3d3450721 100644 --- a/contracts/modules/TransferManager/LockUpTransferManager.sol +++ b/contracts/modules/TransferManager/LockUpTransferManager.sol @@ -487,8 +487,13 @@ contract LockUpTransferManager is ITransferManager { internal { /*solium-disable-next-line security/no-block-members*/ - require(lockups[_lockupName].startTime > now, "Not allowed to modify"); - require(_startTime >= now, "Past time is not allowed"); + uint256 startTime = _startTime; + + if (_startTime == 0) { + startTime = now; + } + require(startTime >= now, "Invalid start time"); + require(lockups[_lockupName].lockupAmount != 0, "Doesn't exist"); _checkLockUpParams( _lockupAmount, @@ -498,14 +503,14 @@ contract LockUpTransferManager is ITransferManager { lockups[_lockupName] = LockUp( _lockupAmount, - _startTime, + startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds ); emit ModifyLockUpType( _lockupAmount, - _startTime, + startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds, _lockupName @@ -589,14 +594,18 @@ contract LockUpTransferManager is ITransferManager { ) internal { + uint256 startTime = _startTime; require(_lockupName != bytes32(0), "Invalid name"); require(lockups[_lockupName].lockupAmount == 0, "Already exist"); /*solium-disable-next-line security/no-block-members*/ - require(_startTime >= now, "Past time not allowed"); + if (_startTime == 0) { + startTime = now; + } + require(startTime >= now, "Invalid start time"); _checkLockUpParams(_lockupAmount, _lockUpPeriodSeconds, _releaseFrequencySeconds); - lockups[_lockupName] = LockUp(_lockupAmount, _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds); + lockups[_lockupName] = LockUp(_lockupAmount, startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds); lockupArray.push(_lockupName); - emit AddNewLockUpType(_lockupName, _lockupAmount, _startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds); + emit AddNewLockUpType(_lockupName, _lockupAmount, startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds); } /** diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js index 834ab8cca..59e1ed816 100644 --- a/test/w_lockup_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -900,22 +900,20 @@ contract('LockUpTransferManager', accounts => { }); - it("Modify the lockup during the lockup periods --fail because already tokens get unlocked", async() => { + it("Modify the lockup during the lockup periods", async() => { let balance = await I_SecurityToken.balanceOf(account_investor1) let lockUp = await I_LockUpTransferManager.getLockUp(account_investor1, "f_lockup"); console.log(lockUp[4].dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); // edit the lockup - await catchRevert( - I_LockUpTransferManager.modifyLockUpType( + await I_LockUpTransferManager.modifyLockUpType( balance, - temp, + latestTime() + duration.days(10), 90, 30, "f_lockup", { from: token_owner } - ) ); }); From 976e6d6934fbb3240c237fae99ec71f93af2fbf5 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 30 Nov 2018 16:23:39 +0200 Subject: [PATCH 290/582] removed trim function, changed pushAvailableTokensMulti --- .../modules/Wallet/VestingEscrowWallet.sol | 25 +++++-------------- test/z_vesting_escrow_wallet.js | 7 +++--- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index c8a05defe..09c6151c9 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -453,28 +453,15 @@ contract VestingEscrowWallet is IWallet { } } - /** - * @notice Used to remove beneficiaries without schedules - * TODO: Improve the Trim beneficiary logic -- remain because of size of bytecode hit the limit - */ - function trimBeneficiaries() external withPerm(ADMIN) { - for (uint256 i = 0; i < beneficiaries.length; i++) { - if (schedules[beneficiaries[i]].length == 0) { - if (i != beneficiaries.length - 1) { - beneficiaries[i] = beneficiaries[beneficiaries.length - 1]; - } - beneficiaries.length--; - } - } - } - /** * @notice Used to bulk send available tokens for each of beneficiaries - * @param _beneficiaries array of beneficiary's addresses + * @param _fromIndex start index of array of beneficiary's addresses + * @param _toIndex end index of array of beneficiary's addresses */ - function pushAvailableTokensMulti(address[] _beneficiaries) external withPerm(ADMIN) { - for (uint256 i = 0; i < _beneficiaries.length; i++) { - pushAvailableTokens(_beneficiaries[i]); + function pushAvailableTokensMulti(uint256 _fromIndex, uint256 _toIndex) external withPerm(ADMIN) { + require(_toIndex <= beneficiaries.length - 1, "Array out of bound"); + for (uint256 i = _fromIndex; i <= _toIndex; i++) { + pushAvailableTokens(beneficiaries[i]); } } diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index bad3e9e8e..cc0aed2d3 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -974,18 +974,18 @@ contract('VestingEscrowWallet', accounts => { it("Should not be able to send available tokens to the beneficiaries addresses -- fail because of array size", async () => { await catchRevert( - I_VestingEscrowWallet.pushAvailableTokensMulti([account_beneficiary1], {from: wallet_admin}) + I_VestingEscrowWallet.pushAvailableTokensMulti(0, 2, {from: wallet_admin}) ); }); it("Should not be able to send available tokens to the beneficiaries -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.pushAvailableTokensMulti([account_beneficiary1], {from: account_beneficiary1}) + I_VestingEscrowWallet.pushAvailableTokensMulti(0, 2, {from: account_beneficiary1}) ); }); it("Should send available tokens to the beneficiaries addresses", async () => { - const tx = await I_VestingEscrowWallet.pushAvailableTokensMulti(beneficiaries, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.pushAvailableTokensMulti(0, 2, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; @@ -1056,7 +1056,6 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 0); } - await I_VestingEscrowWallet.trimBeneficiaries({from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); From 6bcab54bde9cd089860885804a9a3ebced7cf148 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 30 Nov 2018 15:34:48 +0100 Subject: [PATCH 291/582] WIP --- test/d_count_transfer_manager.js | 80 ++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 9656c45c9..4a2b0b306 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -40,6 +40,7 @@ contract("CountTransferManager", accounts => { let I_GeneralPermissionManager; let I_CountTransferManager; let I_GeneralTransferManager; + let I_GeneralTransferManager2; let I_ExchangeTransferManager; let I_ModuleRegistry; let I_ModuleRegistryProxy; @@ -49,12 +50,14 @@ contract("CountTransferManager", accounts => { let I_SecurityTokenRegistry; let I_STFactory; let I_SecurityToken; + let I_SecurityToken2; let I_PolyToken; let I_PolymathRegistry; // SecurityToken Details const name = "Team"; const symbol = "sap"; + const symbol2 = "sapp"; const tokenDetails = "This is equity type of issuance"; const decimals = 18; const contact = "team@polymath.network"; @@ -339,11 +342,11 @@ contract("CountTransferManager", accounts => { await catchRevert(I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2", "ether"), { from: account_investor2 })); }); - it("Should be able to transfer to a new token holder if all tokens are transferred and existing holder is removed", async () => { - console.log('acc2 balancce is ' + (await I_SecurityToken.balanceOf(account_investor2)).toNumber()); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4", "ether"), { from: account_investor2 }); - assert((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("4", "ether")); - }); + // it("Should be able to transfer to a new token holder if all tokens are transferred and existing holder is removed", async () => { + // console.log('acc2 balancce is ' + (await I_SecurityToken.balanceOf(account_investor2)).toNumber()); + // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4", "ether"), { from: account_investor2 }); + // assert((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("4", "ether")); + // }); it("Should be able to consolidate balances", async () => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); @@ -354,6 +357,73 @@ contract("CountTransferManager", accounts => { assert.equal(perm.length, 1); }); + describe("Test cases for adding and removing acc holder at the same time", async () => { + it("deploy a new token & auto attach modules", async () => { + + //register ticker and deploy token + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol2, contact, { from: token_owner }); + + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx2 = await I_STRProxied.generateSecurityToken(name, symbol2, tokenDetails, false, { from: token_owner }); + + I_SecurityToken2 = SecurityToken.at(tx2.logs[1].args._securityTokenAddress); + + let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + }); + + it("add 3 holders to the token", async () => { + + await I_GeneralTransferManager2.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + + await I_GeneralTransferManager2.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + + await I_GeneralTransferManager2.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken2.mint(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_SecurityToken2.mint(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_SecurityToken2.mint(account_investor3, web3.utils.toWei("1", "ether"), { from: token_owner }); + + assert.equal((await I_SecurityToken2.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + }); + }); + describe("Test cases for the factory", async () => { it("should get the exact details of the factory", async () => { assert.equal(await I_CountTransferManagerFactory.getSetupCost.call(), 0); From b9df9cbcab5681d95437aae4b02937c25eb11780 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 30 Nov 2018 17:35:13 +0200 Subject: [PATCH 292/582] minor fixes with treasury --- contracts/modules/Wallet/VestingEscrowWallet.sol | 2 +- contracts/modules/Wallet/VestingEscrowWalletFactory.sol | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 09c6151c9..361512698 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -131,7 +131,7 @@ contract VestingEscrowWallet is IWallet { function _depositTokens(uint256 _numberOfTokens) internal { require(_numberOfTokens > 0, "Should be > 0"); - ISecurityToken(securityToken).transferFrom(msg.sender, address(this), _numberOfTokens); + ISecurityToken(securityToken).transferFrom(treasuryWallet, address(this), _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); emit DepositTokens(_numberOfTokens, msg.sender); } diff --git a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol index d0035da10..88db1919d 100644 --- a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol +++ b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol @@ -29,11 +29,15 @@ contract VestingEscrowWalletFactory is ModuleFactory { * _data Data used for the intialization of the module factory variables * @return address Contract address of the Module */ - function deploy(bytes /*_data*/) external returns(address) { + function deploy(bytes _data) external returns(address) { if (setupCost > 0) { require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance provided"); } VestingEscrowWallet vestingEscrowWallet = new VestingEscrowWallet(msg.sender, address(polyToken)); + //Checks that _data is valid (not calling anything it shouldn't) + require(Util.getSig(_data) == vestingEscrowWallet.getInitFunction(), "Invalid data"); + /*solium-disable-next-line security/no-low-level-calls*/ + require(address(vestingEscrowWallet).call(_data), "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(vestingEscrowWallet), getName(), address(this), msg.sender, setupCost, now); return address(vestingEscrowWallet); From 861fbea17e2ccdd4cd976c79b9543240990e3ffe Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Fri, 30 Nov 2018 11:03:42 -0500 Subject: [PATCH 293/582] Updates --- .../GeneralTransferManager.sol | 85 +++++++++---------- test/h_general_transfer_manager.js | 6 +- 2 files changed, 41 insertions(+), 50 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index c43531db7..5412afe94 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -24,7 +24,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag // Emit when there is change in the flag variable called signingAddress event ChangeSigningAddress(address _signingAddress); // Emit when investor details get modified related to their whitelisting - event DefaultsModified(uint64 _defaultFromTime, uint64 _defaultToTime); + event ChangeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime); // _fromTime is the time from which the _investor can send tokens // _toTime is the time from which the _investor can receive tokens @@ -52,12 +52,6 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag { } - function modifyDefaults(uint64 _defaultFromTime, uint64 _defaultToTime) public withPerm(FLAGS) { - defaults.fromTime = _defaultFromTime; - defaults.toTime = _defaultToTime; - emit DefaultsModified(_defaultFromTime, _defaultToTime); - } - /** * @notice This function returns the signature of configure function */ @@ -65,6 +59,17 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag return bytes4(0); } + /** + * @notice Used to change the default times used when fromTime / toTime are zero + * @param _defaultFromTime default for zero fromTime + * @param _defaultToTime default for zero toTime + */ + function changeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime) public withPerm(FLAGS) { + defaults.fromTime = _defaultFromTime; + defaults.toTime = _defaultToTime; + emit ChangeDefaults(_defaultFromTime, _defaultToTime); + } + /** * @notice Used to change the Issuance Address * @param _issuanceAddress new address for the issuance @@ -126,7 +131,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag allowAllBurnTransfers = _allowAllBurnTransfers; emit AllowAllBurnTransfers(_allowAllBurnTransfers); } - event Times(uint64 _from, uint64 _to); + /** * @notice Default implementation of verifyTransfer used by SecurityToken * If the transfer request comes from the STO, it only checks that the investor is in the whitelist @@ -150,17 +155,21 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag //Anyone on the whitelist can transfer, regardless of time return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA; } - if (_from == issuanceAddress && (whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { - return Result.NA; - } - if (allowAllWhitelistIssuances && _from == issuanceAddress) { - return _onWhitelist(_to) ? Result.VALID : Result.NA; - } - (uint64 adjustedFromTime, uint64 adjustedToTime) = _adjustTimes(whitelist[_from].fromTime, whitelist[_to].toTime); + (uint64 adjustedFromTime, uint64 adjustedToTime) = _adjustTimes(whitelist[_from].fromTime, whitelist[_to].toTime); if (_from == issuanceAddress) { - return (_onWhitelist(_to) && (adjustedToTime <= uint64(now))) ? Result.VALID : Result.NA; + // Possible STO transaction, but investor not allowed to purchased from STO + if ((whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { + return Result.NA; + } + // if allowAllWhitelistIssuances is true, so time stamp ignored + if (allowAllWhitelistIssuances) { + return _onWhitelist(_to) ? Result.VALID : Result.NA; + } else { + return (_onWhitelist(_to) && (adjustedToTime <= uint64(now))) ? Result.VALID : Result.NA; + } } + //Anyone on the whitelist can transfer provided the blocknumber is large enough /*solium-disable-next-line security/no-block-members*/ return ((_onWhitelist(_from) && (adjustedFromTime <= uint64(now))) && @@ -187,13 +196,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag public withPerm(WHITELIST) { - uint8 canBuyFromSTO = 0; - if (_canBuyFromSTO) { - canBuyFromSTO = 1; - } - _modifyWhitelist(_investor, uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO); - /*solium-disable-next-line security/no-block-members*/ - emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** @@ -206,18 +209,23 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag */ function _modifyWhitelist( address _investor, - uint64 _fromTime, - uint64 _toTime, - uint64 _expiryTime, - uint8 _canBuyFromSTO + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, + bool _canBuyFromSTO ) internal { require(_investor != address(0), "Invalid investor"); + uint8 canBuyFromSTO = 0; + if (_canBuyFromSTO) { + canBuyFromSTO = 1; + } if (whitelist[_investor].added == uint8(0)) { investors.push(_investor); } - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO, uint8(1)); + whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); + emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** @@ -239,16 +247,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag require(_fromTimes.length == _toTimes.length, "Mismatched input lengths"); require(_toTimes.length == _expiryTimes.length, "Mismatched input lengths"); require(_canBuyFromSTO.length == _toTimes.length, "Mismatched input length"); - uint8 canBuyFromSTO; for (uint256 i = 0; i < _investors.length; i++) { - if (_canBuyFromSTO[i]) { - canBuyFromSTO = 1; - } else { - canBuyFromSTO = 0; - } - _modifyWhitelist(_investors[i], uint64(_fromTimes[i]), uint64(_toTimes[i]), uint64(_expiryTimes[i]), canBuyFromSTO); - /*solium-disable-next-line security/no-block-members*/ - emit ModifyWhitelist(_investors[i], now, msg.sender, _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); + _modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); } } @@ -289,16 +289,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) ); _checkSig(hash, _v, _r, _s); - if (whitelist[_investor].added == uint8(0)) { - investors.push(_investor); - } - uint8 canBuyFromSTO = 0; - if (_canBuyFromSTO) { - canBuyFromSTO = 1; - } - whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); - /*solium-disable-next-line security/no-block-members*/ - emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 5d019f521..d00108376 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -421,7 +421,7 @@ contract("GeneralTransferManager", accounts => { }); it("Add a from default and check transfers are disabled then enabled in the future", async () => { - let tx = await I_GeneralTransferManager.modifyDefaults(latestTime() + duration.days(5), 0, {from: token_owner}); + let tx = await I_GeneralTransferManager.changeDefaults(latestTime() + duration.days(5), 0, {from: token_owner}); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor2}); await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1})); await increaseTime(duration.days(5)); @@ -429,7 +429,7 @@ contract("GeneralTransferManager", accounts => { }); it("Add a to default and check transfers are disabled then enabled in the future", async () => { - let tx = await I_GeneralTransferManager.modifyDefaults(0, latestTime() + duration.days(5), {from: token_owner}); + let tx = await I_GeneralTransferManager.changeDefaults(0, latestTime() + duration.days(5), {from: token_owner}); await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor2})); await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1}); await increaseTime(duration.days(5)); @@ -446,7 +446,7 @@ contract("GeneralTransferManager", accounts => { gas: 6000000 } ); - await I_GeneralTransferManager.modifyDefaults(0, 0, {from: token_owner}); + await I_GeneralTransferManager.changeDefaults(0, 0, {from: token_owner}); }); From 1ad53fc4dc94326e606c7132109afb3586c57712 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 30 Nov 2018 20:22:26 -0300 Subject: [PATCH 294/582] CSV parser --- CLI/commands/helpers/csv.js | 42 +++++++++++++++++++++++++++++++++++++ CLI/commands/sto_manager.js | 28 ++++++++++++++++++------- CLI/package.json | 1 + CLI/yarn.lock | 5 +++++ 4 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 CLI/commands/helpers/csv.js diff --git a/CLI/commands/helpers/csv.js b/CLI/commands/helpers/csv.js new file mode 100644 index 000000000..560adb935 --- /dev/null +++ b/CLI/commands/helpers/csv.js @@ -0,0 +1,42 @@ +const csvParse = require('csv-parse/lib/sync'); +const fs = require('fs'); + +function _cast(obj) { + if (/^(\-|\+)?([1-9]+[0-9]*)$/.test(obj)) { // Int + obj = parseInt(obj); + } + else if (/^[+-]?([0-9]*[.])?[0-9]+$/.test(obj)) { // Float + obj = parseFloat(obj); + } + else if (/^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.test(obj)) { // Datetime + var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(obj); + var composedDate = new Date(matches[3], matches[1] - 1, matches[2]); + var timestampDate = composedDate.getTime(); + obj = timestampDate / 1000; + } + else if (obj.toLowerCase() === "true" || obj.toLowerCase() === "false") { // Boolean + obj = JSON.parse(obj.toLowerCase()); + } + return obj; +} + +function parse(_csvFilePath, _batchSize) { + // Read file + let input = fs.readFileSync(_csvFilePath); + // Parse csv + let data = csvParse(input, { cast: _cast }); + // Batches + let allBatches = []; + for (let index = 0; index < data.length; index += _batchSize) { + allBatches.push(data.slice(index, index + _batchSize)); + } + // Transform result + let result = []; + let columnsLenght = data[0].length; + for (let index = 0; index < columnsLenght; index++) { + result[index] = allBatches.map(batch => batch.map(record => record[index])); + } + return result; +} + +module.exports = parse; \ No newline at end of file diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 898eb8b45..c77bb2485 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -5,6 +5,7 @@ const abis = require('./helpers/contract_abis'); const common = require('./common/common_functions'); const gbl = require('./common/global'); const csv_shared = require('./common/csv_shared'); +const csvParse = require('./helpers/csv'); const BigNumber = require('bignumber.js'); /////////////////// @@ -696,6 +697,17 @@ async function usdTieredSTO_configure(currentSTO) { await common.sendTransaction(changeAccreditedAction); break; case 2: + let batchSize = 75; + let csvFile = fs.readFileSync('./CLI/data/accredited_data.csv'); + let columns = ['address', 'accredited']; + let resultData = []; + let index = 0; + while (true) { + index++; + let data = csvParse(csvFile, { columns: columns, from_line: index, to_line: batchSize * index }); + resultData.push(data); + } + let accredit; await startCSV(tokenSymbol, 75, 'accredited'); break; case 3: @@ -736,7 +748,7 @@ async function usdTieredSTO_configure(currentSTO) { async function startCSV(tokenSymbol, batchSize, accreditionType) { let file, proccessing, saving; - + switch (accreditionType) { case 'accredited': file = './CLI/data/accredited_data.csv' @@ -756,7 +768,7 @@ async function startCSV(tokenSymbol, batchSize, accreditionType) { distribData = result_processing.distribData; fullFileData = result_processing.fullFileData; badData = result_processing.badData; - + await saving(); } @@ -812,12 +824,12 @@ async function saveInBlockchainAccredited() { for (let i = 0; i < distribData.length; i++) { try { let investorArray = [], isAccreditedArray = []; - + for (let j = 0; j < distribData[i].length; j++) { investorArray.push(distribData[i][j][0]) isAccreditedArray.push(distribData[i][j][1]) } - + let changeAccreditedAction = await usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); let tx = await common.sendTransaction(changeAccreditedAction); console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); @@ -867,7 +879,7 @@ async function saveInBlockchainNonAccredited() { for (let i = 0; i < distribData.length; i++) { try { let investorArray = [], limitArray = []; - + for (let j = 0; j < distribData[i].length; j++) { investorArray.push(distribData[i][j][0]); limitArray.push(web3.utils.toWei(distribData[i][j][1].toString())); @@ -879,7 +891,7 @@ async function saveInBlockchainNonAccredited() { console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); console.log("Change accredited transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString()), "Ether"); console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - + } catch (err) { console.log("ERROR:", err); } @@ -1063,4 +1075,6 @@ module.exports = { startCSV: async function (tokenSymbol, batchSize, accreditionType) { return startCSV(tokenSymbol, batchSize, accreditionType); } -} \ No newline at end of file +} + + diff --git a/CLI/package.json b/CLI/package.json index 95a391b45..64fb2a221 100644 --- a/CLI/package.json +++ b/CLI/package.json @@ -11,6 +11,7 @@ "dependencies": { "chalk": "^2.4.1", "commander": "^2.16.0", + "csv-parse": "^4.0.1", "ethers": "^4.0.7", "moment": "^2.22.2", "readline-sync": "^1.4.9", diff --git a/CLI/yarn.lock b/CLI/yarn.lock index 4d20bee11..51925f5ef 100644 --- a/CLI/yarn.lock +++ b/CLI/yarn.lock @@ -437,6 +437,11 @@ crypto-browserify@3.12.0: randombytes "^2.0.0" randomfill "^1.0.3" +csv-parse@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-4.0.1.tgz#4ad438352cbf12d5317d0fb9d588e53473293851" + integrity sha512-ehkwejEj05wwO7Q9JD+YSI6dNMIauHIroNU1RALrmRrqPoZIwRnfBtgq5GkU6i2RxZOJqjo3dtI1NrVSXvaimA== + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" From d0d51933ca9f56af2f38154d9eba266dc863a709 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 30 Nov 2018 20:26:44 -0300 Subject: [PATCH 295/582] Data folder reorganization --- CLI/data/{ => Checkpoint}/dividendsExclusions_data.csv | 0 CLI/data/{ => ST}/multi_mint_data.csv | 0 CLI/data/{ => STO/USDTieredSTO}/accredited_data.csv | 0 CLI/data/{ => STO/USDTieredSTO}/nonAccreditedLimits_data.csv | 0 CLI/data/{ => STO}/capped_sto_data.yml | 0 CLI/data/{ => STO}/usd_tiered_sto_data.yml | 0 CLI/data/{ => Ticker}/ticker_data.csv | 0 CLI/data/{ => Transfer/GTM}/whitelist_data.csv | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename CLI/data/{ => Checkpoint}/dividendsExclusions_data.csv (100%) rename CLI/data/{ => ST}/multi_mint_data.csv (100%) rename CLI/data/{ => STO/USDTieredSTO}/accredited_data.csv (100%) rename CLI/data/{ => STO/USDTieredSTO}/nonAccreditedLimits_data.csv (100%) rename CLI/data/{ => STO}/capped_sto_data.yml (100%) rename CLI/data/{ => STO}/usd_tiered_sto_data.yml (100%) rename CLI/data/{ => Ticker}/ticker_data.csv (100%) rename CLI/data/{ => Transfer/GTM}/whitelist_data.csv (100%) diff --git a/CLI/data/dividendsExclusions_data.csv b/CLI/data/Checkpoint/dividendsExclusions_data.csv similarity index 100% rename from CLI/data/dividendsExclusions_data.csv rename to CLI/data/Checkpoint/dividendsExclusions_data.csv diff --git a/CLI/data/multi_mint_data.csv b/CLI/data/ST/multi_mint_data.csv similarity index 100% rename from CLI/data/multi_mint_data.csv rename to CLI/data/ST/multi_mint_data.csv diff --git a/CLI/data/accredited_data.csv b/CLI/data/STO/USDTieredSTO/accredited_data.csv similarity index 100% rename from CLI/data/accredited_data.csv rename to CLI/data/STO/USDTieredSTO/accredited_data.csv diff --git a/CLI/data/nonAccreditedLimits_data.csv b/CLI/data/STO/USDTieredSTO/nonAccreditedLimits_data.csv similarity index 100% rename from CLI/data/nonAccreditedLimits_data.csv rename to CLI/data/STO/USDTieredSTO/nonAccreditedLimits_data.csv diff --git a/CLI/data/capped_sto_data.yml b/CLI/data/STO/capped_sto_data.yml similarity index 100% rename from CLI/data/capped_sto_data.yml rename to CLI/data/STO/capped_sto_data.yml diff --git a/CLI/data/usd_tiered_sto_data.yml b/CLI/data/STO/usd_tiered_sto_data.yml similarity index 100% rename from CLI/data/usd_tiered_sto_data.yml rename to CLI/data/STO/usd_tiered_sto_data.yml diff --git a/CLI/data/ticker_data.csv b/CLI/data/Ticker/ticker_data.csv similarity index 100% rename from CLI/data/ticker_data.csv rename to CLI/data/Ticker/ticker_data.csv diff --git a/CLI/data/whitelist_data.csv b/CLI/data/Transfer/GTM/whitelist_data.csv similarity index 100% rename from CLI/data/whitelist_data.csv rename to CLI/data/Transfer/GTM/whitelist_data.csv From 3617971080cb6a7b877ddedaa86f37d484a4c37f Mon Sep 17 00:00:00 2001 From: satyam Date: Sun, 2 Dec 2018 22:16:31 +0530 Subject: [PATCH 296/582] simplification in the code --- .../TransferManager/VolumeRestrictionTM.sol | 47 +- .../VolumeRestrictionTMFactory.sol | 2 +- test/y_volume_restriction_tm.js | 475 +++++++++--------- 3 files changed, 280 insertions(+), 244 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index e3282fd65..f16dc9de7 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -495,13 +495,14 @@ contract VolumeRestrictionTM is ITransferManager { globalRestriction ); // Total amout that is transacted uptill now for `fromTimestamp` day - uint256 txSumOfDay = globalBucket[fromTimestamp]; - // Global transaction check - if (_globalTxCheck(sumOfLastPeriod, txSumOfDay, _amount)) { + uint256 txSumOfDay = bucket[_from][fromTimestamp]; + // Daily transaction check + if (_dailyTxCheck(sumOfLastPeriod, txSumOfDay, _amount, individualRestriction[_from])) { // allow modification in storage when `_isTransfer` equals true if(_isTransfer) { // update the global storage _updateGlobalStorage( + _from, fromTimestamp, _amount, sumOfLastPeriod, @@ -517,6 +518,7 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Internal function to update the state variables related to global restriction */ function _updateGlobalStorage( + address _from, uint256 _fromTime, uint256 _amount, uint256 _sumOfLastPeriod, @@ -535,6 +537,8 @@ contract VolumeRestrictionTM is ITransferManager { // Increasing the total amount of the day by `_amount` globalBucket[_fromTime] = globalBucket[_fromTime].add(_amount); + // Updating the total day amount traded. + bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); } } @@ -585,7 +589,7 @@ contract VolumeRestrictionTM is ITransferManager { // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... // where T1,T2,T3 are timestamps having 24 hrs difference _fromTime = _fromTime.add(_diffDays.mul(1 days)); - return (_bucketDetails.sumOfLastPeriod, _fromTime, counter.add(_diffDays)); + return (_bucketDetails.sumOfLastPeriod, _fromTime, counter.add(_bucketDetails.daysCovered)); } /** @@ -623,8 +627,14 @@ contract VolumeRestrictionTM is ITransferManager { false, individualRestriction[_from] ); - if (_checkValidAmountToTransact(sumOfLastPeriod, _amount, individualRestriction[_from])) { + // Total amout that is transacted uptill now for `fromTimestamp` day + // re-using the same variable to avoid the stach too deep error. here it will give you the sum of + // tokens traded in the current day (tx day) + diffDays = bucket[_from][fromTimestamp]; + // Daily transaction check + if (_dailyTxCheck(sumOfLastPeriod, diffDays, _amount, individualRestriction[_from])) { if (_isTransfer) { + // update the Individual storage _updateIndividualStorage( _from, fromTimestamp, @@ -639,10 +649,11 @@ contract VolumeRestrictionTM is ITransferManager { } - function _globalTxCheck( + function _dailyTxCheck( uint256 _sumOfLastPeriod, uint256 _dailyAmount, - uint256 _amount + uint256 _amount, + VolumeRestriction _restriction ) internal view @@ -650,12 +661,12 @@ contract VolumeRestrictionTM is ITransferManager { { // Checking whether the global day restriction is added or not if yes then calculate // the total amount get traded on a particular day (~ _fromTime) - if (!_checkValidAmountToTransact(_dailyAmount, _amount, dailyGlobalRestriction) && - now <= dailyGlobalRestriction.endTime && now >= dailyGlobalRestriction.startTime - ) { - return false; + if ( now <= dailyGlobalRestriction.endTime && now >= dailyGlobalRestriction.startTime) + { + if (!_checkValidAmountToTransact(_dailyAmount, _amount, dailyGlobalRestriction)) + return false; } - return _checkValidAmountToTransact(_sumOfLastPeriod, _amount, globalRestriction); + return _checkValidAmountToTransact(_sumOfLastPeriod, _amount, _restriction); } function _checkValidAmountToTransact( @@ -830,11 +841,13 @@ contract VolumeRestrictionTM is ITransferManager { * @param _user Address of the token holder for whom the bucket details has queried * @return uint256 lastTradedDayTime * @return uint256 sumOfLastPeriod + * @return uint256 days covered */ - function getBucketDetailsToUser(address _user) external view returns(uint256, uint256) { + function getBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256) { return( bucketToUser[_user].lastTradedDayTime, - bucketToUser[_user].sumOfLastPeriod + bucketToUser[_user].sumOfLastPeriod, + bucketToUser[_user].daysCovered ); } @@ -851,13 +864,11 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Use to get the global bucket details * @return uint256 lastTradedDayTime * @return uint256 sumOfLastPeriod - * @return uint256 Total amount traded on the latest timestamp */ - function getGlobalBucketDetails() external view returns(uint256, uint256, uint256) { + function getGlobalBucketDetails() external view returns(uint256, uint256) { return( globalBucketDetails.lastTradedDayTime, - globalBucketDetails.sumOfLastPeriod, - globalBucket[globalBucketDetails.lastTradedDayTime] + globalBucketDetails.sumOfLastPeriod ); } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol index 03d6e89fc..9ac511183 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol @@ -58,7 +58,7 @@ contract VolumeRestrictionTMFactory is ModuleFactory { * @notice Get the tags related to the module factory */ function getTags() public view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](3); + bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "Maximum Volume"; availableTags[1] = "Transfer Restriction"; availableTags[2] = "Daily Restriction"; diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 9c33cb1c7..4be373516 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -603,240 +603,237 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log(` SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Days Covered : ${data[0].length -1} + Days Covered : ${data[2]} `); assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 0.3); tempArray.push(0.3); }) - // it("Should successfully transact the tokens after 1 and half days", async() => { - // await increaseTime(duration.days(1.5)); - // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor1}); - // // Check the balance of the investors - // let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); - // // Verifying the balances - // assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 33.7); - // tempArray.push(1); - // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - - // for (let i = 0; i < data[0].length; i++) { - // console.log(` - // Timestamps array index ${i}: ${data[0][i].toNumber()} - // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18)).toNumber()} - // `); - // assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i]); - // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - // } - // console.log(` - // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - // Last Timestamp Index : ${data[0].length -1} - // `); - // assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1.3); - // assert.equal(data[0].length -1, 1); - // }); - - // it("Should successfully transact more tokens on the same day (Fuzz test)", async() => { - // // Check the balance of the investors - // let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - // let totalAmountTransacted = 0; - // for (let i = 0; i < 10; i++) { - // let amount = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; - // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); - // console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); - // totalAmountTransacted += amount; - // } + it("Should successfully transact the tokens after 1 and half days", async() => { + await increaseTime(duration.days(1.5)); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor1}); + // Check the balance of the investors + let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 33.7); + tempArray.push(1); + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + + console.log(` + Timestamps array index : ${data[0].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) + .dividedBy(new BigNumber(10).pow(18)).toNumber()} + `); + assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[tempArray.length - 1]); + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Days Covered : ${data[2]} + `); + assert.equal(data[0].toNumber(), (startTime + duration.days(data[2]))); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1.3); + }); + + it.skip("Should successfully transact more tokens on the same day (Fuzz test)", async() => { + // Check the balance of the investors + let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + let totalAmountTransacted = 0; + for (let i = 0; i < 10; i++) { + let amount = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); + console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); + totalAmountTransacted += amount; + } - // // Check the balance of the investors - // let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); - // // Verifying the balances - // assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - // tempArray[1] = tempArray[1] + totalAmountTransacted; - // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - - // for (let i = 0; i < data[0].length; i++) { - // console.log(` - // Timestamps array index ${i}: ${data[0][i].toNumber()} - // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18))} - // `); - // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); - // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - // } - // console.log(` - // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - // Last Timestamp Index : ${data[0].length - 1} - // `); - // assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 1.3 + totalAmountTransacted, 0.000001); - // assert.equal(data[0].length -1, 1); - // }); - - // it("Should successfully transfer the tokens after half days-- should increase the day covered by 1", async() => { - // let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - // await increaseTime(duration.days(.5)); - // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); - // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - // tempArray.push(2); - - // for (let i = 0; i < data[0].length; i++) { - // console.log(` - // Timestamps array index ${i}: ${data[0][i].toNumber()} - // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18))} - // `); - // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); - // } + // Check the balance of the investors + let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); + tempArray[1] = tempArray[1] + totalAmountTransacted; + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + `); + assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 1.3 + totalAmountTransacted, 0.000001); + assert.equal(data[0].length -1, 1); + }); + + it.skip("Should successfully transfer the tokens after half days-- should increase the day covered by 1", async() => { + let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + await increaseTime(duration.days(.5)); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + tempArray.push(2); + + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); + } - // console.log(` - // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - // Last Timestamp Index : ${data[0].length - 1} - // `); - // assert.equal(data[0].length - 1, 2); - // assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), - // (oldData[1].plus(new BigNumber(2).times(new BigNumber(10).pow(18)))) - // .dividedBy(new BigNumber(10).pow(18)).toNumber()); - // }); - - // it("Should successfully transfer the tokens in the last day of rolling period", async() => { - // // Check the balance of the investors - // let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - // let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - - // let totalAmountTransacted = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; - // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(totalAmountTransacted.toString()), {from: account_investor1}); + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + `); + assert.equal(data[0].length - 1, 2); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), + (oldData[1].plus(new BigNumber(2).times(new BigNumber(10).pow(18)))) + .dividedBy(new BigNumber(10).pow(18)).toNumber()); + }); + + it.skip("Should successfully transfer the tokens in the last day of rolling period", async() => { + // Check the balance of the investors + let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + + let totalAmountTransacted = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(totalAmountTransacted.toString()), {from: account_investor1}); - // // Check the balance of the investors - // let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); - // // Verifying the balances - // assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - // tempArray[2] = tempArray[2] + totalAmountTransacted; - // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - // for (let i = 0; i < data[0].length; i++) { - // console.log(` - // Timestamps array index ${i}: ${data[0][i].toNumber()} - // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18))} - // `); - // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); - // } + // Check the balance of the investors + let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); + tempArray[2] = tempArray[2] + totalAmountTransacted; + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 0; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); + } - // console.log(` - // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - // Last Timestamp Index : ${data[0].length - 1} - // `); - // assert.equal(data[0].length - 1, 2); - // assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), - // oldData[1].dividedBy(new BigNumber(10).pow(18)).toNumber() + totalAmountTransacted, 0.001); - // }); - - // it("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { - // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - // let minimumAmount = new BigNumber(12).times(new BigNumber(10).pow(18)).minus(data[1]); - // let testAmount = minimumAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))) - // await catchRevert( - // I_SecurityToken.transfer(account_investor3, testAmount, {from: account_investor1}) - // ); - // }); - - // it("Should fail to buy tokens in the new rolling period --failed because amount is more than last two timestamps", async() => { - // await increaseTime(duration.days(2)); - // await catchRevert( - // I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_investor1}) - // ); - // }); - - // it("Should transfer the tokens in a new rolling period", async() => { - // let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - // let firstDayAmount; - // tempAmount = new BigNumber(0); - // for (let i = 0; i < oldData[0].length; i++) { - // console.log(` - // Timestamps array index ${i}: ${oldData[0][i].toNumber()} - // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])) - // .dividedBy(new BigNumber(10).pow(18))} - // `); - // if (i != 2) { - // firstDayAmount = await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][0]); - // tempAmount = tempAmount.plus(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])); - // } - // } - - // console.log(` - // SumOfLastPeriod : ${web3.utils.fromWei((oldData[1].toNumber()).toString())} - // Last Timestamp Index : ${oldData[0].length -1} - // `); - - // let currentDayAmount = firstDayAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))); - // let tx = await I_SecurityToken.transfer(account_investor3, currentDayAmount, {from: account_investor1}); - // tempAmount = tempAmount.minus(currentDayAmount); - // tempArray.push(0); - // tempArray.push(currentDayAmount.dividedBy(new BigNumber(10).pow(18)).toNumber()); - // console.log('\n'); - // let newData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - // for (let i = 2; i < newData[0].length; i++) { - // console.log(` - // Timestamps array index ${i}: ${newData[0][i].toNumber()} - // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) - // .dividedBy(new BigNumber(10).pow(18))} - // `); - // assert.equal(newData[0][i].toNumber(), startTime + duration.days(i)) - // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) - // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); - // } - // console.log(` - // SumOfLastPeriod : ${web3.utils.fromWei((newData[1].toNumber()).toString())} - // Last Timestamp Index : ${newData[0].length -1} - // `); - // }); - - // it("Should transfer the more tokens on the same day", async() => { - // // Check the balance of the investors - // let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - // let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - // await I_SecurityToken.transfer(account_investor3, tempAmount, {from: account_investor1}); - - // // Check the balance of the investors - // let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); - // // Verifying the balances - // assert.closeTo( - // (balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), - // tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(), - // 0.01 - // ); - // tempArray[tempArray.length -1] = tempArray[tempArray.length -1] + tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(); - // let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - // for (let i = 2; i < data[0].length; i++) { - // console.log(` - // Timestamps array index ${i}: ${data[0][i].toNumber()} - // Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18))} - // `); - // assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - // assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - // .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); - // } - // console.log(` - // SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - // Last Timestamp Index : ${data[0].length -1} - // `); - // let sumOflastperiod = 0; - // for (let i = tempArray.length - 1; i >= tempArray.length - 3; i--) { - // sumOflastperiod += tempArray[i]; - // } - // assert.equal(data[0].length - 1, 4); - // assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), sumOflastperiod, 0.001); - // }); + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length - 1} + `); + assert.equal(data[0].length - 1, 2); + assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), + oldData[1].dividedBy(new BigNumber(10).pow(18)).toNumber() + totalAmountTransacted, 0.001); + }); + + it.skip("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + let minimumAmount = new BigNumber(12).times(new BigNumber(10).pow(18)).minus(data[1]); + let testAmount = minimumAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))) + await catchRevert( + I_SecurityToken.transfer(account_investor3, testAmount, {from: account_investor1}) + ); + }); + + it.skip("Should fail to buy tokens in the new rolling period --failed because amount is more than last two timestamps", async() => { + await increaseTime(duration.days(2)); + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_investor1}) + ); + }); + + it.skip("Should transfer the tokens in a new rolling period", async() => { + let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + let firstDayAmount; + tempAmount = new BigNumber(0); + for (let i = 0; i < oldData[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${oldData[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + if (i != 2) { + firstDayAmount = await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][0]); + tempAmount = tempAmount.plus(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])); + } + } + + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((oldData[1].toNumber()).toString())} + Last Timestamp Index : ${oldData[0].length -1} + `); + + let currentDayAmount = firstDayAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))); + let tx = await I_SecurityToken.transfer(account_investor3, currentDayAmount, {from: account_investor1}); + tempAmount = tempAmount.minus(currentDayAmount); + tempArray.push(0); + tempArray.push(currentDayAmount.dividedBy(new BigNumber(10).pow(18)).toNumber()); + console.log('\n'); + let newData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 2; i < newData[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${newData[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(newData[0][i].toNumber(), startTime + duration.days(i)) + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((newData[1].toNumber()).toString())} + Last Timestamp Index : ${newData[0].length -1} + `); + }); + + it.skip("Should transfer the more tokens on the same day", async() => { + // Check the balance of the investors + let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + await I_SecurityToken.transfer(account_investor3, tempAmount, {from: account_investor1}); + + // Check the balance of the investors + let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.closeTo( + (balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), + tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(), + 0.01 + ); + tempArray[tempArray.length -1] = tempArray[tempArray.length -1] + tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(); + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + for (let i = 2; i < data[0].length; i++) { + console.log(` + Timestamps array index ${i}: ${data[0][i].toNumber()} + Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18))} + `); + assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) + assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); + } + console.log(` + SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} + Last Timestamp Index : ${data[0].length -1} + `); + let sumOflastperiod = 0; + for (let i = tempArray.length - 1; i >= tempArray.length - 3; i--) { + sumOflastperiod += tempArray[i]; + } + assert.equal(data[0].length - 1, 4); + assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), sumOflastperiod, 0.001); + }); }); describe.skip("Test case for the variable individual restriction", async() => { @@ -1468,5 +1465,33 @@ contract('VolumeRestrictionTransferManager', accounts => { }); }); + + describe("VolumeRestriction Transfer Manager Factory test cases", async() => { + + it("Should get the exact details of the factory", async() => { + assert.equal(await I_VolumeRestrictionTMFactory.getSetupCost.call(),0); + assert.equal((await I_VolumeRestrictionTMFactory.getTypes.call())[0],2); + assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTMFactory.getName.call()) + .replace(/\u0000/g, ''), + "VolumeRestrictionTM", + "Wrong Module added"); + assert.equal(await I_VolumeRestrictionTMFactory.description.call(), + "Manage transfers based on the volume of tokens that needs to be transact", + "Wrong Module added"); + assert.equal(await I_VolumeRestrictionTMFactory.title.call(), + "Volume Restriction Transfer Manager", + "Wrong Module added"); + assert.equal(await I_VolumeRestrictionTMFactory.getInstructions.call(), + "Module used to restrict the volume of tokens traded by the token holders", + "Wrong Module added"); + assert.equal(await I_VolumeRestrictionTMFactory.version.call(), "1.0.0"); + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_VolumeRestrictionTMFactory.getTags.call(); + assert.equal(tags.length, 4); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Maximum Volume"); + }); + }); }); \ No newline at end of file From d47cc3270ce814f5543935828cae62bbef51c3ef Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 2 Dec 2018 14:47:01 -0300 Subject: [PATCH 297/582] Refactoring and improvements --- CLI/commands/common/common_functions.js | 51 ++++++++++++++++--------- CLI/commands/helpers/csv.js | 17 +++------ 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index 0d21d06f3..a59b9ac21 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -42,7 +42,7 @@ function getFinalOptions(options) { async function getGasLimit(options, action) { let block = await web3.eth.getBlock("latest"); let networkGasLimit = block.gasLimit; - let gas = Math.round(options.factor * (await action.estimateGas({ from: options.from.address, value: options.value}))); + let gas = Math.round(options.factor * (await action.estimateGas({ from: options.from.address, value: options.value }))); return (gas > networkGasLimit) ? networkGasLimit : gas; } @@ -65,16 +65,16 @@ async function checkPermissions(action) { module.exports = { convertToDaysRemaining: function (timeRemaining) { var seconds = parseInt(timeRemaining, 10); - + var days = Math.floor(seconds / (3600 * 24)); - seconds -= days * 3600 * 24; - var hrs = Math.floor(seconds / 3600); - seconds -= hrs * 3600; + seconds -= days * 3600 * 24; + var hrs = Math.floor(seconds / 3600); + seconds -= hrs * 3600; var mnts = Math.floor(seconds / 60); - seconds -= mnts * 60; + seconds -= mnts * 60; return (days + " days, " + hrs + " Hrs, " + mnts + " Minutes, " + seconds + " Seconds"); }, - logAsciiBull: function() { + logAsciiBull: function () { console.log(` /######%%, /#( ##########%%%%%, ,%%%. % @@ -103,8 +103,8 @@ module.exports = { options = getFinalOptions(options); let gasLimit = await getGasLimit(options, action); - - console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gasLimit} ----`)); + + console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gasLimit} ----`)); let nonce = await web3.eth.getTransactionCount(options.from.address); let abi = action.encodeABI(); @@ -117,24 +117,24 @@ module.exports = { nonce: nonce, value: web3.utils.toHex(options.value) }; - + const transaction = new Tx(parameter); transaction.sign(Buffer.from(options.from.privateKey.replace('0x', ''), 'hex')); return await web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex')) - .on('transactionHash', function(hash){ - console.log(` + .on('transactionHash', function (hash) { + console.log(` Your transaction is being processed. Please wait... TxHash: ${hash}` - ); - }) - .on('receipt', function(receipt){ - console.log(` + ); + }) + .on('receipt', function (receipt) { + console.log(` Congratulations! The transaction was successfully completed. Gas used: ${receipt.gasUsed} - Gas spent: ${web3.utils.fromWei((new web3.utils.BN(options.gasPrice)).mul(new web3.utils.BN(receipt.gasUsed)))} Ether Review it on Etherscan. TxHash: ${receipt.transactionHash}\n` - ); - }); + ); + }); }, getEventFromLogs: function (jsonInterface, logs, eventName) { let eventJsonInterface = jsonInterface.find(o => o.name === eventName && o.type === 'event'); @@ -145,5 +145,20 @@ module.exports = { let eventJsonInterface = jsonInterface.find(o => o.name === eventName && o.type === 'event'); let filteredLogs = logs.filter(l => l.topics.includes(eventJsonInterface.signature)); return filteredLogs.map(l => web3.eth.abi.decodeLog(eventJsonInterface.inputs, l.data, l.topics.slice(1))); + }, + splitIntoBatches: function (data, batchSize) { + let allBatches = []; + for (let index = 0; index < data.length; index += batchSize) { + allBatches.push(data.slice(index, index + batchSize)); + } + return allBatches; + }, + transposeBatches: function (batches) { + let result = []; + let columns = batches[0][0].length; + for (let index = 0; index < columns; index++) { + result[index] = batches.map(batch => batch.map(record => record[index])); + } + return result; } }; diff --git a/CLI/commands/helpers/csv.js b/CLI/commands/helpers/csv.js index 560adb935..a36dcec15 100644 --- a/CLI/commands/helpers/csv.js +++ b/CLI/commands/helpers/csv.js @@ -1,5 +1,6 @@ const csvParse = require('csv-parse/lib/sync'); const fs = require('fs'); +const web3Utils = require('web3-utils'); function _cast(obj) { if (/^(\-|\+)?([1-9]+[0-9]*)$/.test(obj)) { // Int @@ -16,6 +17,8 @@ function _cast(obj) { } else if (obj.toLowerCase() === "true" || obj.toLowerCase() === "false") { // Boolean obj = JSON.parse(obj.toLowerCase()); + } else if (web3Utils.isAddress(obj)) { + obj = web3Utils.toChecksumAddress(obj); } return obj; } @@ -25,18 +28,8 @@ function parse(_csvFilePath, _batchSize) { let input = fs.readFileSync(_csvFilePath); // Parse csv let data = csvParse(input, { cast: _cast }); - // Batches - let allBatches = []; - for (let index = 0; index < data.length; index += _batchSize) { - allBatches.push(data.slice(index, index + _batchSize)); - } - // Transform result - let result = []; - let columnsLenght = data[0].length; - for (let index = 0; index < columnsLenght; index++) { - result[index] = allBatches.map(batch => batch.map(record => record[index])); - } - return result; + + return data; } module.exports = parse; \ No newline at end of file From 1fecc9a3941de0e47b9208a66ed50334a9d099eb Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 2 Dec 2018 15:18:31 -0300 Subject: [PATCH 298/582] STO manager refactoring for batch operations --- CLI/commands/common/constants.js | 15 +- CLI/commands/sto_manager.js | 238 ++++++++----------------------- CLI/polymath-cli.js | 18 --- 3 files changed, 66 insertions(+), 205 deletions(-) diff --git a/CLI/commands/common/constants.js b/CLI/commands/common/constants.js index c3e2b796c..bb9c8f69c 100644 --- a/CLI/commands/common/constants.js +++ b/CLI/commands/common/constants.js @@ -7,22 +7,22 @@ module.exports = Object.freeze({ BURN: 5 }, DURATION: { - seconds: function(val) { + seconds: function (val) { return val }, - minutes: function(val) { + minutes: function (val) { return val * this.seconds(60) }, - hours: function(val) { + hours: function (val) { return val * this.minutes(60) }, - days: function(val) { + days: function (val) { return val * this.hours(24) }, - weeks: function(val) { + weeks: function (val) { return val * this.days(7) }, - years: function(val) { + years: function (val) { return val * this.days(365) } }, @@ -30,5 +30,6 @@ module.exports = Object.freeze({ ETH: 0, POLY: 1, DAI: 2 - } + }, + DEFAULT_BATCH_SIZE: 75 }); \ No newline at end of file diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index c77bb2485..8e2a347f0 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -8,6 +8,11 @@ const csv_shared = require('./common/csv_shared'); const csvParse = require('./helpers/csv'); const BigNumber = require('bignumber.js'); +/////////////////// +// Constants +const ACCREDIT_DATA_CSV = './CLI/data/STO/USDTieredSTO/accredited_data.csv'; +const NON_ACCREDIT_LIMIT_DATA_CSV = './CLI/data/STO/USDTieredSTO/nonAccreditedLimits_data.csv' + /////////////////// // Crowdsale params let tokenSymbol; @@ -19,12 +24,6 @@ let polyToken; let usdToken; let securityToken; -/* CSV variables */ -let distribData = new Array(); -let fullFileData = new Array(); -let badData = new Array(); -/* End CSV variables */ - async function executeApp() { let exit = false; while (!exit) { @@ -697,18 +696,7 @@ async function usdTieredSTO_configure(currentSTO) { await common.sendTransaction(changeAccreditedAction); break; case 2: - let batchSize = 75; - let csvFile = fs.readFileSync('./CLI/data/accredited_data.csv'); - let columns = ['address', 'accredited']; - let resultData = []; - let index = 0; - while (true) { - index++; - let data = csvParse(csvFile, { columns: columns, from_line: index, to_line: batchSize * index }); - resultData.push(data); - } - let accredit; - await startCSV(tokenSymbol, 75, 'accredited'); + await changeAccreditedInBatch(currentSTO); break; case 3: let account = readlineSync.question('Enter the address to change non accredited limit: '); @@ -716,11 +704,10 @@ async function usdTieredSTO_configure(currentSTO) { let accounts = [account]; let limits = [web3.utils.toWei(limit)]; let changeNonAccreditedLimitAction = currentSTO.methods.changeNonAccreditedLimit(accounts, limits); - // 2 GAS? await common.sendTransaction(changeNonAccreditedLimitAction); break; case 4: - await startCSV(tokenSymbol, 75, 'nonAccreditedLimit'); + await changeNonAccreditedLimitsInBatch(currentSTO); break; case 5: await modfifyTimes(currentSTO); @@ -746,164 +733,60 @@ async function usdTieredSTO_configure(currentSTO) { } } -async function startCSV(tokenSymbol, batchSize, accreditionType) { - let file, proccessing, saving; - - switch (accreditionType) { - case 'accredited': - file = './CLI/data/accredited_data.csv' - proccessing = accredit_processing - saving = saveInBlockchainAccredited - break; - case 'nonAccreditedLimit': - file = './CLI/data/nonAccreditedLimits_data.csv' - proccessing = nonAccredited_processing - saving = saveInBlockchainNonAccredited - break; - } - - securityToken = await csv_shared.start(tokenSymbol, batchSize); - - let result_processing = await csv_shared.read(file, proccessing); - distribData = result_processing.distribData; - fullFileData = result_processing.fullFileData; - badData = result_processing.badData; - - await saving(); -} - -function nonAccredited_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let isNumber = !isNaN(csv_line[1]); - - if (isAddress && isNumber) { - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), csv_line[1])] - } else { - return [false, new Array(csv_line[0], csv_line[1])] - } -} - -function accredit_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let isAccredited = (typeof JSON.parse(csv_line[1].toLowerCase())) == "boolean" ? JSON.parse(csv_line[1].toLowerCase()) : "not-valid"; - - if (isAddress && - (isAccredited != "not-valid")) { - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), isAccredited)] - } else { - return [false, new Array(csv_line[0], isAccredited)] - } -} - -async function saveInBlockchainAccredited() { - let gtmModules; - try { - gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); - } catch (e) { - console.log("Please attach USDTieredSTO module before launch this action.", e) - process.exit(0) - } - - if (!gtmModules.length) { - console.log("Please attach USDTieredSTO module before launch this action.") - process.exit(0) - } - - let usdTieredSTO = new web3.eth.Contract(abis.usdTieredSTO(), gtmModules[0]); - - console.log(` - -------------------------------------------------------- - ----- Sending accreditation changes to blockchain ----- - -------------------------------------------------------- - `); - - for (let i = 0; i < distribData.length; i++) { - try { - - // Splitting the user arrays to be organized by input - for (let i = 0; i < distribData.length; i++) { - try { - let investorArray = [], isAccreditedArray = []; - - for (let j = 0; j < distribData[i].length; j++) { - investorArray.push(distribData[i][j][0]) - isAccreditedArray.push(distribData[i][j][1]) - } - - let changeAccreditedAction = await usdTieredSTO.methods.changeAccredited(investorArray, isAccreditedArray); - let tx = await common.sendTransaction(changeAccreditedAction); - console.log(`Batch ${i} - Attempting to change accredited accounts:\n\n`, investorArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Change accredited transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - } catch (err) { - console.log("ERROR:", err); - } - } - - } catch (err) { - console.log("ERROR", err) - process.exit(0) - } +async function changeAccreditedInBatch(currentSTO) { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ACCREDIT_DATA_CSV}): `, { + defaultInput: ACCREDIT_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => web3.utils.isAddress(row[0]) && typeof row[1] === 'boolean'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')}`)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, isAccreditedArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to change accredited accounts:\n\n`, investorArray[batch], '\n'); + let action = await currentSTO.methods.changeAccredited(investorArray[batch], isAccreditedArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Change accredited transaction was successful.')); + console.log(`${receipt.gasUsed} gas used. Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } - - return; } -async function saveInBlockchainNonAccredited() { - let gtmModules; - try { - gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('USDTieredSTO')).call(); - } catch (e) { - console.log("Please attach USDTieredSTO module before launch this action.", e) - process.exit(0) - } - - if (!gtmModules.length) { - console.log("Please attach USDTieredSTO module before launch this action.") - process.exit(0) - } - - let usdTieredSTO = new web3.eth.Contract(abis.usdTieredSTO(), gtmModules[0]); - - console.log(` - -------------------------------------------------------------- - ----- Sending non accredited limit changes to blockchain ----- - -------------------------------------------------------------- - `); - - for (let i = 0; i < distribData.length; i++) { - try { - - // Splitting the user arrays to be organized by input - for (let i = 0; i < distribData.length; i++) { - try { - let investorArray = [], limitArray = []; - - for (let j = 0; j < distribData[i].length; j++) { - investorArray.push(distribData[i][j][0]); - limitArray.push(web3.utils.toWei(distribData[i][j][1].toString())); - } - - let changeNonAccreditedLimitAction = await usdTieredSTO.methods.changeNonAccreditedLimit(investorArray, limitArray); - let tx = await common.sendTransaction(changeNonAccreditedLimitAction); - console.log(`Batch ${i} - Attempting to change non accredited limits to accounts:\n\n`, investorArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Change accredited transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString()), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - - } catch (err) { - console.log("ERROR:", err); - } - } - - } catch (err) { - console.log("ERROR", err) - process.exit(0) - } +async function changeNonAccreditedLimitsInBatch(currentSTO) { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${NON_ACCREDIT_LIMIT_DATA_CSV}): `, { + defaultInput: NON_ACCREDIT_LIMIT_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => web3.utils.isAddress(row[0]) && !isNaN(row[1])); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')}`)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, limitArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to change accredited accounts:\n\n`, investorArray[batch], '\n'); + let action = await currentSTO.methods.changeNonAccreditedLimit(investorArray[batch], limitArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Change non accredited limits transaction was successful.')); + console.log(`${receipt.gasUsed} gas used. Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } - - return; } async function modfifyTimes(currentSTO) { @@ -1071,10 +954,5 @@ module.exports = { addSTOModule: async function (_tokenSymbol, stoConfig) { await initialize(_tokenSymbol); return addSTOModule(stoConfig) - }, - startCSV: async function (tokenSymbol, batchSize, accreditionType) { - return startCSV(tokenSymbol, batchSize, accreditionType); } -} - - +} \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 3e2494a3f..524c167cb 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -144,24 +144,6 @@ program await contract_manager.executeApp(); }); -program - .command('accredit [batchSize]') - .alias('a') - .description('Runs accredit') - .action(async function (tokenSymbol, batchSize) { - await gbl.initialize(program.remoteNode); - await sto_manager.startCSV(tokenSymbol, batchSize, 'accredited') - }); - -program - .command('nonAccreditedLimit [batchSize]') - .alias('nal') - .description('Runs changeNonAccreditedLimit') - .action(async function (tokenSymbol, batchSize) { - await gbl.initialize(program.remoteNode); - await sto_manager.startCSV(tokenSymbol, batchSize, 'nonAccreditedLimit') - }); - program .command('strMigrator [toStrAddress] [fromTrAddress] [fromStrAddress]') .alias('str') From dde9bf0c2bfddf8c9cd0fae7c8b2b382628ecc24 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 2 Dec 2018 16:03:43 -0300 Subject: [PATCH 299/582] Transfer manager refactoring for batches --- CLI/commands/sto_manager.js | 2 - CLI/commands/transfer_manager.js | 293 +++++++++---------------------- CLI/polymath-cli.js | 9 - 3 files changed, 82 insertions(+), 222 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 8e2a347f0..d5bd58a4d 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -4,9 +4,7 @@ const contracts = require('./helpers/contract_addresses'); const abis = require('./helpers/contract_abis'); const common = require('./common/common_functions'); const gbl = require('./common/global'); -const csv_shared = require('./common/csv_shared'); const csvParse = require('./helpers/csv'); -const BigNumber = require('bignumber.js'); /////////////////// // Constants diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index dc5aba389..ca2f4ee06 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1,26 +1,21 @@ -var readlineSync = require('readline-sync'); -var chalk = require('chalk'); -var moment = require('moment'); -var common = require('./common/common_functions'); -var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis'); -var gbl = require('./common/global'); -var transferManager = require('./transfer_manager'); -var csv_shared = require('./common/csv_shared'); -var BigNumber = require('bignumber.js'); +const readlineSync = require('readline-sync'); +const chalk = require('chalk'); +const moment = require('moment'); +const common = require('./common/common_functions'); +const contracts = require('./helpers/contract_addresses'); +const abis = require('./helpers/contract_abis'); +const gbl = require('./common/global'); +const csvParse = require('./helpers/csv'); + +/////////////////// +// Constants +const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; // App flow let tokenSymbol; let securityToken; let securityTokenRegistry; let currentTransferManager; -let generalTransferManager; - -/* CSV variables */ -let distribData = new Array(); -let fullFileData = new Array(); -let badData = new Array(); -/* End CSV variables */ async function executeApp() { let exit = false; @@ -334,7 +329,7 @@ async function generalTransferManager() { console.log(`- Allow all burn transfers: ${displayAllowAllBurnTransfers ? `YES` : `NO`}`); // ------------------ - let options = ['Modify whitelist', 'Modify whitelist from CSV', /*'Modify Whitelist Signed',*/ + let options = ['Check whitelist', 'Modify whitelist', 'Modify whitelist from CSV', /*'Modify Whitelist Signed',*/ `Change issuance address`, 'Change signing address']; if (displayAllowAllTransfers) { options.push('Disallow all transfers'); @@ -361,6 +356,19 @@ async function generalTransferManager() { let optionSelected = options[index]; console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); switch (optionSelected) { + case 'Check whitelist': + let investorToCheck = readlineSync.question('Enter the address you want to check: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let timeRestriction = await currentTransferManager.methods.whitelist(investorToCheck).call(); + console.log(`Sale lockup: ${moment.unix(timeRestriction.fromTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`Buy lockup: ${moment.unix(timeRestriction.toTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`KYC expiry time: ${moment.unix(timeRestriction.expiryTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`Restricted investor: ${timeRestriction.canBuyFromSTO ? 'YES' : 'NO'} `); + break; case 'Modify whitelist': let investor = readlineSync.question('Enter the address to whitelist: ', { limit: function (input) { @@ -369,10 +377,10 @@ async function generalTransferManager() { limitMessage: "Must be a valid address" }); let now = Math.floor(Date.now() / 1000); - let fromTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens (now = ${now}): `, { defaultInput: now }); - let toTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (now = ${now}): `, { defaultInput: now }); + let fromTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens(now = ${now}): `, { defaultInput: now }); + let toTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others(now = ${now}): `, { defaultInput: now }); let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated (after that investor need to do re-KYC) (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated(after that investor need to do re - KYC) (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); @@ -380,10 +388,7 @@ async function generalTransferManager() { console.log(chalk.green(`${modifyWhitelistEvent._investor} has been whitelisted sucessfully!`)); break; case 'Modify whitelist from CSV': - console.log(chalk.yellow(`Data is going to be read from 'data/whitelist_data.csv'. Be sure this file is updated!`)); - if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { - await transferManager.startCSV(tokenSymbol); - } + await modifyWhitelistInBatch(); break; /* case 'Modify Whitelist Signed': @@ -403,7 +408,7 @@ async function generalTransferManager() { let modifyWhitelistSignedAction = currentTransferManager.methods.modifyWhitelistSigned(investorSigned, fromTimeSigned, toTimeSigned, expiryTimeSigned, canBuyFromSTOSigned); let modifyWhitelistSignedReceipt = await common.sendTransaction(Issuer, modifyWhitelistSignedAction, defaultGasPrice); let modifyWhitelistSignedEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistSignedReceipt.logs, 'ModifyWhitelist'); - console.log(chalk.green(`${modifyWhitelistSignedEvent._investor} has been whitelisted sucessfully!`)); + console.log(chalk.green(`${ modifyWhitelistSignedEvent._investor } has been whitelisted sucessfully!`)); break; */ case 'Change issuance address': @@ -477,173 +482,42 @@ async function generalTransferManager() { } } -async function startCSV(tokenSymbol, batchSize) { - securityToken = await csv_shared.start(tokenSymbol, batchSize); - - let result_processing = await csv_shared.read('./CLI/data/whitelist_data.csv', whitelist_processing); - distribData = result_processing.distribData; - fullFileData = result_processing.fullFileData; - badData = result_processing.badData; - - await saveInBlockchain(); - await finalResults(); -}; - -function whitelist_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let sellValid = isValidDate(csv_line[1]) - let buyValid = isValidDate(csv_line[2]) - let kycExpiryDate = isValidDate(csv_line[3]) - let canBuyFromSTO = (typeof JSON.parse(csv_line[4].toLowerCase())) == "boolean" ? JSON.parse(csv_line[4].toLowerCase()) : "not-valid"; - - if (isAddress && - sellValid && - buyValid && - kycExpiryDate && - (canBuyFromSTO != "not-valid")) { - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] - } else { - return [false, new Array(csv_line[0], sellValid, buyValid, kycExpiryDate, canBuyFromSTO)] - } -} - -function isValidDate(date) { - var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(date); - if (matches == null) return false; - var d = matches[2]; - var m = matches[1] - 1; - var y = matches[3]; - var composedDate = new Date(y, m, d); - var timestampDate = composedDate.getTime() - - // For some reason these timestamps are being recorded +4 hours UTC - if (composedDate.getDate() == d && - composedDate.getMonth() == m && - composedDate.getFullYear() == y) { - return timestampDate / 1000 - } else { - return false - } -} - -async function saveInBlockchain() { - let gtmModules; - try { - gtmModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); - } catch (e) { - console.log("Please attach General Transfer module before launch this action.", e) - process.exit(0) - } - - generalTransferManager = new web3.eth.Contract(abis.generalTransferManager(), gtmModules[0]); - - console.log(` - ------------------------------------------------------- - ----- Sending buy/sell restrictions to blockchain ----- - ------------------------------------------------------- - `); - - for (let i = 0; i < distribData.length; i++) { - try { - let investorArray = [], fromTimesArray = [], toTimesArray = [], expiryTimeArray = [], canBuyFromSTOArray = []; - - // Splitting the user arrays to be organized by input - for (let j = 0; j < distribData[i].length; j++) { - investorArray.push(distribData[i][j][0]) - fromTimesArray.push(distribData[i][j][1]) - toTimesArray.push(distribData[i][j][2]) - expiryTimeArray.push(distribData[i][j][3]) - canBuyFromSTOArray.push(distribData[i][j][4]) - } - - let modifyWhitelistMultiAction = await generalTransferManager.methods.modifyWhitelistMulti(investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray); - let tx = await common.sendTransaction(modifyWhitelistMultiAction); - console.log(`Batch ${i} - Attempting to modifyWhitelist accounts:\n\n`, investorArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Whitelist transaxction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - - } catch (err) { - console.log("ERROR", err) - process.exit(0) - } - } - - return; -} - -async function finalResults() { - let totalInvestors = 0; - let updatedInvestors = 0; - let investorObjectLookup = {}; - let investorData_Events = new Array(); - let event_data = await generalTransferManager.getPastEvents('ModifyWhitelist', {fromBlock: 0, toBlock: 'latest'}, () => {}); - - for (var i = 0; i < event_data.length; i++) { - let combineArray = []; - - let investorAddress_Event = event_data[i].returnValues._investor - let fromTime_Event = event_data[i].returnValues._fromTime - let toTime_Event = event_data[i].returnValues._toTime - let expiryTime_Event = event_data[i].returnValues._expiryTime - let canBuyFromSTO_Event = event_data[i].returnValues._canBuyFromSTO - let blockNumber = event_data[i].blockNumber - - combineArray.push(investorAddress_Event); - combineArray.push(fromTime_Event); - combineArray.push(toTime_Event); - combineArray.push(expiryTime_Event); - combineArray.push(canBuyFromSTO_Event); - combineArray.push(blockNumber) - - investorData_Events.push(combineArray) - - // We have already recorded it, so this is an update to our object - if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { - // The block number form the event we are checking is bigger, so we gotta replace it - if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { - investorObjectLookup[investorAddress_Event] = {fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber}; - updatedInvestors += 1; - } - } else { - investorObjectLookup[investorAddress_Event] = {fromTime: fromTime_Event, toTime: toTime_Event, expiryTime: expiryTime_Event, canBuyFromSTO: canBuyFromSTO_Event, recordedBlockNumber: blockNumber}; - totalInvestors += 1; - } - } - - let investorAddress_Events = Object.keys(investorObjectLookup) - - console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); - console.log(`A total of ${totalInvestors} investors have been whitelisted total, all time.\n`); - console.log(`This script in total sent ${fullFileData.length - badData.length} new investors and updated investors to the blockchain.\n`); - console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); - console.log("************************************************************************************************"); - console.log("OBJECT WITH EVERY USER AND THEIR UPDATED TIMES: \n\n", investorObjectLookup) - console.log("************************************************************************************************"); - console.log("LIST OF ALL INVESTORS WHITELISTED: \n\n", investorAddress_Events) - - let missingDistribs = []; - for (let l = 0; l < fullFileData.length; l++) { - if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { - missingDistribs.push(fullFileData[l]) - } +async function modifyWhitelistInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file(${WHITELIST_DATA_CSV}): `, { + defaultInput: WHITELIST_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size(${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => + web3.utils.isAddress(row[0]) && + moment.unix(row[1]).isValid() && + moment.unix(row[2]).isValid() && + moment.unix(row[3]).isValid() && + typeof row[4] === 'boolean' + ); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); } - - if (missingDistribs.length > 0) { - console.log("************************************************************************************************"); - console.log("-- No LogModifyWhitelist event was found for the following data arrays. Please review them manually --") - console.log(missingDistribs) - console.log("************************************************************************************************"); - } else { - console.log("\n************************************************************************************************"); - console.log("All accounts passed through from the CSV were successfully whitelisted, because we were able to read them all from events") - console.log("************************************************************************************************"); + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to change accredited accounts: \n\n`, investorArray[batch], '\n'); + let action = await currentTransferManager.methods.modifyWhitelistMulti(investorArray[batch], fromTimesArray[batch], toTimesArray[batch], expiryTimeArray[batch], canBuyFromSTOArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Whitelist transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } - } async function manualApprovalTransferManager() { - console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address} `), '\n'); let options = ['Check manual approval', 'Add manual approval', 'Revoke manual approval', 'Check manual blocking', 'Add manual blocking', 'Revoke manual blocking']; @@ -671,8 +545,8 @@ async function manualApprovalTransferManager() { let manualApproval = await getManualApproval(from, to); if (manualApproval) { console.log(`Manual approval found!`); - console.log(`Allowance: ${web3.utils.fromWei(manualApproval.allowance)}`); - console.log(`Expiry time: ${moment.unix(manualApproval.expiryTime).format('MMMM Do YYYY, HH:mm:ss')};`) + console.log(`Allowance: ${web3.utils.fromWei(manualApproval.allowance)} `); + console.log(`Expiry time: ${moment.unix(manualApproval.expiryTime).format('MMMM Do YYYY, HH:mm:ss')}; `) } else { console.log(chalk.yellow(`There are no manual approvals from ${from} to ${to}.`)); } @@ -693,13 +567,13 @@ async function manualApprovalTransferManager() { if (!await getManualApproval(from, to)) { let allowance = readlineSync.question('Enter the amount of tokens which will be approved: '); let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) until which the transfer is allowed (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is allowed(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); let addManualApprovalAction = currentTransferManager.methods.addManualApproval(from, to, web3.utils.toWei(allowance), expiryTime); let addManualApprovalReceipt = await common.sendTransaction(addManualApprovalAction); let addManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualApprovalReceipt.logs, 'AddManualApproval'); console.log(chalk.green(`Manual approval has been added successfully!`)); } else { - console.log(chalk.red(`A manual approval already exists from ${from} to ${to}. Revoke it first if you want to add a new one.`)); + console.log(chalk.red(`A manual approval already exists from ${from} to ${to}.Revoke it first if you want to add a new one.`)); } break; case 'Revoke manual approval': @@ -741,7 +615,7 @@ async function manualApprovalTransferManager() { let manualBlocking = await getManualBlocking(from, to); if (manualBlocking) { console.log(`Manual blocking found!`); - console.log(`Expiry time: ${moment.unix(manualBlocking).format('MMMM Do YYYY, HH:mm:ss')};`) + console.log(`Expiry time: ${moment.unix(manualBlocking).format('MMMM Do YYYY, HH:mm:ss')}; `) } else { console.log(chalk.yellow(`There are no manual blockings from ${from} to ${to}.`)); } @@ -761,13 +635,13 @@ async function manualApprovalTransferManager() { }); if (!await getManualBlocking(from, to)) { let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) until which the transfer is blocked (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is blocked(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); let addManualBlockingAction = currentTransferManager.methods.addManualBlocking(from, to, expiryTime); let addManualBlockingReceipt = await common.sendTransaction(addManualBlockingAction); let addManualBlockingEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualBlockingReceipt.logs, 'AddManualBlocking'); console.log(chalk.green(`Manual blocking has been added successfully!`)); } else { - console.log(chalk.red(`A manual blocking already exists from ${from} to ${to}. Revoke it first if you want to add a new one.`)); + console.log(chalk.red(`A manual blocking already exists from ${from} to ${to}.Revoke it first if you want to add a new one.`)); } break; case 'Revoke manual blocking': @@ -818,7 +692,7 @@ async function getManualBlocking(_from, _to) { } async function singleTradeVolumeRestrictionTM() { - console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address}`)); + console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address} `)); console.log(); // Show current data @@ -831,9 +705,9 @@ async function singleTradeVolumeRestrictionTM() { } let displayAllowPrimaryIssuance = await currentTransferManager.methods.allowPrimaryIssuance().call(); - console.log(`- Limit type: ${displayIsInPercentage ? `Percentage` : `Tokens`}`); - console.log(`- Default transfer limit: ${displayGlobalTransferLimit} ${displayIsInPercentage ? `%` : `${tokenSymbol}`}`); - console.log(`- Allow primary issuance: ${displayAllowPrimaryIssuance ? `YES` : `NO`}`); + console.log(`- Limit type: ${displayIsInPercentage ? `Percentage` : `Tokens`} `); + console.log(`- Default transfer limit: ${displayGlobalTransferLimit} ${displayIsInPercentage ? `%` : `${tokenSymbol}`} `); + console.log(`- Allow primary issuance: ${displayAllowPrimaryIssuance ? `YES` : `NO`} `); // ------------------ let options = []; @@ -895,7 +769,7 @@ async function singleTradeVolumeRestrictionTM() { let changeTransferLimitToTokensReceipt = await common.sendTransaction(changeTransferLimitToTokensAction); let changeTransferLimitToTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); - console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeTransferLimitToTokensEvent._amount)} ${tokenSymbol}`)); + console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeTransferLimitToTokensEvent._amount)} ${tokenSymbol} `)); break; case 'Change transfer limit to percentage': let newDefaultLimitInPercentage = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { @@ -908,7 +782,7 @@ async function singleTradeVolumeRestrictionTM() { let changeTransferLimitToPercentageReceipt = await common.sendTransaction(changeTransferLimitToPercentageAction); let changeTransferLimitToPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); - console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeTransferLimitToPercentageEvent._percentage)} %`)); + console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeTransferLimitToPercentageEvent._percentage)} % `)); break; case 'Change default percentage limit': let defaultLimitInPercentage = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { @@ -920,7 +794,7 @@ async function singleTradeVolumeRestrictionTM() { let changeGlobalLimitInPercentageAction = currentTransferManager.methods.changeGlobalLimitInPercentage(defaultLimitInPercentage); let changeGlobalLimitInPercentageReceipt = await common.sendTransaction(changeGlobalLimitInPercentageAction); let changeGlobalLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); - console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeGlobalLimitInPercentageEvent._percentage)} %`)); + console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeGlobalLimitInPercentageEvent._percentage)} % `)); break; case 'Change default tokens limit': let defaultLimitInTokens = web3.utils.toWei(readlineSync.question('Enter the amount of tokens for default limit: ', { @@ -932,7 +806,7 @@ async function singleTradeVolumeRestrictionTM() { let changeGlobalLimitInTokensAction = currentTransferManager.methods.changeGlobalLimitInTokens(defaultLimitInTokens); let changeGlobalLimitInTokensReceipt = await common.sendTransaction(changeGlobalLimitInTokensAction); let changeGlobalLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); - console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeGlobalLimitInTokensEvent._amount)} ${tokenSymbol}`)); + console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeGlobalLimitInTokensEvent._amount)} ${tokenSymbol} `)); break; case 'Set percentage transfer limit per account': let percentageAccount = readlineSync.question('Enter the wallet: ', { @@ -950,7 +824,7 @@ async function singleTradeVolumeRestrictionTM() { let setTransferLimitInPercentageAction = currentTransferManager.methods.setTransferLimitInPercentage(percentageAccount, accountLimitInPercentage); let setTransferLimitInPercentageReceipt = await common.sendTransaction(setTransferLimitInPercentageAction); let setTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageSet'); - console.log(chalk.green(`The transfer limit for ${setTransferLimitInPercentageEvent._wallet} is ${fromWeiPercentage(setTransferLimitInPercentageEvent._percentage)} %`)); + console.log(chalk.green(`The transfer limit for ${setTransferLimitInPercentageEvent._wallet} is ${fromWeiPercentage(setTransferLimitInPercentageEvent._percentage)} % `)); break; case 'Set tokens transfer limit per account': let tokensAccount = readlineSync.question('Enter the wallet: ', { @@ -968,7 +842,7 @@ async function singleTradeVolumeRestrictionTM() { let setTransferLimitInTokensAction = currentTransferManager.methods.setTransferLimitInTokens(tokensAccount, accountLimitInTokens); let setTransferLimitInTokensReceipt = await common.sendTransaction(setTransferLimitInTokensAction); let setTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensSet'); - console.log(chalk.green(`The transfer limit for ${setTransferLimitInTokensEvent._wallet} is ${web3.utils.fromWei(setTransferLimitInTokensEvent._amount)} ${tokenSymbol}`)); + console.log(chalk.green(`The transfer limit for ${setTransferLimitInTokensEvent._wallet} is ${web3.utils.fromWei(setTransferLimitInTokensEvent._amount)} ${tokenSymbol} `)); break; case 'Remove percentage transfer limit per account': let percentageAccountToRemove = readlineSync.question('Enter the wallet to remove: ', { @@ -1007,8 +881,8 @@ function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, rest ) .slice(2); packedData = new Buffer(packedData, "hex"); - packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message:\n${packedData.length.toString()}`), packedData]); - packedData = web3.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); + packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message: \n${ packedData.length.toString() } `), packedData]); + packedData = web3.sha3(`0x${ packedData.toString("hex") } `, { encoding: "hex" }); return ethUtil.ecsign(new Buffer(packedData.slice(2), "hex"), new Buffer(pk, "hex")); } */ @@ -1098,7 +972,7 @@ async function selectToken() { return { symbol: tokenData[0], address: t }; })); let options = tokenDataArray.map(function (t) { - return `${t.symbol} - Deployed at ${t.address}`; + return `${t.symbol} - Deployed at ${t.address} `; }); options.push('Enter token symbol manually'); @@ -1126,8 +1000,5 @@ module.exports = { addTransferManagerModule: async function (_tokenSymbol) { await initialize(_tokenSymbol); return addTransferManagerModule() - }, - startCSV: async function (tokenSymbol, batchSize) { - return startCSV(tokenSymbol, batchSize); } } \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 524c167cb..0ffba10dd 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -107,15 +107,6 @@ program await transfer_ownership.executeApp(contractAddress, transferTo); }); -program - .command('whitelist [batchSize]') - .alias('w') - .description('Mass-update a whitelist of allowed/known investors') - .action(async function (tokenSymbol, batchSize) { - await gbl.initialize(program.remoteNode); - await transfer_manager.startCSV(tokenSymbol, batchSize); - }); - program .command('dividends_manager [dividendsType]') .alias('dm') From 11702df8b86daa83033a735ecd1bf9447e06ff53 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 3 Dec 2018 14:04:57 +0530 Subject: [PATCH 300/582] adopting the optimisation deployment of factory --- .../modules/Wallet/VestingEscrowWallet.sol | 45 +---------------- .../Wallet/VestingEscrowWalletFactory.sol | 15 +++--- .../Wallet/VestingEscrowWalletStorage.sol | 50 +++++++++++++++++++ contracts/proxy/VestingEscrowWalletProxy.sol | 27 ++++++++++ 4 files changed, 88 insertions(+), 49 deletions(-) create mode 100644 contracts/modules/Wallet/VestingEscrowWalletStorage.sol create mode 100644 contracts/proxy/VestingEscrowWalletProxy.sol diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 361512698..2ec52c0e4 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -1,6 +1,7 @@ pragma solidity ^0.4.24; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "./VestingEscrowWalletStorage.sol"; import "./IWallet.sol"; /** @@ -11,51 +12,9 @@ contract VestingEscrowWallet is IWallet { bytes32 public constant ADMIN = "ADMIN"; - struct Schedule { - // Name of the template - bytes32 templateName; - // Tokens that were already claimed - uint256 claimedTokens; - // Start time of the schedule - uint256 startTime; - } - - struct Template { - // Total amount of tokens - uint256 numberOfTokens; - // Schedule duration (How long the schedule will last) - uint256 duration; - // Schedule frequency (It is a cliff time period) - uint256 frequency; - } - // States used to represent the status of the schedule enum State {CREATED, STARTED, COMPLETED} - // Number of tokens that are hold by the `this` contract but are unassigned to any schedule - uint256 public unassignedTokens; - // Address of the Treasury wallet. All of the unassigned token will transfer to that address. - address public treasuryWallet; - // List of all beneficiaries who have the schedules running/completed/created - address[] public beneficiaries; - - // Holds schedules array corresponds to the affiliate/employee address - mapping(address => Schedule[]) public schedules; - // Holds template names array corresponds to the affiliate/employee address - mapping(address => bytes32[]) internal userToTemplates; - // Mapping use to store the indexes for different template names for a user. - // affiliate/employee address => template name => index - mapping(address => mapping(bytes32 => uint256)) internal userToTemplateIndex; - // Holds affiliate/employee addresses coressponds to the template name - mapping(bytes32 => address[]) internal templateToUsers; - // Mapping use to store the indexes for different users for a template. - // template name => affiliate/employee address => index - mapping(bytes32 => mapping(address => uint256)) internal templateToUserIndex; - // Store the template details corresponds to the template name - mapping(bytes32 => Template) templates; - - // List of all template names - bytes32[] public templateNames; - + // Emit when new schedule is added event AddSchedule( address indexed _beneficiary, diff --git a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol index 88db1919d..62de4c1c6 100644 --- a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol +++ b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./VestingEscrowWallet.sol"; +import "../../proxy/VestingEscrowWalletProxy.sol"; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; @@ -8,20 +8,23 @@ import "../../libraries/Util.sol"; * @title Factory for deploying VestingEscrowWallet module */ contract VestingEscrowWalletFactory is ModuleFactory { - + + address public logicContract; /** * @notice Constructor * @param _polyAddress Address of the polytoken */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; name = "VestingEscrowWallet"; title = "Vesting Escrow Wallet"; description = "Manage vesting schedules to employees / affiliates"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,7 +36,7 @@ contract VestingEscrowWalletFactory is ModuleFactory { if (setupCost > 0) { require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance provided"); } - VestingEscrowWallet vestingEscrowWallet = new VestingEscrowWallet(msg.sender, address(polyToken)); + VestingEscrowWalletProxy vestingEscrowWallet = new VestingEscrowWalletProxy(msg.sender, address(polyToken), logicContract); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == vestingEscrowWallet.getInitFunction(), "Invalid data"); /*solium-disable-next-line security/no-low-level-calls*/ @@ -65,8 +68,8 @@ contract VestingEscrowWalletFactory is ModuleFactory { */ function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](2); - availableTags[0] = "Vested Wallet"; - availableTags[1] = "Escrow"; + availableTags[0] = "Vested"; + availableTags[1] = "Escrow Wallet"; return availableTags; } } diff --git a/contracts/modules/Wallet/VestingEscrowWalletStorage.sol b/contracts/modules/Wallet/VestingEscrowWalletStorage.sol new file mode 100644 index 000000000..f51b7e8a1 --- /dev/null +++ b/contracts/modules/Wallet/VestingEscrowWalletStorage.sol @@ -0,0 +1,50 @@ +pragma solidity ^0.4.24; + +/** + * @title Wallet for core vesting escrow functionality + */ +contract VestingEscrowWalletStorage { + + struct Schedule { + // Name of the template + bytes32 templateName; + // Tokens that were already claimed + uint256 claimedTokens; + // Start time of the schedule + uint256 startTime; + } + + struct Template { + // Total amount of tokens + uint256 numberOfTokens; + // Schedule duration (How long the schedule will last) + uint256 duration; + // Schedule frequency (It is a cliff time period) + uint256 frequency; + } + + // Number of tokens that are hold by the `this` contract but are unassigned to any schedule + uint256 public unassignedTokens; + // Address of the Treasury wallet. All of the unassigned token will transfer to that address. + address public treasuryWallet; + // List of all beneficiaries who have the schedules running/completed/created + address[] public beneficiaries; + + // Holds schedules array corresponds to the affiliate/employee address + mapping(address => Schedule[]) public schedules; + // Holds template names array corresponds to the affiliate/employee address + mapping(address => bytes32[]) internal userToTemplates; + // Mapping use to store the indexes for different template names for a user. + // affiliate/employee address => template name => index + mapping(address => mapping(bytes32 => uint256)) internal userToTemplateIndex; + // Holds affiliate/employee addresses coressponds to the template name + mapping(bytes32 => address[]) internal templateToUsers; + // Mapping use to store the indexes for different users for a template. + // template name => affiliate/employee address => index + mapping(bytes32 => mapping(address => uint256)) internal templateToUserIndex; + // Store the template details corresponds to the template name + mapping(bytes32 => Template) templates; + + // List of all template names + bytes32[] public templateNames; +} \ No newline at end of file diff --git a/contracts/proxy/VestingEscrowWalletProxy.sol b/contracts/proxy/VestingEscrowWalletProxy.sol new file mode 100644 index 000000000..7f73203eb --- /dev/null +++ b/contracts/proxy/VestingEscrowWalletProxy.sol @@ -0,0 +1,27 @@ +pragma solidity ^0.4.24; + +import "../modules/wallet/VestingEscrowWalletStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + /** + * @title Escrow wallet module for vesting functionality + */ +contract VestingEscrowWalletProxy is VestingEscrowWalletStorage, ModuleStorage, Pausable, OwnedProxy { + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + } \ No newline at end of file From 2026bcaea0661b57d9228b49b7bc5b1b8372e5ae Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 3 Dec 2018 14:11:19 +0530 Subject: [PATCH 301/582] add require statement in factory constructors --- .../modules/Checkpoint/ERC20DividendCheckpointFactory.sol | 2 ++ .../modules/Checkpoint/EtherDividendCheckpointFactory.sol | 2 ++ .../modules/TransferManager/GeneralTransferManagerFactory.sol | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index a684e553b..b7e668111 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -16,10 +16,12 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module + * @param _logicContract Contract address that contains the logic related to `description` */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid logic contract"); version = "1.0.0"; name = "ERC20DividendCheckpoint"; title = "ERC20 Dividend Checkpoint"; diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 3129fba42..2d8d8f529 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -16,10 +16,12 @@ contract EtherDividendCheckpointFactory is ModuleFactory { * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module + * @param _logicContract Contract address that contains the logic related to `description` */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid logic contract"); version = "1.0.0"; name = "EtherDividendCheckpoint"; title = "Ether Dividend Checkpoint"; diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 27c894fb2..4259e8b9f 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -13,6 +13,10 @@ contract GeneralTransferManagerFactory is ModuleFactory { /** * @notice Constructor * @param _polyAddress Address of the polytoken + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _subscriptionCost Subscription cost of the module + * @param _logicContract Contract address that contains the logic related to `description` */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) From 9274cdeee0121931496818f14bc3793a6914e8e2 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Mon, 3 Dec 2018 12:03:18 +0100 Subject: [PATCH 302/582] remove all blocking functions --- .../ManualApprovalTransferManager.sol | 57 +------------------ .../ManualApprovalTransferManagerFactory.sol | 4 +- test/j_manual_approval_transfer_manager.js | 54 +----------------- 3 files changed, 6 insertions(+), 109 deletions(-) diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index d95241e9a..fd25ab43d 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -4,7 +4,7 @@ import "./ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** - * @title Transfer Manager module for manually approving or blocking transactions between accounts + * @title Transfer Manager module for manually approving transactions between accounts */ contract ManualApprovalTransferManager is ITransferManager { using SafeMath for uint256; @@ -23,17 +23,9 @@ contract ManualApprovalTransferManager is ITransferManager { uint256 expiryTime; } - //Manual blocking allows you to specify a list of blocked address pairs with an associated expiry time for the block - struct ManualBlocking { - uint256 expiryTime; - } - //Store mappings of address => address with ManualApprovals mapping (address => mapping (address => ManualApproval)) public manualApprovals; - //Store mappings of address => address with ManualBlockings - mapping (address => mapping (address => ManualBlocking)) public manualBlockings; - event AddManualApproval( address indexed _from, address indexed _to, @@ -42,25 +34,12 @@ contract ManualApprovalTransferManager is ITransferManager { address indexed _addedBy ); - event AddManualBlocking( - address indexed _from, - address indexed _to, - uint256 _expiryTime, - address indexed _addedBy - ); - event RevokeManualApproval( address indexed _from, address indexed _to, address indexed _addedBy ); - event RevokeManualBlocking( - address indexed _from, - address indexed _to, - address indexed _addedBy - ); - /** * @notice Constructor * @param _securityToken Address of the security token @@ -88,13 +67,8 @@ contract ManualApprovalTransferManager is ITransferManager { function verifyTransfer(address _from, address _to, uint256 _amount, bytes /* _data */, bool _isTransfer) public returns(Result) { // function must only be called by the associated security token if _isTransfer == true require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); - // manual blocking takes precidence over manual approval + if (!paused) { - /*solium-disable-next-line security/no-block-members*/ - if (manualBlockings[_from][_to].expiryTime >= now) { - return Result.INVALID; - } - /*solium-disable-next-line security/no-block-members*/ if ((manualApprovals[_from][_to].expiryTime >= now) && (manualApprovals[_from][_to].allowance >= _amount)) { if (_isTransfer) { manualApprovals[_from][_to].allowance = manualApprovals[_from][_to].allowance.sub(_amount); @@ -114,28 +88,12 @@ contract ManualApprovalTransferManager is ITransferManager { */ function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { require(_to != address(0), "Invalid to address"); - /*solium-disable-next-line security/no-block-members*/ require(_expiryTime > now, "Invalid expiry time"); require(manualApprovals[_from][_to].allowance == 0, "Approval already exists"); manualApprovals[_from][_to] = ManualApproval(_allowance, _expiryTime); emit AddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender); } - /** - * @notice Adds a pair of addresses to manual blockings - * @param _from is the address from which transfers are blocked - * @param _to is the address to which transfers are blocked - * @param _expiryTime is the time until which the transfer is blocked - */ - function addManualBlocking(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { - require(_to != address(0), "Invalid to address"); - /*solium-disable-next-line security/no-block-members*/ - require(_expiryTime > now, "Invalid expiry time"); - require(manualBlockings[_from][_to].expiryTime == 0, "Blocking already exists"); - manualBlockings[_from][_to] = ManualBlocking(_expiryTime); - emit AddManualBlocking(_from, _to, _expiryTime, msg.sender); - } - /** * @notice Removes a pairs of addresses from manual approvals * @param _from is the address from which transfers are approved @@ -147,17 +105,6 @@ contract ManualApprovalTransferManager is ITransferManager { emit RevokeManualApproval(_from, _to, msg.sender); } - /** - * @notice Removes a pairs of addresses from manual approvals - * @param _from is the address from which transfers are approved - * @param _to is the address to which transfers are approved - */ - function revokeManualBlocking(address _from, address _to) public withPerm(TRANSFER_APPROVAL) { - require(_to != address(0), "Invalid to address"); - delete manualBlockings[_from][_to]; - emit RevokeManualBlocking(_from, _to, msg.sender); - } - /** * @notice Returns the permissions flag that are associated with ManualApproval transfer manager */ diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 9c5513ee7..26dae0136 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -21,7 +21,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { version = "2.0.1"; name = "ManualApprovalTransferManager"; title = "Manual Approval Transfer Manager"; - description = "Manage transfers using single approvals / blocking"; + description = "Manage transfers using single approvals"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } @@ -53,7 +53,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { */ function getInstructions() external view returns(string) { /*solium-disable-next-line max-len*/ - return "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters."; + return "Allows an issuer to set manual approvals for specific pairs of addresses and amounts. Init function takes no parameters."; } /** diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 5779a1c13..80efb2cda 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -442,56 +442,6 @@ contract("ManualApprovalTransferManager", accounts => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); }); - it("Should fail to add a manual block because invalid _to address", async () => { - await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking(account_investor1, "", latestTime() + duration.days(1), { - from: token_owner - }) - ); - }); - - it("Should fail to add a manual block because invalid expiry time", async () => { - await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, 99999, { from: token_owner }) - ); - }); - - it("Add a manual block for a 2nd investor", async () => { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: token_owner - }); - }); - - it("Should fail to add a manual block because blocking already exist", async () => { - await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(5), { from: token_owner }) - ); - }); - - it("Check manual block causes failure", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 })); - }); - - it("Should fail to revoke manual block because invalid _to address", async () => { - await catchRevert(I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, "0x0", { from: token_owner })); - }); - - it("Revoke manual block and check transfer works", async () => { - await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: token_owner }); - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("2", "ether")); - }); - - it("Check manual block ignored after expiry", async () => { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: token_owner - }); - - await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 })); - await increaseTime(1 + 24 * 60 * 60); - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); - }); - it("Should successfully attach the CountTransferManager with the security token (count of 1)", async () => { let bytesCountTM = web3.eth.abi.encodeFunctionCall( { @@ -532,13 +482,13 @@ contract("ManualApprovalTransferManager", accounts => { let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); assert.equal(name, "ManualApprovalTransferManager", "Wrong Module added"); let desc = await I_ManualApprovalTransferManagerFactory.description.call(); - assert.equal(desc, "Manage transfers using single approvals / blocking", "Wrong Module added"); + assert.equal(desc, "Manage transfers using single approvals", "Wrong Module added"); let title = await I_ManualApprovalTransferManagerFactory.title.call(); assert.equal(title, "Manual Approval Transfer Manager", "Wrong Module added"); let inst = await I_ManualApprovalTransferManagerFactory.getInstructions.call(); assert.equal( inst, - "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.", + "Allows an issuer to set manual approvals for specific pairs of addresses and amounts. Init function takes no parameters.", "Wrong Module added" ); assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.0.1"); From df121ea290c8603cf21d734aefeaedef38a738f5 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 3 Dec 2018 14:48:24 +0200 Subject: [PATCH 303/582] test fixes - data structure refactoring --- .../modules/Wallet/VestingEscrowWallet.sol | 16 +- docs/permissions_list.md | 9 +- test/z_vesting_escrow_wallet.js | 183 +++++++++++++----- 3 files changed, 148 insertions(+), 60 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 361512698..6e2fe717e 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -37,6 +37,8 @@ contract VestingEscrowWallet is IWallet { address public treasuryWallet; // List of all beneficiaries who have the schedules running/completed/created address[] public beneficiaries; + // Flag whether beneficiary has been already added or not + mapping(address => bool) internal beneficiaryAdded; // Holds schedules array corresponds to the affiliate/employee address mapping(address => Schedule[]) public schedules; @@ -131,7 +133,7 @@ contract VestingEscrowWallet is IWallet { function _depositTokens(uint256 _numberOfTokens) internal { require(_numberOfTokens > 0, "Should be > 0"); - ISecurityToken(securityToken).transferFrom(treasuryWallet, address(this), _numberOfTokens); + ISecurityToken(securityToken).transferFrom(msg.sender, address(this), _numberOfTokens); unassignedTokens = unassignedTokens.add(_numberOfTokens); emit DepositTokens(_numberOfTokens, msg.sender); } @@ -186,8 +188,8 @@ contract VestingEscrowWallet is IWallet { * @param _name name of template */ function removeTemplate(bytes32 _name) external withPerm(ADMIN) { - require(_isTemplateExists(_name), "Already exists"); - require(templateToUsers[_name].length == 0); + require(_isTemplateExists(_name), "Template not found"); + require(templateToUsers[_name].length == 0, "Template is used"); // delete template data delete templates[_name]; uint256 i; @@ -215,7 +217,7 @@ contract VestingEscrowWallet is IWallet { * @notice get the list of template names * @return bytes32 Array of template names */ - function getTemplateNames() external view returns(bytes32[]) { + function getAllTemplateNames() external view returns(bytes32[]) { return templateNames; } @@ -268,7 +270,7 @@ contract VestingEscrowWallet is IWallet { function _addScheduleFromTemplate(address _beneficiary, bytes32 _templateName, uint256 _startTime) internal { require(_beneficiary != address(0), "Invalid address"); - require(_isTemplateExists(_templateName)); + require(_isTemplateExists(_templateName), "Template not found"); uint256 index = userToTemplateIndex[_beneficiary][_templateName]; require( schedules[_beneficiary].length == 0 || @@ -281,9 +283,9 @@ contract VestingEscrowWallet is IWallet { _depositTokens(numberOfTokens.sub(unassignedTokens)); } unassignedTokens = unassignedTokens.sub(numberOfTokens); - //add beneficiary to the schedule list only if adding first schedule - if (schedules[_beneficiary].length == 0) { + if (!beneficiaryAdded[_beneficiary]) { beneficiaries.push(_beneficiary); + beneficiaryAdded[_beneficiary] = true; } schedules[_beneficiary].push(Schedule(_templateName, 0, _startTime)); userToTemplates[_beneficiary].push(_templateName); diff --git a/docs/permissions_list.md b/docs/permissions_list.md index 009781c05..61de6d2d7 100644 --- a/docs/permissions_list.md +++ b/docs/permissions_list.md @@ -275,8 +275,12 @@ Wallet VestingEscrowWallet + changeTreasuryWallet() + onlyOwner + + depositTokens() - withPerm(ADMIN) + withPerm(ADMIN) sendToTreasury() @@ -305,9 +309,6 @@ revokeAllSchedules() - - trimBeneficiaries() - pushAvailableTokensMulti() diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index cc0aed2d3..5bc1f335b 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -274,9 +274,32 @@ contract('VestingEscrowWallet', accounts => { describe("Depositing and withdrawing tokens", async () => { + it("Should not be able to change treasury wallet -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.changeTreasuryWallet(0, {from: token_owner}) + ); + }); + + it("Should not be able to deposit -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.changeTreasuryWallet(account_beneficiary1, {from: account_beneficiary1}) + ); + }); + + it("Should change treasury wallet", async () => { + const tx = await I_VestingEscrowWallet.changeTreasuryWallet(account_beneficiary1, {from: token_owner}); + + assert.equal(tx.logs[0].args._newWallet, account_beneficiary1); + assert.equal(tx.logs[0].args._oldWallet, token_owner); + let treasuryWallet = await I_VestingEscrowWallet.treasuryWallet.call(); + assert.equal(treasuryWallet, account_beneficiary1); + + await I_VestingEscrowWallet.changeTreasuryWallet(token_owner, {from: token_owner}); + }); + it("Should fail to deposit zero amount of tokens", async () => { await catchRevert( - I_VestingEscrowWallet.depositTokens(0, {from: wallet_admin}) + I_VestingEscrowWallet.depositTokens(0, {from: token_owner}) ); }); @@ -291,7 +314,7 @@ contract('VestingEscrowWallet', accounts => { it("Should deposit tokens for new vesting schedules", async () => { let numberOfTokens = 25000; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); - const tx = await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); @@ -329,7 +352,7 @@ contract('VestingEscrowWallet', accounts => { let timeShift = durationUtil.seconds(100); let startTime = latestTime() + timeShift; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); - await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency); @@ -338,6 +361,12 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should not be able to remove template -- fail because template is used", async () => { + await catchRevert( + I_VestingEscrowWallet.removeTemplate("template-01", {from: wallet_admin}) + ); + }); + it("Should push available tokens to the beneficiary address", async () => { let numberOfTokens = 75000; const tx = await I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: wallet_admin}); @@ -352,7 +381,7 @@ contract('VestingEscrowWallet', accounts => { it("Should fail to modify vesting schedule -- fail because schedule already started", async () => { let templateName = "template-01"; - let startTime = latestTime() + timeShift; + let startTime = latestTime() + 100; await catchRevert( I_VestingEscrowWallet.modifySchedule(account_beneficiary3, templateName, startTime, {from: wallet_admin}) ); @@ -362,6 +391,12 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); + it("Should fail to modify vesting schedule -- fail because date in the past", async () => { + await catchRevert( + I_VestingEscrowWallet.modifySchedule(account_beneficiary3, "template-01", latestTime() - 1000, {from: wallet_admin}) + ); + }); + it("Should withdraw available tokens to the beneficiary address", async () => { let templateName = "template-02"; let numberOfTokens = 33000; @@ -370,11 +405,11 @@ contract('VestingEscrowWallet', accounts => { let timeShift = durationUtil.seconds(100); let startTime = latestTime() + timeShift; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); - await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.addSchedule(account_beneficiary3, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); await increaseTime(timeShift + frequency * 3); - const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); + const tx = await I_VestingEscrowWallet.pullAvailableTokens({from: account_beneficiary3}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); @@ -414,7 +449,7 @@ contract('VestingEscrowWallet', accounts => { let totalNumberOfTokens = getTotalNumberOfTokens(schedules); await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: token_owner}); for (let i = 0; i < schedules.length; i++) { let templateName = schedules[i].templateName; let numberOfTokens = schedules[i].numberOfTokens; @@ -427,7 +462,7 @@ contract('VestingEscrowWallet', accounts => { await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); let numberOfTokens = 100000 + (30000 / 6 * stepCount) + (2000 / 10 * stepCount); - const tx = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); + const tx = await I_VestingEscrowWallet.pullAvailableTokens({from: account_beneficiary3}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), 100000); @@ -442,7 +477,7 @@ contract('VestingEscrowWallet', accounts => { stepCount = 4; await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); - const tx2 = await I_VestingEscrowWallet.withdrawAvailableTokens({from: account_beneficiary3}); + const tx2 = await I_VestingEscrowWallet.pullAvailableTokens({from: account_beneficiary3}); assert.equal(tx2.logs[0].args._beneficiary, account_beneficiary3); assert.equal(tx2.logs[0].args._numberOfTokens.toNumber(), 2000 / 10 * stepCount); @@ -540,7 +575,7 @@ contract('VestingEscrowWallet', accounts => { let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); - await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); await catchRevert( I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: account_beneficiary1}) ); @@ -554,16 +589,20 @@ contract('VestingEscrowWallet', accounts => { let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); - await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); - checkScheduleLog(tx.logs[0], account_beneficiary1, templateName, startTime); + checkTemplateLog(tx.logs[0], templateName, numberOfTokens, duration, frequency); + checkScheduleLog(tx.logs[1], account_beneficiary1, templateName, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 1); let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, templateName); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); + + let templates = await I_VestingEscrowWallet.getTemplateNames.call(account_beneficiary1); + assert.equal(web3.utils.hexToUtf8(templates[0]), templateName); }); it("Should add vesting schedule without depositing to the beneficiary address", async () => { @@ -573,10 +612,11 @@ contract('VestingEscrowWallet', accounts => { let frequency = schedules[0].frequency; let startTime = schedules[0].startTime; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); - const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: token_owner}); - assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); - checkScheduleLog(tx.logs[1], account_beneficiary1, templateName, startTime); + checkTemplateLog(tx.logs[0], templateName, numberOfTokens, duration, frequency); + assert.equal(tx.logs[1].args._numberOfTokens, numberOfTokens); + checkScheduleLog(tx.logs[2], account_beneficiary1, templateName, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 2); @@ -599,16 +639,17 @@ contract('VestingEscrowWallet', accounts => { it("Should not be able to modify schedule -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.modifySchedule(account_beneficiary1, "template-2-01", 10000, 4, 1, latestTime() + 100, {from: account_beneficiary1}) + I_VestingEscrowWallet.modifySchedule(account_beneficiary1, "template-2-01", latestTime() + 100, {from: account_beneficiary1}) ); }); it("Should modify vesting schedule for the beneficiary's address", async () => { + let templateName = "template-2-01"; let numberOfTokens = schedules[0].numberOfTokens; let duration = schedules[0].duration; let frequency = schedules[0].frequency; let startTime = schedules[1].startTime; - const tx = await I_VestingEscrowWallet.modifySchedule(account_beneficiary1, "template-2-01", startTime, {from: wallet_admin}); + const tx = await I_VestingEscrowWallet.modifySchedule(account_beneficiary1, templateName, startTime, {from: wallet_admin}); checkScheduleLog(tx.logs[0], account_beneficiary1, templateName, startTime); @@ -628,16 +669,17 @@ contract('VestingEscrowWallet', accounts => { }); it("Should revoke vesting schedule from the beneficiary address", async () => { - const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, "template-2-01", {from: wallet_admin}); + let templateName = "template-2-01"; + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, templateName, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); - assert.equal(tx.logs[0].args._index, 0); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._templateName), templateName); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 0); - await I_VestingEscrowWallet.removeTemplate("template-2-01", {from: account_beneficiary1}) + await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}) }); it("Should fail to revoke vesting schedule -- fail because address is invalid", async () => { @@ -661,7 +703,7 @@ contract('VestingEscrowWallet', accounts => { it("Should add 3 vesting schedules to the beneficiary address", async () => { let totalNumberOfTokens = getTotalNumberOfTokens(schedules); await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: token_owner}); for (let i = 0; i < schedules.length; i++) { let templateName = schedules[i].templateName; let numberOfTokens = schedules[i].numberOfTokens; @@ -670,12 +712,13 @@ contract('VestingEscrowWallet', accounts => { let startTime = schedules[i].startTime; const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary2, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); - checkScheduleLog(tx.logs[0], account_beneficiary2, templateName, startTime); + checkTemplateLog(tx.logs[0], templateName, numberOfTokens, duration, frequency); + checkScheduleLog(tx.logs[1], account_beneficiary2, templateName, startTime); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); assert.equal(scheduleCount, i + 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, i); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary2, templateName); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); } }); @@ -686,13 +729,13 @@ contract('VestingEscrowWallet', accounts => { ); }); - it("Should revoke vesting schedule from the beneficiary address", async () => { + it("Should revoke 1 of 3 vesting schedule from the beneficiary address", async () => { let templateName = schedules[1].templateName; const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, templateName, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); - assert.equal(tx.logs[0].args._templateName, templateName); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._templateName), templateName); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); assert.equal(scheduleCount, 2); @@ -732,7 +775,7 @@ contract('VestingEscrowWallet', accounts => { let totalNumberOfTokens = getTotalNumberOfTokens(schedules); await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: token_owner}); for (let i = 0; i < schedules.length; i++) { let templateName = schedules[i].templateName; let numberOfTokens = schedules[i].numberOfTokens; @@ -805,6 +848,12 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should not be able to add template -- fail because of invalid name", async () => { + await catchRevert( + I_VestingEscrowWallet.addTemplate("", 25000, 4, 1, {from: wallet_admin}) + ); + }); + it("Should add 3 Templates", async () => { for (let i = 0; i < schedules.length; i++) { let templateName = schedules[i].templateName; @@ -813,23 +862,35 @@ contract('VestingEscrowWallet', accounts => { let frequency = schedules[i].frequency; const tx = await I_VestingEscrowWallet.addTemplate(templateName, numberOfTokens, duration, frequency, {from: wallet_admin}); - assert.equal(tx.logs[0].args._name, templateName); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), templateName); assert.equal(tx.logs[0].args._numberOfTokens.toNumber(), numberOfTokens); assert.equal(tx.logs[0].args._duration.toNumber(), duration); assert.equal(tx.logs[0].args._frequency.toNumber(), frequency); } }); + it("Should not be able to add template -- fail because template already exists", async () => { + await catchRevert( + I_VestingEscrowWallet.addTemplate("template-4-01", 25000, 4, 1, {from: wallet_admin}) + ); + }); + it("Should not be able to remove template -- fail because of permissions check", async () => { await catchRevert( I_VestingEscrowWallet.removeTemplate("template-4-02", {from: account_beneficiary1}) ); }); + it("Should not be able to remove template -- fail because template not found", async () => { + await catchRevert( + I_VestingEscrowWallet.removeTemplate("template-444-02", {from: wallet_admin}) + ); + }); + it("Should remove template", async () => { const tx = await I_VestingEscrowWallet.removeTemplate("template-4-02", {from: wallet_admin}); - assert.equal(tx.logs[0].args._name, removeTemplate); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), "template-4-02"); }); it("Should fail to add vesting schedule from template -- fail because template not found", async () => { @@ -845,6 +906,12 @@ contract('VestingEscrowWallet', accounts => { ); }); + it("Should not be able to add vesting schedule from template -- fail because template not found", async () => { + await catchRevert( + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, "template-777", latestTime() + 100, {from: wallet_admin}) + ); + }); + it("Should add vesting schedule from template", async () => { let templateName = schedules[2].templateName; let numberOfTokens = schedules[2].numberOfTokens; @@ -852,7 +919,7 @@ contract('VestingEscrowWallet', accounts => { let frequency = schedules[2].frequency; let startTime = schedules[2].startTime; await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); - await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); const tx = await I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, templateName, startTime, {from: wallet_admin}); checkScheduleLog(tx.logs[0], account_beneficiary1, templateName, startTime); @@ -860,13 +927,20 @@ contract('VestingEscrowWallet', accounts => { let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); assert.equal(scheduleCount, 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, 0); + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, templateName); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, templateName, {from: wallet_admin}); await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); + it("Should not be able to add vesting schedule from template -- fail because template already added", async () => { + let templateName = schedules[2].templateName; + await catchRevert( + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, templateName, latestTime() + 100, {from: wallet_admin}) + ); + }); + it("Should fail to remove template", async () => { await catchRevert( I_VestingEscrowWallet.removeTemplate("template-4-02", {from: wallet_admin}) @@ -874,11 +948,13 @@ contract('VestingEscrowWallet', accounts => { }); it("Should remove 2 Templates", async () => { + let templateCount = await I_VestingEscrowWallet.getTemplateCount.call({from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate("template-4-01", {from: wallet_admin}); await I_VestingEscrowWallet.removeTemplate("template-4-03", {from: wallet_admin}); - let templateCount = await I_VestingEscrowWallet.getTemplateCount.call({from: wallet_admin}); - assert.equal(templateCount, 0); + let templateCountAfterRemoving = await I_VestingEscrowWallet.getTemplateCount.call({from: wallet_admin}); + assert.equal(templateCount - templateCountAfterRemoving, 2); }); }); @@ -898,7 +974,7 @@ contract('VestingEscrowWallet', accounts => { let startTimes = [latestTime() + 100, latestTime() + 100, latestTime() + 100]; let totalNumberOfTokens = 60000; await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: token_owner}); await catchRevert( I_VestingEscrowWallet.addScheduleMulti(beneficiaries, templateNames, [20000, 30000, 10000], [4, 4], [1, 1, 1], startTimes, {from: wallet_admin}) ); @@ -914,19 +990,20 @@ contract('VestingEscrowWallet', accounts => { let totalNumberOfTokens = 60000; await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: token_owner}); let tx = await I_VestingEscrowWallet.addScheduleMulti(beneficiaries, templateNames, numberOfTokens, durations, frequencies, startTimes, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { - let log = tx.logs[i]; + let templateName = templateNames[i]; let beneficiary = beneficiaries[i]; - checkScheduleLog(log, beneficiary, templateNames[i], startTimes[i]); + checkTemplateLog(tx.logs[i* 2], templateName, numberOfTokens[i], durations[i], frequencies[i]); + checkScheduleLog(tx.logs[i * 2 + 1], beneficiary, templateName, startTimes[i]); let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); assert.equal(scheduleCount, 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, 0); + let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, templateName); checkSchedule(schedule, numberOfTokens[i], durations[i], frequencies[i], startTimes[i], CREATED); } }); @@ -974,7 +1051,7 @@ contract('VestingEscrowWallet', accounts => { it("Should not be able to send available tokens to the beneficiaries addresses -- fail because of array size", async () => { await catchRevert( - I_VestingEscrowWallet.pushAvailableTokensMulti(0, 2, {from: wallet_admin}) + I_VestingEscrowWallet.pushAvailableTokensMulti(0, 3, {from: wallet_admin}) ); }); @@ -990,7 +1067,6 @@ contract('VestingEscrowWallet', accounts => { for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; let beneficiary = beneficiaries[i]; - assert.equal(log.args._beneficiary, beneficiary); assert.equal(log.args._numberOfTokens.toNumber(), 3000); let balance = await I_SecurityToken.balanceOf.call(beneficiary); @@ -1004,38 +1080,40 @@ contract('VestingEscrowWallet', accounts => { }); it("Should not be able to add schedules from template to the beneficiaries -- fail because of permissions check", async () => { - let templateName = "template-5-01"; + let templateName = "template-6-01"; let numberOfTokens = 18000; let duration = durationUtil.weeks(3); let frequency = durationUtil.weeks(1); + let templateNames = [templateName, templateName, templateName]; let startTimes = [latestTime() + durationUtil.seconds(100), latestTime() + durationUtil.seconds(100), latestTime() + durationUtil.seconds(100)]; let totalNumberOfTokens = numberOfTokens * 3; await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); - await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: wallet_admin}); + await I_VestingEscrowWallet.depositTokens(totalNumberOfTokens, {from: token_owner}); await I_VestingEscrowWallet.addTemplate(templateName, numberOfTokens, duration, frequency, {from: wallet_admin}); await catchRevert( - I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, templateName, startTimes, {from: account_beneficiary1}) + I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, templateNames, startTimes, {from: account_beneficiary1}) ); }); it("Should add schedules from template for 3 beneficiaries", async () => { - let templateName = "template-5-01"; + let templateName = "template-6-01"; + let numberOfTokens = 18000; + let duration = durationUtil.weeks(3); + let frequency = durationUtil.weeks(1); + let templateNames = [templateName, templateName, templateName]; + let startTimes = [latestTime() + 100, latestTime() + 100, latestTime() + 100]; - let tx = await I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, [templateName, templateName, templateName], startTimes, {from: wallet_admin}); + let tx = await I_VestingEscrowWallet.addScheduleFromTemplateMulti(beneficiaries, templateNames, startTimes, {from: wallet_admin}); for (let i = 0; i < beneficiaries.length; i++) { let log = tx.logs[i]; let beneficiary = beneficiaries[i]; checkScheduleLog(log, beneficiary, templateName, startTimes[i]); - let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(beneficiary); - assert.equal(scheduleCount.toNumber(), 1); - let schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, templateName); checkSchedule(schedule, numberOfTokens, duration, frequency, startTimes[i], CREATED); } - await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}); }); it("Should not be able to revoke schedules of the beneficiaries -- fail because of permissions check", async () => { @@ -1063,9 +1141,16 @@ contract('VestingEscrowWallet', accounts => { }); +function checkTemplateLog(log, templateName, numberOfTokens, duration, frequency) { + assert.equal(web3.utils.hexToUtf8(log.args._name), templateName); + assert.equal(log.args._numberOfTokens.toNumber(), numberOfTokens); + assert.equal(log.args._duration.toNumber(), duration); + assert.equal(log.args._frequency.toNumber(), frequency); +} + function checkScheduleLog(log, beneficiary, templateName, startTime) { assert.equal(log.args._beneficiary, beneficiary); - assert.equal(log.args._templateName, templateName); + assert.equal(web3.utils.hexToUtf8(log.args._templateName), templateName); assert.equal(log.args._startTime.toNumber(), startTime); } From e4252109678f58f54fb03e57802490f763a50209 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 3 Dec 2018 10:06:11 -0300 Subject: [PATCH 304/582] Fix --- CLI/commands/common/common_functions.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index a59b9ac21..c19834037 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -155,9 +155,11 @@ module.exports = { }, transposeBatches: function (batches) { let result = []; - let columns = batches[0][0].length; - for (let index = 0; index < columns; index++) { - result[index] = batches.map(batch => batch.map(record => record[index])); + if (batches.length > 0 && batches[0].length > 0) { + let columns = batches[0][0].length; + for (let index = 0; index < columns; index++) { + result[index] = batches.map(batch => batch.map(record => record[index])); + } } return result; } From ee54b6d907d3f88d2a577cb12da17ad067f355fe Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 3 Dec 2018 10:07:05 -0300 Subject: [PATCH 305/582] Multi mint in batches --- CLI/commands/common/constants.js | 3 +- CLI/commands/sto_manager.js | 2 +- CLI/commands/token_manager.js | 252 ++++++++----------------------- CLI/commands/transfer_manager.js | 6 +- CLI/polymath-cli.js | 18 +-- 5 files changed, 75 insertions(+), 206 deletions(-) diff --git a/CLI/commands/common/constants.js b/CLI/commands/common/constants.js index bb9c8f69c..30a3bf699 100644 --- a/CLI/commands/common/constants.js +++ b/CLI/commands/common/constants.js @@ -31,5 +31,6 @@ module.exports = Object.freeze({ POLY: 1, DAI: 2 }, - DEFAULT_BATCH_SIZE: 75 + DEFAULT_BATCH_SIZE: 75, + ADDRESS_ZERO: '0x0000000000000000000000000000000000000000' }); \ No newline at end of file diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index d5bd58a4d..b66f3d80e 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -779,7 +779,7 @@ async function changeNonAccreditedLimitsInBatch(currentSTO) { let batches = common.splitIntoBatches(validData, batchSize); let [investorArray, limitArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { - console.log(`Batch ${batch + 1} - Attempting to change accredited accounts:\n\n`, investorArray[batch], '\n'); + console.log(`Batch ${batch + 1} - Attempting to change non accredited limit to accounts:\n\n`, investorArray[batch], '\n'); let action = await currentSTO.methods.changeNonAccreditedLimit(investorArray[batch], limitArray[batch]); let receipt = await common.sendTransaction(action); console.log(chalk.green('Change non accredited limits transaction was successful.')); diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index e8556450d..e10f81467 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -5,8 +5,10 @@ const stoManager = require('./sto_manager'); const transferManager = require('./transfer_manager'); const common = require('./common/common_functions'); const gbl = require('./common/global'); -const csv_shared = require('./common/csv_shared'); -const BigNumber = require('bignumber.js'); +const csvParse = require('./helpers/csv'); + +// Constants +const MULTIMINT_DATA_CSV = './CLI/data/ST/multi_mint_data.csv'; // Load contract artifacts const contracts = require('./helpers/contract_addresses'); @@ -16,19 +18,10 @@ let securityTokenRegistry; let polyToken; let featureRegistry; let securityToken; -let tokenDivisible; let allModules; let tokenSymbol -/* CSV data control */ -let distribData = new Array(); -let fullFileData = new Array(); -let badData = new Array(); -let affiliatesFailedArray = new Array(); -let affiliatesKYCInvalidArray = new Array(); -/* End CSV data control */ - async function setup() { try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); @@ -289,7 +282,7 @@ async function listInvestorsAtCheckpoint(checkpointId) { } async function mintTokens() { - let options = ['Modify whitelist', 'Mint tokens to a single address', `Modify whitelist and mint tokens using data from 'whitelist_data.csv' and 'multi_mint_data.csv'`]; + let options = ['Modify whitelist', 'Mint tokens to a single address', `Mint tokens to multiple addresses from CSV`]; let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); let selected = index == -1 ? 'Return' : options[index]; console.log('Selected:', selected); @@ -313,8 +306,9 @@ async function mintTokens() { let amount = readlineSync.question(`Enter the amount of tokens to mint: `); await mintToSingleAddress(receiver, amount); break; - case `Modify whitelist and mint tokens using data from 'whitelist_data.csv' and 'multi_mint_data.csv'`: - await multi_mint_tokens(); + case `Mint tokens to multiple addresses from CSV`: + console.log(chalk.yellow(`Investors should be previously whitelisted.`)); + await multiMint(); break; } } @@ -345,192 +339,67 @@ async function mintToSingleAddress(_investor, _amount) { } } -async function multi_mint_tokens() { - await transferManager.startCSV(tokenSymbol, 75); - console.log(chalk.green(`\nCongratulations! All the affiliates get succssfully whitelisted, Now its time to Mint the tokens\n`)); - console.log(chalk.red(`WARNING: `) + `Please make sure all the addresses that get whitelisted are only eligible to hold or get Security token\n`); - - await startCSV(tokenSymbol, 75) - console.log(chalk.green(`\nCongratulations! Tokens get successfully Minted and transferred to token holders`)); -} -/// - -async function startCSV(tokenSymbol, batchSize) { - securityToken = await csv_shared.start(tokenSymbol, batchSize); - - let result_processing = await csv_shared.read('./CLI/data/multi_mint_data.csv', multimint_processing); - distribData = result_processing.distribData; - fullFileData = result_processing.fullFileData; - badData = result_processing.badData; - - tokenDivisible = await securityToken.methods.granularity().call() == 1; - - await saveInBlockchain(); - await finalResults(); -} - -function multimint_processing(csv_line) { - let isAddress = web3.utils.isAddress(csv_line[0]); - let validToken = isValidToken(csv_line[1]); - - if (isAddress && - validToken) { - return [true, new Array(web3.utils.toChecksumAddress(csv_line[0]), validToken)] +async function multiMint(_csvFilePath, _batchSize) { + let csvFilePath; + if (typeof _csvFilePath !== 'undefined') { + csvFilePath = _csvFilePath; } else { - return [false, new Array(csv_line[0], csv_line[1])] + csvFilePath = readlineSync.question(`Enter the path for csv data file (${MULTIMINT_DATA_CSV}): `, { + defaultInput: MULTIMINT_DATA_CSV + }); } -} - -function isValidToken(token) { - var tokenAmount = parseFloat(token); - if (tokenDivisible) { - return tokenAmount + let batchSize; + if (typeof _batchSize !== 'undefined') { + batchSize = _batchSize; } else { - if ((tokenAmount % 1 == 0)) { - return tokenAmount; - } - return false - } -} - -async function saveInBlockchain() { - let gtmModules = await securityToken.methods.getModulesByType(3).call(); - - if (gtmModules.length > 0) { - console.log("Minting of tokens is only allowed before the STO get attached"); - process.exit(0); - } - - console.log(` - ----------------------------------------- - ----- Mint the tokens to affiliates ----- - ----------------------------------------- - `); - - for (let i = 0; i < distribData.length; i++) { - try { - let affiliatesVerifiedArray = [], tokensVerifiedArray = []; - - // Splitting the user arrays to be organized by input - for (let j = 0; j < distribData[i].length; j++) { - let investorAccount = distribData[i][j][0]; - let tokenAmount = web3.utils.toWei((distribData[i][j][1]).toString(), "ether"); - let verifiedTransaction = await securityToken.methods.verifyTransfer("0x0000000000000000000000000000000000000000", investorAccount, tokenAmount, web3.utils.fromAscii('')).call(); - if (verifiedTransaction) { - affiliatesVerifiedArray.push(investorAccount); - tokensVerifiedArray.push(tokenAmount); - } else { - let gtmModule = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); - let generalTransferManager = new web3.eth.Contract(abis.generalTransferManager(), gtmModule[0]); - let validKYC = (await generalTransferManager.methods.whitelist(Issuer.address).call()).expiryTime > Math.floor(Date.now()/1000); - if (validKYC) { - affiliatesFailedArray.push(investorAccount); - } else { - affiliatesKYCInvalidArray.push(investorAccount); - } - } - } - - let mintMultiAction = await securityToken.methods.mintMulti(affiliatesVerifiedArray, tokensVerifiedArray); - let tx = await common.sendTransaction(mintMultiAction); - console.log(`Batch ${i} - Attempting to send the Minted tokens to affiliates accounts:\n\n`, affiliatesVerifiedArray, "\n\n"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------"); - console.log("Multi Mint transaction was successful.", tx.gasUsed, "gas used. Spent:", web3.utils.fromWei(BigNumber(tx.gasUsed * defaultGasPrice).toString(), "ether"), "Ether"); - console.log("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\n\n"); - - } catch (err) { - console.log("ERROR", err) - process.exit(0) - } - } - - return; -} - -async function finalResults() { - let totalInvestors = 0; - let updatedInvestors = 0; - let investorObjectLookup = {}; - let investorData_Events = new Array(); - - let event_data = await securityToken.getPastEvents('Minted', {fromBlock: 0, toBlock: 'latest'}, () => {}); - - for (var i = 0; i < event_data.length; i++) { - let combineArray = []; - - let investorAddress_Event = event_data[i].returnValues._to; - let amount_Event = event_data[i].returnValues._value; - let blockNumber = event_data[i].blockNumber; - - combineArray.push(investorAddress_Event); - combineArray.push(amount_Event); - combineArray.push(blockNumber); - - investorData_Events.push(combineArray) - - // We have already recorded it, so this is an update to our object - if (investorObjectLookup.hasOwnProperty(investorAddress_Event)) { - // The block number form the event we are checking is bigger, so we gotta replace it - if (investorObjectLookup[investorAddress_Event].recordedBlockNumber < blockNumber) { - investorObjectLookup[investorAddress_Event] = {amount: amount_Event, recordedBlockNumber: blockNumber}; - updatedInvestors += 1; - } + batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + } + let parsedData = csvParse(csvFilePath); + let tokenDivisible = await securityToken.methods.granularity().call() == 1; + let validData = parsedData.filter(row => + web3.utils.isAddress(row[0]) && + (!isNaN(row[1]) && (tokenDivisible || parseFloat(row[1]) % 1 == 0)) + ); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let verifiedData = []; + let unverifiedData = []; + for (const row of validData) { + let investorAccount = row[0]; + let tokenAmount = web3.utils.toWei(row[1].toString()); + let verifiedTransaction = await securityToken.methods.verifyTransfer(gbl.constants.ADDRESS_ZERO, investorAccount, tokenAmount, web3.utils.fromAscii('')).call(); + if (verifiedTransaction) { + verifiedData.push(row); } else { - investorObjectLookup[investorAddress_Event] = {amount: amount_Event, recordedBlockNumber: blockNumber}; - totalInvestors += 1; + unverifiedData.push(row); } } - let investorAddress_Events = Object.keys(investorObjectLookup) - - console.log(`******************** EVENT LOGS ANALYSIS COMPLETE ********************\n`); - console.log(`A total of ${totalInvestors} affiliated investors get the token\n`); - console.log(`This script in total sent ${fullFileData.length - badData.length - affiliatesFailedArray.length - affiliatesKYCInvalidArray.length} new investors and updated investors to the blockchain.\n`); - console.log(`There were ${badData.length} bad entries that didnt get sent to the blockchain in the script.\n`); - console.log(`There were ${affiliatesKYCInvalidArray.length} accounts with invalid KYC.\n`); - console.log(`There were ${affiliatesFailedArray.length} accounts that didn't get sent to the blockchain as they would fail.\n`); - console.log("************************************************************************************************"); - console.log("OBJECT WITH EVERY USER AND THEIR MINTED TOKEN: \n\n", investorObjectLookup) - console.log("************************************************************************************************"); - console.log("LIST OF ALL INVESTORS WHO GOT THE MINTED TOKENS: \n\n", investorAddress_Events) - - let missingDistribs = [], failedVerificationDistribs = [], invalidKYCDistribs = []; - for (let l = 0; l < fullFileData.length; l++) { - if (affiliatesKYCInvalidArray.includes(fullFileData[l][0])) { - invalidKYCDistribs.push(fullFileData[l]); - } else if (affiliatesFailedArray.includes(fullFileData[l][0])) { - failedVerificationDistribs.push(fullFileData[l]); - } else if (!investorObjectLookup.hasOwnProperty(fullFileData[l][0])) { - missingDistribs.push(fullFileData[l]); - } + let batches = common.splitIntoBatches(verifiedData, batchSize); + let [investorArray, amountArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to mint tokens to accounts: \n\n`, investorArray[batch], '\n'); + amountArray[batch] = amountArray[batch].map(a => web3.utils.toWei(a.toString())); + let action = await securityToken.methods.mintMulti(investorArray[batch], amountArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Multi mint transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } - if (invalidKYCDistribs.length > 0) { - console.log("**************************************************************************************************************************"); - console.log("The following data arrays have an invalid KYC. Please review if these accounts are whitelisted and their KYC is not expired\n"); - console.log(invalidKYCDistribs); - console.log("**************************************************************************************************************************"); - } - if (failedVerificationDistribs.length > 0) { + if (unverifiedData.length > 0) { console.log("*********************************************************************************************************"); - console.log("-- The following data arrays failed at verifyTransfer. Please review if these accounts are whitelisted --\n"); - console.log(failedVerificationDistribs); + console.log('The following data arrays failed at verifyTransfer. Please review if these accounts are whitelisted\n'); + console.log(chalk.red(unverifiedData.map(d => `${d[0]}, ${d[1]}`).join('\n'))); console.log("*********************************************************************************************************"); } - if (missingDistribs.length > 0) { - console.log("******************************************************************************************"); - console.log("-- No Minted event was found for the following data arrays. Please review them manually --\n"); - console.log(missingDistribs); - console.log("******************************************************************************************"); - } - if (missingDistribs.length == 0 && - failedVerificationDistribs.length == 0 && - invalidKYCDistribs.length == 0) { - console.log("\n**************************************************************************************************************************"); - console.log("All accounts passed through from the CSV were successfully get the tokens, because we were able to read them all from events"); - console.log("****************************************************************************************************************************"); - } - } async function withdrawFromContract(erc20address, value) { @@ -824,10 +693,11 @@ async function selectToken() { module.exports = { executeApp: async function (_tokenSymbol) { - await initialize(_tokenSymbol) + await initialize(_tokenSymbol); return executeApp(); }, - startCSV: async function (tokenSymbol, batchSize) { - return startCSV(tokenSymbol, batchSize); + multiMint: async function (_tokenSymbol, _csvPath, _batchSize) { + await initialize(_tokenSymbol); + return multiMint(_csvPath, _batchSize); } } diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index ca2f4ee06..ee42b2fa4 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -483,10 +483,10 @@ async function generalTransferManager() { } async function modifyWhitelistInBatch() { - let csvFilePath = readlineSync.question(`Enter the path for csv data file(${WHITELIST_DATA_CSV}): `, { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${WHITELIST_DATA_CSV}): `, { defaultInput: WHITELIST_DATA_CSV }); - let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size(${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { limit: function (input) { return parseInt(input) > 0; }, @@ -508,7 +508,7 @@ async function modifyWhitelistInBatch() { let batches = common.splitIntoBatches(validData, batchSize); let [investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { - console.log(`Batch ${batch + 1} - Attempting to change accredited accounts: \n\n`, investorArray[batch], '\n'); + console.log(`Batch ${batch + 1} - Attempting to modify whitelist to accounts: \n\n`, investorArray[batch], '\n'); let action = await currentTransferManager.methods.modifyWhitelistMulti(investorArray[batch], fromTimesArray[batch], toTimesArray[batch], expiryTimeArray[batch], canBuyFromSTOArray[batch]); let receipt = await common.sendTransaction(action); console.log(chalk.green('Whitelist transaction was successful.')); diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 0ffba10dd..2ce101a4d 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -74,19 +74,17 @@ program .command('token_manager') .alias('stm') .option('-t, --securityToken ', 'Selects a ST to manage') + .option('-m, --multiMint ', 'Distribute tokens to previously whitelisted investors') + .option('-b, --batchSize ', 'Max number of records per transaction') .description('Manage your Security Tokens, mint tokens, add modules and change config') .action(async function (cmd) { await gbl.initialize(program.remoteNode); - await token_manager.executeApp(cmd.securityToken); - }); - -program - .command('multi_mint [batchSize]') - .alias('mi') - .description('Distribute tokens to previously whitelisted investors') - .action(async function (tokenSymbol, batchSize) { - await gbl.initialize(program.remoteNode); - await token_manager.startCSV(tokenSymbol, batchSize); + if (cmd.multiMint) { + let batchSize = cmd.batchSize ? cmd.batchSize : gbl.constants.DEFAULT_BATCH_SIZE; + await token_manager.multiMint(cmd.securityToken, cmd.multiMint, batchSize); + } else { + await token_manager.executeApp(cmd.securityToken); + } }); program From cb079cb8ac75aa6003e8d0c0a796c7f87e11b214 Mon Sep 17 00:00:00 2001 From: Ricko Date: Mon, 3 Dec 2018 14:41:51 +0100 Subject: [PATCH 306/582] Fuzz test permissions manager module (#395) * count transfer manager module fuzz testfinished * fuzz test for general transfer manager * fuzz tests updates * permission manager fuzzer volumn restriction transfer manager * mint token err * minting issue * fixing some testsing issuesss * all done * fixed cleaning up and commenting of the fuzz test codes * fixed conflict and merged new development functions, deleted all code with STVRTM. * get rid of test for STVTM * adding back missing file * get rid of STVR test * Delete x_single_trade_volume_restriction.js * deleted unused code :( --- .eslintrc.js | 4 +- test/helpers/createInstances.js | 14 - test/x_single_trade_volume_restriction.js | 726 -------------------- test/z_general_permission_manager_fuzzer.js | 669 ++++++++++++++++++ 4 files changed, 672 insertions(+), 741 deletions(-) delete mode 100644 test/x_single_trade_volume_restriction.js create mode 100644 test/z_general_permission_manager_fuzzer.js diff --git a/.eslintrc.js b/.eslintrc.js index 463539deb..8b0c0ac0f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,6 +14,8 @@ module.exports = { "quotes": 0, "semi": 0, "no-undef": 0, - "key-spacing": 0 + "key-spacing": 0, + "no-tabs": 0, + "no-mixed-spaces-and-tabs":0 } }; diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 2021d350e..a739e86fb 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -11,7 +11,6 @@ const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock const ERC20DividendCheckpointFactory = artifacts.require("./ERC20DividendCheckpointFactory.sol"); const EtherDividendCheckpointFactory = artifacts.require("./EtherDividendCheckpointFactory.sol"); const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); -const SingleTradeVolumeRestrictionManagerFactory = artifacts.require('./SingleTradeVolumeRestrictionTMFactory.sol'); const TrackedRedemptionFactory = artifacts.require("./TrackedRedemptionFactory.sol"); const PercentageTransferManagerFactory = artifacts.require("./PercentageTransferManagerFactory.sol"); const ScheduledCheckpointFactory = artifacts.require('./ScheduledCheckpointFactory.sol'); @@ -41,7 +40,6 @@ let I_TrackedRedemptionFactory; let I_ScheduledCheckpointFactory; let I_MockBurnFactory; let I_MockWrongTypeBurnFactory; -let I_SingleTradeVolumeRestrictionManagerFactory; let I_ManualApprovalTransferManagerFactory; let I_VolumeRestrictionTransferManagerFactory; let I_PercentageTransferManagerFactory; @@ -255,18 +253,6 @@ export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyI return new Array(I_VolumeRestrictionTransferManagerFactory); } -export async function deploySingleTradeVolumeRMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); - assert.notEqual( - I_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SingleTradeVolumeRestrictionManagerFactory contract was not deployed" - ); - - await registerAndVerifyByMR(I_SingleTradeVolumeRestrictionManagerFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_SingleTradeVolumeRestrictionManagerFactory); -} - export async function deployScheduleCheckpointAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { I_ScheduledCheckpointFactory = await ScheduledCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js deleted file mode 100644 index 15c01e68c..000000000 --- a/test/x_single_trade_volume_restriction.js +++ /dev/null @@ -1,726 +0,0 @@ -import latestTime from './helpers/latestTime'; -import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeModuleCall } from './helpers/encodeCall'; -import {deploySingleTradeVolumeRMAndVerified, setUpPolymathNetwork } from "./helpers/createInstances"; -import { catchRevert } from "./helpers/exceptions"; - -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionTM'); -const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('SingleTradeVolumeRestrictionManager', accounts => { - - - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_investor5; - let zero_address = '0x0000000000000000000000000000000000000000'; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_SecurityTokenRegistryProxy - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_SingleTradeVolumeRestrictionManagerFactory; - let I_SingleTradeVolumeRestrictionManager; - let P_SingleTradeVolumeRestrictionManagerFactory; - let P_SingleTradeVolumeRestrictionManager; - let I_SingleTradeVolumeRestrictionPercentageManager; - let I_ModuleRegistry; - let I_MRProxied; - let I_ModuleRegistryProxy; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - const STVRParameters = ["bool", "uint256", "bool"]; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - before(async () => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[6]; - account_investor2 = accounts[7]; - account_investor3 = accounts[8]; - account_investor4 = accounts[9]; - account_investor5 = accounts[5]; - - let instances = await setUpPolymathNetwork(account_polymath, token_owner); - - [ - I_PolymathRegistry, - I_PolyToken, - I_FeatureRegistry, - I_ModuleRegistry, - I_ModuleRegistryProxy, - I_MRProxied, - I_GeneralTransferManagerFactory, - I_STFactory, - I_SecurityTokenRegistry, - I_SecurityTokenRegistryProxy, - I_STRProxied - ] = instances; - - // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory - [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); - - }); - - describe("Generate the SecurityToken", async () => { - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { - from: token_owner - }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { - from: token_owner - }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { - from: token_owner - }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { - from: token_owner - }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ - from: _blockNo - }), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - }); - // - describe("Buy tokens using whitelist & manual approvals", async () => { - - it("Should Buy the tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('100', 'ether'), { - from: token_owner - }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('100', 'ether') - ); - }); - - it("Should Buy some more tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { - from: token_owner - }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - // - it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - await catchRevert( - I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { from: token_owner}) - ); - }); - - it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); - - let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { - from: token_owner - }); - - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "SingleTradeVolumeRestrictionManager did not get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestrictionManagerFactory module was not added" - ); - P_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[3].args._module); - }); - - it("Should successfully attach the SingleTradeVolumeRestrictionManager with the security token", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [false, (7 * Math.pow(10, 16)).toString(), false]) - const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { - from: token_owner - }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "TransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestriction module was not added" - ); - I_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); - }); - - it("Should successfully attach the SingleTradeVolumeRestrictionManager (Percentage) with the security token", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { - from: token_owner - }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestriction module was not added" - ); - I_SingleTradeVolumeRestrictionPercentageManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); - }); - - it('should return get permissions', async () => { - let permissions = await I_SingleTradeVolumeRestrictionPercentageManager.getPermissions(); - assert.equal(permissions.length, 1, "Invalid Permissions"); - assert.equal( - web3.utils.toAscii(permissions[0]).replace(/\u0000/g, ''), - "ADMIN", - 'Wrong permissions' - ); - }); - - it("Should allow the primary issuance", async() => { - let snapId = await takeSnapshot(); - await I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}); - await catchRevert( - I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}) - ) - await revertToSnapshot(snapId); - }) - - it("add exempt wallet -- Not authorised ", async () => { - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]) - ); - - await catchRevert( - I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet added as exempt"); - }); - - it("Should remove an exempt wallet", async () => { - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5]) - ); - // 0 address are not allowed to add - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeExemptWallet(zero_address, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { from: token_owner }); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet removed from exempt"); - }); - - it('should set transfer limit for a wallet', async () => { - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100) - ); - - // Transfer limits can't be set to 0 - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 0, { from: token_owner }) - ); - - // Transfer limit cannot be set in percentage - await catchRevert( - I_SingleTradeVolumeRestrictionManager.setTransferLimitInPercentage(accounts[4], 10, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[4]); - assert.equal(tx.logs[0].args._amount, 100); - - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 0, { from: token_owner }) - ); - // Transfer limit can not be set to more 0 - await catchRevert ( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { from: token_owner }) - ); - // Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage - await catchRevert ( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { from: token_owner }) - ); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 50, { from: token_owner }); - assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet added to transfer limits"); - assert.equal(tx.logs[0].args._percentage, 50, "Wrong percentage set"); - }); - - it('should remove transfer limit for wallet', async () => { - // Non Admins cannot set/remove transfer limits - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4]) - ); - - // Non Admins cannot set/remove transfer limits - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[0], { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4], { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet removed"); - }); - - it("Should pause the tranfers at Manager level", async () => { - let tx = await I_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - }); - - it('Should be able to set a global transfer limit', async () => { - // only owner is allowed - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(100 * 10 ** 18) - ); - //Cannot change global limit in percentage when set to tokens - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(100 * 10 ** 18, { from: token_owner }) - ); - // Global limit cannot be set to 0 - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(0, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { - from: token_owner - }); - assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - - //Global limit can be set by non-admins - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89) - ); - // cannot change global limit in tokens if transfer limit is set to percentage - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89, { from: token_owner }) - ); - // Cannot set global limit in tokens to 0 - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(0, { from: token_owner }) - ); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(40, { from: token_owner }); - assert.equal(tx.logs[0].args._percentage, 40, "Global Limit not set"); - // Global limit cannot be set to more than 100 - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(101 * 10 ** 16, { from: token_owner }) - ); - // Global limit in percentage cannot be set when limit is in tokens - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(10, { from: token_owner }) - ); - // Global limit in tokens cannot be set when limit is in percentage - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(10, { from: token_owner }) - ); - }); - - it("Should perform batch updates", async () => { - let wallets = [accounts[0], accounts[1], accounts[2]]; - let tokenLimits = [1, 2, 3]; - let percentageLimits = [5, 6, 7]; - - // Exempt wallet multi cannot be empty wallet - await catchRevert( - P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti([], { from: token_owner }) - ); - - // add exempt wallet multi - let tx = await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { - from: token_owner - }); - let logs = tx.logs.filter(log => log.event === 'ExemptWalletAdded'); - assert.equal(logs.length, wallets.length, "Batch Exempt wallets not added"); - for (let i = 0; i < logs.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); - } - - // Exempt wallet multi cannot be empty wallet - await catchRevert( - P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti([], { from: token_owner }) - ); - - // remove exempt wallet multi - tx = await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { - from: token_owner - }) - logs = tx.logs.filter(log => log.event === 'ExemptWalletRemoved'); - assert.equal(logs.length, wallets.length, "Batch Exempt wallets not removed"); - - for (let i = 0; i < logs.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); - } - // wallets cannot be empty - await catchRevert( - P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([], tokenLimits, { from: token_owner }) - ); - // wallet array length dont match - await catchRevert( - P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([accounts[0]], tokenLimits, { from: token_owner }) - ); - - tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInTokensSet'); - assert.equal(wallets.length, logs.length, "Transfer limit not set"); - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not set for wallet"); - assert.equal(logs[i].args._amount.toNumber(), tokenLimits[i]); - } - // Wallets cannot be empty - await catchRevert( - P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti([], { from: token_owner }) - ); - tx = await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event === 'TransferLimitInTokensRemoved'); - assert.equal(logs.length, wallets.length, "Transfer limit not removed"); - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not removed for wallet"); - } - // wallets cannot be empty - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti([], percentageLimits, { from: token_owner }) - ); - // wallets and amounts dont match be empty - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, [], { from: token_owner }) - ); - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageSet'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - assert.equal(logs[i].args._percentage.toNumber(), percentageLimits[i]); - } - // Wallets cannot be empty - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti([], { from: token_owner }) - ); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageRemoved'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - } - // Wallet should not be removed - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentage(wallets[0], { from: token_owner }) - ); - }) - - it('should be able to transfer tokens SingleTradeVolumeRestriction', async () => { - await I_SingleTradeVolumeRestrictionManager.unpause({ - from: token_owner - }) - await I_SingleTradeVolumeRestrictionPercentageManager.pause({ - from: token_owner - }) - await P_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor4, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor5, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - - //setting a max of 5 tokens - await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(web3.utils.toWei('5', 'ether'), { - from: token_owner - }) - // Transfer should have not happened - await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei('6', 'ether'), { from: account_investor1 }) - ); - - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('4', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('4', 'ether')); - - // exempt wallet - await I_SingleTradeVolumeRestrictionManager.addExemptWallet(account_investor1, { - from: token_owner - }); - await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('7', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toNumber(), web3.utils.toWei('7', 'ether')); - - //special limits wallet - await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(account_investor5, web3.utils.toWei('5', 'ether'), { - from: token_owner - }); - - // Transfer should have not happened - await catchRevert( - I_SecurityToken.transfer(account_investor4, web3.utils.toWei('7', 'ether'), { from: account_investor5 }) - ); - - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('4', 'ether'), { - from: account_investor5 - }) - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei('4', 'ether')) - }) - - it('should be able to transfer tokens (percentage transfer limit)', async () => { - await I_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - let balance = (await I_SecurityToken.balanceOf(account_investor2)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor2 - }); - - - balance = (await I_SecurityToken.balanceOf(account_investor3)).toNumber(); - - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor3 - }); - - - balance = (await I_SecurityToken.balanceOf(account_investor4)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor4 - }); - - balance = (await I_SecurityToken.balanceOf(account_investor5)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor5 - }); - - await I_SingleTradeVolumeRestrictionPercentageManager.unpause({ - from: token_owner - }); - // // - await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(49 * 10 ** 16, { - from: token_owner - }); - - // Transfer above limit happened - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('90', 'ether'), { from: account_investor1 }) - ); - - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('20', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei('20', 'ether')) - - await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(account_investor1, 5 * 10 ** 16, { - from: token_owner - }); - // transfer happened above limit - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('35', 'ether'), { from: account_investor1 }) - ); - - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('1', 'ether')); - }); - - it('should change transfer limits to tokens', async () => { - // Should not change to percentage again - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { from: token_owner }) - ); - - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { - from: token_owner - }); - assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); - assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); - }) - - it('should change transfer limits to percentage', async () => { - // Should not change to tokens again - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeTransferLimitToTokens(1, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { - from: token_owner - }); - assert.ok(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), "Error Changing"); - assert.equal(tx.logs[0].args._percentage.toNumber(), 1, "Transfer limit not changed"); - }) - - - - }); - - describe("SingleTradeVolumeRestrictionManager Factory test cases", async () => { - - it("Should get the exact details of the factory", async () => { - assert.equal(await I_SingleTradeVolumeRestrictionManagerFactory.getSetupCost.call(), 0); - assert.equal((await I_SingleTradeVolumeRestrictionManagerFactory.getTypes.call())[0], 2); - let name = web3.utils.toUtf8(await I_SingleTradeVolumeRestrictionManagerFactory.getName.call()); - assert.equal(name, "SingleTradeVolumeRestrictionTM", "Wrong Module added"); - let desc = await I_SingleTradeVolumeRestrictionManagerFactory.description.call(); - assert.equal(desc, "Imposes volume restriction on a single trade", "Wrong Module added"); - let title = await I_SingleTradeVolumeRestrictionManagerFactory.title.call(); - assert.equal(title, "Single Trade Volume Restriction Manager", "Wrong Module added"); - let inst = await I_SingleTradeVolumeRestrictionManagerFactory.getInstructions.call(); - assert.equal(inst, "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens", "Wrong Module added"); - let version = await I_SingleTradeVolumeRestrictionManagerFactory.version.call(); - assert.equal(version, "1.0.0", "Version not correct"); - }); - - it("Should get the tags of the factory", async () => { - let tags = await I_SingleTradeVolumeRestrictionManagerFactory.getTags.call(); - assert.equal(web3.utils.toUtf8(tags[0]), "Single Trade"); - assert.equal(web3.utils.toUtf8(tags[1]), "Transfer"); - assert.equal(web3.utils.toUtf8(tags[2]), "Volume"); - }); - - - }); -}); diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js new file mode 100644 index 000000000..4206991ee --- /dev/null +++ b/test/z_general_permission_manager_fuzzer.js @@ -0,0 +1,669 @@ +import latestTime from './helpers/latestTime'; +import {signData} from './helpers/signData'; +import { pk } from './helpers/testprivateKey'; +import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { catchRevert } from "./helpers/exceptions"; +import { setUpPolymathNetwork, + deployGPMAndVerifyed, + deployCountTMAndVerifyed, + deployLockupVolumeRTMAndVerified, + deployPercentageTMAndVerified, + deployManualApprovalTMAndVerifyed +} from "./helpers/createInstances"; +import { encodeModuleCall } from "./helpers/encodeCall"; + +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const CountTransferManager = artifacts.require("./CountTransferManager"); +const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); +const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); +const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('GeneralPermissionManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let token_owner_pk; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_delegate; + let account_delegate2; + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let P_GeneralPermissionManagerFactory; + let I_SecurityTokenRegistryProxy; + let P_GeneralPermissionManager; + let I_GeneralTransferManagerFactory; + let I_VolumeRestrictionTransferManagerFactory; + let I_PercentageTransferManagerFactory; + let I_PercentageTransferManager; + let I_VolumeRestrictionTransferManager; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_DummySTOFactory; + let I_STFactory; + let I_SecurityToken; + let I_MRProxied; + let I_STRProxied; + let I_PolyToken; + let I_PolymathRegistry; + let I_CountTransferManagerFactory; + let I_CountTransferManager; + let I_SingleTradeVolumeRestrictionManagerFactory; + let I_SingleTradeVolumeRestrictionManager; + let I_SingleTradeVolumeRestrictionPercentageManager; + let P_SingleTradeVolumeRestrictionManager; + let P_SingleTradeVolumeRestrictionManagerFactory; + let I_ManualApprovalTransferManagerFactory; + let I_ManualApprovalTransferManager; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + const delegateDetails = "Hello I am legit delegate"; + const STVRParameters = ["bool", "uint256", "bool"]; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // CountTransferManager details + const holderCount = 2; // Maximum number of token holders + let bytesSTO = encodeModuleCall(["uint256"], [holderCount]); + + let _details = "details holding for test"; + let testRepeat = 20; + + // permission manager fuzz test + let perms = ['ADMIN','WHITELIST', 'FLAGS', 'TRANSFER_APPROVAL']; + let totalPerms = perms.length; + + before(async () => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + token_owner_pk = pk.account_1; + + account_investor1 = accounts[8]; + account_investor2 = accounts[9]; + account_investor3 = accounts[5]; + account_investor4 = accounts[6]; + account_delegate = accounts[7]; + // account_delegate2 = accounts[6]; + + + // Step 1: Deploy the genral PM ecosystem + let instances = await setUpPolymathNetwork(account_polymath, token_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; + + // STEP 5: Deploy the GeneralDelegateManagerFactory + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 6: Deploy the GeneralDelegateManagerFactory + [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + + // Deploy Modules + [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${I_PolymathRegistry.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistryProxy ${I_ModuleRegistryProxy.address} + ModuleRegistry: ${I_ModuleRegistry.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + STFactory: ${I_STFactory.address} + GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${I_GeneralPermissionManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async () => { + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from: token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal(web3.utils.toAscii(log.args._name).replace(/\u0000/g, ""), "GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + + it("Should successfully attach the General permission manager factory with the security token -- failed because Token is not paid", async () => { + let errorThrown = false; + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await catchRevert( + I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }) + ); + }); + + it("Should successfully attach the General permission manager factory with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); + const tx = await I_SecurityToken.addModule( + P_GeneralPermissionManagerFactory.address, + "0x", + web3.utils.toWei("500", "ether"), + 0, + { from: token_owner } + ); + assert.equal(tx.logs[3].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), + "GeneralPermissionManager", + "GeneralPermissionManagerFactory module was not added" + ); + P_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the General permission manager factory with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "GeneralPermissionManager", + "GeneralPermissionManagerFactory module was not added" + ); + I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); + }); + }); + + describe("fuzz test for general transfer manager", async () => { + + it("should pass fuzz test for changeIssuanceAddress(), changeSigningAddress() ", async () => { + + console.log("1"); + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, 'FLAGS') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, 'FLAGS', false, { from: token_owner }); + } else if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, 'WHITELIST') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, 'WHITELIST', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + let fromTime = latestTime(); + let toTime = latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + + await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, randomPerms, true, { from: token_owner }); + + let currentAllowAllTransferStats = await I_GeneralTransferManager.allowAllTransfers(); + let currentAllowAllWhitelistTransfersStats = await I_GeneralTransferManager.allowAllWhitelistTransfers(); + let currentAllowAllWhitelistIssuancesStats = await I_GeneralTransferManager.allowAllWhitelistIssuances(); + let currentAllowAllBurnTransfersStats = await I_GeneralTransferManager.allowAllBurnTransfers(); + console.log("2"); + // let userPerm = await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, 'FLAGS'); + if (randomPerms === 'FLAGS') { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " about to start") + await I_GeneralTransferManager.changeIssuanceAddress( accounts[j], { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.issuanceAddress(), accounts[j]); + + await I_GeneralTransferManager.changeSigningAddress( accounts[j], { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.signingAddress(), accounts[j]); + + await I_GeneralTransferManager.changeAllowAllTransfers(!currentAllowAllTransferStats, { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.allowAllTransfers(), !currentAllowAllTransferStats); + + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(!currentAllowAllWhitelistTransfersStats, { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.allowAllWhitelistTransfers(), !currentAllowAllWhitelistTransfersStats); + + await I_GeneralTransferManager.changeAllowAllWhitelistIssuances(!currentAllowAllWhitelistIssuancesStats, { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.allowAllWhitelistIssuances(), !currentAllowAllWhitelistIssuancesStats); + + await I_GeneralTransferManager.changeAllowAllBurnTransfers(!currentAllowAllBurnTransfersStats, { from: accounts[j] }); + assert.equal(await I_GeneralTransferManager.allowAllBurnTransfers(), !currentAllowAllBurnTransfersStats); + + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " for functions with require perm FLAGS passed") + } else { + await catchRevert(I_GeneralTransferManager.changeIssuanceAddress( accounts[j], { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeSigningAddress( accounts[j], { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeAllowAllTransfers( !currentAllowAllTransferStats, { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeAllowAllWhitelistTransfers( !currentAllowAllWhitelistTransfersStats, { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeAllowAllWhitelistIssuances( !currentAllowAllWhitelistIssuancesStats, { from: accounts[j] })); + await catchRevert(I_GeneralTransferManager.changeAllowAllBurnTransfers( !currentAllowAllBurnTransfersStats, { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " for functions require perm FLAGS failed as expected"); + } + + console.log("3"); + if (randomPerms === 'WHITELIST') { + let tx = await I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, 1, { from: accounts[j] }); + assert.equal(tx.logs[0].args._investor, accounts[j]); + console.log("3.1"); + let tx2 = await I_GeneralTransferManager.modifyWhitelistMulti([accounts[3], accounts[4]], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], [1, 1], { from: accounts[j] }); + console.log(tx2.logs[1].args); + assert.equal(tx2.logs[1].args._investor, accounts[4]); + console.log("3.2"); + } else { + console.log("3.3"); + await catchRevert(I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, 1, { from: accounts[j] })); + console.log("3.4"); + await catchRevert(I_GeneralTransferManager.modifyWhitelistMulti([accounts[3], accounts[4]], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], [1, 1], { from: accounts[j] })); + console.log("3.5"); + } + } + console.log("4"); + await I_GeneralTransferManager.changeIssuanceAddress("0x0000000000000000000000000000000000000000", { from: token_owner }); + }) + }); + + describe("fuzz test for count transfer manager", async () => { + + it("Should successfully attach the CountTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "CountTransferManager", + "CountTransferManager module was not added" + ); + I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); + }); + + it("should pass fuzz test for changeHolderCount()", async () => { + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_CountTransferManager.address, 'ADMIN') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_CountTransferManager.address, 'ADMIN', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_CountTransferManager.address, randomPerms, true, { from: token_owner }); + if (randomPerms === 'ADMIN') { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + await I_CountTransferManager.changeHolderCount(i + 1, { from: accounts[j] }); + assert.equal((await I_CountTransferManager.maxHolderCount()).toNumber(), i + 1); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " passed"); + } else { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert(I_CountTransferManager.changeHolderCount(i+1, { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + } + }); + }); + + + describe("fuzz test for percentage transfer manager", async () => { + + // PercentageTransferManager details + const holderPercentage = 70 * 10**16; // Maximum number of token holders + + let bytesSTO = web3.eth.abi.encodeFunctionCall({ + name: 'configure', + type: 'function', + inputs: [{ + type: 'uint256', + name: '_maxHolderPercentage' + },{ + type: 'bool', + name: '_allowPrimaryIssuance' + } + ] + }, [holderPercentage, false]); + + it("Should successfully attach the percentage transfer manager with the security token", async () => { + console.log("1"); + const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + I_PercentageTransferManager = PercentageTransferManager.at(tx.logs[2].args._module); + }); + + it("should pass fuzz test for modifyWhitelist with perm WHITELIST", async () => { + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, randomPerms, true, { from: token_owner }); + + //try add multi lock ups + if (randomPerms === 'WHITELIST') { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + await I_PercentageTransferManager.modifyWhitelist(account_investor3, 1, { from: accounts[j] }); + console.log("Test number " + i + " with account " + j + " and perm WHITELIST passed as expected"); + } else { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert(I_PercentageTransferManager.modifyWhitelist(account_investor3, 1, { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + } + }); + + it("should pass fuzz test for modifyWhitelistMulti with perm WHITELIST", async () => { + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, 'WHITELIST', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms === 'WHITELIST') { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + await I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [0, 1], { from: accounts[j] }); + console.log("Test number " + i + " with account " + j + " and perm WHITELIST passed as expected"); + + } else { + // console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert( I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [0, 1], { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + } + }); + + it("should pass fuzz test for setAllowPrimaryIssuance with perm ADMIN", async () => { + + // let snapId = await takeSnapshot(); + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, 'ADMIN') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, 'ADMIN', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, randomPerms, true, { from: token_owner }); + + let primaryIssuanceStat = await I_PercentageTransferManager.allowPrimaryIssuance({ from: token_owner }); + + if (randomPerms === 'ADMIN') { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should pass"); + await I_PercentageTransferManager.setAllowPrimaryIssuance(!primaryIssuanceStat, { from: accounts[j] }); + console.log("Test number " + i + " with account " + j + " and perm ADMIN passed as expected"); + + } else { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert( I_PercentageTransferManager.setAllowPrimaryIssuance(!primaryIssuanceStat, { from: accounts[j] })); + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + // await revertToSnapshot(snapId); + } + }); + }); + + + describe("fuzz test for manual approval transfer manager", async () => { + + it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toUtf8(tx.logs[2].args._name), + "ManualApprovalTransferManager", + "ManualApprovalTransferManager module was not added" + ); + I_ManualApprovalTransferManager = ManualApprovalTransferManager.at(tx.logs[2].args._module); + }); + + it("should pass fuzz test for addManualApproval & revokeManualApproval with perm TRANSFER_APPROVAL", async () => { + + let tx; + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + let snapId = await takeSnapshot(); + + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms === "TRANSFER_APPROVAL" ) { + console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL " + " should pass"); + await I_ManualApprovalTransferManager.addManualApproval( + account_investor1, + account_investor4, + web3.utils.toWei("2", "ether"), + latestTime() + duration.days(1), + { from: accounts[j] } + ); + + console.log("2"); + tx = await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { + from: accounts[j] + }); + assert.equal(tx.logs[0].args._from, account_investor1); + assert.equal(tx.logs[0].args._to, account_investor4); + assert.equal(tx.logs[0].args._addedBy, accounts[j]); + + console.log("3"); + console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL passed as expected"); + } else { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert( + I_ManualApprovalTransferManager.addManualApproval( + account_investor1, + account_investor4, + web3.utils.toWei("2", "ether"), + latestTime() + duration.days(1), + { from: accounts[j] } + ) + ); + + await I_ManualApprovalTransferManager.addManualApproval( + account_investor1, + account_investor4, + web3.utils.toWei("2", "ether"), + latestTime() + duration.days(1), + { from: token_owner } + ); + + await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { + from: accounts[j] + }) + ); + + + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + + await revertToSnapshot(snapId); + }; + + + }); + + it("should pass fuzz test for addManualBlocking and revokeManualBlocking with perm TRANSFER_APPROVAL", async () => { + console.log("1"); + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + from: token_owner + }); + console.log("2"); + await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: token_owner }); + console.log("3"); + + // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + for (var i = 2; i < testRepeat; i++) { + + let snapId = await takeSnapshot(); + + var j = Math.floor(Math.random() * 10); + if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms + + // add account as a Delegate if it is not + if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); + } + + // target permission should alaways be false for each test before assigning + if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL') === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL', false, { from: token_owner }); + } + + // assign a random perm + let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, randomPerms, true, { from: token_owner }); + + if (randomPerms === "TRANSFER_APPROVAL") { + console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL " + " should pass"); + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + from: accounts[j] + }); + + console.log("2"); + await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }); + + console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL passed as expected"); + } else { + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); + await catchRevert( + I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + from: accounts[j] + }) + ); + + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + from: token_owner + }); + + await catchRevert( + I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }) + ); + + console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); + } + + await revertToSnapshot(snapId); + }; + }); + }); + +}); From c3a64aca3fd75d7863c8a9959df47e3c34db37b2 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 3 Dec 2018 15:56:21 +0200 Subject: [PATCH 307/582] minor fix in tests --- test/z_vesting_escrow_wallet.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 5bc1f335b..a9328074a 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -855,6 +855,7 @@ contract('VestingEscrowWallet', accounts => { }); it("Should add 3 Templates", async () => { + let oldTemplateCount = await I_VestingEscrowWallet.getTemplateCount.call(); for (let i = 0; i < schedules.length; i++) { let templateName = schedules[i].templateName; let numberOfTokens = schedules[i].numberOfTokens; @@ -867,6 +868,11 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[0].args._duration.toNumber(), duration); assert.equal(tx.logs[0].args._frequency.toNumber(), frequency); } + let templateNames = await I_VestingEscrowWallet.getAllTemplateNames.call(); + + for (let i = 0, j = oldTemplateCount; i < schedules.length; i++, j++) { + assert.equal(web3.utils.hexToUtf8(templateNames[j]), schedules[i].templateName); + } }); it("Should not be able to add template -- fail because template already exists", async () => { From ff45016459f42bb12157fcf3d4c5e429ca6e406a Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 3 Dec 2018 19:53:39 +0530 Subject: [PATCH 308/582] remove the test cases for the STVRTM --- test/x_single_trade_volume_restriction.js | 726 ---------------------- 1 file changed, 726 deletions(-) delete mode 100644 test/x_single_trade_volume_restriction.js diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js deleted file mode 100644 index 99fe5cb9e..000000000 --- a/test/x_single_trade_volume_restriction.js +++ /dev/null @@ -1,726 +0,0 @@ -import latestTime from './helpers/latestTime'; -import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; -import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeModuleCall } from './helpers/encodeCall'; -import {deploySingleTradeVolumeRMAndVerified, setUpPolymathNetwork } from "./helpers/createInstances"; -import { catchRevert } from "./helpers/exceptions"; - -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionTM'); -const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('SingleTradeVolumeRestrictionManager', accounts => { - - - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - let account_investor5; - let zero_address = '0x0000000000000000000000000000000000000000'; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let I_SecurityTokenRegistryProxy - let I_GeneralTransferManagerFactory; - let I_GeneralPermissionManager; - let I_GeneralTransferManager; - let I_SingleTradeVolumeRestrictionManagerFactory; - let I_SingleTradeVolumeRestrictionManager; - let P_SingleTradeVolumeRestrictionManagerFactory; - let P_SingleTradeVolumeRestrictionManager; - let I_SingleTradeVolumeRestrictionPercentageManager; - let I_ModuleRegistry; - let I_MRProxied; - let I_ModuleRegistryProxy; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - const STVRParameters = ["bool", "uint256", "bool"]; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - before(async () => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[6]; - account_investor2 = accounts[7]; - account_investor3 = accounts[8]; - account_investor4 = accounts[9]; - account_investor5 = accounts[5]; - - let instances = await setUpPolymathNetwork(account_polymath, token_owner); - - [ - I_PolymathRegistry, - I_PolyToken, - I_FeatureRegistry, - I_ModuleRegistry, - I_ModuleRegistryProxy, - I_MRProxied, - I_GeneralTransferManagerFactory, - I_STFactory, - I_SecurityTokenRegistry, - I_SecurityTokenRegistryProxy, - I_STRProxied - ] = instances; - - // STEP 4: Deploy the SingleTradeVolumeRestrictionManagerFactory - [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); - - }); - - describe("Generate the SecurityToken", async () => { - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { - from: token_owner - }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { - from: token_owner - }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { - from: token_owner - }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { - from: token_owner - }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ - from: _blockNo - }), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - }); - // - describe("Buy tokens using whitelist & manual approvals", async () => { - - it("Should Buy the tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('100', 'ether'), { - from: token_owner - }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('100', 'ether') - ); - }); - - it("Should Buy some more tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { - from: token_owner - }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('1', 'ether') - ); - }); - // - it("Fails to attach the SingleTradeVolumeRestrictionManager with the security token due to fees not paid", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - await catchRevert( - I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { from: token_owner}) - ); - }); - - it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); - - let tx = await I_SecurityToken.addModule(P_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, web3.utils.toWei("500", "ether"), 0, { - from: token_owner - }); - - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "SingleTradeVolumeRestrictionManager did not get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestrictionManagerFactory module was not added" - ); - P_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[3].args._module); - }); - - it("Should successfully attach the SingleTradeVolumeRestrictionManager with the security token", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [false, (7 * Math.pow(10, 16)).toString(), false]) - const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { - from: token_owner - }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "TransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestriction module was not added" - ); - I_SingleTradeVolumeRestrictionManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); - }); - - it("Should successfully attach the SingleTradeVolumeRestrictionManager (Percentage) with the security token", async () => { - let managerArgs = encodeModuleCall(STVRParameters, [true, 90, false]); - const tx = await I_SecurityToken.addModule(I_SingleTradeVolumeRestrictionManagerFactory.address, managerArgs, 0, 0, { - from: token_owner - }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "SingleTradeVolumeRestrictionTM", - "SingleTradeVolumeRestriction module was not added" - ); - I_SingleTradeVolumeRestrictionPercentageManager = SingleTradeVolumeRestrictionManager.at(tx.logs[2].args._module); - }); - - it('should return get permissions', async () => { - let permissions = await I_SingleTradeVolumeRestrictionPercentageManager.getPermissions(); - assert.equal(permissions.length, 1, "Invalid Permissions"); - assert.equal( - web3.utils.toAscii(permissions[0]).replace(/\u0000/g, ''), - "ADMIN", - 'Wrong permissions' - ); - }); - - it("Should allow the primary issuance", async() => { - let snapId = await takeSnapshot(); - await I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}); - await catchRevert( - I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}) - ) - await revertToSnapshot(snapId); - }) - - it("add exempt wallet -- Not authorised ", async () => { - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]) - ); - - await catchRevert( - I_SingleTradeVolumeRestrictionManager.addExemptWallet(zero_address, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5], { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet added as exempt"); - }); - - it("Should remove an exempt wallet", async () => { - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5]) - ); - // 0 address are not allowed to add - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeExemptWallet(zero_address, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.removeExemptWallet(accounts[5], { from: token_owner }); - assert.equal(tx.logs[0].args._wallet, accounts[5], "Wrong wallet removed from exempt"); - }); - - it('should set transfer limit for a wallet', async () => { - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100) - ); - - // Transfer limits can't be set to 0 - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 0, { from: token_owner }) - ); - - // Transfer limit cannot be set in percentage - await catchRevert( - I_SingleTradeVolumeRestrictionManager.setTransferLimitInPercentage(accounts[4], 10, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(accounts[4], 100, { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[4]); - assert.equal(tx.logs[0].args._amount, 100); - - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 0, { from: token_owner }) - ); - // Transfer limit can not be set to more 0 - await catchRevert ( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 101 * 10 ** 16, { from: token_owner }) - ); - // Transfer limit in tokens can not be set for a manager that has transfer limit set as percentage - await catchRevert ( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInTokens(accounts[4], 1, { from: token_owner }) - ); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(accounts[4], 50, { from: token_owner }); - assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet added to transfer limits"); - assert.equal(tx.logs[0].args._percentage, 50, "Wrong percentage set"); - }); - - it('should remove transfer limit for wallet', async () => { - // Non Admins cannot set/remove transfer limits - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4]) - ); - - // Non Admins cannot set/remove transfer limits - await catchRevert ( - I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[0], { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokens(accounts[4], { - from: token_owner - }); - assert.equal(tx.logs[0].args._wallet, accounts[4], "Wrong wallet removed"); - }); - - it("Should pause the tranfers at Manager level", async () => { - let tx = await I_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - }); - - it('Should be able to set a global transfer limit', async () => { - // only owner is allowed - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(100 * 10 ** 18) - ); - //Cannot change global limit in percentage when set to tokens - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(100 * 10 ** 18, { from: token_owner }) - ); - // Global limit cannot be set to 0 - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(0, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(10, { - from: token_owner - }); - assert.equal(tx.logs[0].args._amount, 10, "Global Limit not set"); - - //Global limit can be set by non-admins - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89) - ); - // cannot change global limit in tokens if transfer limit is set to percentage - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(89, { from: token_owner }) - ); - // Cannot set global limit in tokens to 0 - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(0, { from: token_owner }) - ); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(40, { from: token_owner }); - assert.equal(tx.logs[0].args._percentage, 40, "Global Limit not set"); - // Global limit cannot be set to more than 100 - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(101 * 10 ** 16, { from: token_owner }) - ); - // Global limit in percentage cannot be set when limit is in tokens - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInPercentage(10, { from: token_owner }) - ); - // Global limit in tokens cannot be set when limit is in percentage - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInTokens(10, { from: token_owner }) - ); - }); - - it("Should perform batch updates", async () => { - let wallets = [accounts[0], accounts[1], accounts[2]]; - let tokenLimits = [1, 2, 3]; - let percentageLimits = [5, 6, 7]; - - // Exempt wallet multi cannot be empty wallet - await catchRevert( - P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti([], { from: token_owner }) - ); - - // add exempt wallet multi - let tx = await P_SingleTradeVolumeRestrictionManager.addExemptWalletMulti(wallets, { - from: token_owner - }); - let logs = tx.logs.filter(log => log.event === 'ExemptWalletAdded'); - assert.equal(logs.length, wallets.length, "Batch Exempt wallets not added"); - for (let i = 0; i < logs.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); - } - - // Exempt wallet multi cannot be empty wallet - await catchRevert( - P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti([], { from: token_owner }) - ); - - // remove exempt wallet multi - tx = await P_SingleTradeVolumeRestrictionManager.removeExemptWalletMulti(wallets, { - from: token_owner - }) - logs = tx.logs.filter(log => log.event === 'ExemptWalletRemoved'); - assert.equal(logs.length, wallets.length, "Batch Exempt wallets not removed"); - - for (let i = 0; i < logs.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Wallet not added as exempt wallet"); - } - // wallets cannot be empty - await catchRevert( - P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([], tokenLimits, { from: token_owner }) - ); - // wallet array length dont match - await catchRevert( - P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti([accounts[0]], tokenLimits, { from: token_owner }) - ); - - tx = await P_SingleTradeVolumeRestrictionManager.setTransferLimitInTokensMulti(wallets, tokenLimits, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInTokensSet'); - assert.equal(wallets.length, logs.length, "Transfer limit not set"); - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not set for wallet"); - assert.equal(logs[i].args._amount.toNumber(), tokenLimits[i]); - } - // Wallets cannot be empty - await catchRevert( - P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti([], { from: token_owner }) - ); - tx = await P_SingleTradeVolumeRestrictionManager.removeTransferLimitInTokensMulti(wallets, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event === 'TransferLimitInTokensRemoved'); - assert.equal(logs.length, wallets.length, "Transfer limit not removed"); - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "transfer limit not removed for wallet"); - } - // wallets cannot be empty - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti([], percentageLimits, { from: token_owner }) - ); - // wallets and amounts dont match be empty - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, [], { from: token_owner }) - ); - tx = await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentageMulti(wallets, percentageLimits, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageSet'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - assert.equal(logs[i].args._percentage.toNumber(), percentageLimits[i]); - } - // Wallets cannot be empty - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti([], { from: token_owner }) - ); - - tx = await I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentageMulti(wallets, { - from: token_owner - }); - logs = tx.logs.filter(log => log.event == 'TransferLimitInPercentageRemoved'); - assert.equal(logs.length, wallets.length, "transfer limits not set for wallets"); - - for (let i = 0; i < wallets.length; i++) { - assert.equal(logs[i].args._wallet, wallets[i], "Transfer limit not set for wallet"); - } - // Wallet should not be removed - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.removeTransferLimitInPercentage(wallets[0], { from: token_owner }) - ); - }) - - it('should be able to transfer tokens SingleTradeVolumeRestriction', async () => { - await I_SingleTradeVolumeRestrictionManager.unpause({ - from: token_owner - }) - await I_SingleTradeVolumeRestrictionPercentageManager.pause({ - from: token_owner - }) - await P_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor4, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - await I_GeneralTransferManager.modifyWhitelist( - account_investor5, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, { - from: account_issuer - } - ); - - - //setting a max of 5 tokens - await I_SingleTradeVolumeRestrictionManager.changeGlobalLimitInTokens(web3.utils.toWei('5', 'ether'), { - from: token_owner - }) - // Transfer should have not happened - await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei('6', 'ether'), { from: account_investor1 }) - ); - - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('4', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('4', 'ether')); - - // exempt wallet - await I_SingleTradeVolumeRestrictionManager.addExemptWallet(account_investor1, { - from: token_owner - }); - await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('7', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toNumber(), web3.utils.toWei('7', 'ether')); - - //special limits wallet - await I_SingleTradeVolumeRestrictionManager.setTransferLimitInTokens(account_investor5, web3.utils.toWei('5', 'ether'), { - from: token_owner - }); - - // Transfer should have not happened - await catchRevert( - I_SecurityToken.transfer(account_investor4, web3.utils.toWei('7', 'ether'), { from: account_investor5 }) - ); - - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei('4', 'ether'), { - from: account_investor5 - }) - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei('4', 'ether')) - }) - - it('should be able to transfer tokens (percentage transfer limit)', async () => { - await I_SingleTradeVolumeRestrictionManager.pause({ - from: token_owner - }); - let balance = (await I_SecurityToken.balanceOf(account_investor2)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor2 - }); - - - balance = (await I_SecurityToken.balanceOf(account_investor3)).toNumber(); - - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor3 - }); - - - balance = (await I_SecurityToken.balanceOf(account_investor4)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor4 - }); - - balance = (await I_SecurityToken.balanceOf(account_investor5)).toNumber(); - await I_SecurityToken.transfer(account_investor1, balance, { - from: account_investor5 - }); - - await I_SingleTradeVolumeRestrictionPercentageManager.unpause({ - from: token_owner - }); - // // - await I_SingleTradeVolumeRestrictionPercentageManager.changeGlobalLimitInPercentage(49 * 10 ** 16, { - from: token_owner - }); - - // Transfer above limit happened - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('90', 'ether'), { from: account_investor1 }) - ); - - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('20', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei('20', 'ether')) - - await I_SingleTradeVolumeRestrictionPercentageManager.setTransferLimitInPercentage(account_investor1, 5 * 10 ** 16, { - from: token_owner - }); - // transfer happened above limit - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('35', 'ether'), { from: account_investor1 }) - ); - - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { - from: account_investor1 - }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei('1', 'ether')); - }); - - it('should change transfer limits to tokens', async () => { - // Should not change to percentage again - await catchRevert( - I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { from: token_owner }) - ); - - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToTokens(1, { - from: token_owner - }); - assert.equal(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), false, "Error Changing"); - assert.equal(tx.logs[0].args._amount.toNumber(), 1, "Transfer limit not changed"); - }) - - it('should change transfer limits to percentage', async () => { - // Should not change to tokens again - await catchRevert( - I_SingleTradeVolumeRestrictionManager.changeTransferLimitToTokens(1, { from: token_owner }) - ); - - let tx = await I_SingleTradeVolumeRestrictionPercentageManager.changeTransferLimitToPercentage(1, { - from: token_owner - }); - assert.ok(await I_SingleTradeVolumeRestrictionPercentageManager.isTransferLimitInPercentage(), "Error Changing"); - assert.equal(tx.logs[0].args._percentage.toNumber(), 1, "Transfer limit not changed"); - }) - - - - }); - - describe("SingleTradeVolumeRestrictionManager Factory test cases", async () => { - - it("Should get the exact details of the factory", async () => { - assert.equal(await I_SingleTradeVolumeRestrictionManagerFactory.getSetupCost.call(), 0); - assert.equal((await I_SingleTradeVolumeRestrictionManagerFactory.getTypes.call())[0], 2); - let name = web3.utils.toUtf8(await I_SingleTradeVolumeRestrictionManagerFactory.getName.call()); - assert.equal(name, "SingleTradeVolumeRestrictionTM", "Wrong Module added"); - let desc = await I_SingleTradeVolumeRestrictionManagerFactory.description.call(); - assert.equal(desc, "Imposes volume restriction on a single trade", "Wrong Module added"); - let title = await I_SingleTradeVolumeRestrictionManagerFactory.title.call(); - assert.equal(title, "Single Trade Volume Restriction Manager", "Wrong Module added"); - let inst = await I_SingleTradeVolumeRestrictionManagerFactory.getInstructions.call(); - assert.equal(inst, "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens", "Wrong Module added"); - let version = await I_SingleTradeVolumeRestrictionManagerFactory.version.call(); - assert.equal(version, "1.0.0", "Version not correct"); - }); - - it("Should get the tags of the factory", async () => { - let tags = await I_SingleTradeVolumeRestrictionManagerFactory.getTags.call(); - assert.equal(web3.utils.toUtf8(tags[0]), "Single Trade"); - assert.equal(web3.utils.toUtf8(tags[1]), "Transfer"); - assert.equal(web3.utils.toUtf8(tags[2]), "Volume"); - }); - - - }); -}); From 78bf819f4f9521f1dcf19b20745deabb12f7edc1 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Mon, 3 Dec 2018 16:42:52 -0300 Subject: [PATCH 309/582] adding and listing stable coins in sto manager --- CLI/commands/common/common_functions.js | 11 +- CLI/commands/common/constants.js | 2 +- CLI/commands/helpers/contract_abis.js | 5 + CLI/commands/sto_manager.js | 133 ++++++++++++++++++++---- 4 files changed, 123 insertions(+), 28 deletions(-) diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index 0d21d06f3..e9d4b61a1 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -3,7 +3,7 @@ const Tx = require('ethereumjs-tx'); const permissionsList = require('./permissions_list'); const abis = require('../helpers/contract_abis'); -async function connect(abi, address) { +function connect(abi, address) { contractRegistry = new web3.eth.Contract(abi, address); contractRegistry.setProvider(web3.currentProvider); return contractRegistry @@ -15,7 +15,7 @@ async function checkPermission(contractName, functionName, contractRegistry) { return true } else { let stAddress = await contractRegistry.methods.securityToken().call(); - let securityToken = await connect(abis.securityToken(), stAddress); + let securityToken = connect(abis.securityToken(), stAddress); let stOwner = await securityToken.methods.owner().call(); if (stOwner == Issuer.address) { return true @@ -47,11 +47,11 @@ async function getGasLimit(options, action) { } async function checkPermissions(action) { - let contractRegistry = await connect(action._parent.options.jsonInterface, action._parent._address); + let contractRegistry = connect(action._parent.options.jsonInterface, action._parent._address); //NOTE this is a condition to verify if the transaction comes from a module or not. if (contractRegistry.methods.hasOwnProperty('factory')) { let moduleAddress = await contractRegistry.methods.factory().call(); - let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress); + let moduleRegistry = connect(abis.moduleFactory(), moduleAddress); let parentModule = await moduleRegistry.methods.getName().call(); let result = await checkPermission(web3.utils.hexToUtf8(parentModule), action._method.name, contractRegistry); if (!result) { @@ -145,5 +145,8 @@ module.exports = { let eventJsonInterface = jsonInterface.find(o => o.name === eventName && o.type === 'event'); let filteredLogs = logs.filter(l => l.topics.includes(eventJsonInterface.signature)); return filteredLogs.map(l => web3.eth.abi.decodeLog(eventJsonInterface.inputs, l.data, l.topics.slice(1))); + }, + connect: function (abi, address) { + return connect(abi, address) } }; diff --git a/CLI/commands/common/constants.js b/CLI/commands/common/constants.js index c3e2b796c..2f10d6930 100644 --- a/CLI/commands/common/constants.js +++ b/CLI/commands/common/constants.js @@ -29,6 +29,6 @@ module.exports = Object.freeze({ FUND_RAISE_TYPES: { ETH: 0, POLY: 1, - DAI: 2 + STABLE: 2 } }); \ No newline at end of file diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index f93f18ac7..aa98aa5f1 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -19,6 +19,7 @@ let ownableABI; let iSTOABI; let iTransferManagerABI; let moduleFactoryABI; +let erc20; try { polymathRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolymathRegistry.json').toString()).abi; @@ -42,6 +43,7 @@ try { iSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/ISTO.json').toString()).abi iTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ITransferManager.json').toString()).abi moduleFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleFactory.json').toString()).abi; + erc20ABI = JSON.parse(require('fs').readFileSync('./build/contracts/DetailedERC20.json').toString()).abi; } catch (err) { console.log('\x1b[31m%s\x1b[0m', "Couldn't find contracts' artifacts. Make sure you ran truffle compile first"); throw err; @@ -110,5 +112,8 @@ module.exports = { }, moduleFactory: function () { return moduleFactoryABI; + }, + erc20: function () { + return erc20ABI; } } \ No newline at end of file diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index d0fd1c3ea..18e342e57 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -6,6 +6,7 @@ const contracts = require('./helpers/contract_addresses'); const abis = require('./helpers/contract_abis'); const common = require('./common/common_functions'); const gbl = require('./common/global'); +const STABLE = 'STABLE'; /////////////////// // Crowdsale params @@ -270,7 +271,7 @@ async function cappedSTO_status(currentSTO) { function fundingConfigUSDTieredSTO() { let funding = {}; - let selectedFunding = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise,' + chalk.green(` D `) + 'for DAI raise,' + chalk.green(` E `) + 'for Ether raise or any combination of them (i.e.' + chalk.green(` PED `) + 'for all): ').toUpperCase(); + let selectedFunding = readlineSync.question('Enter' + chalk.green(` P `) + 'for POLY raise,' + chalk.green(` S `) + 'for Stable Coin raise,' + chalk.green(` E `) + 'for Ether raise or any combination of them (i.e.' + chalk.green(` PSE `) + 'for all): ').toUpperCase(); funding.raiseType = []; if (selectedFunding.includes('E')) { @@ -279,17 +280,17 @@ function fundingConfigUSDTieredSTO() { if (selectedFunding.includes('P')) { funding.raiseType.push(gbl.constants.FUND_RAISE_TYPES.POLY); } - if (selectedFunding.includes('D')) { - funding.raiseType.push(gbl.constants.FUND_RAISE_TYPES.DAI); + if (selectedFunding.includes('S')) { + funding.raiseType.push(gbl.constants.FUND_RAISE_TYPES.STABLE); } if (funding.raiseType.length == 0) { - funding.raiseType = [gbl.constants.FUND_RAISE_TYPES.ETH, gbl.constants.FUND_RAISE_TYPES.POLY, gbl.constants.FUND_RAISE_TYPES.DAI]; + funding.raiseType = [gbl.constants.FUND_RAISE_TYPES.ETH, gbl.constants.FUND_RAISE_TYPES.POLY, gbl.constants.FUND_RAISE_TYPES.STABLE]; } return funding; } -function addressesConfigUSDTieredSTO(usdTokenRaise) { +async function addressesConfigUSDTieredSTO(usdTokenRaise) { let addresses = {}; addresses.wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): ', { @@ -310,22 +311,74 @@ function addressesConfigUSDTieredSTO(usdTokenRaise) { }); if (addresses.reserveWallet == "") addresses.reserveWallet = Issuer.address; + let listOfAddress; + if (usdTokenRaise) { - addresses.usdToken = readlineSync.question('Enter the address of the USD Token or stable coin (' + usdToken.options.address + '): ', { + addresses.usdToken = readlineSync.question('Enter the address (or many addresses that you want separated by comma) of the USD Token or stable coin (' + usdToken.options.address + '): ', { limit: function (input) { - return web3.utils.isAddress(input); + listOfAddress = input.split(','); + let response = true + listOfAddress.forEach((addr) => { + if (!web3.utils.isAddress(addr)) { + response = false + } + }) + return response }, limitMessage: "Must be a valid address", defaultInput: usdToken.options.address }); - if (addresses.usdToken == "") addresses.usdToken = usdToken.options.address; + if (addresses.usdToken == "") { + listOfAddress = [usdToken.options.address] + addresses.usdToken = [usdToken.options.address]; + } } else { - addresses.usdToken = '0x0000000000000000000000000000000000000000'; + listOfAddress = ['0x0000000000000000000000000000000000000000'] + addresses.usdToken = ['0x0000000000000000000000000000000000000000']; + } + + if (!await processArray(listOfAddress)) { + console.log(`Please, verify your stable coins addresses to continue with this process.`) + process.exit(0) + } + + if (typeof addresses.usdToken === 'string') { + addresses.usdToken = addresses.usdToken.split(",") } return addresses; } +async function checkSymbol(address) { + let stableCoin = common.connect(abis.erc20(), address); + try { + return await stableCoin.methods.symbol().call(); + } catch (e) { + return "" + } +} + +async function processArray(array) { + let result = true; + for (const address of array) { + let symbol = await checkSymbol(address); + if (symbol == "") { + result = false; + console.log(`${address} seems not to be a stable coin`) + } + } + return result +} + +async function processAddress(array) { + let list = []; + for (const address of array) { + let symbol = await checkSymbol(address); + list.push(symbol) + } + return list +} + function tiersConfigUSDTieredSTO(polyRaise) { let tiers = {}; @@ -474,7 +527,7 @@ async function usdTieredSTO_launch(stoConfig) { let useConfigFile = typeof stoConfig !== 'undefined'; let funding = useConfigFile ? stoConfig.funding : fundingConfigUSDTieredSTO(); - let addresses = useConfigFile ? stoConfig.addresses : addressesConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.DAI)); + let addresses = useConfigFile ? stoConfig.addresses : await addressesConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.STABLE)); let tiers = useConfigFile ? stoConfig.tiers : tiersConfigUSDTieredSTO(funding.raiseType.includes(gbl.constants.FUND_RAISE_TYPES.POLY)); let limits = useConfigFile ? stoConfig.limits : limitsConfigUSDTieredSTO(); let times = timesConfigUSDTieredSTO(stoConfig); @@ -519,12 +572,17 @@ async function usdTieredSTO_status(currentSTO) { let displayInvestorCount = await currentSTO.methods.investorCount().call(); let displayIsFinalized = await currentSTO.methods.isFinalized().call() ? "YES" : "NO"; let displayTokenSymbol = await securityToken.methods.symbol().call(); - - let tiersLength = await currentSTO.methods.getNumberOfTiers().call();; - + let tiersLength = await currentSTO.methods.getNumberOfTiers().call(); + //REMOVE ONCE SMART CONTRACT SUPPORT METHOD TO GET STABLE COIN ADDRESSES + let listOfStableCoins = ["0xa016B2ae79436E20FBe22Bf230a92A5Fb055762F", "0xae794d38cb481868a8CB19b9d7A5073851bC6dB7"]; let raiseTypes = []; + let stableSymbols = []; + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { + if (fundType == STABLE) { + stableSymbols = await processAddress(listOfStableCoins) + } raiseTypes.push(fundType); } } @@ -554,8 +612,13 @@ async function usdTieredSTO_status(currentSTO) { } let mintedPerTier = mintedPerTierPerRaiseType[gbl.constants.FUND_RAISE_TYPES[type]]; - displayMintedPerTierPerType += ` - Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + if ((type == STABLE) && (stableSymbols.length)) { + displayMintedPerTierPerType += ` + Sold for ${stableSymbols.toString()}:\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + } else { + displayMintedPerTierPerType += ` + Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + } } displayTiers += ` @@ -579,28 +642,52 @@ async function usdTieredSTO_status(currentSTO) { let balance = await getBalance(displayWallet, gbl.constants.FUND_RAISE_TYPES[type]); let walletBalance = web3.utils.fromWei(balance); let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); - displayWalletBalancePerType += ` + if ((type == STABLE) && (stableSymbols.length)) { + displayWalletBalancePerType += ` + Balance ${stableSymbols.toString()}:\t ${walletBalanceUSD} USD`; + } else { + displayWalletBalancePerType += ` Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; - + } + balance = await getBalance(displayReserveWallet, gbl.constants.FUND_RAISE_TYPES[type]); let reserveWalletBalance = web3.utils.fromWei(balance); let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); - displayReserveWalletBalancePerType += ` + if ((type == STABLE) && (stableSymbols.length)) { + displayReserveWalletBalancePerType += ` + Balance ${stableSymbols.toString()}:\t ${reserveWalletBalanceUSD} USD`; + } else { + displayReserveWalletBalancePerType += ` Balance ${type}:\t\t ${reserveWalletBalance} ${type} (${reserveWalletBalanceUSD} USD)`; + } let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); - displayFundsRaisedPerType += ` + if ((type == STABLE) && (stableSymbols.length)) { + displayFundsRaisedPerType += ` + ${stableSymbols.toString()}:\t\t ${fundsRaised} USD`; + } else { + displayFundsRaisedPerType += ` ${type}:\t\t\t ${fundsRaised} ${type}`; + } //Only show sold for if more than one raise type are allowed if (raiseTypes.length > 1) { let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(gbl.constants.FUND_RAISE_TYPES[type]).call()); - displayTokensSoldPerType += ` - Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; + if ((type == STABLE) && (stableSymbols.length)) { + displayTokensSoldPerType += ` + Sold for ${stableSymbols.toString()}:\t ${tokensSoldPerType} ${displayTokenSymbol}`; + } else { + displayTokensSoldPerType += ` + Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; + } } } let displayRaiseType = raiseTypes.join(' - '); + //If STO has stable coins, we list them one by one + if (stableSymbols.length) { + displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.toString().replace(`,`,` - `)}` + } let now = Math.floor(Date.now() / 1000); let timeTitle; @@ -747,7 +834,7 @@ async function modfifyFunding(currentSTO) { } async function modfifyAddresses(currentSTO) { - let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.DAI).call()); + let addresses = await addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.STABLE).call()); let modifyAddressesAction = currentSTO.methods.modifyAddresses(addresses.wallet, addresses.reserveWallet, addresses.usdToken); await common.sendTransaction(modifyAddressesAction); } @@ -772,7 +859,7 @@ async function getBalance(from, type) { return await web3.eth.getBalance(from); case gbl.constants.FUND_RAISE_TYPES.POLY: return await polyToken.methods.balanceOf(from).call(); - case gbl.constants.FUND_RAISE_TYPES.DAI: + case gbl.constants.FUND_RAISE_TYPES.STABLE: return await usdToken.methods.balanceOf(from).call(); } } From 9af58992bbe143794d9ab71fd6956132ca5ad564 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 3 Dec 2018 15:16:29 -0500 Subject: [PATCH 310/582] Return investor data in getAllInvestorsData --- .../modules/TransferManager/GeneralTransferManager.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 5412afe94..12bfa72ca 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -344,8 +344,11 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag /** * @dev Returns list of all investors data */ - function getAllInvestorsData() external view returns(uint256[], uint256[], uint256[], bool[]) { - return _investorsData(investors); + function getAllInvestorsData() external view returns(address[], uint256[], uint256[], uint256[], bool[]) { + (uint256[] memory fromTimes, uint256[] memory toTimes, uint256[] memory expiryTimes, bool[] memory canBuyFromSTOs) + = _investorsData(investors); + return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs); + } /** From e394850343c4e3a4b192b8510b31f2c2df8f590e Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 3 Dec 2018 17:42:22 -0300 Subject: [PATCH 311/582] CLI changes according GTM optimizations --- CLI/commands/transfer_manager.js | 62 +++++++++++++++++++++-- CLI/package.json | 1 + CLI/yarn.lock | 85 +++++++++++++++++++++++++++++++- 3 files changed, 142 insertions(+), 6 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 44ae64ca1..af50af8cb 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -6,6 +6,7 @@ var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); var gbl = require('./common/global'); var whitelist = require('./whitelist'); +const { table } = require('table') // App flow let tokenSymbol; @@ -316,6 +317,8 @@ async function generalTransferManager() { let displayAllowAllWhitelistTransfers = await currentTransferManager.methods.allowAllWhitelistTransfers().call(); let displayAllowAllWhitelistIssuances = await currentTransferManager.methods.allowAllWhitelistIssuances().call(); let displayAllowAllBurnTransfers = await currentTransferManager.methods.allowAllBurnTransfers().call(); + let displayDefaults = await currentTransferManager.methods.defaults().call(); + let displayInvestors = await currentTransferManager.methods.getInvestors().call(); console.log(`- Issuance address: ${displayIssuanceAddress}`); console.log(`- Signing address: ${displaySigningAddress}`); @@ -323,10 +326,18 @@ async function generalTransferManager() { console.log(`- Allow all whitelist transfers: ${displayAllowAllWhitelistTransfers ? `YES` : `NO`}`); console.log(`- Allow all whitelist issuances: ${displayAllowAllWhitelistIssuances ? `YES` : `NO`}`); console.log(`- Allow all burn transfers: ${displayAllowAllBurnTransfers ? `YES` : `NO`}`); + console.log(`- Default times:`); + console.log(` - From time: ${displayDefaults.fromTime} (${moment.unix(displayDefaults.fromTime).format('MMMM Do YYYY, HH:mm:ss')})`); + console.log(` - To time: ${displayDefaults.toTime} (${moment.unix(displayDefaults.toTime).format('MMMM Do YYYY, HH:mm:ss')})`); + console.log(`- Investors: ${displayInvestors.length}`); // ------------------ - let options = ['Modify whitelist', 'Modify whitelist from CSV', /*'Modify Whitelist Signed',*/ - `Change issuance address`, 'Change signing address']; + let options = []; + if (displayInvestors.length > 0) { + options.push(`Show investors`, `Show whitelist data`); + } + options.push('Modify whitelist', 'Modify whitelist from CSV', /*'Modify Whitelist Signed',*/ + 'Change the default times used when they are zero', `Change issuance address`, 'Change signing address'); if (displayAllowAllTransfers) { options.push('Disallow all transfers'); } else { @@ -352,6 +363,34 @@ async function generalTransferManager() { let optionSelected = options[index]; console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); switch (optionSelected) { + case `Show investors`: + console.log('***** List of investors on whitelist *****'); + displayInvestors.map(i => console.log(i)); + break; + case `Show whitelist data`: + let investorsToShow = readlineSync.question(`Enter the addresses of the investors you want to show (i.e: addr1,addr2,addr3) or leave empty to show them all: `, { + limit: function (input) { + return input === '' || input.split(",").every(a => web3.utils.isAddress(a)); + }, + limitMessage: `All addresses must be valid` + }); + if (investorsToShow === '') { + let whitelistData = await currentTransferManager.methods.getAllInvestorsData().call(); + showWhitelistTable(whitelistData[0], whitelistData[1], whitelistData[2], whitelistData[3], whitelistData[4]); + } else { + let investorsArray = investorsToShow.split(','); + let whitelistData = await currentTransferManager.methods.getInvestorsData(investorsArray).call(); + showWhitelistTable(investorsArray, whitelistData[0], whitelistData[1], whitelistData[2], whitelistData[3]); + } + break; + case 'Change the default times used when they are zero': + let fromTimeDefault = readlineSync.questionInt(`Enter the default time (Unix Epoch time) used when fromTime is zero: `); + let toTimeDefault = readlineSync.questionInt(`Enter the default time (Unix Epoch time) used when fromTime is zero: `); + let changeDefaultsAction = currentTransferManager.methods.changeDefaults(fromTimeDefault, toTimeDefault); + let changeDefaultsReceipt = await common.sendTransaction(changeDefaultsAction); + let changeDefaultsEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeDefaultsReceipt.logs, 'ChangeDefaults'); + console.log(chalk.green(`Default times have been updated successfully!`)); + break; case 'Modify whitelist': let investor = readlineSync.question('Enter the address to whitelist: ', { limit: function (input) { @@ -373,7 +412,7 @@ async function generalTransferManager() { case 'Modify whitelist from CSV': console.log(chalk.yellow(`Data is going to be read from 'data/whitelist_data.csv'. Be sure this file is updated!`)); if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { - await whitelist.executeApp(tokenSymbl); + await whitelist.executeApp(tokenSymbol); } break; /* @@ -468,6 +507,21 @@ async function generalTransferManager() { } } +function showWhitelistTable(investorsArray, fromTimeArray, toTimeArray, expiryTimeArray, canBuyFromSTOArray) { + let dataTable = [['Investor', 'From time', 'To time', 'KYC expiry date', 'Restricted']]; + for (let i = 0; i < investorsArray.length; i++) { + dataTable.push([ + investorsArray[i], + moment.unix(fromTimeArray[i]).format('MM/DD/YYYY HH:mm'), + moment.unix(toTimeArray[i]).format('MM/DD/YYYY HH:mm'), + moment.unix(expiryTimeArray[i]).format('MM/DD/YYYY HH:mm'), + canBuyFromSTOArray[i] ? 'YES' : 'NO' + ]); + } + console.log(); + console.log(table(dataTable)); +} + async function manualApprovalTransferManager() { console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address}`), '\n'); @@ -498,7 +552,7 @@ async function manualApprovalTransferManager() { if (manualApproval) { console.log(`Manual approval found!`); console.log(`Allowance: ${web3.utils.fromWei(manualApproval.allowance)}`); - console.log(`Expiry time: ${moment.unix(manualApproval.expiryTime).format('MMMM Do YYYY, HH:mm:ss')};`) + console.log(`Expiry time: ${moment.unix(manualApproval.expiryTime).format('MMMM Do YYYY, HH:mm:ss')}`); } else { console.log(chalk.yellow(`There are no manual approvals from ${from} to ${to}.`)); } diff --git a/CLI/package.json b/CLI/package.json index 95a391b45..59fb4650f 100644 --- a/CLI/package.json +++ b/CLI/package.json @@ -16,6 +16,7 @@ "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", + "table": "^5.1.1", "web3": "1.0.0-beta.35" } } diff --git a/CLI/yarn.lock b/CLI/yarn.lock index 4d20bee11..0723cde58 100644 --- a/CLI/yarn.lock +++ b/CLI/yarn.lock @@ -30,7 +30,22 @@ ajv@^5.3.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ansi-styles@^3.2.1: +ajv@^6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.1.tgz#6360f5ed0d80f232cc2b294c362d5dc2e538dd61" + integrity sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -68,6 +83,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" @@ -736,6 +756,11 @@ fast-deep-equal@^1.0.0: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -1037,6 +1062,11 @@ is-callable@^1.1.3: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" @@ -1115,6 +1145,11 @@ json-schema-traverse@^0.3.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -1150,7 +1185,7 @@ keccakjs@^0.2.1: browserify-sha3 "^0.0.1" sha3 "^1.1.0" -lodash@^4.13.1: +lodash@^4.13.1, lodash@^4.17.11: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== @@ -1491,6 +1526,11 @@ punycode@^1.4.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -1744,6 +1784,15 @@ simple-get@^2.7.0: once "^1.3.1" simple-concat "^1.0.0" +slice-ansi@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.0.0.tgz#5373bdb8559b45676e8541c66916cdd6251612e7" + integrity sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + sshpk@^1.7.0: version "1.15.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2" @@ -1779,6 +1828,14 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= +string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -1786,6 +1843,13 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" @@ -1826,6 +1890,16 @@ swarm-js@0.1.37: tar.gz "^1.0.5" xhr-request-promise "^0.1.2" +table@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/table/-/table-5.1.1.tgz#92030192f1b7b51b6eeab23ed416862e47b70837" + integrity sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw== + dependencies: + ajv "^6.6.1" + lodash "^4.17.11" + slice-ansi "2.0.0" + string-width "^2.1.1" + tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" @@ -1951,6 +2025,13 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" From 343b43208f337ca5e07696f54a4ba90f0aa2944c Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 3 Dec 2018 19:35:48 -0300 Subject: [PATCH 312/582] modifyWhitelistMulti for PercentageTM --- CLI/commands/common/csv_shared.js | 82 ------------------- CLI/commands/common/csv_sync.js | 39 --------- CLI/commands/transfer_manager.js | 28 ++++++- .../Transfer/PercentageTM/whitelist_data.csv | 10 +++ 4 files changed, 37 insertions(+), 122 deletions(-) delete mode 100644 CLI/commands/common/csv_shared.js delete mode 100644 CLI/commands/common/csv_sync.js create mode 100644 CLI/data/Transfer/PercentageTM/whitelist_data.csv diff --git a/CLI/commands/common/csv_shared.js b/CLI/commands/common/csv_shared.js deleted file mode 100644 index 471db13d1..000000000 --- a/CLI/commands/common/csv_shared.js +++ /dev/null @@ -1,82 +0,0 @@ -var contracts = require('../helpers/contract_addresses'); -var abis = require('../helpers/contract_abis'); -var csv = require('./csv_sync'); - -let BATCH_SIZE = 70; - -async function startScript(tokenSymbol, batchSize) { - if (batchSize) { - BATCH_SIZE = batchSize; - } - let STAddress = await checkST(tokenSymbol); - return new web3.eth.Contract(abis.securityToken(), STAddress); -}; - -async function checkST(tokenSymbol) { - let securityTokenRegistry = await STConnect(); - - return await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call({}, function (error, result) { - if (result != "0x0000000000000000000000000000000000000000") { - return result - } else { - console.log("Token doesn't exist") - process.exit(0) - } - }); -} - -async function STConnect() { - try { - let STRegistryAddress = await contracts.securityTokenRegistry(); - let STRegistry = new web3.eth.Contract(abis.securityTokenRegistry(), STRegistryAddress); - return STRegistry; - } catch (err) { - console.log("There was a problem getting the contracts. Make sure they are deployed to the selected network."); - process.exit(0); - } -} - -async function readScript(file, processing) { - let allocData = new Array(); - let distribData = new Array(); - let fullFileData = new Array(); - let badData = new Array(); - let i = 0; - - var CSV_STRING = csv(file); - - CSV_STRING.forEach(line => { - let data_processed = processing(line); - fullFileData.push(data_processed[1]); - - if (data_processed[0]) { - allocData.push(data_processed[1]); - i++; - if (i >= BATCH_SIZE) { - distribData.push(allocData); - allocData = []; - i = 0; - } - } else { - badData.push(data_processed[1]); - } - }); - - distribData.push(allocData); - allocData = []; - - return { - distribData: distribData, - fullFileData: fullFileData, - badData: badData - } -} - -module.exports = { - start: async (tokenSymbol, batchSize) => { - return await startScript(tokenSymbol, batchSize); - }, - read: async (file, processing) => { - return await readScript(file, processing); - } -} \ No newline at end of file diff --git a/CLI/commands/common/csv_sync.js b/CLI/commands/common/csv_sync.js deleted file mode 100644 index 6955a2445..000000000 --- a/CLI/commands/common/csv_sync.js +++ /dev/null @@ -1,39 +0,0 @@ -var fs = require('fs'); - -function load(filename, options) { - var content = fs.readFileSync(filename, 'utf-8'); - var lines = content.split('\n'); - var splitToColumns = options && check.fn(options.getColumns) ? options.getColumns : getColumns; - var results = []; - - lines.forEach(function (line, index) { - if (!line) { - return; - } - - var obj = []; - var values = stripQuotes(splitToColumns(line, index)); - - values.forEach(function (value) { - obj.push(value) - }); - - results.push(obj); - }); - - return results; -} - -function getColumns(line) { - var columns = line.split(','); - return columns; -} - -function stripQuotes(words) { - return words.map(function (word) { - word = word.trim(); - return word.replace(/"/g, ''); - }); -} - -module.exports = load; diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 79eae49f4..e56233466 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -10,6 +10,7 @@ const csvParse = require('./helpers/csv'); /////////////////// // Constants const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; +const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelist_data.csv'; // App flow let tokenSymbol; @@ -518,7 +519,7 @@ async function modifyWhitelistInBatch() { console.log(`Batch ${batch + 1} - Attempting to modify whitelist to accounts: \n\n`, investorArray[batch], '\n'); let action = await currentTransferManager.methods.modifyWhitelistMulti(investorArray[batch], fromTimesArray[batch], toTimesArray[batch], expiryTimeArray[batch], canBuyFromSTOArray[batch]); let receipt = await common.sendTransaction(action); - console.log(chalk.green('Whitelist transaction was successful.')); + console.log(chalk.green('Modify whitelist transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } } @@ -785,6 +786,31 @@ async function percentageTransferManager() { } break; case 'Modify whitelist from CSV': + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${PERCENTAGE_WHITELIST_DATA_CSV}): `, { + defaultInput: PERCENTAGE_WHITELIST_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => web3.utils.isAddress(row[0]) && typeof row[1] === 'boolean'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')}`)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, isWhitelistedArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to modify whitelist accounts:\n\n`, investorArray[batch], '\n'); + let action = await currentTransferManager.methods.modifyWhitelistMulti(investorArray[batch], isWhitelistedArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Modify whitelist transaction was successful.')); + console.log(`${receipt.gasUsed} gas used. Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } break; case 'Allow primary issuance': case 'Disallow primary issuance': diff --git a/CLI/data/Transfer/PercentageTM/whitelist_data.csv b/CLI/data/Transfer/PercentageTM/whitelist_data.csv new file mode 100644 index 000000000..19d7f163c --- /dev/null +++ b/CLI/data/Transfer/PercentageTM/whitelist_data.csv @@ -0,0 +1,10 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,true +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,true +0xac297053173b02b02a737d47f7b4a718e5b170ef,true +0x49fc0b78238dab644698a90fa351b4c749e123d2,true +0x10223927009b8add0960359dd90d1449415b7ca9,true +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,true +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,true +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,false +0x56be93088141b16ebaa9416122fd1d928da25ecf,false +0xbb276b6f68f0a41d54b7e0a608fe8eb1ebdee7b0,false \ No newline at end of file From 6121319bf63f9da363b06a84187b0e1b0d5b2207 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 29 Nov 2018 13:48:35 -0300 Subject: [PATCH 313/582] CLI - Single blacklist operations --- CLI/commands/helpers/contract_abis.js | 5 + CLI/commands/transfer_manager.js | 220 +++++++++++++++++++++++++- 2 files changed, 223 insertions(+), 2 deletions(-) diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index f93f18ac7..5c152ba69 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -8,6 +8,7 @@ let cappedSTOABI; let usdTieredSTOABI; let generalTransferManagerABI; let manualApprovalTransferManagerABI; +let blacklistTransferManagerABI; let generalPermissionManagerABI; let polyTokenABI; let cappedSTOFactoryABI; @@ -31,6 +32,7 @@ try { usdTieredSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTO.json').toString()).abi; generalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralTransferManager.json').toString()).abi; manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ManualApprovalTransferManager.json').toString()).abi; + blacklistTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/BlacklistTransferManager.json').toString()).abi; generalPermissionManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralPermissionManager.json').toString()).abi; polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; @@ -78,6 +80,9 @@ module.exports = { manualApprovalTransferManager: function () { return manualApprovalTransferManagerABI; }, + blacklistTransferManager: function () { + return blacklistTransferManagerABI; + }, generalPermissionManager: function () { return generalPermissionManagerABI; }, diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index ee42b2fa4..4dc06bcd0 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -197,6 +197,11 @@ async function configExistingModules(tmModules) { currentTransferManager.setProvider(web3.currentProvider); await manualApprovalTransferManager(); break; + case 'BlacklistTransferManager': + currentTransferManager = new web3.eth.Contract(abis.blacklistTransferManager(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await blacklistTransferManager(); + break; case 'PercentageTransferManager': //await percentageTransferManager(); console.log(chalk.red(` @@ -230,8 +235,8 @@ async function configExistingModules(tmModules) { } async function addTransferManagerModule() { - let options = ['GeneralTransferManager', 'ManualApprovalTransferManager'/*, 'PercentageTransferManager', -'CountTransferManager', 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM'*/]; + let options = ['GeneralTransferManager', 'ManualApprovalTransferManager', 'BlacklistTransferManager']; + /*, 'PercentageTransferManager', 'CountTransferManager', 'SingleTradeVolumeRestrictionTM', 'LookupVolumeRestrictionTM'];*/ let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', { cancel: 'Return' }); if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { @@ -691,6 +696,217 @@ async function getManualBlocking(_from, _to) { return result; } +async function blacklistTransferManager() { + console.log(chalk.blue(`Blacklist Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + + let currentBlacklists = await currentTransferManager.methods.getAllBlacklists().call(); + console.log(`- Blacklists: ${currentBlacklists.length}`); + + let options = ['Add new blacklist']; + if (currentBlacklists.length > 0) { + options.push('Manage existing blacklist'); + } + options.push('Delete investors from all blacklists', 'Operate with multiple blacklists'); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: "Return" }); + let optionSelected = index !== -1 ? options[index] : 'Return'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add new blacklist': + let name = readlineSync.question(`Enter the name of the blacklist type: `, { + limit: function (input) { + return input !== ""; + }, + limitMessage: `Invalid blacklist name` + }); + let minuteFromNow = Math.floor(Date.now() / 1000) + 60; + let startTime = readlineSync.questionInt(`Enter the start date (Unix Epoch time) of the blacklist type (a minute from now = ${minuteFromNow}): `, { defaultInput: minuteFromNow }); + let oneDayFromStartTime = startTime + 24 * 60 * 60; + let endTime = readlineSync.questionInt(`Enter the end date (Unix Epoch time) of the blacklist type (1 day from start time = ${oneDayFromStartTime}): `, { defaultInput: oneDayFromStartTime }); + let repeatPeriodTime = readlineSync.questionInt(`Enter the repeat period (days) of the blacklist type, 0 to disable (90 days): `, { defaultInput: 90 }); + if (readlineSync.keyInYNStrict(`Do you want to add an investor to this blacklist type? `)) { + let investor = readlineSync.question(`Enter the address of the investor: `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: `Must be a valid address` + }); + let addInvestorToNewBlacklistAction = currentTransferManager.methods.addInvestorToNewBlacklist( + startTime, + endTime, + web3.utils.toHex(name), + repeatPeriodTime, + investor + ); + let addInvestorToNewBlacklistReceipt = await common.sendTransaction(addInvestorToNewBlacklistAction); + let addNewBlacklistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addInvestorToNewBlacklistReceipt.logs, 'AddBlacklistType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(addNewBlacklistEvent._blacklistName)} blacklist type has been added successfully!`)); + let addInvestorToNewBlacklistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addInvestorToNewBlacklistReceipt.logs, 'AddInvestorToBlacklist'); + console.log(chalk.green(`${addInvestorToNewBlacklistEvent._investor} has been added to ${web3.utils.hexToUtf8(addInvestorToNewBlacklistEvent._blacklistName)} successfully!`)); + } else { + let addBlacklistTypeAction = currentTransferManager.methods.addBlacklistType(startTime, endTime, web3.utils.toHex(name), repeatPeriodTime); + let addBlacklistTypeReceipt = await common.sendTransaction(addBlacklistTypeAction); + let addBlacklistTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addBlacklistTypeReceipt.logs, 'AddBlacklistType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(addBlacklistTypeEvent._blacklistName)} blacklist type has been added successfully!`)); + } + break; + case 'Manage existing blacklist': + let options = currentBlacklists.map(b => web3.utils.hexToUtf8(b)); + let index = readlineSync.keyInSelect(options, 'Which blacklist type do you want to manage? ', { cancel: "Return" }); + let optionSelected = index !== -1 ? options[index] : 'Return'; + console.log('Selected:', optionSelected, '\n'); + if (index !== -1) { + await manageExistingBlacklist(currentBlacklists[index]); + } + break; + case 'Remove investors from all blacklists': + let investorsToRemove = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e. addr1,addr2,addr3): `, { + limit: function (input) { + let addresses = input.split(","); + return ( + addresses.length > 0 && + addresses.every(a => web3.utils.isAddress(a)) + ); + }, + limitMessage: `All addresses must be valid` + }).split(','); + let deleteInvestorFromAllBlacklistAction; + if (investorsToRemove.length === 1) { + deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.deleteInvestorFromAllBlacklist(investorsToAdd[0]); + } else { + deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.adeleteInvestorFromAllBlacklistMulti(nvestorsToAdd); + } + let deleteInvestorFromAllBlacklistReceipt = await common.sendTransaction(deleteInvestorFromAllBlacklistAction); + let deleteInvestorFromAllBlacklistEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, deleteInvestorFromAllBlacklistReceipt.logs, 'DeleteInvestorFromBlacklist'); + deleteInvestorFromAllBlacklistEvents.map(e => console.log(chalk.green(`${e._investor} has been removed from ${web3.utils.hexToUtf8(e._blacklistName)} successfully!`))); + break; + case 'Operate with multiple blacklists': + await operateWithMultipleBlacklists(); + break; + } +} + +async function manageExistingBlacklist(blacklistName) { + // Show current data + let currentBlacklist = await currentTransferManager.methods.blacklists(blacklistName).call(); + let investors = await currentTransferManager.methods.getListOfAddresses(blacklistName).call(); + + console.log(`- Name: ${web3.utils.hexToUtf8(blacklistName)}`); + console.log(`- Start time: ${moment.unix(currentBlacklist.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- End time: ${moment.unix(currentBlacklist.endTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- Span: ${gbl.constants.DURATION.days(currentBlacklist.endTime - currentBlacklist.startTime)} days`); + console.log(`- Repeat period time: ${currentBlacklist.repeatPeriodTime} days`); + console.log(`- Investors: ${investors.length}`); + // ------------------ + + let options = [ + "Modify properties", + "Show investors", + "Add investors", + "Remove investor", + "Delete this blacklist type" + ]; + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); + let optionSelected = index !== -1 ? options[index] : 'Return'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Modify properties': + let minuteFromNow = Math.floor(Date.now() / 1000) + 60; + let startTime = readlineSync.questionInt(`Enter the start date (Unix Epoch time) of the blacklist type (a minute from now = ${minuteFromNow}): `, { defaultInput: minuteFromNow }); + let oneDayFromStartTime = startTime + 24 * 60 * 60; + let endTime = readlineSync.questionInt(`Enter the end date (Unix Epoch time) of the blacklist type (1 day from start time = ${oneDayFromStartTime}): `, { defaultInput: oneDayFromStartTime }); + let repeatPeriodTime = readlineSync.questionInt(`Enter the repeat period (days) of the blacklist type, 0 to disable (90 days): `, { defaultInput: 90 }); + let modifyBlacklistTypeAction = currentTransferManager.methods.modifyBlacklistType( + startTime, + endTime, + blacklistName, + repeatPeriodTime + ); + let modifyBlacklistTypeReceipt = await common.sendTransaction(modifyBlacklistTypeAction); + let modifyBlacklistTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyBlacklistTypeReceipt.logs, 'ModifyBlacklistType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(modifyBlacklistTypeEvent._blacklistName)} blacklist type has been modified successfully!`)); + break; + case 'Show investors': + if (investors.length > 0) { + console.log("************ List of investors ************"); + investors.map(i => console.log(i)); + } else { + console.log(chalk.yellow("There are no investors yet")); + } + break; + case 'Add investors': + let investorsToAdd = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e. addr1,addr2,addr3): `, { + limit: function (input) { + let addresses = input.split(","); + return ( + addresses.length > 0 && + addresses.every(a => web3.utils.isAddress(a)) + ); + }, + limitMessage: `All addresses must be valid` + }).split(","); + let addInvestorToBlacklistAction; + if (investorsToAdd.length === 1) { + addInvestorToBlacklistAction = currentTransferManager.methods.addInvestorToBlacklist(investorsToAdd[0], blacklistName); + } else { + addInvestorToBlacklistAction = currentTransferManager.methods.addInvestorToBlacklistMulti(investorsToAdd, blacklistName); + } + let addInvestorToBlacklistReceipt = await common.sendTransaction(addInvestorToBlacklistAction); + let addInvestorToBlacklistEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, addInvestorToBlacklistReceipt.logs, 'AddInvestorToBlacklist'); + addInvestorToBlacklistEvents.map(e => console.log(chalk.green(`${e._investor} has been added to ${web3.utils.hexToUtf8(e._blacklistName)} successfully!`))); + break; + case "Remove investor": + let investorsToRemove = readlineSync.question(`Enter the address of the investor: `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: `Must be a valid address` + }); + let deleteInvestorFromBlacklistAction = currentTransferManager.methods.deleteInvestorFromBlacklist(investorsToRemove, blacklistName); + let deleteInvestorFromBlacklistReceipt = await common.sendTransaction(deleteInvestorFromBlacklistAction); + let deleteInvestorFromBlacklistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, deleteInvestorFromBlacklistReceipt.logs, 'DeleteInvestorFromBlacklist'); + console.log(chalk.green(`${deleteInvestorFromBlacklistEvent._investor} has been removed from ${web3.utils.hexToUtf8(deleteInvestorFromBlacklistEvent._blacklistName)} successfully!`)); + break; + case "Delete this blacklist type": + if (readlineSync.keyInYNStrict()) { + let deleteBlacklistTypeAction = currentTransferManager.methods.deleteBlacklistType(blacklistName); + let deleteBlacklistTypeReceipt = await common.sendTransaction(deleteBlacklistTypeAction); + let deleteBlacklistTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, deleteBlacklistTypeReceipt.logs, 'DeleteBlacklistType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(deleteBlacklistTypeEvent._blacklistName)} blacklist type has been deleted successfully!`)); + } + break; + } +} + +async function operateWithMultipleBlacklists() { + let options = ['Add multiple blacklists']; + if (currentBlacklists.length > 0) { + options.push('Modify multiple blacklists'); + } + options.push( + 'Delete multiple blacklists', + 'Add investors to multiple blacklists', + 'Remove investors from multiple blacklists' + ); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); + let optionSelected = index !== -1 ? options[index] : 'Return'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add multiple blacklists': + break; + case 'Modify multiple blacklists': + break; + case 'Delete multiple blacklists': + break; + case 'Add investors to multiple blacklists': + break; + case 'Remove investors from multiple blacklists': + break; + } +} + async function singleTradeVolumeRestrictionTM() { console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address} `)); console.log(); From 04f02c1d72eb486b71d4c39cefb28ac05796c6dd Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 3 Dec 2018 18:58:46 -0500 Subject: [PATCH 314/582] Bump versions --- contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol | 2 +- contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol | 2 +- .../modules/TransferManager/GeneralTransferManagerFactory.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index b7e668111..bae9913b8 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -22,7 +22,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); - version = "1.0.0"; + version = "2.1.0"; name = "ERC20DividendCheckpoint"; title = "ERC20 Dividend Checkpoint"; description = "Create ERC20 dividends for token holders at a specific checkpoint"; diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 2d8d8f529..712292d0a 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -22,7 +22,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); - version = "1.0.0"; + version = "2.1.0"; name = "EtherDividendCheckpoint"; title = "Ether Dividend Checkpoint"; description = "Create ETH dividends for token holders at a specific checkpoint"; diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 4259e8b9f..cffc61a32 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -22,7 +22,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); - version = "2.0.0"; + version = "2.1.0"; name = "GeneralTransferManager"; title = "General Transfer Manager"; description = "Manage transfers using a time based whitelist"; From bae7d62e98cf16e1800f3fe68ecc9a0eef27fe75 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 3 Dec 2018 23:48:00 -0300 Subject: [PATCH 315/582] CLI - Multi blacklist operations for BlacklistTM --- CLI/commands/common/common_functions.js | 2 +- CLI/commands/transfer_manager.js | 187 ++++++++++++++++-- .../BlacklistTM/add_blacklist_data.csv | 4 + .../add_investor_blacklist_data.csv | 12 ++ .../BlacklistTM/delete_blacklist_data.csv | 4 + .../BlacklistTM/modify_blacklist_data.csv | 4 + .../remove_investor_blacklist_data.csv | 12 ++ 7 files changed, 210 insertions(+), 15 deletions(-) create mode 100644 CLI/data/Transfer/BlacklistTM/add_blacklist_data.csv create mode 100644 CLI/data/Transfer/BlacklistTM/add_investor_blacklist_data.csv create mode 100644 CLI/data/Transfer/BlacklistTM/delete_blacklist_data.csv create mode 100644 CLI/data/Transfer/BlacklistTM/modify_blacklist_data.csv create mode 100644 CLI/data/Transfer/BlacklistTM/remove_investor_blacklist_data.csv diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index c19834037..36bcb5d21 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -102,7 +102,7 @@ module.exports = { await checkPermissions(action); options = getFinalOptions(options); - let gasLimit = await getGasLimit(options, action); + let gasLimit = 8000000//await getGasLimit(options, action); console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gasLimit} ----`)); diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 4dc06bcd0..4b88eae92 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -10,6 +10,11 @@ const csvParse = require('./helpers/csv'); /////////////////// // Constants const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; +const ADD_BLACKLIST_DATA_CSV = './CLI/data/Transfer/BlacklistTM/add_blacklist_data.csv'; +const MODIFY_BLACKLIST_DATA_CSV = './CLI/data/Transfer/BlacklistTM/modify_blacklist_data.csv'; +const DELETE_BLACKLIST_DATA_CSV = './CLI/data/Transfer/BlacklistTM/delete_blacklist_data.csv'; +const ADD_INVESTOR_BLACKLIST_DATA_CSV = './CLI/data/Transfer/BlacklistTM/add_investor_blacklist_data.csv'; +const REMOVE_INVESTOR_BLACKLIST_DATA_CSV = './CLI/data/Transfer/BlacklistTM/remove_investor_blacklist_data.csv'; // App flow let tokenSymbol; @@ -514,7 +519,7 @@ async function modifyWhitelistInBatch() { let [investorArray, fromTimesArray, toTimesArray, expiryTimeArray, canBuyFromSTOArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { console.log(`Batch ${batch + 1} - Attempting to modify whitelist to accounts: \n\n`, investorArray[batch], '\n'); - let action = await currentTransferManager.methods.modifyWhitelistMulti(investorArray[batch], fromTimesArray[batch], toTimesArray[batch], expiryTimeArray[batch], canBuyFromSTOArray[batch]); + let action = currentTransferManager.methods.modifyWhitelistMulti(investorArray[batch], fromTimesArray[batch], toTimesArray[batch], expiryTimeArray[batch], canBuyFromSTOArray[batch]); let receipt = await common.sendTransaction(action); console.log(chalk.green('Whitelist transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); @@ -762,11 +767,7 @@ async function blacklistTransferManager() { case 'Remove investors from all blacklists': let investorsToRemove = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e. addr1,addr2,addr3): `, { limit: function (input) { - let addresses = input.split(","); - return ( - addresses.length > 0 && - addresses.every(a => web3.utils.isAddress(a)) - ); + return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); }, limitMessage: `All addresses must be valid` }).split(','); @@ -781,7 +782,7 @@ async function blacklistTransferManager() { deleteInvestorFromAllBlacklistEvents.map(e => console.log(chalk.green(`${e._investor} has been removed from ${web3.utils.hexToUtf8(e._blacklistName)} successfully!`))); break; case 'Operate with multiple blacklists': - await operateWithMultipleBlacklists(); + await operateWithMultipleBlacklists(currentBlacklists); break; } } @@ -794,7 +795,7 @@ async function manageExistingBlacklist(blacklistName) { console.log(`- Name: ${web3.utils.hexToUtf8(blacklistName)}`); console.log(`- Start time: ${moment.unix(currentBlacklist.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); console.log(`- End time: ${moment.unix(currentBlacklist.endTime).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(`- Span: ${gbl.constants.DURATION.days(currentBlacklist.endTime - currentBlacklist.startTime)} days`); + console.log(`- Span: ${(currentBlacklist.endTime - currentBlacklist.startTime) / 60 / 60 / 24} days`); console.log(`- Repeat period time: ${currentBlacklist.repeatPeriodTime} days`); console.log(`- Investors: ${investors.length}`); // ------------------ @@ -838,11 +839,7 @@ async function manageExistingBlacklist(blacklistName) { case 'Add investors': let investorsToAdd = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e. addr1,addr2,addr3): `, { limit: function (input) { - let addresses = input.split(","); - return ( - addresses.length > 0 && - addresses.every(a => web3.utils.isAddress(a)) - ); + return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); }, limitMessage: `All addresses must be valid` }).split(","); @@ -879,7 +876,7 @@ async function manageExistingBlacklist(blacklistName) { } } -async function operateWithMultipleBlacklists() { +async function operateWithMultipleBlacklists(currentBlacklists) { let options = ['Add multiple blacklists']; if (currentBlacklists.length > 0) { options.push('Modify multiple blacklists'); @@ -895,18 +892,180 @@ async function operateWithMultipleBlacklists() { console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Add multiple blacklists': + await addBlacklistsInBatch(); break; case 'Modify multiple blacklists': + await modifyBlacklistsInBatch(); break; case 'Delete multiple blacklists': + await deleteBlacklistsInBatch(); break; case 'Add investors to multiple blacklists': + await addInvestorsToBlacklistsInBatch(); break; case 'Remove investors from multiple blacklists': + await removeInvestorsFromBlacklistsInBatch(); break; } } +async function addBlacklistsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_BLACKLIST_DATA_CSV}): `, { + defaultInput: ADD_BLACKLIST_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => moment.unix(row[0]).isValid() && + moment.unix(row[1]).isValid() && + typeof row[2] === 'string' && + (!isNaN(row[3] && (parseFloat(row[3]) % 1 === 0)))); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [startTimeArray, endTimeArray, blacklistNameArray, repeatPeriodTimeArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add the following blacklists:\n\n`, blacklistNameArray[batch], '\n'); + blacklistNameArray[batch] = blacklistNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.addBlacklistTypeMulti(startTimeArray[batch], endTimeArray[batch], blacklistNameArray[batch], repeatPeriodTimeArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add multiple blacklists transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function modifyBlacklistsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${MODIFY_BLACKLIST_DATA_CSV}): `, { + defaultInput: MODIFY_BLACKLIST_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => moment.unix(row[0]).isValid() && + moment.unix(row[1]).isValid() && + typeof row[2] === 'string' && + (!isNaN(row[3] && (parseFloat(row[3]) % 1 === 0)))); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [startTimeArray, endTimeArray, blacklistNameArray, repeatPeriodTimeArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to modify the following blacklists:\n\n`, blacklistNameArray[batch], '\n'); + blacklistNameArray[batch] = blacklistNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.modifyBlacklistTypeMulti(startTimeArray[batch], endTimeArray[batch], blacklistNameArray[batch], repeatPeriodTimeArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Modify multiple blacklists transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function deleteBlacklistsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${DELETE_BLACKLIST_DATA_CSV}): `, { + defaultInput: DELETE_BLACKLIST_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => typeof row[0] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [blacklistNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to delete the following blacklists:\n\n`, blacklistNameArray[batch], '\n'); + blacklistNameArray[batch] = blacklistNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.deleteBlacklistTypeMulti(blacklistNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Delete multiple blacklists transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function addInvestorsToBlacklistsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_INVESTOR_BLACKLIST_DATA_CSV}): `, { + defaultInput: ADD_INVESTOR_BLACKLIST_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + typeof row[1] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, blacklistNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add the following investors:\n\n`, investorArray[batch], '\n'); + blacklistNameArray[batch] = blacklistNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.addMultiInvestorToBlacklistMulti(investorArray[batch], blacklistNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add investors to multiple blacklists transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function removeInvestorsFromBlacklistsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REMOVE_INVESTOR_BLACKLIST_DATA_CSV}): `, { + defaultInput: REMOVE_INVESTOR_BLACKLIST_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + typeof row[1] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, blacklistNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to remove the following investors:\n\n`, investorArray[batch], '\n'); + blacklistNameArray[batch] = blacklistNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.deleteMultiInvestorsFromBlacklistMulti(investorArray[batch], blacklistNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Remove investors from multiple blacklists transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + async function singleTradeVolumeRestrictionTM() { console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address} `)); console.log(); diff --git a/CLI/data/Transfer/BlacklistTM/add_blacklist_data.csv b/CLI/data/Transfer/BlacklistTM/add_blacklist_data.csv new file mode 100644 index 000000000..1d925053d --- /dev/null +++ b/CLI/data/Transfer/BlacklistTM/add_blacklist_data.csv @@ -0,0 +1,4 @@ +1559401200,1560178800,"FirstTenDays",30 +1560535200,1560621600,"NoRepeat",0 +1566734400,1567252800,"Every90",90 +1567296000,1567303200,"TwoHours",2 diff --git a/CLI/data/Transfer/BlacklistTM/add_investor_blacklist_data.csv b/CLI/data/Transfer/BlacklistTM/add_investor_blacklist_data.csv new file mode 100644 index 000000000..cd0fe922c --- /dev/null +++ b/CLI/data/Transfer/BlacklistTM/add_investor_blacklist_data.csv @@ -0,0 +1,12 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,"FirstTenDays" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,"FirstTenDays" +0xac297053173b02b02a737d47f7b4a718e5b170ef,"FirstTenDays" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"FirstTenDays" +0x10223927009b8add0960359dd90d1449415b7ca9,"FirstTenDays" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"NoRepeat" +0x10223927009b8add0960359dd90d1449415b7ca9,"NoRepeat" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,"NoRepeat" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,"NoRepeat" +0x10223927009b8add0960359dd90d1449415b7ca9,"Every90" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,"Every90" +0x56be93088141b16ebaa9416122fd1d928da25ecf,"Every90" \ No newline at end of file diff --git a/CLI/data/Transfer/BlacklistTM/delete_blacklist_data.csv b/CLI/data/Transfer/BlacklistTM/delete_blacklist_data.csv new file mode 100644 index 000000000..752cb89c1 --- /dev/null +++ b/CLI/data/Transfer/BlacklistTM/delete_blacklist_data.csv @@ -0,0 +1,4 @@ +"FirstTenDays" +"Every90" +"NoRepeat" +"TwoHours" \ No newline at end of file diff --git a/CLI/data/Transfer/BlacklistTM/modify_blacklist_data.csv b/CLI/data/Transfer/BlacklistTM/modify_blacklist_data.csv new file mode 100644 index 000000000..4b5e45b4d --- /dev/null +++ b/CLI/data/Transfer/BlacklistTM/modify_blacklist_data.csv @@ -0,0 +1,4 @@ +1559412000,1560178800,"FirstTenDays",30 +1560535200,1561032000,"NoRepeat",0 +1566734400,1567252800,"Every90",90 +1567296000,1567303200,"TwoHours",3 diff --git a/CLI/data/Transfer/BlacklistTM/remove_investor_blacklist_data.csv b/CLI/data/Transfer/BlacklistTM/remove_investor_blacklist_data.csv new file mode 100644 index 000000000..cd0fe922c --- /dev/null +++ b/CLI/data/Transfer/BlacklistTM/remove_investor_blacklist_data.csv @@ -0,0 +1,12 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,"FirstTenDays" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,"FirstTenDays" +0xac297053173b02b02a737d47f7b4a718e5b170ef,"FirstTenDays" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"FirstTenDays" +0x10223927009b8add0960359dd90d1449415b7ca9,"FirstTenDays" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"NoRepeat" +0x10223927009b8add0960359dd90d1449415b7ca9,"NoRepeat" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,"NoRepeat" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,"NoRepeat" +0x10223927009b8add0960359dd90d1449415b7ca9,"Every90" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,"Every90" +0x56be93088141b16ebaa9416122fd1d928da25ecf,"Every90" \ No newline at end of file From 0b5191693caceaedafa8de7c9f94c4104accef63 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 3 Dec 2018 23:48:40 -0300 Subject: [PATCH 316/582] CLI - Typo --- CLI/commands/sto_manager.js | 4 ++-- CLI/commands/token_manager.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index b66f3d80e..bbc262849 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -752,7 +752,7 @@ async function changeAccreditedInBatch(currentSTO) { let [investorArray, isAccreditedArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { console.log(`Batch ${batch + 1} - Attempting to change accredited accounts:\n\n`, investorArray[batch], '\n'); - let action = await currentSTO.methods.changeAccredited(investorArray[batch], isAccreditedArray[batch]); + let action = currentSTO.methods.changeAccredited(investorArray[batch], isAccreditedArray[batch]); let receipt = await common.sendTransaction(action); console.log(chalk.green('Change accredited transaction was successful.')); console.log(`${receipt.gasUsed} gas used. Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); @@ -780,7 +780,7 @@ async function changeNonAccreditedLimitsInBatch(currentSTO) { let [investorArray, limitArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { console.log(`Batch ${batch + 1} - Attempting to change non accredited limit to accounts:\n\n`, investorArray[batch], '\n'); - let action = await currentSTO.methods.changeNonAccreditedLimit(investorArray[batch], limitArray[batch]); + let action = currentSTO.methods.changeNonAccreditedLimit(investorArray[batch], limitArray[batch]); let receipt = await common.sendTransaction(action); console.log(chalk.green('Change non accredited limits transaction was successful.')); console.log(`${receipt.gasUsed} gas used. Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index e10f81467..4928623a8 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -388,7 +388,7 @@ async function multiMint(_csvFilePath, _batchSize) { for (let batch = 0; batch < batches.length; batch++) { console.log(`Batch ${batch + 1} - Attempting to mint tokens to accounts: \n\n`, investorArray[batch], '\n'); amountArray[batch] = amountArray[batch].map(a => web3.utils.toWei(a.toString())); - let action = await securityToken.methods.mintMulti(investorArray[batch], amountArray[batch]); + let action = securityToken.methods.mintMulti(investorArray[batch], amountArray[batch]); let receipt = await common.sendTransaction(action); console.log(chalk.green('Multi mint transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); From ee059b04bcf9d5d5885be0d0f829860f43ad35f6 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 4 Dec 2018 15:16:30 +0530 Subject: [PATCH 317/582] change business logic of verify transfer --- .../TransferManager/VolumeRestrictionTM.sol | 256 +++-- .../VolumeRestrictionTM_prev.sol | 932 ------------------ 2 files changed, 111 insertions(+), 1077 deletions(-) delete mode 100644 contracts/modules/TransferManager/VolumeRestrictionTM_prev.sol diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index f16dc9de7..5f2df00e4 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -26,8 +26,10 @@ contract VolumeRestrictionTM is ITransferManager { struct BucketDetails { uint256 lastTradedDayTime; - uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays + uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays + uint256 globalSumOfLastPeriod; uint256 daysCovered; // No of days covered till (from the startTime of VolumeRestriction) + uint256 globalDaysCovered; } // Global restriction that applies to all token holders @@ -44,8 +46,6 @@ contract VolumeRestrictionTM is ITransferManager { mapping(address => BucketDetails) internal bucketToUser; // List of wallets that are exempted from all the restrictions applied by the this contract mapping(address => bool) public exemptList; - // Store the amount of tokens get transacted in a day - mapping(uint256 => uint256) public globalBucket; // Emit when the token holder is added/removed from the exemption list event ChangedExemptWalletList(address indexed _wallet, bool _change); @@ -130,13 +130,7 @@ contract VolumeRestrictionTM is ITransferManager { if (!paused && _from != address(0) && !exemptList[_from]) { // Function must only be called by the associated security token if _isTransfer == true require(msg.sender == securityToken || !_isTransfer); - // Checking the individual restriction if the `_from` comes in the individual category - if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { - return _individualRestrictionCheck(_from, _amount, _isTransfer); - // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically - } else if (globalRestriction.endTime >= now && globalRestriction.startTime <= now) { - return _globalRestrictionCheck(_from, _amount, _isTransfer); - } + return _restrictionCheck(_from, _amount, _isTransfer); } return Result.NA; } @@ -471,16 +465,52 @@ contract VolumeRestrictionTM is ITransferManager { /** * @notice Internal function have a logic to validate the txn amount with global restriction */ - function _globalRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + function _restrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + uint256 sumOfLastPeriod = 0; + uint256 daysCovered = 0; + uint256 lastTradedDayTime; + uint256 globalSumOfLastPeriod; + uint256 globalDaysCovered; + bool validIR = true; + bool validGR = true; + if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { + (validIR, sumOfLastPeriod, lastTradedDayTime, daysCovered) = _individualRestrictionCheck(_from, _amount); + } + (validGR, globalSumOfLastPeriod, lastTradedDayTime, globalDaysCovered) = _globalRestrictionCheck(_from, _amount); + // Total amout that is transacted uptill now for `fromTimestamp` day + uint256 txSumOfDay = bucket[_from][lastTradedDayTime]; + // allow modification in storage when `_isTransfer` equals true + if (_isTransfer) { + // update the storage + _updateStorage( + _from, + _amount, + lastTradedDayTime, + sumOfLastPeriod, + globalSumOfLastPeriod, + daysCovered, + globalDaysCovered + ); + } + if (validGR && validIR && _dailyTxCheck(txSumOfDay, _amount)) + return Result.NA; + else + return Result.INVALID; + } + + /** + * @notice Internal function have a logic to validate the txn amount with global restriction + */ + function _globalRestrictionCheck(address _from, uint256 _amount) internal view returns (bool, uint256, uint256, uint256) { + uint256 daysCovered; uint256 fromTimestamp; uint256 sumOfLastPeriod = 0; - uint256 daysCovered = 0; - if (globalBucketDetails.lastTradedDayTime == 0) { + if (bucketToUser[_from].lastTradedDayTime < globalRestriction.startTime) { // It will execute when the txn is performed first time after the addition of global restriction fromTimestamp = globalRestriction.startTime; } else { // picking up the preivous timestamp - fromTimestamp = globalBucketDetails.lastTradedDayTime; + fromTimestamp = bucketToUser[_from].lastTradedDayTime; } // Calculating the difference of days uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); @@ -490,56 +520,49 @@ contract VolumeRestrictionTM is ITransferManager { fromTimestamp, diffDays, _from, - globalBucketDetails, + bucketToUser[_from], true, - globalRestriction + globalRestriction.rollingPeriodInDays ); - // Total amout that is transacted uptill now for `fromTimestamp` day - uint256 txSumOfDay = bucket[_from][fromTimestamp]; - // Daily transaction check - if (_dailyTxCheck(sumOfLastPeriod, txSumOfDay, _amount, individualRestriction[_from])) { - // allow modification in storage when `_isTransfer` equals true - if(_isTransfer) { - // update the global storage - _updateGlobalStorage( - _from, - fromTimestamp, - _amount, - sumOfLastPeriod, - daysCovered - ); - } - return Result.NA; - } - return Result.INVALID; + // validation of the transaction amount + if (_checkValidAmountToTransact(sumOfLastPeriod, _amount, globalRestriction)) { + return (true, sumOfLastPeriod, fromTimestamp, daysCovered); + } + return (false, sumOfLastPeriod, fromTimestamp, daysCovered); } /** - * @notice Internal function to update the state variables related to global restriction + * @notice Internal function used to validate the transaction for a given address + * If it validates then it also update the storage corressponds to the individual restriction */ - function _updateGlobalStorage( - address _from, - uint256 _fromTime, - uint256 _amount, - uint256 _sumOfLastPeriod, - uint256 _daysCovered - ) - internal - { - if (globalBucketDetails.lastTradedDayTime != _fromTime) { - // Assigning the latest transaction timestamp of the day - globalBucketDetails.lastTradedDayTime = _fromTime; - globalBucketDetails.daysCovered = _daysCovered; - } - if (_amount != 0) { - // updating the sumOfLastPeriod - globalBucketDetails.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); - - // Increasing the total amount of the day by `_amount` - globalBucket[_fromTime] = globalBucket[_fromTime].add(_amount); - // Updating the total day amount traded. - bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); + function _individualRestrictionCheck(address _from, uint256 _amount) internal view returns (bool, uint256, uint256, uint256) { + // using the variable to avoid stack too deep error + uint256 daysCovered = individualRestriction[_from].rollingPeriodInDays; + uint256 fromTimestamp; + uint256 sumOfLastPeriod = 0; + if (bucketToUser[_from].lastTradedDayTime < individualRestriction[_from].startTime) { + // It will execute when the txn is performed first time after the addition of individual restriction + fromTimestamp = individualRestriction[_from].startTime; + } else { + // Picking up the last timestamp + fromTimestamp = bucketToUser[_from].lastTradedDayTime; } + + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod + // re-using the local variables to avoid the stack too deep error. + (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( + fromTimestamp, + BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now), + _from, + bucketToUser[_from], + false, + daysCovered + ); + // validation of the transaction amount + if (_checkValidAmountToTransact(sumOfLastPeriod, _amount, individualRestriction[_from])) { + return (true, sumOfLastPeriod, fromTimestamp, daysCovered); + } + return (false, sumOfLastPeriod, fromTimestamp, daysCovered); } /// Internal function for the bucket check @@ -549,35 +572,32 @@ contract VolumeRestrictionTM is ITransferManager { address _from, BucketDetails memory _bucketDetails, bool _isGlobal, - VolumeRestriction _restriction + uint256 _rollingPeriodInDays ) internal view returns (uint256, uint256, uint256) { - uint256 counter = _bucketDetails.daysCovered; + uint256 counter = _bucketDetails.globalDaysCovered; + uint256 sumOfLastPeriod = _bucketDetails.globalSumOfLastPeriod; uint256 i = 0; - if (_diffDays >= _restriction.rollingPeriodInDays) { + if (!_isGlobal) { + counter = _bucketDetails.daysCovered; + sumOfLastPeriod = _bucketDetails.sumOfLastPeriod; + } + if (_diffDays >= _rollingPeriodInDays) { // If the difference of days is greater than the rollingPeriod then sumOfLastPeriod will always be zero - _bucketDetails.sumOfLastPeriod = 0; - + sumOfLastPeriod = 0; } else { for (i = 0; i < _diffDays; i++) { // This condition is to check whether the first rolling period is covered or not // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting // the earlier value at that index - if (counter >= _restriction.rollingPeriodInDays) { - if (_isGlobal) { - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. - sub(globalBucket[_bucketDetails.lastTradedDayTime.sub((counter.sub(_restriction.rollingPeriodInDays)).mul(1 days))]); - } else { - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. - sub(bucket[_from][_bucketDetails.lastTradedDayTime.sub((counter.sub(_restriction.rollingPeriodInDays)).mul(1 days))]); - } + if (counter >= _rollingPeriodInDays) { + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + sumOfLastPeriod = sumOfLastPeriod. + sub(bucket[_from][_bucketDetails.lastTradedDayTime.sub((counter.sub(_rollingPeriodInDays)).mul(1 days))]); } - // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand // the alogrithm //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); @@ -589,71 +609,12 @@ contract VolumeRestrictionTM is ITransferManager { // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... // where T1,T2,T3 are timestamps having 24 hrs difference _fromTime = _fromTime.add(_diffDays.mul(1 days)); - return (_bucketDetails.sumOfLastPeriod, _fromTime, counter.add(_bucketDetails.daysCovered)); + return (sumOfLastPeriod, _fromTime, counter); } - /** - * @notice Internal function used to validate the transaction for a given address - * If it validates then it also update the storage corressponds to the individual restriction - */ - function _individualRestrictionCheck( - address _from, - uint256 _amount, - bool _isTransfer - ) - internal - returns(Result) - { - uint256 daysCovered; - uint256 fromTimestamp; - uint256 sumOfLastPeriod = 0; - if (bucketToUser[_from].lastTradedDayTime == 0) { - // It will execute when the txn is performed first time after the addition of individual restriction - fromTimestamp = individualRestriction[_from].startTime; - } else { - // Picking up the last timestamp - fromTimestamp = bucketToUser[_from].lastTradedDayTime; - } - // Calculating the difference of days - uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); - - // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod - // re-using the local variables to avoid the stack too deep error. - (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( - fromTimestamp, - diffDays, - _from, - bucketToUser[_from], - false, - individualRestriction[_from] - ); - // Total amout that is transacted uptill now for `fromTimestamp` day - // re-using the same variable to avoid the stach too deep error. here it will give you the sum of - // tokens traded in the current day (tx day) - diffDays = bucket[_from][fromTimestamp]; - // Daily transaction check - if (_dailyTxCheck(sumOfLastPeriod, diffDays, _amount, individualRestriction[_from])) { - if (_isTransfer) { - // update the Individual storage - _updateIndividualStorage( - _from, - fromTimestamp, - _amount, - sumOfLastPeriod, - daysCovered - ); - } - return Result.NA; - } - return Result.INVALID; - } - - function _dailyTxCheck( - uint256 _sumOfLastPeriod, uint256 _dailyAmount, - uint256 _amount, - VolumeRestriction _restriction + uint256 _amount ) internal view @@ -666,7 +627,7 @@ contract VolumeRestrictionTM is ITransferManager { if (!_checkValidAmountToTransact(_dailyAmount, _amount, dailyGlobalRestriction)) return false; } - return _checkValidAmountToTransact(_sumOfLastPeriod, _amount, _restriction); + return true; } function _checkValidAmountToTransact( @@ -692,25 +653,30 @@ contract VolumeRestrictionTM is ITransferManager { } } - function _updateIndividualStorage( + function _updateStorage( address _from, - uint256 _fromTime, uint256 _amount, + uint256 _lastTradedDayTime, uint256 _sumOfLastPeriod, - uint256 _daysCovered + uint256 _globalSumOfLastPeriod, + uint256 _daysCovered, + uint256 _globalDaysCovered ) internal { - if (bucketToUser[_from].lastTradedDayTime != _fromTime) { + if (bucketToUser[_from].lastTradedDayTime != _lastTradedDayTime) { // Assigning the latest transaction timestamp of the day - bucketToUser[_from].lastTradedDayTime = _fromTime; - bucketToUser[_from].daysCovered = _daysCovered; + bucketToUser[_from].lastTradedDayTime = _lastTradedDayTime; } - if(_amount != 0) { - bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); - + if (_amount != 0) { + if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { + bucketToUser[_from].daysCovered = _daysCovered; + bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + } + bucketToUser[_from].globalSumOfLastPeriod = _globalSumOfLastPeriod.add(_amount); + bucketToUser[_from].globalDaysCovered = _globalDaysCovered; // Increasing the total amount of the day by `_amount` - bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); + bucket[_from][_lastTradedDayTime] = bucket[_from][_lastTradedDayTime].add(_amount); } } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM_prev.sol b/contracts/modules/TransferManager/VolumeRestrictionTM_prev.sol deleted file mode 100644 index 5a42ede3f..000000000 --- a/contracts/modules/TransferManager/VolumeRestrictionTM_prev.sol +++ /dev/null @@ -1,932 +0,0 @@ -pragma solidity ^0.4.24; - -import "./ITransferManager.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../../libraries/BokkyPooBahsDateTimeLibrary.sol"; - -contract VolumeRestrictionTM_prev is ITransferManager { - - using SafeMath for uint256; - - // permission definition - bytes32 public constant ADMIN = "ADMIN"; - - enum RestrictionType { Fixed, Variable } - - struct VolumeRestriction { - uint256 allowedTokens; - uint256 allowedPercentageOfTokens; - uint256 startTime; - uint256 rollingPeriodInDays; - uint256 endTime; - RestrictionType typeOfRestriction; - } - - struct BucketDetails { - uint256[] timestamps; - uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays - } - - // Global restriction that applies to all token holders - VolumeRestriction public globalRestriction; - // Daily global restriction that applies to all token holders (Total ST traded daily is restricted) - VolumeRestriction public dailyGlobalRestriction; - // Variable stores the data matrix for the globa restrictions - BucketDetails internal globalBucketDetails; - // Restriction stored corresponds to a particular token holder - mapping(address => VolumeRestriction) public individualRestriction; - // Storing _from => day's timestamp => total amount transact in a day --individual - mapping(address => mapping(uint256 => uint256)) internal bucket; - // Storing the information that used to validate the transaction - mapping(address => BucketDetails) internal bucketToUser; - // List of wallets that are exempted from all the restrictions applied by the this contract - mapping(address => bool) public exemptList; - // Store the amount of tokens get transacted in a day - mapping(uint256 => uint256) public globalBucket; - - // Emit when the token holder is added/removed from the exemption list - event ChangedExemptWalletList(address indexed _wallet, bool _change); - // Emit when the new individual restriction is added corresponds to new token holders - event AddNewIndividualRestriction( - address indexed _holder, - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _typeOfRestriction - ); - // Emit when the individual restriction is modified for a given address - event ModifyIndividualRestriction( - address indexed _holder, - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _typeOfRestriction - ); - // Emit when the new global restriction is added - event AddGlobalRestriction( - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _typeOfRestriction - ); - // Emit when the new daily (global) restriction is added - event AddDailyGlobalRestriction( - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _typeOfRestriction - ); - // Emit when global restriction get modified - event ModifyGlobalRestriction( - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _typeOfRestriction - ); - // Emit when daily global restriction get modified - event ModifyDailyGlobalRestriction( - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _typeOfRestriction - ); - // Emit when the individual restriction gets removed - event IndividualRestrictionRemoved(address _user); - // Emit when the global restriction gets removed - event GlobalRestrictionRemoved(); - // Emit when the daily global restriction gets removed - event DailyGlobalRestrictionRemoved(); - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) - public - Module(_securityToken, _polyAddress) - { - - } - - /** - * @notice Used to verify the transfer/transferFrom transaction and prevent tranaction - * whose volume of tokens will voilate the maximum volume transfer restriction - * @param _from Address of the sender - * @param _amount The amount of tokens to transfer - * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable - */ - function verifyTransfer(address _from, address /*_to */, uint256 _amount, bytes /*_data*/, bool _isTransfer) public returns (Result) { - // If `_from` is present in the exemptionList or it is `0x0` address then it will not follow the vol restriction - if (!paused && _from != address(0) && !exemptList[_from]) { - // Function must only be called by the associated security token if _isTransfer == true - require(msg.sender == securityToken || !_isTransfer); - // Checking the individual restriction if the `_from` comes in the individual category - if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { - return _individualRestrictionCheck(_from, _amount, _isTransfer); - // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically - } else if (globalRestriction.endTime >= now && globalRestriction.startTime <= now) { - return _globalRestrictionCheck(_from, _amount, _isTransfer); - } - } - return Result.NA; - } - - /** - * @notice Add/Remove wallet address from the exempt list - * @param _wallet Ethereum wallet/contract address that need to be exempted - * @param _change Boolean value used to add (i.e true) or remove (i.e false) from the list - */ - function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { - require(_wallet != address(0), "Invalid address"); - exemptList[_wallet] = _change; - emit ChangedExemptWalletList(_wallet, _change); - } - - /** - * @notice Use to add the new individual restriction for a given token holder - * @param _holder Address of the token holder, whom restriction will be implied - * @param _allowedTokens Amount of tokens allowed to be trade for a given address. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. - * @param _startTime Unix timestamp at which restriction get into effect - * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) - * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) - */ - function addIndividualRestriction( - address _holder, - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _restrictionType - ) - external - withPerm(ADMIN) - { - _addIndividualRestriction( - _holder, - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - _restrictionType - ); - } - - /** - * @notice Use to add the new individual restriction for multiple token holders - * @param _holders Array of address of the token holders, whom restriction will be implied - * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. - * @param _allowedPercentageOfTokens Array of percentage of tokens w.r.t to totalSupply allowed to transact. - * @param _startTimes Array of unix timestamps at which restrictions get into effect - * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) - * @param _endTimes Array of unix timestamps at which restriction effects will gets end. - * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for variable) - */ - function addIndividualRestrictionMulti( - address[] _holders, - uint256[] _allowedTokens, - uint256[] _allowedPercentageOfTokens, - uint256[] _startTimes, - uint256[] _rollingPeriodInDays, - uint256[] _endTimes, - uint256[] _restrictionTypes - ) - public - withPerm(ADMIN) - { - _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); - require(_holders.length == _allowedTokens.length, "Length mismatch"); - for (uint256 i = 0; i < _holders.length; i++) { - _addIndividualRestriction( - _holders[i], - _allowedTokens[i], - _allowedPercentageOfTokens[i], - _startTimes[i], - _rollingPeriodInDays[i], - _endTimes[i], - _restrictionTypes[i] - ); - } - } - - /** - * @notice Use to add the new global restriction for all token holder - * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. - * @param _startTime Unix timestamp at which restriction get into effect - * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) - * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) - */ - function addGlobalRestriction( - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _restrictionType - ) - external - withPerm(ADMIN) - { - require( - globalRestriction.endTime < now, - "Not allowed" - ); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - if (globalRestriction.endTime != 0) { - removeGlobalRestriction(); - } - globalRestriction = VolumeRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - RestrictionType(_restrictionType) - ); - emit AddGlobalRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - _restrictionType - ); - } - - /** - * @notice Use to add the new global daily restriction for all token holder - * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. - * @param _startTime Unix timestamp at which restriction get into effect - * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) - */ - function addDailyGlobalRestriction( - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _endTime, - uint256 _restrictionType - ) - external - withPerm(ADMIN) - { - require( - dailyGlobalRestriction.endTime < now, - "Not Allowed" - ); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); - dailyGlobalRestriction = VolumeRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - 1, - _endTime, - RestrictionType(_restrictionType) - ); - emit AddDailyGlobalRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - 1, - _endTime, - _restrictionType - ); - } - - /** - * @notice use to remove the individual restriction for a given address - * @param _user Address of the user - */ - function removeIndividualRestriction(address _user) external withPerm(ADMIN) { - _removeIndividualRestriction(_user); - } - - /** - * @notice use to remove the individual restriction for a given address - * @param _users Array of address of the user - */ - function removeIndividualRestrictionMulti(address[] _users) external withPerm(ADMIN) { - for (uint256 i = 0; i < _users.length; i++) { - _removeIndividualRestriction(_users[i]); - } - } - - /** - * @notice Use to remove the global restriction - */ - function removeGlobalRestriction() public withPerm(ADMIN) { - require(globalRestriction.endTime != 0); - globalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); - globalBucketDetails.timestamps.length = 0; - globalBucketDetails.sumOfLastPeriod = 0; - emit GlobalRestrictionRemoved(); - } - - /** - * @notice Use to remove the daily global restriction - */ - function removeDailyGlobalRestriction() external withPerm(ADMIN) { - require(dailyGlobalRestriction.endTime != 0); - dailyGlobalRestriction = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); - emit DailyGlobalRestrictionRemoved(); - } - - /** - * @notice Use to modify the existing individual restriction for a given token holder - * @param _holder Address of the token holder, whom restriction will be implied - * @param _allowedTokens Amount of tokens allowed to be trade for a given address. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. - * @param _startTime Unix timestamp at which restriction get into effect - * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) - * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) - */ - function modifyIndividualRestriction( - address _holder, - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _restrictionType - ) - external - withPerm(ADMIN) - { - _modifyIndividualRestriction( - _holder, - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - _restrictionType - ); - } - - /** - * @notice Use to modify the existing individual restriction for multiple token holders - * @param _holders Array of address of the token holders, whom restriction will be implied - * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. - * @param _allowedPercentageOfTokens Array of percentage of tokens w.r.t to totalSupply allowed to transact. - * @param _startTimes Array of unix timestamps at which restrictions get into effect - * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) - * @param _endTimes Array of unix timestamps at which restriction effects will gets end. - * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for variable) - */ - function modifyIndividualRestrictionMulti( - address[] _holders, - uint256[] _allowedTokens, - uint256[] _allowedPercentageOfTokens, - uint256[] _startTimes, - uint256[] _rollingPeriodInDays, - uint256[] _endTimes, - uint256[] _restrictionTypes - ) - public - withPerm(ADMIN) - { - _checkLengthOfArray(_allowedTokens, _allowedPercentageOfTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); - require(_holders.length == _allowedTokens.length, "Length mismatch"); - for (uint256 i = 0; i < _holders.length; i++) { - _modifyIndividualRestriction( - _holders[i], - _allowedTokens[i], - _allowedPercentageOfTokens[i], - _startTimes[i], - _rollingPeriodInDays[i], - _endTimes[i], - _restrictionTypes[i] - ); - } - } - - /** - * @notice Use to modify the global restriction for all token holder - * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. - * @param _startTime Unix timestamp at which restriction get into effect - * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) - * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) - */ - function modifyGlobalRestriction( - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _restrictionType - ) - external - withPerm(ADMIN) - { - require(globalRestriction.startTime > now, "Not allowed"); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - globalRestriction = VolumeRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - RestrictionType(_restrictionType) - ); - emit ModifyGlobalRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - _restrictionType - ); - } - - /** - * @notice Use to modify the daily global restriction for all token holder - * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. - * @param _allowedPercentageOfTokens Percentage of tokens w.r.t to totalSupply allowed to transact. - * @param _startTime Unix timestamp at which restriction get into effect - * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for variable) - */ - function modifyDailyGlobalRestriction( - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _endTime, - uint256 _restrictionType - ) - external - withPerm(ADMIN) - { - require(dailyGlobalRestriction.startTime > now, "Not allowed"); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, 1, _endTime, _restrictionType); - dailyGlobalRestriction = VolumeRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - 1, - _endTime, - RestrictionType(_restrictionType) - ); - emit ModifyDailyGlobalRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - 1, - _endTime, - _restrictionType - ); - } - - /** - * @notice Internal function have a logic to validate the txn amount with global restriction - */ - function _globalRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { - uint256[] memory timestamps = globalBucketDetails.timestamps; - uint256 fromTimestamp; - uint256 sumOfLastPeriod = 0; - if (timestamps.length == 0) { - // It will execute when the txn is performed first time after the addition of global restriction - fromTimestamp = globalRestriction.startTime; - } else { - // picking up the preivous timestamp - fromTimestamp = timestamps[timestamps.length -1]; - } - // Calculating the difference of days - uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); - uint256[] memory passedTimestamps = new uint256[](diffDays); - // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod - // re-using the local variables to avoid the stack too deep error. - (sumOfLastPeriod, fromTimestamp, passedTimestamps) = _bucketCheck( - fromTimestamp, - diffDays, - _from, - globalBucketDetails, - true, - globalRestriction - ); - // Total amout that is transacted uptill now for `fromTimestamp` day - uint256 txSumOfDay = globalBucket[fromTimestamp]; - // Global transaction check - if (_globalTxCheck(sumOfLastPeriod, txSumOfDay, _amount)) { - // allow modification in storage when `_isTransfer` equals true - if(_isTransfer) { - // update the global storage - _updateGlobalStorage( - passedTimestamps, - fromTimestamp, - _amount, - diffDays, - sumOfLastPeriod - ); - } - return Result.NA; - } - return Result.INVALID; - } - - /** - * @notice Internal function to update the state variables related to global restriction - */ - function _updateGlobalStorage( - uint256[] passedTimestamps, - uint256 _fromTime, - uint256 _amount, - uint256 _diffDays, - uint256 _sumOfLastPeriod - ) - internal - { - for (uint256 i = 0; i < passedTimestamps.length; i++) { - // Add the timestamp that is already passed - globalBucketDetails.timestamps.push(passedTimestamps[i]); - } - // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) - if (globalBucketDetails.timestamps.length == 0) { - globalBucketDetails.timestamps.push(_fromTime); - } - if(_amount != 0) { - // updating the sumOfLastPeriod - globalBucketDetails.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); - - // Re-using the local variable to avoid stack too deep error - _fromTime = globalBucketDetails.timestamps[globalBucketDetails.timestamps.length -1]; - globalBucket[_fromTime] = globalBucket[_fromTime].add(_amount); - } - } - - /// Internal function for the bucket check - function _bucketCheck( - uint256 _fromTime, - uint256 _diffDays, - address _from, - BucketDetails memory _bucketDetails, - bool _isGlobal, - VolumeRestriction _restriction - ) - internal - view - returns (uint256, uint256, uint256[]) - { - uint256[] memory passedTimestamps = new uint256[](_diffDays); - uint256 counter = _bucketDetails.timestamps.length; - uint256 i = 0; - if (_diffDays != 0) { - for (i = 0; i < _diffDays; i++) { - // calculating the timestamp that will used as an index of the next bucket - // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... - // where T1,T2,T3 are timestamps having 24 hrs difference - _fromTime = _fromTime.add(1 days); - - // This condition is to check whether the first rolling period is covered or not - // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting - // the earlier value at that index - if (counter >= _restriction.rollingPeriodInDays) { - if (_isGlobal) { - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. - sub(globalBucket[_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); - } else { - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - _bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod. - sub(bucket[_from][_bucketDetails.timestamps[counter.sub(_restriction.rollingPeriodInDays)]]); - } - - } - - // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand - // the alogrithm - //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); - // Storing all those timestamps whose total transacted value is 0 - passedTimestamps[i] = _fromTime; - counter++; - } - } - return (_bucketDetails.sumOfLastPeriod, _fromTime, passedTimestamps); - } - - /** - * @notice Internal function used to validate the transaction for a given address - * If it validates then it also update the storage corressponds to the individual restriction - */ - function _individualRestrictionCheck( - address _from, - uint256 _amount, - bool _isTransfer - ) - internal - returns(Result) - { - uint256 fromTimestamp; - uint256 sumOfLastPeriod = 0; - if (bucketToUser[_from].timestamps.length == 0) { - // It will execute when the txn is performed first time after the addition of individual restriction - fromTimestamp = individualRestriction[_from].startTime; - } else { - // Picking up the last timestamp - fromTimestamp = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; - } - // Calculating the difference of days - uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); - uint256[] memory passedTimestamps = new uint256[](diffDays); - // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod - // re-using the local variables to avoid the stack too deep error. - (sumOfLastPeriod, fromTimestamp, passedTimestamps) = _bucketCheck( - fromTimestamp, - diffDays, - _from, - bucketToUser[_from], - false, - individualRestriction[_from] - ); - if (_checkValidAmountToTransact(sumOfLastPeriod, _amount, individualRestriction[_from])) { - if (_isTransfer) { - _updateIndividualStorage( - passedTimestamps, - _from, - fromTimestamp, - _amount, - diffDays, - sumOfLastPeriod - ); - } - return Result.NA; - } - return Result.INVALID; - } - - - function _globalTxCheck( - uint256 _sumOfLastPeriod, - uint256 _dailyAmount, - uint256 _amount - ) - internal - view - returns(bool) - { - // Checking whether the global day restriction is added or not if yes then calculate - // the total amount get traded on a particular day (~ _fromTime) - if (!_checkValidAmountToTransact(_dailyAmount, _amount, dailyGlobalRestriction) && - now <= dailyGlobalRestriction.endTime && now >= dailyGlobalRestriction.startTime - ) { - return false; - } - return _checkValidAmountToTransact(_sumOfLastPeriod, _amount, globalRestriction); - } - - function _checkValidAmountToTransact( - uint256 _sumOfLastPeriod, - uint256 _amountToTransact, - VolumeRestriction _restriction - ) - internal - view - returns (bool) - { - uint256 _allowedAmount = 0; - if (_restriction.typeOfRestriction == RestrictionType.Variable) { - _allowedAmount = (_restriction.allowedPercentageOfTokens.mul(ISecurityToken(securityToken).totalSupply()))/ uint256(10) ** 18; - } else { - _allowedAmount = _restriction.allowedTokens; - } - // Validation on the amount to transact - if (_allowedAmount >= _sumOfLastPeriod.add(_amountToTransact)) { - return true; - } else { - return false; - } - } - - function _updateIndividualStorage( - uint256[] passedTimestamps, - address _from, - uint256 _fromTime, - uint256 _amount, - uint256 _diffDays, - uint256 _sumOfLastPeriod - ) - internal - { - if (_diffDays != 0) { - for (uint256 i = 0; i < passedTimestamps.length; i++) { - // Add the timestamp that is already passed - bucketToUser[_from].timestamps.push(passedTimestamps[i]); - } - } - // This condition is the works only when the transaction performed just after the startTime (_diffDays == 0) - if (bucketToUser[_from].timestamps.length == 0) { - bucketToUser[_from].timestamps.push(_fromTime); - } - if(_amount != 0) { - bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); - - // Re-using the local variable to avoid stack too deep error - _fromTime = bucketToUser[_from].timestamps[bucketToUser[_from].timestamps.length -1]; - bucket[_from][_fromTime] = bucket[_from][_fromTime].add(_amount); - } - - } - - function _removeIndividualRestriction(address _user) internal { - require(_user != address(0), "Invalid address"); - require(individualRestriction[_user].endTime != 0, "Not present"); - individualRestriction[_user] = VolumeRestriction(0, 0, 0, 0, 0, RestrictionType(0)); - bucketToUser[_user].timestamps.length = 0; - bucketToUser[_user].sumOfLastPeriod = 0; - emit IndividualRestrictionRemoved(_user); - } - - function _modifyIndividualRestriction( - address _holder, - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _restrictionType - ) - internal - { - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - require(individualRestriction[_holder].startTime > now, "Not allowed"); - - individualRestriction[_holder] = VolumeRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - RestrictionType(_restrictionType) - ); - emit ModifyIndividualRestriction( - _holder, - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - _restrictionType - ); - } - - function _addIndividualRestriction( - address _holder, - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _restrictionType - ) - internal - { - require( - individualRestriction[_holder].endTime < now, - "Already present" - ); - require(_holder != address(0) && !exemptList[_holder], "Invalid address"); - _checkInputParams(_allowedTokens, _allowedPercentageOfTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - - if (individualRestriction[_holder].endTime != 0) { - _removeIndividualRestriction(_holder); - } - individualRestriction[_holder] = VolumeRestriction( - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - RestrictionType(_restrictionType) - ); - emit AddNewIndividualRestriction( - _holder, - _allowedTokens, - _allowedPercentageOfTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - _restrictionType - ); - } - - function _checkInputParams( - uint256 _allowedTokens, - uint256 _allowedPercentageOfTokens, - uint256 _startTime, - uint256 _rollingPeriodDays, - uint256 _endTime, - uint256 _restrictionType - ) - internal - view - { - require(_restrictionType == 0 || _restrictionType == 1, "Invalid type"); - if (_restrictionType == uint256(RestrictionType.Fixed)) { - require(_allowedTokens > 0, "Invalid value"); - } else { - require( - _allowedPercentageOfTokens > 0 && _allowedPercentageOfTokens <= 100 * 10 ** 16, - "Percentage is not within (0,100]" - ); - } - require(_startTime >= now && _endTime > _startTime); - // Maximum limit for the rollingPeriod is 365 days - require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365); - require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays); - } - - function _checkLengthOfArray( - uint256[] _allowedTokens, - uint256[] _allowedPercentageOfTokens, - uint256[] _startTimes, - uint256[] _rollingPeriodInDays, - uint256[] _endTimes, - uint256[] _restrictionTypes - ) - internal - pure - { - require( - _allowedTokens.length == _allowedPercentageOfTokens.length && - _allowedPercentageOfTokens.length == _startTimes.length && - _startTimes.length == _rollingPeriodInDays.length && - _rollingPeriodInDays.length == _endTimes.length && - _endTimes.length == _restrictionTypes.length, - "Array length mismatch" - ); - } - - /** - * @notice Use to get the bucket details for a given address - * @param _user Address of the token holder for whom the bucket details has queried - * @return uint256 Array of the timestamps - * @return uint256 sumOfLastPeriod - */ - function getBucketDetailsToUser(address _user) external view returns(uint256[], uint256) { - return( - bucketToUser[_user].timestamps, - bucketToUser[_user].sumOfLastPeriod - ); - } - - /** - * @notice Use to get the volume of token that being traded at a particular day (`_at` + 24 hours) for a given user - * @param _user Address of the token holder - * @param _at Timestamp - */ - function getTotalTradeByuser(address _user, uint256 _at) external view returns(uint256) { - return bucket[_user][_at]; - } - - /** - * @notice Use to get the global bucket details - * @return uint256 Array of timestamps - * @return uint256 sumOfLastPeriod - * @return uint256 Total amount traded on the latest timestamp - */ - function getGlobalBucketDetails() external view returns(uint256[], uint256, uint256) { - return( - globalBucketDetails.timestamps, - globalBucketDetails.sumOfLastPeriod, - globalBucket[globalBucketDetails.timestamps[globalBucketDetails.timestamps.length - 1]] - ); - } - - /** - * @notice This function returns the signature of configure function - */ - function getInitFunction() public view returns(bytes4) { - return bytes4(0); - } - - /** - * @notice Returns the permissions flag that are associated with Percentage transfer Manager - */ - function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](1); - allPermissions[0] = ADMIN; - return allPermissions; - } - -} From 847c0ff1804460a4010461e737487ac25e0d4cb5 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 4 Dec 2018 15:38:34 +0530 Subject: [PATCH 318/582] version changes --- CHANGELOG.md | 8 ++++++-- .../ManualApprovalTransferManagerFactory.sol | 2 +- test/e_erc20_dividends.js | 2 +- test/f_ether_dividends.js | 2 +- test/h_general_transfer_manager.js | 2 +- test/j_manual_approval_transfer_manager.js | 2 +- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 288ed8037..483d50c8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,13 +16,17 @@ All notable changes to this project will be documented in this file. ## GeneralTransferManager * `getInvestors`, `getAllInvestorsData`, `getInvestorsData` added to GTM to allow easy data queries. * `modifyDefaults(uint64 _defaultFromTime, uint64 _defaultToTime)` added which sets a default timestamp used when `fromTime` or `toTime` are 0 -* Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`) +* Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`). +* Changed the version of `GeneralTransferManagerFactory` from `1.0.0` to `2.1.0`. ## Manual Approval TransferManager * Removed `0x0` check for the `_from` address to `ManualApprovalTransferManager`. This allows for the Issuer/Transfer Agent to approve a one-off mint of tokens that otherwise would not be possible. -* Changed the version of `ManualApprovalTransferManagerFactory` from `1.0.0` to `2.0.1`. +* Changed the version of `ManualApprovalTransferManagerFactory` from `1.0.0` to `2.1.0`. * Deployed 2.0.1 `ManualApprovalTransferManagerFactory` to address 0x6af2afad53cb334e62b90ddbdcf3a086f654c298 +## Dividends +* Changed the version of `ERC20DividendCheckpointFactory` & `EtherDividendCheckpointFactory` from `1.0.0` to `2.1.0`. + ## Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. * General Transfer Manager: Fix for when `allowAllWhitelistIssuances` is FALSE diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 9c5513ee7..3fd33a39b 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -18,7 +18,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "2.0.1"; + version = "2.1.0"; name = "ManualApprovalTransferManager"; title = "Manual Approval Transfer Manager"; description = "Manage transfers using single approvals / blocking"; diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index aac008d4a..96f27883b 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -1105,7 +1105,7 @@ contract("ERC20DividendCheckpoint", accounts => { it("should get the exact details of the factory", async () => { assert.equal((await I_ERC20DividendCheckpointFactory.getSetupCost.call()).toNumber(), 0); assert.equal((await I_ERC20DividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(await I_ERC20DividendCheckpointFactory.version.call(), "1.0.0"); + assert.equal(await I_ERC20DividendCheckpointFactory.version.call(), "2.1.0"); assert.equal( web3.utils.toAscii(await I_ERC20DividendCheckpointFactory.getName.call()).replace(/\u0000/g, ""), "ERC20DividendCheckpoint", diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 694b8611a..6b7461629 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -954,7 +954,7 @@ contract("EtherDividendCheckpoint", accounts => { it("should get the exact details of the factory", async () => { assert.equal((await I_EtherDividendCheckpointFactory.getSetupCost.call()).toNumber(), 0); assert.equal((await I_EtherDividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(await I_EtherDividendCheckpointFactory.version.call(), "1.0.0"); + assert.equal(await I_EtherDividendCheckpointFactory.version.call(), "2.1.0"); assert.equal( web3.utils.toAscii(await I_EtherDividendCheckpointFactory.getName.call()).replace(/\u0000/g, ""), "EtherDividendCheckpoint", diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index d00108376..76a9d5806 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -890,7 +890,7 @@ contract("GeneralTransferManager", accounts => { "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters.", "Wrong Module added" ); - assert.equal(await I_GeneralPermissionManagerFactory.version.call(), "1.0.0"); + assert.equal(await I_GeneralTransferManagerFactory.version.call(), "2.1.0"); }); it("Should get the tags of the factory", async () => { diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 5779a1c13..dae21b9c1 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -541,7 +541,7 @@ contract("ManualApprovalTransferManager", accounts => { "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.", "Wrong Module added" ); - assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.0.1"); + assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.1.0"); }); it("Should get the tags of the factory", async () => { From fcbb93dd3a0c7f766f3b150bcfc89372f6b5e335 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 4 Dec 2018 12:43:06 +0200 Subject: [PATCH 319/582] updated doc for getSchedule --- contracts/modules/Wallet/VestingEscrowWallet.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 6e2fe717e..02236ec29 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -383,7 +383,7 @@ contract VestingEscrowWallet is IWallet { * @notice Returns beneficiary's schedule * @param _beneficiary beneficiary's address * @param _templateName name of the template - * @return beneficiary's schedule + * @return beneficiary's schedule data (numberOfTokens, duration, frequency, startTime, claimedTokens, State) */ function getSchedule(address _beneficiary, bytes32 _templateName) external view returns(uint256, uint256, uint256, uint256, uint256, State) { _checkSchedule(_beneficiary, _templateName); From 1319a81387ee3bf25d68f74eb678caa64812727e Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Tue, 4 Dec 2018 12:07:19 +0100 Subject: [PATCH 320/582] adjust test cases for adding and removing holders at the same time when max holder amount is full --- test/d_count_transfer_manager.js | 45 +++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 4a2b0b306..303a3b6c0 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -39,6 +39,7 @@ contract("CountTransferManager", accounts => { let I_CountTransferManagerFactory; let I_GeneralPermissionManager; let I_CountTransferManager; + let I_CountTransferManager2; let I_GeneralTransferManager; let I_GeneralTransferManager2; let I_ExchangeTransferManager; @@ -342,12 +343,6 @@ contract("CountTransferManager", accounts => { await catchRevert(I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2", "ether"), { from: account_investor2 })); }); - // it("Should be able to transfer to a new token holder if all tokens are transferred and existing holder is removed", async () => { - // console.log('acc2 balancce is ' + (await I_SecurityToken.balanceOf(account_investor2)).toNumber()); - // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4", "ether"), { from: account_investor2 }); - // assert((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("4", "ether")); - // }); - it("Should be able to consolidate balances", async () => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); }); @@ -418,10 +413,46 @@ contract("CountTransferManager", accounts => { // Mint some tokens await I_SecurityToken2.mint(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); await I_SecurityToken2.mint(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); - await I_SecurityToken2.mint(account_investor3, web3.utils.toWei("1", "ether"), { from: token_owner }); assert.equal((await I_SecurityToken2.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); }); + + // Add count transfer manager and only allow 2 holders + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + }); + + it("Should successfully attach the CountTransferManager factory with the security token", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await catchRevert( + I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + from: token_owner + }) + ); + }); + + it("Should successfully attach the CountTransferManager with the security token and set max holder to 2", async () => { + const tx = await I_SecurityToken2.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "CountTransferManager", + "CountTransferManager module was not added" + ); + I_CountTransferManager2 = CountTransferManager.at(tx.logs[2].args._module); + await I_CountTransferManager2.changeHolderCount(2, {from: token_owner}); + console.log('current max holder number is '+ await I_CountTransferManager2.maxHolderCount({from: token_owner})); + }); + + it("Should allow add a new token holder while transfer all the tokens at one go", async () => { + + let amount = (await I_SecurityToken2.balanceOf(account_investor2)).toNumber(); + console.log('amount is '+amount); + await I_SecurityToken2.transfer(account_investor3, amount, { from: account_investor2 }); + assert((await I_SecurityToken2.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("2", "ether")); + + }); }); describe("Test cases for the factory", async () => { From b040af43908ca3bd6e739a8f46eb799d2a58dc23 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Tue, 4 Dec 2018 08:47:42 -0300 Subject: [PATCH 321/582] investor portal improvements --- CLI/commands/investor_portal.js | 72 ++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 1ced21ce0..7502d7d8e 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -10,6 +10,7 @@ var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); const STO_KEY = 3; +const STABLE = 'STABLE'; let securityTokenRegistry; let securityToken; @@ -157,13 +158,13 @@ async function showUserInfo(_user) { console.log(` ******************* User Information ******************** - Address: ${_user}`); - if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.POLY)) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.POLY).call()) { console.log(` - POLY balance:\t ${await polyBalance(_user)}`); } - if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.ETH)) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.ETH).call()) { console.log(` - ETH balance:\t ${web3.utils.fromWei(await web3.eth.getBalance(_user))}`); } - if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.DAI)) { + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.STABLE).call()) { console.log(` - DAI balance:\t ${await usdBalance(_user)}`); } } @@ -237,12 +238,41 @@ async function showCappedSTOInfo() { } } +async function processAddress(array) { + let list = []; + for (const address of array) { + let symbol = await checkSymbol(address); + list.push(symbol) + } + return list +} + +async function checkSymbol(address) { + let stableCoin = common.connect(abis.erc20(), address); + try { + return await stableCoin.methods.symbol().call(); + } catch (e) { + return "" + } +} + async function showUserInfoForUSDTieredSTO() { + let stableSymbols = []; + //REMOVE ONCE SMART CONTRACT SUPPORT METHOD TO GET STABLE COIN ADDRESSES + let listOfStableCoins = ["0xa016B2ae79436E20FBe22Bf230a92A5Fb055762F", "0xae794d38cb481868a8CB19b9d7A5073851bC6dB7"]; + for (const fundType in gbl.constants.FUND_RAISE_TYPES) { if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { + if (fundType == STABLE) { + stableSymbols = await processAddress(listOfStableCoins) + } let displayInvestorInvested = web3.utils.fromWei(await currentSTO.methods.investorInvested(User.address, gbl.constants.FUND_RAISE_TYPES[fundType]).call()); - console.log(` - Invested in ${fundType}:\t ${displayInvestorInvested} ${fundType}`); + if ((fundType == STABLE) && (stableSymbols.length)) { + console.log(` - Invested in ${stableSymbols.toString()}:\t ${displayInvestorInvested} USD`); + } else { + console.log(` - Invested in ${fundType}:\t ${displayInvestorInvested} ${fundType}`); + } } } @@ -280,10 +310,16 @@ async function showUSDTieredSTOInfo() { let displayIsOpen = await currentSTO.methods.isOpen().call(); let displayTokenSymbol = await securityToken.methods.symbol().call(); let tiersLength = await currentSTO.methods.getNumberOfTiers().call(); + let stableSymbols = []; + //REMOVE ONCE SMART CONTRACT SUPPORT METHOD TO GET STABLE COIN ADDRESSES + let listOfStableCoins = ["0xa016B2ae79436E20FBe22Bf230a92A5Fb055762F", "0xae794d38cb481868a8CB19b9d7A5073851bC6dB7"]; for (const fundType in gbl.constants.FUND_RAISE_TYPES) { if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { raiseTypes.push(fundType); + if (fundType == STABLE) { + stableSymbols = await processAddress(listOfStableCoins) + } } } @@ -313,8 +349,13 @@ async function showUSDTieredSTOInfo() { let mintedPerTier = mintedPerTierPerRaiseType[gbl.constants.FUND_RAISE_TYPES[type]]; - displayMintedPerTierPerType += ` + if ((type == STABLE) && (stableSymbols.length)) { + displayMintedPerTierPerType += ` + Sold for ${stableSymbols.toString()}:\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + } else { + displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + } } displayTiers += ` @@ -334,18 +375,31 @@ async function showUSDTieredSTOInfo() { let displayTokensSoldPerType = ''; for (const type of raiseTypes) { let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); - displayFundsRaisedPerType += ` - ${type}:\t\t\t ${fundsRaised} ${type}`; - + if ((type == STABLE) && (stableSymbols.length)) { + displayFundsRaisedPerType += ` + ${stableSymbols.toString()}:\t\t ${fundsRaised} USD`; + } else { + displayFundsRaisedPerType += ` + ${type}:\t\t\t ${fundsRaised} ${type}`; + } //Only show sold per raise type is more than one are allowed if (raiseTypes.length > 1) { let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(gbl.constants.FUND_RAISE_TYPES[type]).call()); - displayTokensSoldPerType += ` + if ((type == STABLE) && (stableSymbols.length)) { + displayTokensSoldPerType += ` + Sold for ${stableSymbols.toString()}:\t ${tokensSoldPerType} ${displayTokenSymbol}`; + } else { + displayTokensSoldPerType += ` Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; + } } } let displayRaiseType = raiseTypes.join(' - '); + //If STO has stable coins, we list them one by one + if (stableSymbols.length) { + displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.toString().replace(`,`,` - `)}` + } let now = Math.floor(Date.now()/1000); let timeTitle; From 7cf5c59533892f45b76c9321dc1aaa169af945e3 Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Tue, 4 Dec 2018 07:42:48 -0500 Subject: [PATCH 322/582] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 483d50c8b..bcf26f35e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ All notable changes to this project will be documented in this file. * `getInvestors`, `getAllInvestorsData`, `getInvestorsData` added to GTM to allow easy data queries. * `modifyDefaults(uint64 _defaultFromTime, uint64 _defaultToTime)` added which sets a default timestamp used when `fromTime` or `toTime` are 0 * Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`). +* General Transfer Manager: Fix for when `allowAllWhitelistIssuances` is FALSE +* General Transfer Manager: Make GTM a Proxy based implementation to reduce deployment gas costs * Changed the version of `GeneralTransferManagerFactory` from `1.0.0` to `2.1.0`. ## Manual Approval TransferManager @@ -26,11 +28,11 @@ All notable changes to this project will be documented in this file. ## Dividends * Changed the version of `ERC20DividendCheckpointFactory` & `EtherDividendCheckpointFactory` from `1.0.0` to `2.1.0`. +* Applied proxy pattern to Dividends modules ## Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. -* General Transfer Manager: Fix for when `allowAllWhitelistIssuances` is FALSE -* General Transfer Manager: Make GTM a Proxy based implementation to reduce deployment gas costs + # v1.5.0 - Release Candidate From c161fc912d8e7b1bb2b4c83c5bf9b73861ef3a6d Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 4 Dec 2018 18:58:59 +0530 Subject: [PATCH 323/582] logic fix --- .../TransferManager/VolumeRestrictionTM.sol | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 5f2df00e4..61a9c1af7 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -468,34 +468,42 @@ contract VolumeRestrictionTM is ITransferManager { function _restrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { uint256 sumOfLastPeriod = 0; uint256 daysCovered = 0; - uint256 lastTradedDayTime; - uint256 globalSumOfLastPeriod; - uint256 globalDaysCovered; + uint256 lastTradedDayTime = 0; + uint256 globalSumOfLastPeriod = 0; + uint256 globalDaysCovered = 0; bool validIR = true; bool validGR = true; + uint8 _temp = 0; if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { (validIR, sumOfLastPeriod, lastTradedDayTime, daysCovered) = _individualRestrictionCheck(_from, _amount); - } - (validGR, globalSumOfLastPeriod, lastTradedDayTime, globalDaysCovered) = _globalRestrictionCheck(_from, _amount); - // Total amout that is transacted uptill now for `fromTimestamp` day - uint256 txSumOfDay = bucket[_from][lastTradedDayTime]; - // allow modification in storage when `_isTransfer` equals true - if (_isTransfer) { - // update the storage - _updateStorage( - _from, - _amount, - lastTradedDayTime, - sumOfLastPeriod, - globalSumOfLastPeriod, - daysCovered, - globalDaysCovered - ); + _temp = _temp + 1; + } + if (globalRestriction.endTime >= now && globalRestriction.startTime <= now) { + (validGR, globalSumOfLastPeriod, lastTradedDayTime, globalDaysCovered) = _globalRestrictionCheck(_from, _amount); + _temp = _temp + 1; + } + if (_temp > 0) { + // Total amout that is transacted uptill now for `fromTimestamp` day + uint256 txSumOfDay = bucket[_from][lastTradedDayTime]; + // allow modification in storage when `_isTransfer` equals true + if (_isTransfer) { + // update the storage + _updateStorage( + _from, + _amount, + lastTradedDayTime, + sumOfLastPeriod, + globalSumOfLastPeriod, + daysCovered, + globalDaysCovered + ); + } + if (validGR && validIR && _dailyTxCheck(txSumOfDay, _amount)) + return Result.NA; + else + return Result.INVALID; } - if (validGR && validIR && _dailyTxCheck(txSumOfDay, _amount)) - return Result.NA; - else - return Result.INVALID; + return Result.NA; } /** From 11b6fe3d75e41678a3ef0cf5c7d0c30244e44f8a Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 4 Dec 2018 21:16:14 -0500 Subject: [PATCH 324/582] Add getUsdTokens --- contracts/modules/STO/USDTieredSTO.sol | 23 +++++++++++++++-------- test/p_usd_tiered_sto.js | 8 +++++--- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 58a3bdc2a..d3be00047 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -155,8 +155,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } modifier validSC(address _usdToken) { - require(fundRaiseTypes[uint8(FundRaiseType.SC)], "Stable coins not allowed"); - require(usdTokenEnabled[_usdToken], "Invalid USD token"); + require(fundRaiseTypes[uint8(FundRaiseType.SC)] && usdTokenEnabled[_usdToken], "USD not allowed"); _; } @@ -472,8 +471,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @param _minTokens Minumum number of tokens to buy or else revert * @param _usdToken Address of USD stable coin to buy tokens with */ - function buyWithUSDRateLimited(address _beneficiary, uint256 _investedSC, uint256 _minTokens, IERC20 _usdToken) - public validSC(_usdToken) + function buyWithUSDRateLimited(address _beneficiary, uint256 _investedSC, uint256 _minTokens, IERC20 _usdToken) + public validSC(_usdToken) { _buyWithTokens(_beneficiary, _investedSC, FundRaiseType.SC, _minTokens, _usdToken); } @@ -512,7 +511,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { if (!allowBeneficialInvestments) { require(_beneficiary == msg.sender, "Beneficiary != funder"); } - + uint256 originalUSD = DecimalMath.mul(_rate, _investmentValue); uint256 allowedUSD = _buyTokensChecks(_beneficiary, _investmentValue, originalUSD); @@ -634,7 +633,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { tierData.mintedTotal = tierData.mintedTotal.add(tierPurchasedTokens); } // Now, if there is any remaining USD to be invested, purchase at non-discounted rate - if (investedUSD > 0 && + if (investedUSD > 0 && tierData.tokenTotal.sub(tierData.mintedTotal) > 0 && (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly) ) { @@ -669,7 +668,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { _investedUSD = _investedUSD.sub(spentUSD); } // Now, if there is any remaining USD to be invested, purchase at non-discounted rate - if (_investedUSD > 0 && + if (_investedUSD > 0 && tierData.tokenTotal.sub(tierData.mintedTotal.add(tokensMinted)) > 0 && (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly) ) { @@ -693,7 +692,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { if (purchasedTokens > 0) { require(ISecurityToken(securityToken).mint(_beneficiary, purchasedTokens), "Error in minting"); emit TokenPurchase(msg.sender, _beneficiary, purchasedTokens, spentUSD, _tierPrice, _tier); - } + } } function _purchaseTierAmount( @@ -866,6 +865,14 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { return tiers.length; } + /** + * @notice Return the usd tokens accepted by the STO + * @return address[] usd tokens + */ + function getUsdTokens() public view returns (address[]) { + return usdTokens; + } + /** * @notice Return the permissions flag that are associated with STO */ diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 7cc69286a..c0f9febf9 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -222,7 +222,7 @@ contract("USDTieredSTO", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 4: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, I_PolyToken.address, 0); @@ -635,6 +635,8 @@ contract("USDTieredSTO", accounts => { assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[2].args._name), "USDTieredSTO", "USDTieredSTOFactory module was not added"); I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + let tokens = await I_USDTieredSTO_Array[I_USDTieredSTO_Array.length - 1].getUsdTokens.call(); + assert.equal(tokens, _usdToken[stoId], "USD Tokens should match"); }); it("Should successfully attach the fifth STO module to the security token", async () => { @@ -4521,7 +4523,7 @@ contract("USDTieredSTO", accounts => { "fundsRaisedUSD not changed as expected" ); }); - + it("should return minted tokens in a tier", async () => { let totalMinted = (await I_USDTieredSTO_Array[0].getTokensSoldByTier.call(0)).toNumber(); let individualMinted = await I_USDTieredSTO_Array[0].getTokensMintedByTier.call(0); @@ -4603,7 +4605,7 @@ contract("USDTieredSTO", accounts => { assert.equal((await I_USDTieredSTOFactory.getSetupCost.call()).toNumber(), STOSetupCost); assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0], 3); assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), "USDTieredSTO", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.description.call(), + assert.equal(await I_USDTieredSTOFactory.description.call(), "It allows both accredited and non-accredited investors to contribute into the STO. Non-accredited investors will be capped at a maximum investment limit (as a default or specific to their jurisdiction). Tokens will be sold according to tiers sequentially & each tier has its own price and volume of tokens to sell. Upon receipt of funds (ETH, POLY or DAI), security tokens will automatically transfer to investor’s wallet address", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.title.call(), "USD Tiered STO", "Wrong Module added"); From a4c31ceb9a38448cf2cc18e2e72bd294d60039dd Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 4 Dec 2018 21:31:07 -0500 Subject: [PATCH 325/582] Fix typo --- test/p_usd_tiered_sto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index c0f9febf9..b4e49183a 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -636,7 +636,7 @@ contract("USDTieredSTO", accounts => { assert.equal(web3.utils.hexToString(tx.logs[2].args._name), "USDTieredSTO", "USDTieredSTOFactory module was not added"); I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); let tokens = await I_USDTieredSTO_Array[I_USDTieredSTO_Array.length - 1].getUsdTokens.call(); - assert.equal(tokens, _usdToken[stoId], "USD Tokens should match"); + assert.equal(tokens[0], I_DaiToken.address, "USD Tokens should match"); }); it("Should successfully attach the fifth STO module to the security token", async () => { From a7e6eed6a276ecaa4028e3b83f94ba1063a04630 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 4 Dec 2018 21:58:17 -0500 Subject: [PATCH 326/582] Bump the version --- .../modules/TransferManager/CountTransferManagerFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index d9b1328f7..c42cebc61 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -16,7 +16,7 @@ contract CountTransferManagerFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + version = "2.1.0"; name = "CountTransferManager"; title = "Count Transfer Manager"; description = "Restrict the number of investors"; From 6f0bed7707c73c58c2ccfe275f14851f39c82328 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 5 Dec 2018 12:47:46 +0530 Subject: [PATCH 327/582] VEW deployable by proxy --- contracts/interfaces/IBoot.sol | 7 ++++++ .../modules/Wallet/VestingEscrowWallet.sol | 2 +- .../Wallet/VestingEscrowWalletFactory.sol | 5 ++-- migrations/2_deploy_contracts.js | 24 +++++++++++++++++-- test/helpers/createInstances.js | 5 +++- test/z_vesting_escrow_wallet.js | 8 +++---- 6 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 contracts/interfaces/IBoot.sol diff --git a/contracts/interfaces/IBoot.sol b/contracts/interfaces/IBoot.sol new file mode 100644 index 000000000..dd293664d --- /dev/null +++ b/contracts/interfaces/IBoot.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.4.24; + +interface IBoot { + + function getInitFunction() external pure returns (bytes4); + +} \ No newline at end of file diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 49365089d..78785b4b0 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -7,7 +7,7 @@ import "./IWallet.sol"; /** * @title Wallet for core vesting escrow functionality */ -contract VestingEscrowWallet is IWallet { +contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { using SafeMath for uint256; bytes32 public constant ADMIN = "ADMIN"; diff --git a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol index 62de4c1c6..238d571ea 100644 --- a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol +++ b/contracts/modules/Wallet/VestingEscrowWalletFactory.sol @@ -1,6 +1,7 @@ pragma solidity ^0.4.24; import "../../proxy/VestingEscrowWalletProxy.sol"; +import "../../interfaces/IBoot.sol"; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; @@ -38,7 +39,7 @@ contract VestingEscrowWalletFactory is ModuleFactory { } VestingEscrowWalletProxy vestingEscrowWallet = new VestingEscrowWalletProxy(msg.sender, address(polyToken), logicContract); //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == vestingEscrowWallet.getInitFunction(), "Invalid data"); + require(Util.getSig(_data) == IBoot(vestingEscrowWallet).getInitFunction(), "Invalid data"); /*solium-disable-next-line security/no-low-level-calls*/ require(address(vestingEscrowWallet).call(_data), "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ @@ -60,7 +61,7 @@ contract VestingEscrowWalletFactory is ModuleFactory { */ function getInstructions() external view returns(string) { /*solium-disable-next-line max-len*/ - return "Issuer can send tokens to and then select the address that would be able to withdraw them according to their specific vesting schedule."; + return "Issuer can deposit tokens to the contract and create the vesting schedule for the given address (Affiliate/Employee). These address can withdraw tokens according to there vesting schedule."; } /** diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index f25cfab35..6ba616bfa 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -9,6 +9,8 @@ const EtherDividendCheckpointLogic = artifacts.require('./EtherDividendCheckpoin const ERC20DividendCheckpointLogic = artifacts.require('./ERC20DividendCheckpoint.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') +const VestingEscrowWalletFactory = artifacts.require('./VestingEscrowWalletFactory.sol'); +const VestingEscrowWalletLogic = artifacts.require('./VestingEscrowWallet.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol') @@ -153,13 +155,21 @@ module.exports = function (deployer, network, accounts) { // manager attach with the securityToken contract at the time of deployment) return deployer.deploy(GeneralTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); }).then(() => { - // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // B) Deploy the ERC20DividendCheckpointLogic Contract (Factory used to generate the ERC20DividendCheckpoint contract and this // manager attach with the securityToken contract at the time of deployment) return deployer.deploy(ERC20DividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); }).then(() => { - // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // B) Deploy the EtherDividendCheckpointLogic Contract (Factory used to generate the EtherDividendCheckpoint contract and this // manager attach with the securityToken contract at the time of deployment) return deployer.deploy(EtherDividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the VestingEscrowWalletLogic Contract (Factory used to generate the VestingEscrowWallet contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(VestingEscrowWalletLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the VestingEscrowWalletFactory Contract (Factory used to generate the VestingEscrowWallet contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(VestingEscrowWalletFactory, PolyToken, 0, 0, 0, VestingEscrowWalletLogic.address, {from: PolymathAccount}); }).then(() => { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) @@ -215,6 +225,10 @@ module.exports = function (deployer, network, accounts) { // D) Register the PercentageTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the PercentageTransferManager contract. return moduleRegistry.registerModule(PercentageTransferManagerFactory.address, {from: PolymathAccount}); + }).then(() => { + // D) Register the VestingEscrowWalletFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the VestingEscrowWallet contract. + return moduleRegistry.registerModule(VestingEscrowWalletFactory.address, {from: PolymathAccount}); }).then(() => { // D) Register the CountTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the CountTransferManager contract. @@ -274,6 +288,11 @@ module.exports = function (deployer, network, accounts) { // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(ManualApprovalTransferManagerFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // F) Once the VestingEscrowWalletFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(VestingEscrowWalletFactory.address, true, {from: PolymathAccount}); }).then(() => { // M) Deploy the CappedSTOFactory (Use to generate the CappedSTO contract which will used to collect the funds ). return deployer.deploy(CappedSTOFactory, PolyToken, cappedSTOSetupCost, 0, 0, {from: PolymathAccount}) @@ -333,6 +352,7 @@ module.exports = function (deployer, network, accounts) { ERC20DividendCheckpointLogic: ${ERC20DividendCheckpointLogic.address} EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} + VestingEscrowWalletFactory: ${VestingEscrowWalletFactory.address} --------------------------------------------------------------------------------- `); console.log('\n'); diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index cea1929cf..767b2c632 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -33,6 +33,7 @@ const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); const VestingEscrowWalletFactory = artifacts.require("./VestingEscrowWalletFactory.sol"); +const VestingEscrowWallet = artifacts.require("./VestingEscrowWallet.sol"); const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port @@ -69,6 +70,7 @@ let I_PolyToken; let I_STFactory; let I_PolymathRegistry; let I_SecurityTokenRegistryProxy; +let I_VestingEscrowWalletLogic; let I_STRProxied; let I_MRProxied; @@ -406,7 +408,8 @@ export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstan } export async function deployVestingEscrowWalletAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_VestingEscrowWalletFactory = await VestingEscrowWalletFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_VestingEscrowWalletLogic = await VestingEscrowWallet.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_VestingEscrowWalletFactory = await VestingEscrowWalletFactory.new(polyToken, setupCost, 0, 0, I_VestingEscrowWalletLogic.address, { from: accountPolymath }); assert.notEqual( I_VestingEscrowWalletFactory.address.valueOf(), diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index a9328074a..754bd65bd 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -259,15 +259,15 @@ contract('VestingEscrowWallet', accounts => { it("Should get the tags of the factory", async () => { let tags = await I_VestingEscrowWalletFactory.getTags.call(); assert.equal(tags.length, 2); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ""), "Vested Wallet"); - assert.equal(web3.utils.toAscii(tags[1]).replace(/\u0000/g, ""), "Escrow"); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ""), "Vested"); + assert.equal(web3.utils.toAscii(tags[1]).replace(/\u0000/g, ""), "Escrow Wallet"); }); it("Should get the instructions of the factory", async () => { assert.equal( (await I_VestingEscrowWalletFactory.getInstructions.call()).replace(/\u0000/g, ""), - "Issuer can send tokens to and then select the address that would be able to withdraw them according to their specific vesting schedule." + - ""); + "Issuer can deposit tokens to the contract and create the vesting schedule for the given address (Affiliate/Employee). These address can withdraw tokens according to there vesting schedule." + ); }); }); From 8a8926214709bac11e4eccf9f79a78b733809aa8 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 5 Dec 2018 13:21:04 +0530 Subject: [PATCH 328/582] minor fix --- contracts/proxy/VestingEscrowWalletProxy.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/proxy/VestingEscrowWalletProxy.sol b/contracts/proxy/VestingEscrowWalletProxy.sol index 7f73203eb..0138e0402 100644 --- a/contracts/proxy/VestingEscrowWalletProxy.sol +++ b/contracts/proxy/VestingEscrowWalletProxy.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../modules/wallet/VestingEscrowWalletStorage.sol"; +import "../modules/Wallet/VestingEscrowWalletStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "../modules/ModuleStorage.sol"; From 1358187a77e804da2d5f4d2da350f978ce393631 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 5 Dec 2018 10:59:37 +0100 Subject: [PATCH 329/582] WIP --- test/z_fuzz_test_adding_removing_modules_ST.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index f14522857..b3975cfce 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -117,7 +117,7 @@ contract('GeneralPermissionManager', accounts => { // permission manager fuzz test // let modules = ['CountTransferManager', 'SingleTradeVolumeRestrictionManager', 'ManualApprovalTransferManager', 'I_VolumeRestrictionTransferManager', 'PercentageTransferManager']; - let modules = ['I_CountTransferManager']; + let modules = ['I_CountTransferManagerFactory']; let totalModules = modules.length; @@ -159,6 +159,8 @@ contract('GeneralPermissionManager', accounts => { // STEP 6: Deploy the GeneralDelegateManagerFactory [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // Deploy Modules [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); @@ -266,13 +268,20 @@ contract('GeneralPermissionManager', accounts => { var j = Math.floor(Math.random() * 10); + console.log("1.2"); // choose a random module - let randomModule = modules[Math.floor(Math.random() * Math.floor(totalModules))]; - console.log("choosen module "+ randomModule); + let randomModuleFactory = modules[Math.floor(Math.random() * Math.floor(totalModules))]; + console.log("choosen module "+ randomModuleFactory.address); // attach it to the ST - let tx = await I_SecurityToken.addModule(randomModule.address, bytesSTO, 0, 0, { from: token_owner }); + let tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + console.log("1.3"); + let randomModule = CountTransferManager.at(tx.logs[2].args._module); + console.log("1.4"); console.log("successfully attached module " + randomModule); + console.log("1.5"); + console.log(randomModule.address); + // remove it from the ST tx = await I_SecurityToken.removeModule(randomModule.address, { from: token_owner }); From c0cf9aebadcffa302fe8dabf1e1724e64a6ce7f2 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 5 Dec 2018 11:15:35 +0100 Subject: [PATCH 330/582] remove fuzz test related to manual blocking --- test/z_general_permission_manager_fuzzer.js | 66 --------------------- 1 file changed, 66 deletions(-) diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index 4206991ee..edebcce06 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -597,73 +597,7 @@ contract('GeneralPermissionManager', accounts => { await revertToSnapshot(snapId); }; - - }); - - it("should pass fuzz test for addManualBlocking and revokeManualBlocking with perm TRANSFER_APPROVAL", async () => { - console.log("1"); - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: token_owner - }); - console.log("2"); - await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: token_owner }); - console.log("3"); - - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts - for (var i = 2; i < testRepeat; i++) { - - let snapId = await takeSnapshot(); - - var j = Math.floor(Math.random() * 10); - if (j === 1 || j === 0) { j = 2 }; // exclude account 1 & 0 because they might come with default perms - - // add account as a Delegate if it is not - if (await I_GeneralPermissionManager.checkDelegate(accounts[j]) !== true) { - await I_GeneralPermissionManager.addDelegate(accounts[j], _details, { from: token_owner }); - } - - // target permission should alaways be false for each test before assigning - if (await I_GeneralPermissionManager.checkPermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL') === true) { - await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, 'TRANSFER_APPROVAL', false, { from: token_owner }); - } - - // assign a random perm - let randomPerms = perms[Math.floor(Math.random() * Math.floor(totalPerms))]; - await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, randomPerms, true, { from: token_owner }); - - if (randomPerms === "TRANSFER_APPROVAL") { - console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL " + " should pass"); - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: accounts[j] - }); - - console.log("2"); - await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }); - - console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL passed as expected"); - } else { - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " should failed"); - await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: accounts[j] - }) - ); - - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: token_owner - }); - - await catchRevert( - I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }) - ); - - console.log("Test number " + i + " with account " + j + " and perm " + randomPerms + " failed as expected"); - } - - await revertToSnapshot(snapId); - }; - }); }); }); From b8333bfea881a020993f3782061629f8ce20b3f9 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 5 Dec 2018 12:35:30 +0100 Subject: [PATCH 331/582] adjust test logic --- test/d_count_transfer_manager.js | 97 ++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 303a3b6c0..c3cfa19e8 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -85,6 +85,7 @@ contract("CountTransferManager", accounts => { account_investor1 = accounts[7]; account_investor2 = accounts[8]; account_investor3 = accounts[9]; + account_investor4 = accounts[6]; // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -370,8 +371,7 @@ contract("CountTransferManager", accounts => { }); it("add 3 holders to the token", async () => { - - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyWhitelist( account_investor1, latestTime(), latestTime(), @@ -406,53 +406,64 @@ contract("CountTransferManager", accounts => { gas: 500000 } ); - + + await I_GeneralTransferManager2.modifyWhitelist( + account_investor4, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + // Jump time await increaseTime(5000); - // Mint some tokens + // Add 3 holders to the token await I_SecurityToken2.mint(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); await I_SecurityToken2.mint(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); - + await I_SecurityToken2.mint(account_investor3, web3.utils.toWei("1", "ether"), { from: token_owner }); assert.equal((await I_SecurityToken2.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); - }); - - // Add count transfer manager and only allow 2 holders - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; - I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); - }); - - it("Should successfully attach the CountTransferManager factory with the security token", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - await catchRevert( - I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { - from: token_owner - }) - ); - }); - - it("Should successfully attach the CountTransferManager with the security token and set max holder to 2", async () => { - const tx = await I_SecurityToken2.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), - "CountTransferManager", - "CountTransferManager module was not added" - ); - I_CountTransferManager2 = CountTransferManager.at(tx.logs[2].args._module); - await I_CountTransferManager2.changeHolderCount(2, {from: token_owner}); - console.log('current max holder number is '+ await I_CountTransferManager2.maxHolderCount({from: token_owner})); - }); - - it("Should allow add a new token holder while transfer all the tokens at one go", async () => { - - let amount = (await I_SecurityToken2.balanceOf(account_investor2)).toNumber(); - console.log('amount is '+amount); - await I_SecurityToken2.transfer(account_investor3, amount, { from: account_investor2 }); - assert((await I_SecurityToken2.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("2", "ether")); - - }); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + }); + + it("Should successfully attach the CountTransferManager factory with the security token", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await catchRevert( + I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + from: token_owner + }) + ); + }); + + it("Should successfully attach the CountTransferManager with the security token and set max holder to 2", async () => { + const tx = await I_SecurityToken2.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "CountTransferManager", + "CountTransferManager module was not added" + ); + I_CountTransferManager2 = CountTransferManager.at(tx.logs[2].args._module); + await I_CountTransferManager2.changeHolderCount(2, {from: token_owner}); + console.log('current max holder number is '+ await I_CountTransferManager2.maxHolderCount({from: token_owner})); + }); + + it("Should allow add a new token holder while transfer all the tokens at one go", async () => { + let amount = (await I_SecurityToken2.balanceOf(account_investor2)).toNumber(); + let investorCount = await I_SecurityToken2.getInvestorCount({from: account_investor2 }); + console.log("current investor count is " + investorCount); + await I_SecurityToken2.transfer(account_investor4, amount, { from: account_investor2 }); + assert((await I_SecurityToken2.balanceOf(account_investor4)).toNumber(), amount, {from: account_investor2 }); + assert(await I_SecurityToken2.getInvestorCount({from: account_investor2 }), investorCount); + }); }); describe("Test cases for the factory", async () => { From 69a648ffce457b01fe62ca90c6901afc6488e602 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 5 Dec 2018 18:52:06 +0530 Subject: [PATCH 332/582] modification in the _restrictionCheck --- .../TransferManager/VolumeRestrictionTM.sol | 35 ++++-- test/y_volume_restriction_tm.js | 108 ++++++++++++++---- 2 files changed, 107 insertions(+), 36 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 61a9c1af7..5ee117e35 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -26,6 +26,7 @@ contract VolumeRestrictionTM is ITransferManager { struct BucketDetails { uint256 lastTradedDayTime; + uint256 globalLastTradedDayTime; uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays uint256 globalSumOfLastPeriod; uint256 daysCovered; // No of days covered till (from the startTime of VolumeRestriction) @@ -468,23 +469,24 @@ contract VolumeRestrictionTM is ITransferManager { function _restrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { uint256 sumOfLastPeriod = 0; uint256 daysCovered = 0; - uint256 lastTradedDayTime = 0; + uint256 lastTradedDayTime = 0; + uint256 globalLastTradedDayTime = 0; uint256 globalSumOfLastPeriod = 0; uint256 globalDaysCovered = 0; bool validIR = true; bool validGR = true; - uint8 _temp = 0; + uint256 txSumOfDay = 0; if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { (validIR, sumOfLastPeriod, lastTradedDayTime, daysCovered) = _individualRestrictionCheck(_from, _amount); - _temp = _temp + 1; + txSumOfDay = txSumOfDay + 1; } if (globalRestriction.endTime >= now && globalRestriction.startTime <= now) { - (validGR, globalSumOfLastPeriod, lastTradedDayTime, globalDaysCovered) = _globalRestrictionCheck(_from, _amount); - _temp = _temp + 1; + (validGR, globalSumOfLastPeriod, globalLastTradedDayTime, globalDaysCovered) = _globalRestrictionCheck(_from, _amount); + txSumOfDay = txSumOfDay + 1; } - if (_temp > 0) { + if (txSumOfDay > 0) { // Total amout that is transacted uptill now for `fromTimestamp` day - uint256 txSumOfDay = bucket[_from][lastTradedDayTime]; + txSumOfDay = bucket[_from][lastTradedDayTime] <= bucket[_from][globalLastTradedDayTime]? bucket[_from][lastTradedDayTime] : bucket[_from][globalLastTradedDayTime]; // allow modification in storage when `_isTransfer` equals true if (_isTransfer) { // update the storage @@ -495,7 +497,8 @@ contract VolumeRestrictionTM is ITransferManager { sumOfLastPeriod, globalSumOfLastPeriod, daysCovered, - globalDaysCovered + globalDaysCovered, + globalLastTradedDayTime ); } if (validGR && validIR && _dailyTxCheck(txSumOfDay, _amount)) @@ -668,14 +671,19 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _sumOfLastPeriod, uint256 _globalSumOfLastPeriod, uint256 _daysCovered, - uint256 _globalDaysCovered + uint256 _globalDaysCovered, + uint256 _globalLastTradedDayTime ) internal { if (bucketToUser[_from].lastTradedDayTime != _lastTradedDayTime) { - // Assigning the latest transaction timestamp of the day + // Assigning the latest transaction timestamp of the day bucketToUser[_from].lastTradedDayTime = _lastTradedDayTime; } + if (bucketToUser[_from].globalLastTradedDayTime != _globalLastTradedDayTime) { + // Assigning the latest transaction timestamp of the day + bucketToUser[_from].globalLastTradedDayTime = _globalLastTradedDayTime; + } if (_amount != 0) { if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { bucketToUser[_from].daysCovered = _daysCovered; @@ -817,11 +825,14 @@ contract VolumeRestrictionTM is ITransferManager { * @return uint256 sumOfLastPeriod * @return uint256 days covered */ - function getBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256) { + function getBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256, uint256, uint256) { return( bucketToUser[_user].lastTradedDayTime, bucketToUser[_user].sumOfLastPeriod, - bucketToUser[_user].daysCovered + bucketToUser[_user].daysCovered, + bucketToUser[_user].globalDaysCovered, + bucketToUser[_user].globalSumOfLastPeriod, + bucketToUser[_user].globalLastTradedDayTime ); } diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 4be373516..10b0e4f5b 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -76,6 +76,21 @@ contract('VolumeRestrictionTransferManager', accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); + async function print(data, account) { + console.log(` + Latest timestamp: ${data[0].toNumber()} + SumOfLastPeriod: ${data[1].dividedBy(new BigNumber(10).pow(18)).toNumber()} + Days Covered: ${data[2].toNumber()} + Global days covered: ${data[3].toNumber()} + Global Sum of LastPeriod: ${data[4].dividedBy(new BigNumber(10).pow(18)).toNumber()} + Global Latest timestamp: ${data[5].toNumber()} + Individual Total Trade Till now : ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[0])) + .dividedBy(new BigNumber(10).pow(18)).toNumber()} + Global Total Trade Till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[5])) + .dividedBy(new BigNumber(10).pow(18)).toNumber()} + `) + } + before(async() => { // Accounts setup account_polymath = accounts[0]; @@ -549,6 +564,21 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should add the restriction succesfully after the expiry of previous one", async() => { await increaseTime(duration.days(5.1)); + console.log( + `Estimated gas: + ${await I_VolumeRestrictionTM.addIndividualRestriction.estimateGas( + account_investor1, + web3.utils.toWei("12"), + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + )} + `); + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("12"), @@ -578,6 +608,9 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log(result); assert.equal(result.toNumber(), 1); // Perform the transaction + console.log(`Estimated Gas: + ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei('.3'), {from: account_investor1})}` + ); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('.3'), {from: account_investor1}); // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); @@ -585,12 +618,8 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 34.7); let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - console.log('\n'); - console.log(` - Timestamps array index: ${data[0].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) - .dividedBy(new BigNumber(10).pow(18))} - `); + await print(data, account_investor1); + assert.equal( (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) .dividedBy(new BigNumber(10).pow(18)).toNumber(), @@ -600,39 +629,70 @@ contract('VolumeRestrictionTransferManager', accounts => { data[0].toNumber(), (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber() ); - - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Days Covered : ${data[2]} - `); assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 0.3); tempArray.push(0.3); }) + it("Should successfully add the global restriction", async() => { + await I_VolumeRestrictionTM.addGlobalRestriction( + web3.utils.toWei("15"), + latestTime() + duration.seconds(2), + 5, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ); + + let data = await I_VolumeRestrictionTM.globalRestriction.call(); + assert.equal(data[0].toNumber(), web3.utils.toWei("15")); + assert.equal(data[2].toNumber(), 5); + }); + it("Should successfully transact the tokens after 1 and half days", async() => { await increaseTime(duration.days(1.5)); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor1}); + console.log(`Estimated Gas: + ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei("2"), {from: account_investor1})}` + ); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances - assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 33.7); - tempArray.push(1); + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 32.7); + tempArray.push(2); let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - console.log(` - Timestamps array index : ${data[0].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) - .dividedBy(new BigNumber(10).pow(18)).toNumber()} - `); + await print(data, account_investor1); + assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[tempArray.length - 1]); - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Days Covered : ${data[2]} - `); + assert.equal(data[0].toNumber(), (startTime + duration.days(data[2]))); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1.3); + assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 2.3); + }); + + it("Should add the daily restriction successfully", async() => { + await I_VolumeRestrictionTM.addDailyGlobalRestriction( + web3.utils.toWei("5"), + latestTime() + duration.seconds(2), + latestTime() + duration.days(3), + 0, + { + from: token_owner + } + ); + let data = await I_VolumeRestrictionTM.dailyGlobalRestriction.call(); + assert.equal(data[0].dividedBy(new BigNumber(10).pow(18)).toNumber(), 5); + assert.equal(data[2].toNumber(), 1); + assert.equal(data[4].toNumber(), 0); + }); + + it("Should transfer tokens within the daily limit", async() =>{ + console.log(`Estimated Gas: + ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei("2"), {from: account_investor1})}` + ); }); it.skip("Should successfully transact more tokens on the same day (Fuzz test)", async() => { From 137e6ebb9c8575c8e782c07479d2ac134076798e Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 5 Dec 2018 18:59:36 +0530 Subject: [PATCH 333/582] small fix in the pushAvalilableTokensMulti --- contracts/modules/Wallet/VestingEscrowWallet.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 78785b4b0..d7a425051 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -420,7 +420,8 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { function pushAvailableTokensMulti(uint256 _fromIndex, uint256 _toIndex) external withPerm(ADMIN) { require(_toIndex <= beneficiaries.length - 1, "Array out of bound"); for (uint256 i = _fromIndex; i <= _toIndex; i++) { - pushAvailableTokens(beneficiaries[i]); + if (schedules[beneficiaries[i]].length !=0) + pushAvailableTokens(beneficiaries[i]); } } From 3dba7bdd01ce453d7b2112d902781a4dc2017b66 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 5 Dec 2018 08:33:46 -0500 Subject: [PATCH 334/582] Optimise GTM (#443) * WIP * WIP * Fixes * Update config * Log gas for 50 txs * WIP * update * Fix tests * Fix typo * Change onWhitelist logic * Update changelog * Update all test cases * Add whitelist optimization * Make Dividend modules proxies * Updates * minor cleanup * make script dynamic * Keep ABI constant * Fixes * Update change log * Updates * add require statement in factory constructors * remove the test cases for the STVRTM * Return investor data in getAllInvestorsData * CLI changes according GTM optimizations * Bump versions * version changes * Update CHANGELOG.md --- CHANGELOG.md | 16 +- CLI/commands/transfer_manager.js | 68 +- CLI/package.json | 1 + CLI/yarn.lock | 85 +- .../modules/Checkpoint/DividendCheckpoint.sol | 37 +- .../Checkpoint/DividendCheckpointStorage.sol | 43 + .../Checkpoint/ERC20DividendCheckpoint.sol | 39 +- .../ERC20DividendCheckpointFactory.sol | 13 +- .../ERC20DividendCheckpointStorage.sol | 11 + .../Checkpoint/EtherDividendCheckpoint.sol | 25 +- .../EtherDividendCheckpointFactory.sol | 13 +- contracts/modules/Module.sol | 20 +- contracts/modules/ModuleStorage.sol | 30 + .../GeneralTransferManager.sol | 171 ++- .../GeneralTransferManagerFactory.sol | 16 +- .../GeneralTransferManagerStorage.sol | 53 + .../ManualApprovalTransferManagerFactory.sol | 2 +- .../proxy/ERC20DividendCheckpointProxy.sol | 31 + .../proxy/EtherDividendCheckpointProxy.sol | 30 + .../proxy/GeneralTransferManagerProxy.sol | 30 + contracts/proxy/OwnedProxy.sol | 91 ++ migrations/2_deploy_contracts.js | 24 +- package.json | 1 + scripts/compareStorageLayout.js | 139 ++ test/b_capped_sto.js | 2 +- test/e_erc20_dividends.js | 6 +- test/f_ether_dividends.js | 4 +- test/h_general_transfer_manager.js | 124 +- test/helpers/createInstances.js | 32 +- test/j_manual_approval_transfer_manager.js | 2 +- test/l_percentage_transfer_manager.js | 2 +- test/p_usd_tiered_sto.js | 6 +- test/q_usd_tiered_sto_sim.js | 2 +- test/r_concurrent_STO.js | 4 +- test/u_module_registry_proxy.js | 5 +- test/v_tracked_redemptions.js | 2 +- ...kup_volume_restriction_transfer_manager.js | 8 +- yarn.lock | 1247 +---------------- 38 files changed, 1067 insertions(+), 1368 deletions(-) create mode 100644 contracts/modules/Checkpoint/DividendCheckpointStorage.sol create mode 100644 contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol create mode 100644 contracts/modules/ModuleStorage.sol create mode 100644 contracts/modules/TransferManager/GeneralTransferManagerStorage.sol create mode 100644 contracts/proxy/ERC20DividendCheckpointProxy.sol create mode 100644 contracts/proxy/EtherDividendCheckpointProxy.sol create mode 100644 contracts/proxy/GeneralTransferManagerProxy.sol create mode 100644 contracts/proxy/OwnedProxy.sol create mode 100644 scripts/compareStorageLayout.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bd254564..562d7c4f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,14 +16,26 @@ All notable changes to this project will be documented in this file. * Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. * Removed individual mappings for tier data removed in UDSTSTO. +## GeneralTransferManager +* `getInvestors`, `getAllInvestorsData`, `getInvestorsData` added to GTM to allow easy data queries. +* `modifyDefaults(uint64 _defaultFromTime, uint64 _defaultToTime)` added which sets a default timestamp used when `fromTime` or `toTime` are 0 +* Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`). +* General Transfer Manager: Fix for when `allowAllWhitelistIssuances` is FALSE +* General Transfer Manager: Make GTM a Proxy based implementation to reduce deployment gas costs +* Changed the version of `GeneralTransferManagerFactory` from `1.0.0` to `2.1.0`. + ## Manual Approval TransferManager * Removed `0x0` check for the `_from` address to `ManualApprovalTransferManager`. This allows for the Issuer/Transfer Agent to approve a one-off mint of tokens that otherwise would not be possible. -* Changed the version of `ManualApprovalTransferManagerFactory` from `1.0.0` to `2.0.1`. +* Changed the version of `ManualApprovalTransferManagerFactory` from `1.0.0` to `2.1.0`. * Deployed 2.0.1 `ManualApprovalTransferManagerFactory` to address 0x6af2afad53cb334e62b90ddbdcf3a086f654c298 +## Dividends +* Changed the version of `ERC20DividendCheckpointFactory` & `EtherDividendCheckpointFactory` from `1.0.0` to `2.1.0`. +* Applied proxy pattern to Dividends modules + ## Changed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. - + # v1.5.0 - Release Candidate diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index dd92864df..4d551e05c 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -6,6 +6,7 @@ const contracts = require('./helpers/contract_addresses'); const abis = require('./helpers/contract_abis'); const gbl = require('./common/global'); const csvParse = require('./helpers/csv'); +const { table } = require('table') /////////////////// // Constants @@ -328,6 +329,8 @@ async function generalTransferManager() { let displayAllowAllWhitelistTransfers = await currentTransferManager.methods.allowAllWhitelistTransfers().call(); let displayAllowAllWhitelistIssuances = await currentTransferManager.methods.allowAllWhitelistIssuances().call(); let displayAllowAllBurnTransfers = await currentTransferManager.methods.allowAllBurnTransfers().call(); + let displayDefaults = await currentTransferManager.methods.defaults().call(); + let displayInvestors = await currentTransferManager.methods.getInvestors().call(); console.log(`- Issuance address: ${displayIssuanceAddress}`); console.log(`- Signing address: ${displaySigningAddress}`); @@ -335,10 +338,19 @@ async function generalTransferManager() { console.log(`- Allow all whitelist transfers: ${displayAllowAllWhitelistTransfers ? `YES` : `NO`}`); console.log(`- Allow all whitelist issuances: ${displayAllowAllWhitelistIssuances ? `YES` : `NO`}`); console.log(`- Allow all burn transfers: ${displayAllowAllBurnTransfers ? `YES` : `NO`}`); + console.log(`- Default times:`); + console.log(` - From time: ${displayDefaults.fromTime} (${moment.unix(displayDefaults.fromTime).format('MMMM Do YYYY, HH:mm:ss')})`); + console.log(` - To time: ${displayDefaults.toTime} (${moment.unix(displayDefaults.toTime).format('MMMM Do YYYY, HH:mm:ss')})`); + console.log(`- Investors: ${displayInvestors.length}`); // ------------------ - let options = ['Check whitelist', 'Modify whitelist', 'Modify whitelist from CSV', /*'Modify Whitelist Signed',*/ - `Change issuance address`, 'Change signing address']; + let options = []; + if (displayInvestors.length > 0) { + options.push(`Show investors`, `Show whitelist data`); + } + options.push('Modify whitelist', 'Modify whitelist from CSV', /*'Modify Whitelist Signed',*/ + 'Change the default times used when they are zero', `Change issuance address`, 'Change signing address'); + if (displayAllowAllTransfers) { options.push('Disallow all transfers'); } else { @@ -364,18 +376,33 @@ async function generalTransferManager() { let optionSelected = options[index]; console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); switch (optionSelected) { - case 'Check whitelist': - let investorToCheck = readlineSync.question('Enter the address you want to check: ', { + case `Show investors`: + console.log('***** List of investors on whitelist *****'); + displayInvestors.map(i => console.log(i)); + break; + case `Show whitelist data`: + let investorsToShow = readlineSync.question(`Enter the addresses of the investors you want to show (i.e: addr1,addr2,addr3) or leave empty to show them all: `, { limit: function (input) { - return web3.utils.isAddress(input); + return input === '' || input.split(",").every(a => web3.utils.isAddress(a)); }, - limitMessage: "Must be a valid address" + limitMessage: `All addresses must be valid` }); - let timeRestriction = await currentTransferManager.methods.whitelist(investorToCheck).call(); - console.log(`Sale lockup: ${moment.unix(timeRestriction.fromTime).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(`Buy lockup: ${moment.unix(timeRestriction.toTime).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(`KYC expiry time: ${moment.unix(timeRestriction.expiryTime).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(`Restricted investor: ${timeRestriction.canBuyFromSTO ? 'YES' : 'NO'} `); + if (investorsToShow === '') { + let whitelistData = await currentTransferManager.methods.getAllInvestorsData().call(); + showWhitelistTable(whitelistData[0], whitelistData[1], whitelistData[2], whitelistData[3], whitelistData[4]); + } else { + let investorsArray = investorsToShow.split(','); + let whitelistData = await currentTransferManager.methods.getInvestorsData(investorsArray).call(); + showWhitelistTable(investorsArray, whitelistData[0], whitelistData[1], whitelistData[2], whitelistData[3]); + } + break; + case 'Change the default times used when they are zero': + let fromTimeDefault = readlineSync.questionInt(`Enter the default time (Unix Epoch time) used when fromTime is zero: `); + let toTimeDefault = readlineSync.questionInt(`Enter the default time (Unix Epoch time) used when fromTime is zero: `); + let changeDefaultsAction = currentTransferManager.methods.changeDefaults(fromTimeDefault, toTimeDefault); + let changeDefaultsReceipt = await common.sendTransaction(changeDefaultsAction); + let changeDefaultsEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeDefaultsReceipt.logs, 'ChangeDefaults'); + console.log(chalk.green(`Default times have been updated successfully!`)); break; case 'Modify whitelist': let investor = readlineSync.question('Enter the address to whitelist: ', { @@ -490,6 +517,21 @@ async function generalTransferManager() { } } +function showWhitelistTable(investorsArray, fromTimeArray, toTimeArray, expiryTimeArray, canBuyFromSTOArray) { + let dataTable = [['Investor', 'From time', 'To time', 'KYC expiry date', 'Restricted']]; + for (let i = 0; i < investorsArray.length; i++) { + dataTable.push([ + investorsArray[i], + moment.unix(fromTimeArray[i]).format('MM/DD/YYYY HH:mm'), + moment.unix(toTimeArray[i]).format('MM/DD/YYYY HH:mm'), + moment.unix(expiryTimeArray[i]).format('MM/DD/YYYY HH:mm'), + canBuyFromSTOArray[i] ? 'YES' : 'NO' + ]); + } + console.log(); + console.log(table(dataTable)); +} + async function modifyWhitelistInBatch() { let csvFilePath = readlineSync.question(`Enter the path for csv data file (${WHITELIST_DATA_CSV}): `, { defaultInput: WHITELIST_DATA_CSV @@ -553,8 +595,8 @@ async function manualApprovalTransferManager() { let manualApproval = await getManualApproval(from, to); if (manualApproval) { console.log(`Manual approval found!`); - console.log(`Allowance: ${web3.utils.fromWei(manualApproval.allowance)} `); - console.log(`Expiry time: ${moment.unix(manualApproval.expiryTime).format('MMMM Do YYYY, HH:mm:ss')}; `) + console.log(`Allowance: ${web3.utils.fromWei(manualApproval.allowance)}`); + console.log(`Expiry time: ${moment.unix(manualApproval.expiryTime).format('MMMM Do YYYY, HH:mm:ss')}`); } else { console.log(chalk.yellow(`There are no manual approvals from ${from} to ${to}.`)); } diff --git a/CLI/package.json b/CLI/package.json index 64fb2a221..4dfcbf3a4 100644 --- a/CLI/package.json +++ b/CLI/package.json @@ -17,6 +17,7 @@ "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", + "table": "^5.1.1", "web3": "1.0.0-beta.35" } } diff --git a/CLI/yarn.lock b/CLI/yarn.lock index 51925f5ef..91ef48a56 100644 --- a/CLI/yarn.lock +++ b/CLI/yarn.lock @@ -30,7 +30,22 @@ ajv@^5.3.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ansi-styles@^3.2.1: +ajv@^6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.1.tgz#6360f5ed0d80f232cc2b294c362d5dc2e538dd61" + integrity sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -68,6 +83,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" @@ -741,6 +761,11 @@ fast-deep-equal@^1.0.0: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -1042,6 +1067,11 @@ is-callable@^1.1.3: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" @@ -1120,6 +1150,11 @@ json-schema-traverse@^0.3.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -1155,7 +1190,7 @@ keccakjs@^0.2.1: browserify-sha3 "^0.0.1" sha3 "^1.1.0" -lodash@^4.13.1: +lodash@^4.13.1, lodash@^4.17.11: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== @@ -1496,6 +1531,11 @@ punycode@^1.4.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -1749,6 +1789,15 @@ simple-get@^2.7.0: once "^1.3.1" simple-concat "^1.0.0" +slice-ansi@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.0.0.tgz#5373bdb8559b45676e8541c66916cdd6251612e7" + integrity sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + sshpk@^1.7.0: version "1.15.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2" @@ -1784,6 +1833,14 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= +string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -1791,6 +1848,13 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" @@ -1831,6 +1895,16 @@ swarm-js@0.1.37: tar.gz "^1.0.5" xhr-request-promise "^0.1.2" +table@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/table/-/table-5.1.1.tgz#92030192f1b7b51b6eeab23ed416862e47b70837" + integrity sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw== + dependencies: + ajv "^6.6.1" + lodash "^4.17.11" + slice-ansi "2.0.0" + string-width "^2.1.1" + tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" @@ -1956,6 +2030,13 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 452a48b13..3a345af25 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -8,6 +8,7 @@ pragma solidity ^0.4.24; import "./ICheckpoint.sol"; +import "./DividendCheckpointStorage.sol"; import "../Module.sol"; import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -17,43 +18,9 @@ import "openzeppelin-solidity/contracts/math/Math.sol"; * @title Checkpoint module for issuing ether dividends * @dev abstract contract */ -contract DividendCheckpoint is ICheckpoint, Module { +contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { using SafeMath for uint256; - uint256 public EXCLUDED_ADDRESS_LIMIT = 50; - bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; - bytes32 public constant MANAGE = "MANAGE"; - bytes32 public constant CHECKPOINT = "CHECKPOINT"; - - struct Dividend { - uint256 checkpointId; - uint256 created; // Time at which the dividend was created - uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass - uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - - // set to very high value to bypass - uint256 amount; // Dividend amount in WEI - uint256 claimedAmount; // Amount of dividend claimed so far - uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) - bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend - uint256 dividendWithheld; - uint256 dividendWithheldReclaimed; - mapping (address => bool) claimed; // List of addresses which have claimed dividend - mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends - bytes32 name; // Name/title - used for identification - } - - // List of all dividends - Dividend[] public dividends; - - // List of addresses which cannot claim dividends - address[] public excluded; - - // Mapping from address to withholding tax as a percentage * 10**16 - mapping (address => uint256) public withholdingTax; - - // Total amount of ETH withheld per investor - mapping (address => uint256) public investorWithheld; - event SetDefaultExcludedAddresses(address[] _excluded, uint256 _timestamp); event SetWithholding(address[] _investors, uint256[] _withholding, uint256 _timestamp); event SetWithholdingFixed(address[] _investors, uint256 _withholding, uint256 _timestamp); diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol new file mode 100644 index 000000000..4cf1f2838 --- /dev/null +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -0,0 +1,43 @@ +pragma solidity ^0.4.24; + +/** + * @title Holds the storage variable for the DividendCheckpoint modules (i.e ERC20, Ether) + * @dev abstract contract + */ +contract DividendCheckpointStorage { + + uint256 public EXCLUDED_ADDRESS_LIMIT = 50; + bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; + bytes32 public constant MANAGE = "MANAGE"; + bytes32 public constant CHECKPOINT = "CHECKPOINT"; + + struct Dividend { + uint256 checkpointId; + uint256 created; // Time at which the dividend was created + uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass + uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer - + // set to very high value to bypass + uint256 amount; // Dividend amount in WEI + uint256 claimedAmount; // Amount of dividend claimed so far + uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) + bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend + uint256 dividendWithheld; + uint256 dividendWithheldReclaimed; + mapping (address => bool) claimed; // List of addresses which have claimed dividend + mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends + bytes32 name; // Name/title - used for identification + } + + // List of all dividends + Dividend[] public dividends; + + // List of addresses which cannot claim dividends + address[] public excluded; + + // Mapping from address to withholding tax as a percentage * 10**16 + mapping (address => uint256) public withholdingTax; + + // Total amount of ETH withheld per investor + mapping (address => uint256) public investorWithheld; + +} diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 1f7f25cd5..b779088f7 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -1,17 +1,16 @@ pragma solidity ^0.4.24; import "./DividendCheckpoint.sol"; +import "./ERC20DividendCheckpointStorage.sol"; import "../../interfaces/IOwnable.sol"; import "../../interfaces/IERC20.sol"; /** * @title Checkpoint module for issuing ERC20 dividends */ -contract ERC20DividendCheckpoint is DividendCheckpoint { +contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendCheckpoint { using SafeMath for uint256; - // Mapping to token address for each dividend - mapping (uint256 => address) public dividendTokens; event ERC20DividendDeposited( address indexed _depositor, uint256 _checkpointId, @@ -68,8 +67,8 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { address _token, uint256 _amount, bytes32 _name - ) - external + ) + external withPerm(MANAGE) { createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name); @@ -133,16 +132,16 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _name Name/Title for identification */ function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, address[] _excluded, bytes32 _name - ) + ) public - withPerm(MANAGE) + withPerm(MANAGE) { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, _excluded, _name); } @@ -158,15 +157,15 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @param _name Name/Title for identification */ function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, - uint256 _checkpointId, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, + uint256 _checkpointId, address[] _excluded, bytes32 _name - ) - internal + ) + internal { ISecurityToken securityTokenInstance = ISecurityToken(securityToken); require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); @@ -210,7 +209,7 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { } /** - * @notice Emits the ERC20DividendDeposited event. + * @notice Emits the ERC20DividendDeposited event. * Seperated into a different function as a workaround for stack too deep error */ function _emitERC20DividendDepositedEvent( diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 5fd158c26..bae9913b8 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./ERC20DividendCheckpoint.sol"; +import "../../proxy/ERC20DividendCheckpointProxy.sol"; import "../ModuleFactory.sol"; /** @@ -8,22 +8,27 @@ import "../ModuleFactory.sol"; */ contract ERC20DividendCheckpointFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module + * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + require(_logicContract != address(0), "Invalid logic contract"); + version = "2.1.0"; name = "ERC20DividendCheckpoint"; title = "ERC20 Dividend Checkpoint"; description = "Create ERC20 dividends for token holders at a specific checkpoint"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,7 +38,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "insufficent allowance"); - address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender, address(polyToken)); + address erc20DividendCheckpoint = new ERC20DividendCheckpointProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return erc20DividendCheckpoint; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol new file mode 100644 index 000000000..29401f8d9 --- /dev/null +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.24; + +/** + * @title It holds the storage variables related to ERC20DividendCheckpoint module + */ +contract ERC20DividendCheckpointStorage { + + // Mapping to token address for each dividend + mapping (uint256 => address) public dividendTokens; + +} diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index 4def51468..f5a916818 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -8,6 +8,7 @@ import "../../interfaces/IOwnable.sol"; */ contract EtherDividendCheckpoint is DividendCheckpoint { using SafeMath for uint256; + event EtherDividendDeposited( address indexed _depositor, uint256 _checkpointId, @@ -56,7 +57,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, uint256 _checkpointId, bytes32 _name - ) + ) external payable withPerm(MANAGE) @@ -76,7 +77,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, address[] _excluded, bytes32 _name - ) + ) public payable withPerm(MANAGE) @@ -94,10 +95,10 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _name Name/title for identification */ function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] _excluded, + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] _excluded, bytes32 _name ) public @@ -116,12 +117,12 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _name Name/title for identification */ function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] _excluded, + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] _excluded, bytes32 _name - ) + ) internal { require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); @@ -169,7 +170,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { */ function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee); - _dividend.claimed[_payee] = true; + _dividend.claimed[_payee] = true; uint256 claimAfterWithheld = claim.sub(withheld); if (claimAfterWithheld > 0) { /*solium-disable-next-line security/no-send*/ diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 315760be1..712292d0a 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./EtherDividendCheckpoint.sol"; +import "../../proxy/EtherDividendCheckpointProxy.sol"; import "../ModuleFactory.sol"; /** @@ -8,22 +8,27 @@ import "../ModuleFactory.sol"; */ contract EtherDividendCheckpointFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module + * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + require(_logicContract != address(0), "Invalid logic contract"); + version = "2.1.0"; name = "EtherDividendCheckpoint"; title = "Ether Dividend Checkpoint"; description = "Create ETH dividends for token holders at a specific checkpoint"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,7 +38,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent allowance or balance"); - address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender, address(polyToken)); + address ethDividendCheckpoint = new EtherDividendCheckpointProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return ethDividendCheckpoint; diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index 1e27d424e..1566a3428 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -2,33 +2,23 @@ pragma solidity ^0.4.24; import "../interfaces/IModule.sol"; import "../interfaces/ISecurityToken.sol"; -import "../interfaces/IERC20.sol"; +import "./ModuleStorage.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; /** * @title Interface that any module contract should implement * @notice Contract is abstract */ -contract Module is IModule { - - address public factory; - - address public securityToken; - - bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; - - IERC20 public polyToken; +contract Module is IModule, ModuleStorage { /** * @notice Constructor * @param _securityToken Address of the security token * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public { - require(_securityToken != address(0) && _polyAddress != address(0), "Invalid address"); - securityToken = _securityToken; - factory = msg.sender; - polyToken = IERC20(_polyAddress); + constructor (address _securityToken, address _polyAddress) public + ModuleStorage(_securityToken, _polyAddress) + { } //Allows owner, factory or permissioned delegate diff --git a/contracts/modules/ModuleStorage.sol b/contracts/modules/ModuleStorage.sol new file mode 100644 index 000000000..cd52c9de2 --- /dev/null +++ b/contracts/modules/ModuleStorage.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../interfaces/IERC20.sol"; + +/** + * @title Storage for Module contract + * @notice Contract is abstract + */ +contract ModuleStorage { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) public { + securityToken = _securityToken; + factory = msg.sender; + polyToken = IERC20(_polyAddress); + } + + address public factory; + + address public securityToken; + + bytes32 public constant FEE_ADMIN = "FEE_ADMIN"; + + IERC20 public polyToken; + +} diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 814d54d7b..12bfa72ca 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -1,47 +1,16 @@ pragma solidity ^0.4.24; import "./ITransferManager.sol"; +import "./GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Transfer Manager module for core transfer validation functionality */ -contract GeneralTransferManager is ITransferManager { +contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManager { using SafeMath for uint256; - //Address from which issuances come - address public issuanceAddress = address(0); - - //Address which can sign whitelist changes - address public signingAddress = address(0); - - bytes32 public constant WHITELIST = "WHITELIST"; - bytes32 public constant FLAGS = "FLAGS"; - - //from and to timestamps that an investor can send / receive tokens respectively - struct TimeRestriction { - uint256 fromTime; - uint256 toTime; - uint256 expiryTime; - bool canBuyFromSTO; - } - - // An address can only send / receive tokens once their corresponding uint256 > block.number - // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) - mapping (address => TimeRestriction) public whitelist; - // Map of used nonces by customer - mapping(address => mapping(uint256 => bool)) public nonceMap; - - //If true, there are no transfer restrictions, for any addresses - bool public allowAllTransfers = false; - //If true, time lock is ignored for transfers (address must still be on whitelist) - bool public allowAllWhitelistTransfers = false; - //If true, time lock is ignored for issuances (address must still be on whitelist) - bool public allowAllWhitelistIssuances = true; - //If true, time lock is ignored for burn transactions - bool public allowAllBurnTransfers = false; - // Emit when Issuance address get changed event ChangeIssuanceAddress(address _issuanceAddress); // Emit when there is change in the flag variable called allowAllTransfers @@ -55,6 +24,13 @@ contract GeneralTransferManager is ITransferManager { // Emit when there is change in the flag variable called signingAddress event ChangeSigningAddress(address _signingAddress); // Emit when investor details get modified related to their whitelisting + event ChangeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime); + + // _fromTime is the time from which the _investor can send tokens + // _toTime is the time from which the _investor can receive tokens + // if allowAllWhitelistIssuances is TRUE, then _toTime is ignored when receiving tokens from the issuance address + // if allowAllWhitelistTransfers is TRUE, then _toTime and _fromTime is ignored when sending or receiving tokens + // in any case, any investor sending or receiving tokens, must have a _expiryTime in the future event ModifyWhitelist( address _investor, uint256 _dateAdded, @@ -83,6 +59,17 @@ contract GeneralTransferManager is ITransferManager { return bytes4(0); } + /** + * @notice Used to change the default times used when fromTime / toTime are zero + * @param _defaultFromTime default for zero fromTime + * @param _defaultToTime default for zero toTime + */ + function changeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime) public withPerm(FLAGS) { + defaults.fromTime = _defaultFromTime; + defaults.toTime = _defaultToTime; + emit ChangeDefaults(_defaultFromTime, _defaultToTime); + } + /** * @notice Used to change the Issuance Address * @param _issuanceAddress new address for the issuance @@ -168,16 +155,25 @@ contract GeneralTransferManager is ITransferManager { //Anyone on the whitelist can transfer, regardless of time return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA; } - if (allowAllWhitelistIssuances && _from == issuanceAddress) { - if (!whitelist[_to].canBuyFromSTO && _isSTOAttached()) { + + (uint64 adjustedFromTime, uint64 adjustedToTime) = _adjustTimes(whitelist[_from].fromTime, whitelist[_to].toTime); + if (_from == issuanceAddress) { + // Possible STO transaction, but investor not allowed to purchased from STO + if ((whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { return Result.NA; } - return _onWhitelist(_to) ? Result.VALID : Result.NA; + // if allowAllWhitelistIssuances is true, so time stamp ignored + if (allowAllWhitelistIssuances) { + return _onWhitelist(_to) ? Result.VALID : Result.NA; + } else { + return (_onWhitelist(_to) && (adjustedToTime <= uint64(now))) ? Result.VALID : Result.NA; + } } + //Anyone on the whitelist can transfer provided the blocknumber is large enough /*solium-disable-next-line security/no-block-members*/ - return ((_onWhitelist(_from) && whitelist[_from].fromTime <= now) && - (_onWhitelist(_to) && whitelist[_to].toTime <= now)) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return ((_onWhitelist(_from) && (adjustedFromTime <= uint64(now))) && + (_onWhitelist(_to) && (adjustedToTime <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -200,9 +196,35 @@ contract GeneralTransferManager is ITransferManager { public withPerm(WHITELIST) { - //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); - /*solium-disable-next-line security/no-block-members*/ + _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + } + + /** + * @notice Adds or removes addresses from the whitelist. + * @param _investor is the address to whitelist + * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens + * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others + * @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC + * @param _canBuyFromSTO is used to know whether the investor is restricted investor or not. + */ + function _modifyWhitelist( + address _investor, + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, + bool _canBuyFromSTO + ) + internal + { + require(_investor != address(0), "Invalid investor"); + uint8 canBuyFromSTO = 0; + if (_canBuyFromSTO) { + canBuyFromSTO = 1; + } + if (whitelist[_investor].added == uint8(0)) { + investors.push(_investor); + } + whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -226,7 +248,7 @@ contract GeneralTransferManager is ITransferManager { require(_toTimes.length == _expiryTimes.length, "Mismatched input lengths"); require(_canBuyFromSTO.length == _toTimes.length, "Mismatched input length"); for (uint256 i = 0; i < _investors.length; i++) { - modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); + _modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); } } @@ -267,10 +289,7 @@ contract GeneralTransferManager is ITransferManager { abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) ); _checkSig(hash, _v, _r, _s); - //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist - whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); - /*solium-disable-next-line security/no-block-members*/ - emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** @@ -289,8 +308,7 @@ contract GeneralTransferManager is ITransferManager { * @param _investor Address of the investor */ function _onWhitelist(address _investor) internal view returns(bool) { - return (((whitelist[_investor].fromTime != 0) || (whitelist[_investor].toTime != 0)) && - (whitelist[_investor].expiryTime >= now)); /*solium-disable-line security/no-block-members*/ + return (whitelist[_investor].expiryTime >= uint64(now)); /*solium-disable-line security/no-block-members*/ } /** @@ -301,6 +319,63 @@ contract GeneralTransferManager is ITransferManager { return attached; } + /** + * @notice Internal function to adjust times using default values + */ + function _adjustTimes(uint64 _fromTime, uint64 _toTime) internal view returns(uint64, uint64) { + uint64 adjustedFromTime = _fromTime; + uint64 adjustedToTime = _toTime; + if (_fromTime == 0) { + adjustedFromTime = defaults.fromTime; + } + if (_toTime == 0) { + adjustedToTime = defaults.toTime; + } + return (adjustedFromTime, adjustedToTime); + } + + /** + * @dev Returns list of all investors + */ + function getInvestors() external view returns(address[]) { + return investors; + } + + /** + * @dev Returns list of all investors data + */ + function getAllInvestorsData() external view returns(address[], uint256[], uint256[], uint256[], bool[]) { + (uint256[] memory fromTimes, uint256[] memory toTimes, uint256[] memory expiryTimes, bool[] memory canBuyFromSTOs) + = _investorsData(investors); + return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs); + + } + + /** + * @dev Returns list of specified investors data + */ + function getInvestorsData(address[] _investors) external view returns(uint256[], uint256[], uint256[], bool[]) { + return _investorsData(_investors); + } + + function _investorsData(address[] _investors) internal view returns(uint256[], uint256[], uint256[], bool[]) { + uint256[] memory fromTimes = new uint256[](_investors.length); + uint256[] memory toTimes = new uint256[](_investors.length); + uint256[] memory expiryTimes = new uint256[](_investors.length); + bool[] memory canBuyFromSTOs = new bool[](_investors.length); + for (uint256 i = 0; i < _investors.length; i++) { + fromTimes[i] = whitelist[_investors[i]].fromTime; + toTimes[i] = whitelist[_investors[i]].toTime; + expiryTimes[i] = whitelist[_investors[i]].expiryTime; + if (whitelist[_investors[i]].canBuyFromSTO == 0) { + canBuyFromSTOs[i] = false; + } else { + canBuyFromSTOs[i] = true; + } + } + return (fromTimes, toTimes, expiryTimes, canBuyFromSTOs); + } + /** * @notice Return the permissions flag that are associated with general trnasfer manager */ diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index c15eb52aa..cffc61a32 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./GeneralTransferManager.sol"; +import "../../proxy/GeneralTransferManagerProxy.sol"; import "../ModuleFactory.sol"; /** @@ -8,19 +8,27 @@ import "../ModuleFactory.sol"; */ contract GeneralTransferManagerFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _subscriptionCost Subscription cost of the module + * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + require(_logicContract != address(0), "Invalid logic contract"); + version = "2.1.0"; name = "GeneralTransferManager"; title = "General Transfer Manager"; description = "Manage transfers using a time based whitelist"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } @@ -31,7 +39,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - address generalTransferManager = new GeneralTransferManager(msg.sender, address(polyToken)); + address generalTransferManager = new GeneralTransferManagerProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(generalTransferManager); diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol new file mode 100644 index 000000000..cca7b5dd1 --- /dev/null +++ b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol @@ -0,0 +1,53 @@ +pragma solidity ^0.4.24; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract GeneralTransferManagerStorage { + + //Address from which issuances come + address public issuanceAddress = address(0); + + //Address which can sign whitelist changes + address public signingAddress = address(0); + + bytes32 public constant WHITELIST = "WHITELIST"; + bytes32 public constant FLAGS = "FLAGS"; + + //from and to timestamps that an investor can send / receive tokens respectively + struct TimeRestriction { + uint64 fromTime; + uint64 toTime; + uint64 expiryTime; + uint8 canBuyFromSTO; + uint8 added; + } + + // Allows all TimeRestrictions to be offset + struct Defaults { + uint64 fromTime; + uint64 toTime; + } + + // Offset to be applied to all timings (except KYC expiry) + Defaults public defaults; + + // List of all addresses that have been added to the GTM at some point + address[] public investors; + + // An address can only send / receive tokens once their corresponding uint256 > block.number + // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) + mapping (address => TimeRestriction) public whitelist; + // Map of used nonces by customer + mapping(address => mapping(uint256 => bool)) public nonceMap; + + //If true, there are no transfer restrictions, for any addresses + bool public allowAllTransfers = false; + //If true, time lock is ignored for transfers (address must still be on whitelist) + bool public allowAllWhitelistTransfers = false; + //If true, time lock is ignored for issuances (address must still be on whitelist) + bool public allowAllWhitelistIssuances = true; + //If true, time lock is ignored for burn transactions + bool public allowAllBurnTransfers = false; + +} diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 9c5513ee7..3fd33a39b 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -18,7 +18,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "2.0.1"; + version = "2.1.0"; name = "ManualApprovalTransferManager"; title = "Manual Approval Transfer Manager"; description = "Manage transfers using single approvals / blocking"; diff --git a/contracts/proxy/ERC20DividendCheckpointProxy.sol b/contracts/proxy/ERC20DividendCheckpointProxy.sol new file mode 100644 index 000000000..8839d30e1 --- /dev/null +++ b/contracts/proxy/ERC20DividendCheckpointProxy.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.4.24; + +import "../modules/Checkpoint/ERC20DividendCheckpointStorage.sol"; +import "../modules/Checkpoint/DividendCheckpointStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + +} diff --git a/contracts/proxy/EtherDividendCheckpointProxy.sol b/contracts/proxy/EtherDividendCheckpointProxy.sol new file mode 100644 index 000000000..40b1c1332 --- /dev/null +++ b/contracts/proxy/EtherDividendCheckpointProxy.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../modules/Checkpoint/DividendCheckpointStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract EtherDividendCheckpointProxy is DividendCheckpointStorage, ModuleStorage, Pausable, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + +} diff --git a/contracts/proxy/GeneralTransferManagerProxy.sol b/contracts/proxy/GeneralTransferManagerProxy.sol new file mode 100644 index 000000000..cb9b69070 --- /dev/null +++ b/contracts/proxy/GeneralTransferManagerProxy.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../modules/TransferManager/GeneralTransferManagerStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract GeneralTransferManagerProxy is GeneralTransferManagerStorage, ModuleStorage, Pausable, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + +} diff --git a/contracts/proxy/OwnedProxy.sol b/contracts/proxy/OwnedProxy.sol new file mode 100644 index 000000000..b75142fbe --- /dev/null +++ b/contracts/proxy/OwnedProxy.sol @@ -0,0 +1,91 @@ +pragma solidity ^0.4.18; + +import "./Proxy.sol"; + +/** + * @title OwnedProxy + * @dev This contract combines an upgradeability proxy with basic authorization control functionalities + */ +contract OwnedProxy is Proxy { + + // Owner of the contract + address private __owner; + + // Address of the current implementation + address internal __implementation; + + /** + * @dev Event to show ownership has been transferred + * @param _previousOwner representing the address of the previous owner + * @param _newOwner representing the address of the new owner + */ + event ProxyOwnershipTransferred(address _previousOwner, address _newOwner); + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier ifOwner() { + if (msg.sender == _owner()) { + _; + } else { + _fallback(); + } + } + + /** + * @dev the constructor sets the original owner of the contract to the sender account. + */ + constructor() public { + _setOwner(msg.sender); + } + + /** + * @dev Tells the address of the owner + * @return the address of the owner + */ + function _owner() internal view returns (address) { + return __owner; + } + + /** + * @dev Sets the address of the owner + */ + function _setOwner(address _newOwner) internal { + require(_newOwner != address(0), "Address should not be 0x"); + __owner = _newOwner; + } + + /** + * @notice Internal function to provide the address of the implementation contract + */ + function _implementation() internal view returns (address) { + return __implementation; + } + + /** + * @dev Tells the address of the proxy owner + * @return the address of the proxy owner + */ + function proxyOwner() external ifOwner returns (address) { + return _owner(); + } + + /** + * @dev Tells the address of the current implementation + * @return address of the current implementation + */ + function implementation() external ifOwner returns (address) { + return _implementation(); + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param _newOwner The address to transfer ownership to. + */ + function transferProxyOwnership(address _newOwner) external ifOwner { + require(_newOwner != address(0), "Address should not be 0x"); + emit ProxyOwnershipTransferred(_owner(), _newOwner); + _setOwner(_newOwner); + } + +} diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 694fdf03e..f25cfab35 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,9 +1,12 @@ const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') +const GeneralTransferManagerLogic = artifacts.require('./GeneralTransferManager.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') +const EtherDividendCheckpointLogic = artifacts.require('./EtherDividendCheckpoint.sol') +const ERC20DividendCheckpointLogic = artifacts.require('./ERC20DividendCheckpoint.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); @@ -145,10 +148,22 @@ module.exports = function (deployer, network, accounts) { moduleRegistry = ModuleRegistry.at(ModuleRegistryProxy.address); // Add module registry to polymath registry return polymathRegistry.changeAddress("ModuleRegistry", ModuleRegistryProxy.address, {from: PolymathAccount}); + }).then(() => { + // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(GeneralTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(ERC20DividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(EtherDividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); }).then(() => { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, GeneralTransferManagerLogic.address, {from: PolymathAccount}); }).then(() => { // C) Deploy the GeneralPermissionManagerFactory Contract (Factory used to generate the GeneralPermissionManager contract and // this manager attach with the securityToken contract at the time of deployment) @@ -164,11 +179,11 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // D) Deploy the EtherDividendCheckpointFactory Contract (Factory used to generate the EtherDividendCheckpoint contract use // to provide the functionality of the dividend in terms of ETH) - return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, EtherDividendCheckpointLogic.address, {from: PolymathAccount}); }).then(() => { // D) Deploy the ERC20DividendCheckpointFactory Contract (Factory used to generate the ERC20DividendCheckpoint contract use // to provide the functionality of the dividend in terms of ERC20 token) - return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, ERC20DividendCheckpointLogic.address, {from: PolymathAccount}); }).then(() => { // D) Deploy the ManualApprovalTransferManagerFactory Contract (Factory used to generate the ManualApprovalTransferManager contract use // to manual approve the transfer that will overcome the other transfer restrictions) @@ -303,6 +318,7 @@ module.exports = function (deployer, network, accounts) { POLYOracle: ${POLYOracle} STFactory: ${STFactory.address} + GeneralTransferManagerLogic: ${GeneralTransferManagerLogic.address} GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} @@ -313,6 +329,8 @@ module.exports = function (deployer, network, accounts) { CountTransferManagerFactory: ${CountTransferManagerFactory.address} PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} + EtherDividendCheckpointLogic: ${EtherDividendCheckpointLogic.address} + ERC20DividendCheckpointLogic: ${ERC20DividendCheckpointLogic.address} EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} --------------------------------------------------------------------------------- diff --git a/package.json b/package.json index ef2d76c38..58104d99b 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "ethers": "^3.0.15", "fs": "0.0.1-security", "openzeppelin-solidity": "1.10.0", + "prompt": "^1.0.0", "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", diff --git a/scripts/compareStorageLayout.js b/scripts/compareStorageLayout.js new file mode 100644 index 000000000..c339bf095 --- /dev/null +++ b/scripts/compareStorageLayout.js @@ -0,0 +1,139 @@ +const fs = require('fs'); +const _ = require('underscore'); +const solc = require('solc'); +const prompt = require('prompt'); +const path = require('path'); +const util = require('util'); +const exec = util.promisify(require('child_process').exec); + +prompt.start(); + +prompt.get(['LogicContract', 'ProxyContract'], async(err, result) => { + + let logicContract; + let proxyContract; + + const fileList = walkSync('./contracts', []); + + let paths = findPath(result.LogicContract, result.ProxyContract, fileList); + + if (paths.length == 2) { + + console.log("Contracts exists \n"); + + await flatContracts(paths); + + if (path.basename(paths[0]) === result.LogicContract) { + logicContract = fs.readFileSync(`./flat/${path.basename(paths[0])}`, 'utf8'); + } else { + logicContract = fs.readFileSync(`./flat/${path.basename(paths[1])}`, 'utf8'); + } + if (path.basename(paths[0]) === result.ProxyContract) { + proxyContract = fs.readFileSync(`./flat/${path.basename(paths[0])}`, 'utf8'); + } else { + proxyContract = fs.readFileSync(`./flat/${path.basename(paths[1])}`, 'utf8'); + } + + let logicInput = { + 'contracts': logicContract + } + let proxyInput = { + 'contracts': proxyContract + } + + console.log(compareStorageLayouts(parseContract(logicInput), parseContract(proxyInput))); + + } else { + console.log("Contracts doesn't exists"); + } +}); + +function traverseAST(_input, _elements) { + if(_input.children) { + for(var i=0;i<_input.children.length;i++) { + traverseAST(_input.children[i], _elements); + } + } + _elements.push(_input); +} + +function compareStorageLayouts(logicLayout, proxyLayout) { + function makeComp(x) { + return [x.constant, x.name, x.stateVariable, x.storageLocation, x.type, x.value, x.visibility].join(':'); + } + // if(newLayout.length < oldLayout.length) return false; + for(var i=0; i < logicLayout.length; i++) { + const a = logicLayout[i].attributes; + const comp1 = makeComp(a) + console.log(comp1); + const b = proxyLayout[i].attributes; + const comp2 = makeComp(b); + console.log(comp2); + if(comp1 != comp2) { + return false; + } + } + return true; +} + +function parseContract(input) { + + var output = solc.compile({ sources: input }, 1, _.noop); + const elements = []; + const AST = output.sources.contracts.AST; + // console.log(AST); + traverseAST(AST, elements); + // console.log(elements); + + // filter out all Contract Definitions + const contractDefinitions = _.filter(elements, (e,i) => e.name == 'ContractDefinition'); + + // filter out all linearizedBaseContracts + // pick the last one as the last contract always has the full inheritance + const linearizedBaseContracts = _.last(_.map(contractDefinitions, e => e.attributes.linearizedBaseContracts)); + + // get all stateVariables + const stateVariables = _.filter(elements, e => e.attributes && e.attributes.stateVariable ) + + // group them by scope + const stateVariableMap = _.groupBy(stateVariables, e => e.attributes.scope); + + orderedStateVariables = _.reduceRight(linearizedBaseContracts, (a, b) => { + return a.concat(stateVariableMap[b] || []) + }, []); + return orderedStateVariables; +} + +var walkSync = function(dir, filelist) { + files = fs.readdirSync(dir); + filelist = filelist || []; + files.forEach(function(file) { + if (fs.statSync(path.join(dir, file)).isDirectory()) { + filelist = walkSync(path.join(dir, file), filelist); + } + else { + filelist.push(path.join(dir, file)); + } + }); + return filelist; +}; + +var findPath = function(logicContractName, proxyContractName, fileList) { + let paths = new Array(); + for (let i =0; i < fileList.length; i++) { + if ((logicContractName === path.basename(fileList[i]) || logicContractName === (path.basename(fileList[i])).split(".")[0]) || + (proxyContractName === path.basename(fileList[i]) || proxyContractName === (path.basename(fileList[i])).split(".")[0])) { + paths.push(fileList[i]); + } + } + return paths; +} + +async function flatContracts(_paths, _logic) { + let promises = new Array(); + for (let i = 0; i< _paths.length; i++) { + promises.push(await exec(`./node_modules/.bin/sol-merger ${_paths[i]} ./flat`)); + } + await Promise.all(promises); +} + diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 539d91b26..4ab4c79fc 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -130,7 +130,7 @@ contract("CappedSTO", accounts => { // STEP 5: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - + // STEP 6: Deploy the CappedSTOFactory I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index b832bcee2..96f27883b 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -89,7 +89,7 @@ contract("ERC20DividendCheckpoint", accounts => { account_investor4 = accounts[9]; account_temp = accounts[2]; account_manager = accounts[5]; - + // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -970,7 +970,7 @@ contract("ERC20DividendCheckpoint", accounts => { let expiry = latestTime() + duration.days(10); let exclusions = [1]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); - await I_SecurityToken.createCheckpoint({ from: token_owner }); + await I_SecurityToken.createCheckpoint({ from: token_owner }); await catchRevert(I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, @@ -1105,7 +1105,7 @@ contract("ERC20DividendCheckpoint", accounts => { it("should get the exact details of the factory", async () => { assert.equal((await I_ERC20DividendCheckpointFactory.getSetupCost.call()).toNumber(), 0); assert.equal((await I_ERC20DividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(await I_ERC20DividendCheckpointFactory.version.call(), "1.0.0"); + assert.equal(await I_ERC20DividendCheckpointFactory.version.call(), "2.1.0"); assert.equal( web3.utils.toAscii(await I_ERC20DividendCheckpointFactory.getName.call()).replace(/\u0000/g, ""), "ERC20DividendCheckpoint", diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index b4e5bbf2b..6b7461629 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -851,7 +851,7 @@ contract("EtherDividendCheckpoint", accounts => { let expiry = latestTime() + duration.days(10); let exclusions = [1]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); - await I_SecurityToken.createCheckpoint({ from: token_owner }); + await I_SecurityToken.createCheckpoint({ from: token_owner }); await catchRevert(I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, @@ -954,7 +954,7 @@ contract("EtherDividendCheckpoint", accounts => { it("should get the exact details of the factory", async () => { assert.equal((await I_EtherDividendCheckpointFactory.getSetupCost.call()).toNumber(), 0); assert.equal((await I_EtherDividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(await I_EtherDividendCheckpointFactory.version.call(), "1.0.0"); + assert.equal(await I_EtherDividendCheckpointFactory.version.call(), "2.1.0"); assert.equal( web3.utils.toAscii(await I_EtherDividendCheckpointFactory.getName.call()).replace(/\u0000/g, ""), "EtherDividendCheckpoint", diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 3e060c288..76a9d5806 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -92,6 +92,7 @@ contract("GeneralTransferManager", accounts => { account_investor1 = accounts[8]; account_investor2 = accounts[9]; account_delegate = accounts[7]; + account_investor3 = accounts[5]; account_investor4 = accounts[6]; account_affiliates1 = accounts[3]; @@ -172,14 +173,14 @@ contract("GeneralTransferManager", accounts => { await catchRevert( I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}) ); - }) + }); it("Should attach the paid GTM", async() => { let snap_id = await takeSnapshot(); await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); await I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}); await revertToSnapshot(snap_id); - }) + }); it("Should whitelist the affiliates before the STO attached", async () => { let tx = await I_GeneralTransferManager.modifyWhitelistMulti( @@ -195,6 +196,32 @@ contract("GeneralTransferManager", accounts => { ); assert.equal(tx.logs[0].args._investor, account_affiliates1); assert.equal(tx.logs[1].args._investor, account_affiliates2); + assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2]); + console.log(await I_GeneralTransferManager.getAllInvestorsData.call()); + console.log(await I_GeneralTransferManager.getInvestorsData.call([account_affiliates1, account_affiliates2])); + }); + + it("Should whitelist lots of addresses and check gas", async () => { + let mockInvestors = []; + for (let i = 0; i < 50; i++) { + mockInvestors.push("0x1000000000000000000000000000000000000000".substring(0,42-i.toString().length) + i.toString()); + } + + let times = range1(50); + let bools = rangeB(50); + let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + mockInvestors, + times, + times, + times, + bools, + { + from: account_issuer, + gas: 7900000 + } + ); + console.log("Multi Whitelist x 50: " + tx.receipt.gasUsed); + assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2].concat(mockInvestors)); }); it("Should mint the tokens to the affiliates", async () => { @@ -320,7 +347,7 @@ contract("GeneralTransferManager", accounts => { it("Should fail in buying the tokens from the STO -- because amount is 0", async() => { await catchRevert( I_DummySTO.generateTokens(account_investor1, 0, { from: token_owner }) - ); + ); }); it("Should fail in buying the tokens from the STO -- because STO is paused", async() => { @@ -342,6 +369,90 @@ contract("GeneralTransferManager", accounts => { }); }); + describe("Buy tokens using on-chain whitelist and defaults", async () => { + // let snap_id; + + it("Should Buy the tokens", async () => { + // Add the Investor in to the whitelist + // snap_id = await takeSnapshot(); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + 0, + 0, + latestTime() + duration.days(20), + true, + { + from: account_issuer, + gas: 6000000 + } + ); + + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor1.toLowerCase(), + "Failed in adding the investor in whitelist" + ); + + tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(20), + true, + { + from: account_issuer, + gas: 6000000 + } + ); + + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor2.toLowerCase(), + "Failed in adding the investor in whitelist" + ); + + // Jump time + await increaseTime(5000); + + // Can transfer tokens + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1}); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + }); + + it("Add a from default and check transfers are disabled then enabled in the future", async () => { + let tx = await I_GeneralTransferManager.changeDefaults(latestTime() + duration.days(5), 0, {from: token_owner}); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor2}); + await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1})); + await increaseTime(duration.days(5)); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1}); + }); + + it("Add a to default and check transfers are disabled then enabled in the future", async () => { + let tx = await I_GeneralTransferManager.changeDefaults(0, latestTime() + duration.days(5), {from: token_owner}); + await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), {from: account_investor2})); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), {from: account_investor1}); + await increaseTime(duration.days(5)); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("2", "ether"), {from: account_investor2}); + // revert changes + await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + 0, + 0, + 0, + false, + { + from: account_issuer, + gas: 6000000 + } + ); + await I_GeneralTransferManager.changeDefaults(0, 0, {from: token_owner}); + }); + + + + }); + describe("Buy tokens using off-chain whitelist", async () => { it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { await catchRevert(I_DummySTO.generateTokens(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner })); @@ -690,7 +801,7 @@ contract("GeneralTransferManager", accounts => { [fromTime], [toTime, toTime], [expiryTime, expiryTime], - [true, true], + [1, 1], { from: account_delegate, gas: 6000000 @@ -779,7 +890,7 @@ contract("GeneralTransferManager", accounts => { "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters.", "Wrong Module added" ); - assert.equal(await I_GeneralPermissionManagerFactory.version.call(), "1.0.0"); + assert.equal(await I_GeneralTransferManagerFactory.version.call(), "2.1.0"); }); it("Should get the tags of the factory", async () => { @@ -836,3 +947,6 @@ contract("GeneralTransferManager", accounts => { }) }); }); + +function range1(i) {return i?range1(i-1).concat(i):[]} +function rangeB(i) {return i?rangeB(i-1).concat(0):[]} diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index a739e86fb..81ee9606b 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -8,6 +8,8 @@ const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); +const ERC20DividendCheckpoint = artifacts.require("./ERC20DividendCheckpoint.sol"); +const EtherDividendCheckpoint = artifacts.require("./EtherDividendCheckpoint.sol"); const ERC20DividendCheckpointFactory = artifacts.require("./ERC20DividendCheckpointFactory.sol"); const EtherDividendCheckpointFactory = artifacts.require("./EtherDividendCheckpointFactory.sol"); const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); @@ -19,6 +21,7 @@ const USDTieredSTOProxyFactory = artifacts.require("./USDTieredSTOProxyFactory") const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); const FeatureRegistry = artifacts.require("./FeatureRegistry.sol"); const STFactory = artifacts.require("./STFactory.sol"); +const GeneralTransferManager = artifacts.require("./GeneralTransferManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); @@ -43,10 +46,13 @@ let I_MockWrongTypeBurnFactory; let I_ManualApprovalTransferManagerFactory; let I_VolumeRestrictionTransferManagerFactory; let I_PercentageTransferManagerFactory; +let I_EtherDividendCheckpointLogic; let I_EtherDividendCheckpointFactory; let I_CountTransferManagerFactory; +let I_ERC20DividendCheckpointLogic; let I_ERC20DividendCheckpointFactory; let I_GeneralPermissionManagerFactory; +let I_GeneralTransferManagerLogic; let I_GeneralTransferManagerFactory; let I_GeneralTransferManager; let I_ModuleRegistryProxy; @@ -80,7 +86,9 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { let b = await deployFeatureRegistry(account_polymath); // STEP 3: Deploy the ModuleRegistry let c = await deployModuleRegistry(account_polymath); - // STEP 4: Deploy the GeneralTransferManagerFactory + // STEP 4a: Deploy the GeneralTransferManagerFactory + let logic = await deployGTMLogic(account_polymath); + // STEP 4b: Deploy the GeneralTransferManagerFactory let d = await deployGTM(account_polymath); // Step 6: Deploy the STversionProxy contract let e = await deploySTFactory(account_polymath); @@ -125,8 +133,20 @@ async function deployModuleRegistry(account_polymath) { return new Array(I_ModuleRegistry, I_ModuleRegistryProxy, I_MRProxied); } +async function deployGTMLogic(account_polymath) { + I_GeneralTransferManagerLogic = await GeneralTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + + assert.notEqual( + I_GeneralTransferManagerLogic.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerLogic contract was not deployed" + ); + + return new Array(I_GeneralTransferManagerLogic); +} + async function deployGTM(account_polymath) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); assert.notEqual( I_GeneralTransferManagerFactory.address.valueOf(), @@ -191,7 +211,7 @@ async function registerAndVerifyByMR(factoryAdrress, owner, mr) { /// Deploy the TransferManagers export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(polyToken, setupCost, 0, 0, I_GeneralTransferManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), @@ -341,7 +361,8 @@ export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInst /// Deploy the Dividend Modules export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_ERC20DividendCheckpointLogic = await ERC20DividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(polyToken, setupCost, 0, 0, I_ERC20DividendCheckpointLogic.address, { from: accountPolymath }); assert.notEqual( I_ERC20DividendCheckpointFactory.address.valueOf(), @@ -353,7 +374,8 @@ export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyIns } export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_EtherDividendCheckpointLogic = await EtherDividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(polyToken, setupCost, 0, 0, I_EtherDividendCheckpointLogic.address, { from: accountPolymath }); assert.notEqual( I_EtherDividendCheckpointFactory.address.valueOf(), diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 5779a1c13..dae21b9c1 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -541,7 +541,7 @@ contract("ManualApprovalTransferManager", accounts => { "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.", "Wrong Module added" ); - assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.0.1"); + assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.1.0"); }); it("Should get the tags of the factory", async () => { diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index b15ee41a0..e122bdea2 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -120,7 +120,7 @@ contract("PercentageTransferManager", accounts => { // STEP 4(b): Deploy the PercentageTransferManager [P_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); - + // Printing all the contract addresses console.log(` --------------------- Polymath Network Smart Contracts: --------------------- diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 604eb1aaf..1bec3697f 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -222,7 +222,7 @@ contract("USDTieredSTO", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 4: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, I_PolyToken.address, 0); @@ -4482,7 +4482,7 @@ contract("USDTieredSTO", accounts => { "fundsRaisedUSD not changed as expected" ); }); - + it("should return minted tokens in a tier", async () => { let totalMinted = (await I_USDTieredSTO_Array[0].getTokensSoldByTier.call(0)).toNumber(); let individualMinted = await I_USDTieredSTO_Array[0].getTokensMintedByTier.call(0); @@ -4564,7 +4564,7 @@ contract("USDTieredSTO", accounts => { assert.equal((await I_USDTieredSTOFactory.getSetupCost.call()).toNumber(), STOSetupCost); assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0], 3); assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), "USDTieredSTO", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.description.call(), + assert.equal(await I_USDTieredSTOFactory.description.call(), "It allows both accredited and non-accredited investors to contribute into the STO. Non-accredited investors will be capped at a maximum investment limit (as a default or specific to their jurisdiction). Tokens will be sold according to tiers sequentially & each tier has its own price and volume of tokens to sell. Upon receipt of funds (ETH, POLY or DAI), security tokens will automatically transfer to investor’s wallet address", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.title.call(), "USD Tiered STO", "Wrong Module added"); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 55f84f2b3..b287cb201 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -195,7 +195,7 @@ contract("USDTieredSTO Sim", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 5: Deploy the USDTieredSTOFactory diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index cfe2767af..3274e7fb8 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -2,7 +2,7 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import { takeSnapshot, increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; -import { +import { setUpPolymathNetwork, deployDummySTOAndVerifyed, deployCappedSTOAndVerifyed, @@ -94,7 +94,7 @@ contract("Concurrent STO", accounts => { I_SecurityTokenRegistryProxy, I_STRProxied ] = instances; - + // STEP 2: Deploy the STO Factories [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, STOSetupCost); diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 6d00b8fe2..877d173d4 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -9,6 +9,7 @@ const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); const ModuleRegistry = artifacts.require("./ModuleRegistry.sol"); const STFactory = artifacts.require("./STFactory.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); +const GeneralTransferManagerLogic = artifacts.require("./GeneralTransferManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); @@ -122,7 +123,9 @@ contract("ModuleRegistryProxy", accounts => { await I_MRProxied.updateFromRegistry({ from: account_polymath }); // STEP 4: Deploy the GeneralTransferManagerFactory - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { + let I_GeneralTransferManagerLogic = await GeneralTransferManagerLogic.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 159564651..2d5ae8c6c 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -102,7 +102,7 @@ contract("TrackedRedemption", accounts => { I_STRProxied ] = instances; - + // STEP 4: Deploy the TrackedRedemption [I_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); [P_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index fe06f3f5c..358e5b702 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -112,7 +112,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { STFactory: ${I_STFactory.address} GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} - LockupVolumeRestrictionTransferManagerFactory: + LockupVolumeRestrictionTransferManagerFactory: ${I_VolumeRestrictionTransferManagerFactory.address} ----------------------------------------------------------------------------- `); @@ -346,14 +346,14 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // balance should be 9000000000000000000 here (9 eth) let balance = await I_SecurityToken.balanceOf(account_investor2) - + // create a lockup for their entire balance // over 16 seconds total, with 4 periods of 4 seconds each. // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 await catchRevert( I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }) ); - + }); it("Should prevent the transfer of tokens in a lockup", async() => { @@ -572,7 +572,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); it("Should revert if the parameters are bad when creating multiple lockups", async() => { - + await catchRevert( // pass in the wrong number of params. txn should revert I_VolumeRestrictionTransferManager.addLockUpMulti( diff --git a/yarn.lock b/yarn.lock index 27308427c..31973936e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,12 +5,10 @@ "@soldoc/markdown@^0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@soldoc/markdown/-/markdown-0.1.0.tgz#9f85be75049af9721b5129f133d52dafbf5f671e" - integrity sha512-V0UnvVVJ1qDzpuKLMuh7oHG94puwi8BI3t99Vrr7dQgIHuJdfZJ4SbGuWuFV/fSthyH++WY4ePO3d6gxfZ2//w== "@soldoc/soldoc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@soldoc/soldoc/-/soldoc-0.4.3.tgz#24ffee9264228e1c3edd61fd3162d63587954933" - integrity sha1-JP/ukmQijhw+3WH9MWLWNYeVSTM= dependencies: "@soldoc/markdown" "^0.1.0" chalk "^2.3.1" @@ -24,31 +22,26 @@ abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= abstract-leveldown@~2.6.0: version "2.6.3" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== dependencies: xtend "~4.0.0" abstract-leveldown@~2.7.1: version "2.7.2" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== dependencies: xtend "~4.0.0" accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= dependencies: mime-types "~2.1.18" negotiator "0.6.1" @@ -56,56 +49,46 @@ accepts@~1.3.5: acorn-dynamic-import@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" - integrity sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ= dependencies: acorn "^4.0.3" acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= dependencies: acorn "^3.0.4" acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= acorn@^5.0.0, acorn@^5.5.0: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= aes-js@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072" - integrity sha512-cEA0gBelItZZV7iBiL8ApCiNgc+gBWJJ4uoORhbu6vOqAJ0UL9wIlxr4RI7ij9SSVzy6AnPwiu37kVYiHCl3nw== ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" - integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= ajv@^5.1.1, ajv@^5.2.2, ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" @@ -115,7 +98,6 @@ ajv@^5.1.1, ajv@^5.2.2, ajv@^5.2.3, ajv@^5.3.0: ajv@^6.1.0: version "6.5.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59" - integrity sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -125,7 +107,6 @@ ajv@^6.1.0: align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= dependencies: kind-of "^3.0.2" longest "^1.0.1" @@ -134,7 +115,6 @@ align-text@^0.1.1, align-text@^0.1.3: ambi@^2.2.0: version "2.5.0" resolved "https://registry.yarnpkg.com/ambi/-/ambi-2.5.0.tgz#7c8e372be48891157e7cea01cb6f9143d1f74220" - integrity sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA= dependencies: editions "^1.1.1" typechecker "^4.3.0" @@ -142,44 +122,36 @@ ambi@^2.2.0: amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= ansi-escapes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" - integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== dependencies: micromatch "^2.1.5" normalize-path "^2.0.0" @@ -187,7 +159,6 @@ anymatch@^1.3.0: anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" normalize-path "^2.1.1" @@ -195,12 +166,10 @@ anymatch@^2.0.0: aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -208,85 +177,56 @@ are-we-there-yet@~1.1.2: argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -arguments-extended@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/arguments-extended/-/arguments-extended-0.0.3.tgz#6107e4917d0eb6f0a4dd66320fc15afc72ef4946" - integrity sha1-YQfkkX0OtvCk3WYyD8Fa/HLvSUY= - dependencies: - extended "~0.0.3" - is-extended "~0.0.8" - arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= dependencies: arr-flatten "^1.0.1" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-extended@~0.0.3, array-extended@~0.0.4, array-extended@~0.0.5: - version "0.0.11" - resolved "https://registry.yarnpkg.com/array-extended/-/array-extended-0.0.11.tgz#d7144ae748de93ca726f121009dbff1626d164bd" - integrity sha1-1xRK50jek8pybxIQCdv/FibRZL0= - dependencies: - arguments-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= dependencies: array-uniq "^1.0.1" array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -295,36 +235,30 @@ asn1.js@^4.0.0: asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assert@^1.1.1: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= dependencies: util "0.10.3" assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-eventemitter@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== dependencies: async "^2.4.0" @@ -337,49 +271,44 @@ async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== async@1.x, async@^1.4.2, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.4.1, async@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== dependencies: lodash "^4.17.10" +async@~0.9.0: + version "0.9.2" + resolved "http://registry.npmjs.org/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + async@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" - integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -388,7 +317,6 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: babel-core@^6.0.14, babel-core@^6.26.0: version "6.26.3" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== dependencies: babel-code-frame "^6.26.0" babel-generator "^6.26.0" @@ -413,7 +341,6 @@ babel-core@^6.0.14, babel-core@^6.26.0: babel-generator@^6.26.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" @@ -427,7 +354,6 @@ babel-generator@^6.26.0: babel-helper-bindify-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" - integrity sha1-FMGeXxQte0fxmlJDHlKxzLxAozA= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -436,7 +362,6 @@ babel-helper-bindify-decorators@^6.24.1: babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= dependencies: babel-helper-explode-assignable-expression "^6.24.1" babel-runtime "^6.22.0" @@ -445,7 +370,6 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -455,7 +379,6 @@ babel-helper-call-delegate@^6.24.1: babel-helper-define-map@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.26.0" @@ -465,7 +388,6 @@ babel-helper-define-map@^6.24.1: babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -474,7 +396,6 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-helper-explode-class@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" - integrity sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes= dependencies: babel-helper-bindify-decorators "^6.24.1" babel-runtime "^6.22.0" @@ -484,7 +405,6 @@ babel-helper-explode-class@^6.24.1: babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= dependencies: babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" @@ -495,7 +415,6 @@ babel-helper-function-name@^6.24.1: babel-helper-get-function-arity@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -503,7 +422,6 @@ babel-helper-get-function-arity@^6.24.1: babel-helper-hoist-variables@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -511,7 +429,6 @@ babel-helper-hoist-variables@^6.24.1: babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -519,7 +436,6 @@ babel-helper-optimise-call-expression@^6.24.1: babel-helper-regex@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= dependencies: babel-runtime "^6.26.0" babel-types "^6.26.0" @@ -528,7 +444,6 @@ babel-helper-regex@^6.24.1: babel-helper-remap-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -539,7 +454,6 @@ babel-helper-remap-async-to-generator@^6.24.1: babel-helper-replace-supers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= dependencies: babel-helper-optimise-call-expression "^6.24.1" babel-messages "^6.23.0" @@ -551,7 +465,6 @@ babel-helper-replace-supers@^6.24.1: babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -559,61 +472,50 @@ babel-helpers@^6.24.1: babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= dependencies: babel-runtime "^6.22.0" babel-plugin-check-es2015-constants@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= dependencies: babel-runtime "^6.22.0" babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= babel-plugin-syntax-async-generators@^6.5.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - integrity sha1-a8lj67FuzLrmuStZbrfzXDQqi5o= babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= babel-plugin-syntax-decorators@^6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" - integrity sha1-MSVjtNvePMgGzuPkFszurd0RrAs= babel-plugin-syntax-dynamic-import@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" - integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= babel-plugin-transform-async-generator-functions@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" - integrity sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-generators "^6.5.0" @@ -622,7 +524,6 @@ babel-plugin-transform-async-generator-functions@^6.24.1: babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-functions "^6.8.0" @@ -631,7 +532,6 @@ babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async- babel-plugin-transform-class-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= dependencies: babel-helper-function-name "^6.24.1" babel-plugin-syntax-class-properties "^6.8.0" @@ -641,7 +541,6 @@ babel-plugin-transform-class-properties@^6.24.1: babel-plugin-transform-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" - integrity sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0= dependencies: babel-helper-explode-class "^6.24.1" babel-plugin-syntax-decorators "^6.13.0" @@ -652,21 +551,18 @@ babel-plugin-transform-decorators@^6.24.1: babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= dependencies: babel-runtime "^6.26.0" babel-template "^6.26.0" @@ -677,7 +573,6 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= dependencies: babel-helper-define-map "^6.24.1" babel-helper-function-name "^6.24.1" @@ -692,7 +587,6 @@ babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-cla babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -700,14 +594,12 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transfor babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -715,14 +607,12 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2 babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -731,14 +621,12 @@ babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= dependencies: babel-plugin-transform-es2015-modules-commonjs "^6.24.1" babel-runtime "^6.22.0" @@ -747,7 +635,6 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.26.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== dependencies: babel-plugin-transform-strict-mode "^6.24.1" babel-runtime "^6.26.0" @@ -757,7 +644,6 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -766,7 +652,6 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= dependencies: babel-plugin-transform-es2015-modules-amd "^6.24.1" babel-runtime "^6.22.0" @@ -775,7 +660,6 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= dependencies: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" @@ -783,7 +667,6 @@ babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= dependencies: babel-helper-call-delegate "^6.24.1" babel-helper-get-function-arity "^6.24.1" @@ -795,7 +678,6 @@ babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015- babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -803,14 +685,12 @@ babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transfo babel-plugin-transform-es2015-spread@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -819,21 +699,18 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -842,7 +719,6 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= dependencies: babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" babel-plugin-syntax-exponentiation-operator "^6.8.0" @@ -851,7 +727,6 @@ babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-e babel-plugin-transform-object-rest-spread@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" @@ -859,14 +734,12 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= dependencies: regenerator-transform "^0.10.0" babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -874,7 +747,6 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-polyfill@6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= dependencies: babel-runtime "^6.26.0" core-js "^2.5.0" @@ -883,7 +755,6 @@ babel-polyfill@6.26.0: babel-preset-env@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -919,7 +790,6 @@ babel-preset-env@^1.7.0: babel-preset-es2015@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - integrity sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk= dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-transform-es2015-arrow-functions "^6.22.0" @@ -949,7 +819,6 @@ babel-preset-es2015@6.24.1: babel-preset-stage-2@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" - integrity sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE= dependencies: babel-plugin-syntax-dynamic-import "^6.18.0" babel-plugin-transform-class-properties "^6.24.1" @@ -959,7 +828,6 @@ babel-preset-stage-2@6.24.1: babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" - integrity sha1-g2raCp56f6N8sTj7kyb4eTSkg5U= dependencies: babel-plugin-syntax-trailing-function-commas "^6.22.0" babel-plugin-transform-async-generator-functions "^6.24.1" @@ -970,7 +838,6 @@ babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: babel-register@6.26.0, babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= dependencies: babel-core "^6.26.0" babel-runtime "^6.26.0" @@ -983,7 +850,6 @@ babel-register@6.26.0, babel-register@^6.26.0: babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" @@ -991,7 +857,6 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= dependencies: babel-runtime "^6.26.0" babel-traverse "^6.26.0" @@ -1002,7 +867,6 @@ babel-template@^6.24.1, babel-template@^6.26.0: babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= dependencies: babel-code-frame "^6.26.0" babel-messages "^6.23.0" @@ -1017,7 +881,6 @@ babel-traverse@^6.24.1, babel-traverse@^6.26.0: babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= dependencies: babel-runtime "^6.26.0" esutils "^2.0.2" @@ -1027,7 +890,6 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: babelify@^7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= dependencies: babel-core "^6.0.14" object-assign "^4.0.0" @@ -1035,34 +897,28 @@ babelify@^7.3.0: babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base-x@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" - integrity sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA== dependencies: safe-buffer "^5.0.1" base64-js@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" - integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg= base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -1075,29 +931,24 @@ base@^0.11.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== bignumber.js@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" - integrity sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA== bignumber.js@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" - integrity sha512-KWTu6ZMVk9sxlDJQh2YH1UOnfDP8O8TpxUxgQG/vKASoSnEjK9aVuOueFaPcQEYQ5fyNXNTOYwYw3099RYebWg== bignumber.js@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-6.0.0.tgz#bbfa047644609a5af093e9cbd83b0461fa3f6002" - integrity sha512-x247jIuy60/+FtMRvscqfxtVHQf8AGx2hm9c6btkgC0x/hp9yt+teISNhvF8WlwRkCc5yF2fDECH8SIMe8j+GA== "bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" @@ -1114,24 +965,20 @@ bignumber.js@^6.0.0: binary-extensions@^1.0.0: version "1.12.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" - integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== bindings@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" - integrity sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw== bip66@^1.1.3: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" - integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= dependencies: safe-buffer "^5.0.1" bitcore-lib@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.15.0.tgz#f924be13869f2aab7e04aeec5642ad3359b6cec2" - integrity sha512-AeXLWhiivF6CDFzrABZHT4jJrflyylDWTi32o30rF92HW9msfuKpjzrHtFKYGa9w0kNVv5HABQjCB3OEav4PhQ== dependencies: bn.js "=4.11.8" bs58 "=4.0.1" @@ -1143,7 +990,6 @@ bitcore-lib@^0.15.0: bitcore-mnemonic@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-1.5.0.tgz#c7e785beb6bf0616ed4992785dc3658670425a39" - integrity sha512-sbeP4xwkindLMfIQhVxj6rZSDMwtiKmfc1DqvwpR6Yg+Qo4I4WHO5pvzb12Y04uDh1N3zgD45esHhfH0HHmE4g== dependencies: bitcore-lib "^0.15.0" unorm "^1.3.3" @@ -1151,7 +997,6 @@ bitcore-mnemonic@^1.5.0: bl@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== dependencies: readable-stream "^2.3.5" safe-buffer "^5.1.1" @@ -1159,39 +1004,32 @@ bl@^1.0.0: block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= dependencies: inherits "~2.0.0" bluebird@^2.9.34: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= bluebird@^3.4.6, bluebird@^3.5.0: version "3.5.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" - integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg== bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= bn.js@=4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== bn.js@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625" - integrity sha1-EhYrwq5x/EClYmwzQ486h1zTdiU= body-parser@1.18.3, body-parser@^1.16.0: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" - integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= dependencies: bytes "3.0.0" content-type "~1.0.4" @@ -1207,7 +1045,6 @@ body-parser@1.18.3, body-parser@^1.16.0: borc@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/borc/-/borc-2.0.3.tgz#08845ea73a6d3211120928ee3929f8dc2de9f52e" - integrity sha512-2mfipKUXn7yLgwn8D5jZkJqd2ZyzqmYZQX/9d4On33oGNDLwxj5qQMst+nkKyEdaujQRFfrZCId+k8wehQVANg== dependencies: bignumber.js "^6.0.0" commander "^2.15.0" @@ -1217,7 +1054,6 @@ borc@^2.0.2: brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1225,7 +1061,6 @@ brace-expansion@^1.1.7: braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= dependencies: expand-range "^1.8.1" preserve "^0.2.0" @@ -1234,7 +1069,6 @@ braces@^1.8.2: braces@^2.3.0, braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -1250,22 +1084,18 @@ braces@^2.3.0, braces@^2.3.1: brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1277,7 +1107,6 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: browserify-cipher@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -1286,7 +1115,6 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -1296,7 +1124,6 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= dependencies: bn.js "^4.1.0" randombytes "^2.0.1" @@ -1304,14 +1131,12 @@ browserify-rsa@^4.0.0: browserify-sha3@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" - integrity sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE= dependencies: js-sha3 "^0.3.1" browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= dependencies: bn.js "^4.1.1" browserify-rsa "^4.0.0" @@ -1324,14 +1149,12 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" browserslist@^3.2.6: version "3.2.8" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== dependencies: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" @@ -1339,19 +1162,16 @@ browserslist@^3.2.6: bs58@=4.0.1, bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= dependencies: base-x "^3.0.2" bs58@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" - integrity sha1-VZCNWPGYKrogCPob7Y+RmYopv40= bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== dependencies: bs58 "^4.0.0" create-hash "^1.1.0" @@ -1360,17 +1180,14 @@ bs58check@^2.1.2: bson@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.0.tgz#bee57d1fb6a87713471af4e32bcae36de814b5b0" - integrity sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA== buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== buffer-alloc@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== dependencies: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" @@ -1378,37 +1195,30 @@ buffer-alloc@^1.2.0: buffer-compare@=1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.1.1.tgz#5be7be853af89198d1f4ddc090d1d66a48aef596" - integrity sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY= buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-to-arraybuffer@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^3.0.1: version "3.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" - integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs= dependencies: base64-js "0.0.8" ieee754 "^1.1.4" @@ -1417,7 +1227,6 @@ buffer@^3.0.1: buffer@^4.3.0, buffer@^4.9.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1426,7 +1235,6 @@ buffer@^4.3.0, buffer@^4.9.0: buffer@^5.0.5: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" - integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1434,22 +1242,18 @@ buffer@^5.0.5: builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -1464,34 +1268,28 @@ cache-base@^1.0.1: caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= dependencies: callsites "^0.2.0" callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= caminte@0.3.7: version "0.3.7" resolved "https://registry.yarnpkg.com/caminte/-/caminte-0.3.7.tgz#ec1ec0457664a0f092643b7c646c457d5cd6f693" - integrity sha1-7B7ARXZkoPCSZDt8ZGxFfVzW9pM= dependencies: bluebird "^3.4.6" uuid "^3.0.1" @@ -1499,17 +1297,14 @@ caminte@0.3.7: caniuse-lite@^1.0.30000844: version "1.0.30000890" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000890.tgz#86a18ffcc65d79ec6a437e985761b8bf1c4efeaf" - integrity sha512-4NI3s4Y6ROm+SgZN5sLUG4k7nVWQnedis3c/RWkynV5G6cHSY7+a8fwFyn2yoBDE3E6VswhTNNwR3PvzGqlTkg== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= center-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= dependencies: align-text "^0.1.3" lazy-cache "^1.0.3" @@ -1517,7 +1312,6 @@ center-align@^0.1.1: chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -1528,7 +1322,6 @@ chalk@^1.1.3: chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1537,19 +1330,16 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= checkpoint-store@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= dependencies: functional-red-black-tree "^1.0.1" chokidar@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= dependencies: anymatch "^1.3.0" async-each "^1.0.0" @@ -1565,7 +1355,6 @@ chokidar@^1.6.0: chokidar@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" - integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== dependencies: anymatch "^2.0.0" async-each "^1.0.0" @@ -1585,12 +1374,10 @@ chokidar@^2.0.2: chownr@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -1598,12 +1385,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" @@ -1613,7 +1398,6 @@ class-utils@^0.3.5: cli-color@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.3.0.tgz#cd2ec212efbd1a0eeb5b017f17d4e2d15e91420f" - integrity sha512-XmbLr8MzgOup/sPHF4nOZerCOcL7rD7vKWpEl0axUsMAY+AEimOhYva1ksskWqkLGY/bjR9h7Cfbr+RrJRfmTQ== dependencies: ansi-regex "^2.1.1" d "1" @@ -1625,19 +1409,16 @@ cli-color@^1.2.0: cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= dependencies: center-align "^0.1.1" right-align "^0.1.1" @@ -1646,7 +1427,6 @@ cliui@^2.1.0: cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -1655,7 +1435,6 @@ cliui@^3.2.0: cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" @@ -1664,22 +1443,18 @@ cliui@^4.0.0: clone@2.x, clone@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= coinstring@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - integrity sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q= dependencies: bs58 "^2.0.1" create-hash "^1.1.1" @@ -1687,7 +1462,6 @@ coinstring@^2.0.0: collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -1695,85 +1469,70 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= colors@^1.1.2: version "1.3.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" - integrity sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ== combined-stream@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= dependencies: delayed-stream "~1.0.0" combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" - integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== dependencies: delayed-stream "~1.0.0" commander@2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== commander@2.15.1: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== commander@^2.11.0, commander@^2.14.1, commander@^2.15.0, commander@^2.8.1, commander@^2.9.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== commander@~2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= dependencies: graceful-readlink ">= 1.0.0" compare-versions@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" - integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg== component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" @@ -1783,76 +1542,62 @@ concat-stream@^1.6.0: console-browserify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= dependencies: date-now "^0.1.4" console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== dependencies: safe-buffer "~5.1.1" cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= cookiejar@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0, core-js@^2.5.0: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cors@^2.8.1: version "2.8.4" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" - integrity sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY= dependencies: object-assign "^4" vary "^1" @@ -1860,7 +1605,6 @@ cors@^2.8.1: coveralls@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" - integrity sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw== dependencies: growl "~> 1.10.0" js-yaml "^3.11.0" @@ -1872,7 +1616,6 @@ coveralls@^3.0.1: create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== dependencies: bn.js "^4.1.0" elliptic "^6.0.0" @@ -1880,7 +1623,6 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -1891,7 +1633,6 @@ create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -1903,7 +1644,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: cron-parser@^2.4.0: version "2.6.0" resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.6.0.tgz#ae2514ceda9ccb540256e201bdd23ae814e03674" - integrity sha512-KGfDDTjBIx85MnVYcdhLccoJH/7jcYW+5Z/t3Wsg2QlJhmmjf+97z+9sQftS71lopOYYapjEKEvmWaCsym5Z4g== dependencies: is-nan "^1.2.1" moment-timezone "^0.5.0" @@ -1911,7 +1651,6 @@ cron-parser@^2.4.0: cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" @@ -1920,7 +1659,6 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: crypto-browserify@3.12.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -1937,115 +1675,84 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0: crypto-js@^3.1.4, crypto-js@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" - integrity sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU= crypto-js@^3.1.9-1: version "3.1.9-1" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8" - integrity sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg= crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= csextends@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/csextends/-/csextends-1.2.0.tgz#6374b210984b54d4495f29c99d3dd069b80543e5" - integrity sha512-S/8k1bDTJIwuGgQYmsRoE+8P+ohV32WhQ0l4zqrc0XDdxOhjQQD7/wTZwCzoZX53jSX3V/qwjT+OkPTxWQcmjg== cycle@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= dependencies: es5-ext "^0.10.9" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" -date-extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/date-extended/-/date-extended-0.0.6.tgz#23802d57dd1bf7818813fe0c32e851a86da267c9" - integrity sha1-I4AtV90b94GIE/4MMuhRqG2iZ8k= - dependencies: - array-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" - date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= death@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" - integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= debug@*: version "4.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" - integrity sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg== dependencies: ms "^2.1.1" debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" debug@^3.0.1, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -declare.js@~0.0.4: - version "0.0.8" - resolved "https://registry.yarnpkg.com/declare.js/-/declare.js-0.0.8.tgz#0478adff9564c004f51df73d8bc134019d28dcde" - integrity sha1-BHit/5VkwAT1Hfc9i8E0AZ0o3N4= decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: mimic-response "^1.0.0" decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== dependencies: file-type "^5.2.0" is-stream "^1.1.0" @@ -2054,7 +1761,6 @@ decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: decompress-tarbz2@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== dependencies: decompress-tar "^4.1.0" file-type "^6.1.0" @@ -2065,7 +1771,6 @@ decompress-tarbz2@^4.0.0: decompress-targz@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== dependencies: decompress-tar "^4.1.1" file-type "^5.2.0" @@ -2074,7 +1779,6 @@ decompress-targz@^4.0.0: decompress-unzip@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= dependencies: file-type "^3.8.0" get-stream "^2.2.0" @@ -2084,7 +1788,6 @@ decompress-unzip@^4.0.1: decompress@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= dependencies: decompress-tar "^4.0.0" decompress-tarbz2 "^4.0.0" @@ -2098,57 +1801,52 @@ decompress@^4.0.0: deep-assign@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-2.0.0.tgz#ebe06b1f07f08dae597620e3dd1622f371a1c572" - integrity sha1-6+BrHwfwja5ZdiDj3RYi83GhxXI= dependencies: is-obj "^1.0.0" +deep-equal@~0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" + deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= deferred-leveldown@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== dependencies: abstract-leveldown "~2.6.0" define-properties@^1.1.1, define-properties@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" @@ -2156,12 +1854,10 @@ define-property@^2.0.2: defined@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag= dependencies: globby "^5.0.0" is-path-cwd "^1.0.0" @@ -2174,27 +1870,22 @@ del@^2.0.2: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= delimit-stream@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" - integrity sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs= depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -2202,34 +1893,28 @@ des.js@^1.0.0: destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= dependencies: repeating "^2.0.0" detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= diff@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" @@ -2238,7 +1923,6 @@ diffie-hellman@^5.0.0: doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= dependencies: esutils "^2.0.2" isarray "^1.0.0" @@ -2246,24 +1930,20 @@ doctrine@1.5.0: doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== drbg.js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= dependencies: browserify-aes "^1.0.6" create-hash "^1.1.2" @@ -2272,19 +1952,16 @@ drbg.js@^1.0.1: duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= eachr@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/eachr/-/eachr-2.0.4.tgz#466f7caa10708f610509e32c807aafe57fc122bf" - integrity sha1-Rm98qhBwj2EFCeMsgHqv5X/BIr8= dependencies: typechecker "^2.0.8" ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" @@ -2292,12 +1969,10 @@ ecc-jsbn@~0.1.1: editions@^1.1.1, editions@^1.3.3, editions@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" - integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== editions@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/editions/-/editions-2.0.2.tgz#54fdac6fb24b0a1a72ffc1ba0126c10602c3e0bd" - integrity sha512-0B8aSTWUu9+JW99zHoeogavCi+lkE5l35FK0OKe0pCobixJYoeof3ZujtqYzSsU2MskhRadY5V9oWUuyG4aJ3A== dependencies: errlop "^1.0.2" semver "^5.5.0" @@ -2305,17 +1980,14 @@ editions@^2.0.2: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.47: version "1.3.78" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.78.tgz#ecb72b5b166ba6598efb384461d63cad74678ebf" - integrity sha512-p4D/5iX08c3LNep5bWn/X3dFmec1K9le6O43lgRsO/vYKBTH2smWDMDfkGlPtERFcLVkI8xdKW5EokBZODh1xg== elliptic@6.3.3: version "6.3.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2325,7 +1997,6 @@ elliptic@6.3.3: elliptic@=6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" - integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2338,7 +2009,6 @@ elliptic@=6.4.0: elliptic@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-3.1.0.tgz#c21682ef762769b56a74201609105da11d5f60cc" - integrity sha1-whaC73YnabVqdCAWCRBdoR1fYMw= dependencies: bn.js "^2.0.3" brorand "^1.0.1" @@ -2348,7 +2018,6 @@ elliptic@^3.1.0: elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: version "6.4.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2361,31 +2030,26 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= dependencies: iconv-lite "~0.4.13" end-of-stream@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: once "^1.4.0" enhanced-resolve@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" - integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24= dependencies: graceful-fs "^4.1.2" memory-fs "^0.4.0" @@ -2395,33 +2059,28 @@ enhanced-resolve@^3.4.0: eol@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" - integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== errlop@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/errlop/-/errlop-1.0.3.tgz#dba29c90cf832c3d2ce469fe515d7e5eef2c6676" - integrity sha512-5VTnt0yikY4LlQEfCXVSqfE6oLj1HVM4zVSvAKMnoYjL/zrb6nqiLowZS4XlG7xENfyj7lpYWvT+wfSCr6dtlA== dependencies: editions "^1.3.4" errno@^0.1.3, errno@~0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== dependencies: prr "~1.0.1" error-ex@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" es-abstract@^1.5.0: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" @@ -2432,7 +2091,6 @@ es-abstract@^1.5.0: es-to-primitive@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -2441,7 +2099,6 @@ es-to-primitive@^1.1.1: es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: version "0.10.46" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572" - integrity sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw== dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" @@ -2450,7 +2107,6 @@ es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= dependencies: d "1" es5-ext "^0.10.35" @@ -2459,7 +2115,6 @@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0 es6-map@^0.1.3: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= dependencies: d "1" es5-ext "~0.10.14" @@ -2471,7 +2126,6 @@ es6-map@^0.1.3: es6-set@~0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= dependencies: d "1" es5-ext "~0.10.14" @@ -2482,7 +2136,6 @@ es6-set@~0.1.5: es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= dependencies: d "1" es5-ext "~0.10.14" @@ -2490,7 +2143,6 @@ es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8= dependencies: d "1" es5-ext "^0.10.14" @@ -2500,17 +2152,14 @@ es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= dependencies: esprima "^2.7.1" estraverse "^1.9.1" @@ -2522,7 +2171,6 @@ escodegen@1.8.x: escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= dependencies: es6-map "^0.1.3" es6-weak-map "^2.0.1" @@ -2532,12 +2180,10 @@ escope@^3.6.0: eslint-config-standard@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz#87ee0d3c9d95382dc761958cbb23da9eea31e0ba" - integrity sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw== eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" - integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== dependencies: debug "^2.6.9" resolve "^1.5.0" @@ -2545,7 +2191,6 @@ eslint-import-resolver-node@^0.3.1: eslint-module-utils@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" - integrity sha1-snA2LNiLGkitMIl2zn+lTphBF0Y= dependencies: debug "^2.6.8" pkg-dir "^1.0.0" @@ -2553,7 +2198,6 @@ eslint-module-utils@^2.2.0: eslint-plugin-import@^2.10.0: version "2.14.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" - integrity sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g== dependencies: contains-path "^0.1.0" debug "^2.6.8" @@ -2569,7 +2213,6 @@ eslint-plugin-import@^2.10.0: eslint-plugin-node@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz#bf19642298064379315d7a4b2a75937376fa05e4" - integrity sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw== dependencies: ignore "^3.3.6" minimatch "^3.0.4" @@ -2579,17 +2222,14 @@ eslint-plugin-node@^6.0.1: eslint-plugin-promise@^3.7.0: version "3.8.0" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" - integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ== eslint-plugin-standard@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz#2a9e21259ba4c47c02d53b2d0c9135d4b1022d47" - integrity sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w== eslint-scope@^3.7.1: version "3.7.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" - integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2597,12 +2237,10 @@ eslint-scope@^3.7.1: eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== eslint@^4.19.1: version "4.19.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" - integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" @@ -2646,7 +2284,6 @@ eslint@^4.19.1: espree@^3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== dependencies: acorn "^5.5.0" acorn-jsx "^3.0.0" @@ -2654,51 +2291,42 @@ espree@^3.5.4: esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== dependencies: estraverse "^4.1.0" estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eth-block-tracker@^2.2.2: version "2.3.1" resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz#ab6d177e5b50128fa06d7ae9e0489c7484bac95e" - integrity sha512-NamWuMBIl8kmkJFVj8WzGatySTzQPQag4Xr677yFxdVtIxACFbL/dQowk0MzEqIKk93U1TwY3MjVU6mOcwZnKA== dependencies: async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c eth-query "^2.1.0" @@ -2712,7 +2340,6 @@ eth-block-tracker@^2.2.2: eth-lib@0.1.27, eth-lib@^0.1.26: version "0.1.27" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" - integrity sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA== dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2725,7 +2352,6 @@ eth-lib@0.1.27, eth-lib@^0.1.26: eth-lib@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" - integrity sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco= dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2734,7 +2360,6 @@ eth-lib@0.2.7: eth-lightwallet@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eth-lightwallet/-/eth-lightwallet-3.0.1.tgz#297022932aa568f4e4eb0873bff257f5e5b78709" - integrity sha512-79vVCETy+4l1b6wuOWwjqPW3Bom5ZK46BgkUNwaXhiMG1rrMRHjpjYEWMqH0JHeCzOzB4HBIFz7eK1/4s6w5nA== dependencies: bitcore-lib "^0.15.0" bitcore-mnemonic "^1.5.0" @@ -2751,7 +2376,6 @@ eth-lightwallet@^3.0.1: eth-query@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= dependencies: json-rpc-random-id "^1.0.0" xtend "^4.0.1" @@ -2759,7 +2383,6 @@ eth-query@^2.1.0: eth-sig-util@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= dependencies: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" @@ -2767,7 +2390,6 @@ eth-sig-util@^1.4.2: ethereum-bridge@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/ethereum-bridge/-/ethereum-bridge-0.6.1.tgz#53c93ed7c0e21752a91e5f089a5997e1d6fea228" - integrity sha512-yDTivI85618BoLI71yNRzW6iVcVN2rjnviCIzs0QOCOENj4XpYQhMDGhdqDi8XWDdzTd0Ja/Canuuh3vfE2IcA== dependencies: async "^2.4.1" borc "^2.0.2" @@ -2798,17 +2420,14 @@ ethereum-bridge@^0.6.1: ethereum-common@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= ethereumjs-abi@0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.4.tgz#9ba1bb056492d00c27279f6eccd4d58275912c1a" - integrity sha1-m6G7BWSS0AwnJ59uzNTVgnWRLBo= dependencies: bn.js "^4.10.0" ethereumjs-util "^4.3.0" @@ -2823,7 +2442,6 @@ ethereumjs-abi@^0.6.5, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereu ethereumjs-account@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== dependencies: ethereumjs-util "^5.0.0" rlp "^2.0.0" @@ -2832,7 +2450,6 @@ ethereumjs-account@^2.0.3: ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: version "1.7.1" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== dependencies: async "^2.0.1" ethereum-common "0.2.0" @@ -2843,26 +2460,22 @@ ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: ethereumjs-common@~0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-0.4.1.tgz#27690a24a817b058cc3a2aedef9392e8d7d63984" - integrity sha512-ywYGsOeGCsMNWso5Y4GhjWI24FJv9FK7+VyVKiQgXg8ZRDPXJ7F/kJ1CnjtkjTvDF4e0yqU+FWswlqR3bmZQ9Q== ethereumjs-testrpc-sc@6.1.6: version "6.1.6" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.6.tgz#290595380b5182814564d4aa38f35b7788aab070" - integrity sha512-iv2qiGBFgk9mn5Nq2enX8dG5WQ7Lk+FCqpnxfPfH4Ns8KLPwttmNOy264nh3SXDJJvcQwz/XnlLteDQVILotbg== dependencies: source-map-support "^0.5.3" ethereumjs-testrpc@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc/-/ethereumjs-testrpc-6.0.3.tgz#7a0b87bf3670f92f607f98fa6a78801d9741b124" - integrity sha512-lAxxsxDKK69Wuwqym2K49VpXtBvLEsXr1sryNG4AkvL5DomMdeCBbu3D87UEevKenLHBiT8GTjARwN6Yj039gA== dependencies: webpack "^3.0.0" ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@^1.3.3: version "1.3.7" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== dependencies: ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" @@ -2870,7 +2483,6 @@ ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@ ethereumjs-util@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" - integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= dependencies: bn.js "^4.8.0" create-hash "^1.1.2" @@ -2881,7 +2493,6 @@ ethereumjs-util@^4.3.0: ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.3, ethereumjs-util@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" - integrity sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA== dependencies: bn.js "^4.11.0" create-hash "^1.1.2" @@ -2894,7 +2505,6 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum ethereumjs-vm@^2.0.2: version "2.4.0" resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.4.0.tgz#244f1e35f2755e537a13546111d1a4c159d34b13" - integrity sha512-MJ4lCWa5c6LhahhhvoDKW+YGjK00ZQn0RHHLh4L+WaH1k6Qv7/q3uTluew6sJGNCZdlO0yYMDXYW9qyxLHKlgQ== dependencies: async "^2.1.2" async-eventemitter "^0.2.2" @@ -2911,7 +2521,6 @@ ethereumjs-vm@^2.0.2: ethereumjs-wallet@^0.6.0: version "0.6.2" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz#67244b6af3e8113b53d709124b25477b64aeccda" - integrity sha512-DHEKPV9lYORM7dL8602dkb+AgdfzCYz2lxpdYQoD3OwG355LLDuivW9rGuLpDMCry/ORyBYV6n+QCo/71SwACg== dependencies: aes-js "^3.1.1" bs58check "^2.1.2" @@ -2925,7 +2534,6 @@ ethereumjs-wallet@^0.6.0: ethers@^3.0.15: version "3.0.29" resolved "https://registry.yarnpkg.com/ethers/-/ethers-3.0.29.tgz#ce8139955b4ed44456eb6764b089bb117c86775d" - integrity sha512-OGyA5pW5xFC5o/ZV5MfIoVp/EdA1QMg2bMJFf7Kznsz8m7IzzbgsPHTCjzSfKQDs/XDphGyRcA7A6bkIeJL4gw== dependencies: aes-js "3.0.0" bn.js "^4.4.0" @@ -2941,7 +2549,6 @@ ethers@^3.0.15: ethjs-abi@0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.1.8.tgz#cd288583ed628cdfadaf8adefa3ba1dbcbca6c18" - integrity sha1-zSiFg+1ijN+tr4re+juh28vKbBg= dependencies: bn.js "4.11.6" js-sha3 "0.5.5" @@ -2950,7 +2557,6 @@ ethjs-abi@0.1.8: ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= dependencies: bn.js "4.11.6" number-to-bn "1.7.0" @@ -2958,7 +2564,6 @@ ethjs-unit@0.1.6: ethjs-util@^0.1.3: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== dependencies: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" @@ -2966,7 +2571,6 @@ ethjs-util@^0.1.3: event-emitter@^0.3.5, event-emitter@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= dependencies: d "1" es5-ext "~0.10.14" @@ -2974,22 +2578,18 @@ event-emitter@^0.3.5, event-emitter@~0.3.5: eventemitter3@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" - integrity sha1-R3hr2qCHyvext15zq8XH1UAVjNA= events@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" @@ -2997,7 +2597,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -3010,14 +2609,12 @@ execa@^0.7.0: expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= dependencies: is-posix-bracket "^0.1.0" expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -3030,14 +2627,12 @@ expand-brackets@^2.1.4: expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= dependencies: fill-range "^2.1.0" express@^4.14.0: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" - integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== dependencies: accepts "~1.3.5" array-flatten "1.1.1" @@ -3073,14 +2668,12 @@ express@^4.14.0: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -3088,33 +2681,16 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extended@0.0.6, extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/extended/-/extended-0.0.6.tgz#7fb8bf7b9dae397586e48570acfd642c78e50669" - integrity sha1-f7i/e52uOXWG5IVwrP1kLHjlBmk= - dependencies: - extender "~0.0.5" - -extender@~0.0.5: - version "0.0.10" - resolved "https://registry.yarnpkg.com/extender/-/extender-0.0.10.tgz#589c07482be61a1460b6d81f9c24aa67e8f324cd" - integrity sha1-WJwHSCvmGhRgttgfnCSqZ+jzJM0= - dependencies: - declare.js "~0.0.4" extendr@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/extendr/-/extendr-2.1.0.tgz#301aa0bbea565f4d2dc8f570f2a22611a8527b56" - integrity sha1-MBqgu+pWX00tyPVw8qImEahSe1Y= dependencies: typechecker "~2.0.1" external-editor@^2.0.4: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== dependencies: chardet "^0.4.0" iconv-lite "^0.4.17" @@ -3123,14 +2699,12 @@ external-editor@^2.0.4: extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= dependencies: is-extglob "^1.0.0" extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -3144,87 +2718,64 @@ extglob@^2.0.4: extract-opts@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d" - integrity sha1-H6KOunNSxttID4hc63GkaBC+bX0= dependencies: typechecker "~2.0.1" extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= eyes@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= fake-merkle-patricia-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= dependencies: checkpoint-store "^1.1.0" -fast-csv@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-2.4.1.tgz#bd7dd268391f729367b59445b8dd0ad026881b26" - integrity sha1-vX3SaDkfcpNntZRFuN0K0CaIGyY= - dependencies: - extended "0.0.6" - is-extended "0.0.10" - object-extended "0.0.7" - string-extended "0.0.8" - fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= dependencies: pend "~1.2.0" fetch-ponyfill@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" - integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= dependencies: node-fetch "~1.7.1" figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" @@ -3232,27 +2783,22 @@ file-entry-cache@^2.0.0: file-type@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= file-type@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha1-LdvqfHP/42No365J3DOMBYwritY= file-type@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= fill-range@^2.1.0: version "2.2.4" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== dependencies: is-number "^2.1.0" isobject "^2.0.0" @@ -3263,7 +2809,6 @@ fill-range@^2.1.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -3273,7 +2818,6 @@ fill-range@^4.0.0: finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" - integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== dependencies: debug "2.6.9" encodeurl "~1.0.2" @@ -3286,7 +2830,6 @@ finalhandler@1.1.1: find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" @@ -3294,14 +2837,12 @@ find-up@^1.0.0: find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" - integrity sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE= dependencies: circular-json "^0.3.1" del "^2.0.2" @@ -3311,31 +2852,26 @@ flat-cache@^1.2.1: for-each@^0.3.2, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= dependencies: for-in "^1.0.1" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= dependencies: asynckit "^0.4.0" combined-stream "1.0.6" @@ -3344,29 +2880,24 @@ form-data@~2.3.2: forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3377,7 +2908,6 @@ fs-extra@^0.30.0: fs-extra@^2.0.0, fs-extra@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" - integrity sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3385,7 +2915,6 @@ fs-extra@^2.0.0, fs-extra@^2.1.2: fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3394,7 +2923,6 @@ fs-extra@^4.0.2: fs-extra@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3403,14 +2931,12 @@ fs-extra@^5.0.0: fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== dependencies: minipass "^2.2.1" fs-promise@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" - integrity sha1-9k5PhUvPaJqovdy6JokW2z20aFQ= dependencies: any-promise "^1.3.0" fs-extra "^2.0.0" @@ -3420,17 +2946,14 @@ fs-promise@^2.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fs@0.0.1-security: version "0.0.1-security" resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" - integrity sha1-invTcYa23d84E/I4WLV+yq9eQdQ= fsevents@^1.0.0, fsevents@^1.2.2: version "1.2.4" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -3438,7 +2961,6 @@ fsevents@^1.0.0, fsevents@^1.2.2: fstream@^1.0.2, fstream@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -3448,24 +2970,20 @@ fstream@^1.0.2, fstream@^1.0.8: function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= ganache-cli@^6.1.8: version "6.1.8" resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.8.tgz#49a8a331683a9652183f82ef1378d17e1814fcd3" - integrity sha512-yXzteu4SIgUL31mnpm9j+x6dpHUw0p/nsRVkcySKq0w+1vDxH9jMErP1QhZAJuTVE6ni4nfvGSNkaQx5cD3jfg== dependencies: source-map-support "^0.5.3" gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -3479,12 +2997,10 @@ gauge@~2.7.3: get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= dependencies: object-assign "^4.0.1" pinkie-promise "^2.0.0" @@ -3492,24 +3008,20 @@ get-stream@^2.2.0: get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= dependencies: glob-parent "^2.0.0" is-glob "^2.0.0" @@ -3517,14 +3029,12 @@ glob-base@^0.3.0: glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= dependencies: is-glob "^2.0.0" glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -3532,7 +3042,6 @@ glob-parent@^3.1.0: glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3544,7 +3053,6 @@ glob@7.1.2: glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= dependencies: inflight "^1.0.4" inherits "2" @@ -3555,7 +3063,6 @@ glob@^5.0.15: glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3567,7 +3074,6 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: glob@~6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= dependencies: inflight "^1.0.4" inherits "2" @@ -3578,7 +3084,6 @@ glob@~6.0.4: global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" - integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= dependencies: min-document "^2.19.0" process "~0.5.1" @@ -3586,17 +3091,14 @@ global@~4.3.0: globals@^11.0.1: version "11.8.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" - integrity sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA== globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0= dependencies: array-union "^1.0.1" arrify "^1.0.0" @@ -3608,7 +3110,6 @@ globby@^5.0.0: got@7.1.0, got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== dependencies: decompress-response "^3.2.0" duplexer3 "^0.1.4" @@ -3628,27 +3129,22 @@ got@7.1.0, got@^7.1.0: graceful-fs@*, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= growl@1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== growl@1.10.5, "growl@~> 1.10.0": version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: version "4.0.12" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" - integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA== dependencies: async "^2.5.0" optimist "^0.6.1" @@ -3659,12 +3155,10 @@ handlebars@^4.0.1: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" - integrity sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA== dependencies: ajv "^5.3.0" har-schema "^2.0.0" @@ -3672,51 +3166,42 @@ har-validator@~5.1.0: has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= has-to-string-tag-x@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== dependencies: has-symbol-support-x "^1.4.1" has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -3725,7 +3210,6 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -3734,12 +3218,10 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -3747,14 +3229,12 @@ has-values@^1.0.0: has@^1.0.1, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -3762,7 +3242,6 @@ hash-base@^3.0.0: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.5" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" - integrity sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" @@ -3770,7 +3249,6 @@ hash.js@^1.0.0, hash.js@^1.0.3: hdkey@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.0.tgz#e74e7b01d2c47f797fa65d1d839adb7a44639f29" - integrity sha512-E7aU8pNlWUJbXGjTz/+lKf1LkMcA3hUrC5ZleeizrmLSd++kvf8mSOe3q8CmBDA9j4hdfXO5iY6hGiTUCOV2jQ== dependencies: coinstring "^2.0.0" safe-buffer "^5.1.1" @@ -3779,12 +3257,10 @@ hdkey@^1.0.0: he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -3793,7 +3269,6 @@ hmac-drbg@^1.0.0: home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.1" @@ -3801,12 +3276,10 @@ home-or-tmp@^2.0.0: hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" @@ -3816,12 +3289,10 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: http-https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" @@ -3830,12 +3301,10 @@ http-signature@~1.2.0: https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= i18n@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/i18n/-/i18n-0.8.3.tgz#2d8cf1c24722602c2041d01ba6ae5eaa51388f0e" - integrity sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4= dependencies: debug "*" make-plural "^3.0.3" @@ -3844,41 +3313,39 @@ i18n@^0.8.3: mustache "*" sprintf-js ">=1.0.3" +i@0.3.x: + version "0.3.6" + resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d" + iconv-lite@0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" ieee754@^1.1.4, ieee754@^1.1.8: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== dependencies: minimatch "^3.0.4" ignore@^3.3.3, ignore@^3.3.6: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== ignorefs@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ignorefs/-/ignorefs-1.2.0.tgz#da59fb858976e4a5e43702ccd1f282fdbc9e5756" - integrity sha1-2ln7hYl25KXkNwLM0fKC/byeV1Y= dependencies: editions "^1.3.3" ignorepatterns "^1.1.0" @@ -3886,27 +3353,22 @@ ignorefs@^1.0.0: ignorepatterns@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ignorepatterns/-/ignorepatterns-1.1.0.tgz#ac8f436f2239b5dfb66d5f0d3a904a87ac67cc5e" - integrity sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4= immediate@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" @@ -3914,22 +3376,18 @@ inflight@^1.0.4: inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= inherits@2.0.1, inherits@=2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" - integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -3949,91 +3407,76 @@ inquirer@^3.0.6: interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" - integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= dependencies: builtin-modules "^1.0.0" is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -4042,7 +3485,6 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -4051,261 +3493,210 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= dependencies: is-primitive "^2.0.0" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" -is-extended@0.0.10, is-extended@~0.0.3, is-extended@~0.0.8: - version "0.0.10" - resolved "https://registry.yarnpkg.com/is-extended/-/is-extended-0.0.10.tgz#244e140df75bb1c9a3106f412ff182fb534a6d62" - integrity sha1-JE4UDfdbscmjEG9BL/GC+1NKbWI= - dependencies: - extended "~0.0.3" - is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= dependencies: number-is-nan "^1.0.0" is-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= dependencies: is-extglob "^1.0.0" is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= dependencies: is-extglob "^2.1.1" is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= is-nan@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" - integrity sha1-n69ltvttskt/XAYoR16nH5iEAeI= dependencies: define-properties "^1.1.1" is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= dependencies: kind-of "^3.0.2" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= is-path-in-cwd@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== dependencies: is-path-inside "^1.0.0" is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= dependencies: path-is-inside "^1.0.1" is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= is-promise@^2.1, is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= dependencies: has "^1.0.1" is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== dependencies: has-symbols "^1.0.0" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= dependencies: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" @@ -4313,12 +3704,10 @@ isomorphic-fetch@^2.2.0: isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= dependencies: abbrev "1.0.x" async "1.x" @@ -4338,7 +3727,6 @@ istanbul@^0.4.5: isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== dependencies: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" @@ -4346,37 +3734,30 @@ isurl@^1.0.0-alpha5: js-sha3@0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a" - integrity sha1-uvDA6MVK1ZA0R9+Wreekobynmko= js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= js-sha3@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" - integrity sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM= js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.9.1: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4384,27 +3765,22 @@ js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.9.1: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-loader@^0.5.4: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" - integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== json-rpc-engine@^3.6.0: version "3.8.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" - integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== dependencies: async "^2.0.1" babel-preset-env "^1.7.0" @@ -4416,82 +3792,68 @@ json-rpc-engine@^3.6.0: json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= dependencies: inherits "^2.0.1" json-rpc-random-id@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= dependencies: jsonify "~0.0.0" json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json-text-sequence@^0.1: version "0.1.1" resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" - integrity sha1-py8hfcSvxGKf/1/rME3BvVGi89I= dependencies: delimit-stream "0.1.0" json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= optionalDependencies: graceful-fs "^4.1.6" jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= optionalDependencies: graceful-fs "^4.1.6" jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" extsprintf "1.3.0" @@ -4501,7 +3863,6 @@ jsprim@^1.2.2: keccak@^1.0.2: version "1.4.0" resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" - integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== dependencies: bindings "^1.2.1" inherits "^2.0.3" @@ -4511,7 +3872,6 @@ keccak@^1.0.2: keccakjs@^0.2.0, keccakjs@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" - integrity sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0= dependencies: browserify-sha3 "^0.0.1" sha3 "^1.1.0" @@ -4519,74 +3879,62 @@ keccakjs@^0.2.0, keccakjs@^0.2.1: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= optionalDependencies: graceful-fs "^4.1.9" lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM= level-codec@~7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== level-errors@^1.0.3: version "1.1.2" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== dependencies: errno "~0.1.1" level-errors@~1.0.3: version "1.0.5" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== dependencies: errno "~0.1.1" level-iterator-stream@~1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= dependencies: inherits "^2.0.1" level-errors "^1.0.3" @@ -4596,7 +3944,6 @@ level-iterator-stream@~1.3.0: level-ws@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= dependencies: readable-stream "~1.0.15" xtend "~2.1.1" @@ -4604,7 +3951,6 @@ level-ws@0.0.0: levelup@^1.2.1: version "1.3.9" resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== dependencies: deferred-leveldown "~1.2.1" level-codec "~7.0.0" @@ -4617,7 +3963,6 @@ levelup@^1.2.1: levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -4625,7 +3970,6 @@ levn@^0.3.0, levn@~0.3.0: load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4636,7 +3980,6 @@ load-json-file@^1.0.0: load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4646,12 +3989,10 @@ load-json-file@^2.0.0: loader-runner@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.1.tgz#026f12fe7c3115992896ac02ba022ba92971b979" - integrity sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw== loader-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" - integrity sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0= dependencies: big.js "^3.1.3" emojis-list "^2.0.0" @@ -4660,7 +4001,6 @@ loader-utils@^1.1.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -4668,54 +4008,44 @@ locate-path@^2.0.0: lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash@4.x, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== lodash@=4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= log-driver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" - integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== long-timeout@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" - integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ= longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lru-cache@^4.0.1: version "4.1.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" - integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -4723,57 +4053,48 @@ lru-cache@^4.0.1: lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" - integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= dependencies: es5-ext "~0.10.2" ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== dependencies: pify "^3.0.0" make-plural@^3.0.3, make-plural@~3.0.3: version "3.0.6" resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-3.0.6.tgz#2033a03bac290b8f3bb91258f65b9df7e8b01ca7" - integrity sha1-IDOgO6wpC487uRJY9lud9+iwHKc= optionalDependencies: minimist "^1.2.0" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" math-interval-parser@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-interval-parser/-/math-interval-parser-1.1.0.tgz#dbeda5b06b3249973c6df6170fde2386f0afd893" - integrity sha1-2+2lsGsySZc8bfYXD94jhvCv2JM= dependencies: xregexp "^2.0.0" math-random@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" - integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -4782,19 +4103,16 @@ md5.js@^1.3.4: media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= dependencies: mimic-fn "^1.0.0" memdown@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= dependencies: abstract-leveldown "~2.7.1" functional-red-black-tree "^1.0.1" @@ -4806,7 +4124,6 @@ memdown@^1.0.0: memoizee@^0.4.14: version "0.4.14" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" - integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== dependencies: d "1" es5-ext "^0.10.45" @@ -4820,7 +4137,6 @@ memoizee@^0.4.14: memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= dependencies: errno "^0.1.3" readable-stream "^2.0.1" @@ -4828,17 +4144,14 @@ memory-fs@^0.4.0, memory-fs@~0.4.1: memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= merkle-patricia-tree@^2.1.2: version "2.3.2" resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== dependencies: async "^1.4.2" ethereumjs-util "^5.0.0" @@ -4852,7 +4165,6 @@ merkle-patricia-tree@^2.1.2: messageformat@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/messageformat/-/messageformat-0.3.1.tgz#e58fff8245e9b3971799e5b43db58b3e9417f5a2" - integrity sha1-5Y//gkXps5cXmeW0PbWLPpQX9aI= dependencies: async "~1.5.2" glob "~6.0.4" @@ -4863,12 +4175,10 @@ messageformat@^0.3.1: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@^2.1.5: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= dependencies: arr-diff "^2.0.0" array-unique "^0.2.1" @@ -4887,7 +4197,6 @@ micromatch@^2.1.5: micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4906,7 +4215,6 @@ micromatch@^3.1.10, micromatch@^3.1.4: miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" @@ -4914,73 +4222,60 @@ miller-rabin@^4.0.0: mime-db@~1.36.0: version "1.36.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" - integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw== mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.20" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" - integrity sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A== dependencies: mime-db "~1.36.0" mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= dependencies: dom-walk "^0.1.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@^1.2.0, minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= minipass@^2.2.1, minipass@^2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957" - integrity sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" @@ -4988,14 +4283,12 @@ minipass@^2.2.1, minipass@^2.3.3: minizlib@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" - integrity sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg== dependencies: minipass "^2.2.1" mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -5003,21 +4296,18 @@ mixin-deep@^1.2.0: mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" mocha@^4.0.1, mocha@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" - integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== dependencies: browser-stdout "1.3.0" commander "2.11.0" @@ -5033,7 +4323,6 @@ mocha@^4.0.1, mocha@^4.1.0: mocha@^5.0.1: version "5.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== dependencies: browser-stdout "1.3.1" commander "2.15.1" @@ -5050,39 +4339,32 @@ mocha@^5.0.1: mock-fs@^4.1.0: version "4.7.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" - integrity sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA== moment-timezone@^0.5.0: version "0.5.21" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.21.tgz#3cba247d84492174dbf71de2a9848fa13207b845" - integrity sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A== dependencies: moment ">= 2.9.0" "moment@>= 2.9.0", moment@^2.22.2: version "2.22.2" resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" - integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y= mout@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" - integrity sha1-ujYR318OWx/7/QEWa48C0fX6K5k= ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== multihashes@^0.4.5: version "0.4.14" resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.14.tgz#774db9a161f81a8a27dc60788f91248e020f5244" - integrity sha512-V/g/EIN6nALXfS/xHUAgtfPP3mn3sPIF/i9beuGKf25QXS2QZYCpeVJbDPEannkz32B2fihzCe2D/KMrbcmefg== dependencies: bs58 "^4.0.1" varint "^5.0.0" @@ -5090,22 +4372,18 @@ multihashes@^0.4.5: mustache@*: version "3.0.0" resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.0.tgz#3de22dd9ba38152f7355399a953dd4528c403338" - integrity sha512-bhBDkK/PioIbtQzRIbGUGypvc3MC4c389QnJt8KDIEJ666OidRPoXAQAHPivikfS3JkMEaWoPvcDL7YrQxtSwg== mustache@^2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" - integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== -mute-stream@0.0.7: +mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" object-assign "^4.0.1" @@ -5114,22 +4392,18 @@ mz@^2.6.0: nan@2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== nan@^2.0.8, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" - integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -5146,12 +4420,14 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +ncp@1.0.x: + version "1.0.1" + resolved "http://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== dependencies: debug "^2.1.2" iconv-lite "^0.4.4" @@ -5160,27 +4436,22 @@ needle@^2.2.1: negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= neo-async@^2.5.0: version "2.5.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc" - integrity sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw== next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= node-async-loop@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/node-async-loop/-/node-async-loop-1.2.2.tgz#c5870299bf6477b780c88b431aa5b37733f55a3d" - integrity sha1-xYcCmb9kd7eAyItDGqWzdzP1Wj0= node-cache@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.0.tgz#48ac796a874e762582692004a376d26dfa875811" - integrity sha512-obRu6/f7S024ysheAjoYFEEBqqDWv4LOMNJEuO8vMeEw2AT4z+NCzO4hlc2lhI4vATzbCQv6kke9FVdx0RbCOw== dependencies: clone "2.x" lodash "4.x" @@ -5188,7 +4459,6 @@ node-cache@^4.1.1: node-fetch@^1.0.1, node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== dependencies: encoding "^0.1.11" is-stream "^1.0.1" @@ -5196,7 +4466,6 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: node-libs-browser@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" - integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -5225,7 +4494,6 @@ node-libs-browser@^2.0.0: node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -5241,7 +4509,6 @@ node-pre-gyp@^0.10.0: node-schedule@^1.2.3: version "1.3.0" resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-1.3.0.tgz#e7a7e816a7f2550d5b170bd106e765db28bdf030" - integrity sha512-NNwO9SUPjBwFmPh3vXiPVEhJLn4uqYmZYvJV358SRGM06BR4UoIqxJpeJwDDXB6atULsgQA97MfD1zMd5xsu+A== dependencies: cron-parser "^2.4.0" long-timeout "0.1.1" @@ -5250,14 +4517,12 @@ node-schedule@^1.2.3: nopt@3.x, nopt@~3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" osenv "^0.1.4" @@ -5265,7 +4530,6 @@ nopt@^4.0.1: normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" @@ -5275,19 +4539,16 @@ normalize-package-data@^2.3.2: normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" - integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" - integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -5295,14 +4556,12 @@ npm-packlist@^1.1.6: npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" @@ -5312,12 +4571,10 @@ npmlog@^4.0.2: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -5325,57 +4582,40 @@ number-to-bn@1.7.0: oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" -object-extended@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/object-extended/-/object-extended-0.0.7.tgz#84fd23f56b15582aeb3e88b05cb55d2432d68a33" - integrity sha1-hP0j9WsVWCrrPoiwXLVdJDLWijM= - dependencies: - array-extended "~0.0.4" - extended "~0.0.3" - is-extended "~0.0.3" - object-inspect@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= dependencies: for-own "^0.1.4" is-extendable "^0.1.1" @@ -5383,47 +4623,40 @@ object.omit@^2.0.0: object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" oboe@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" - integrity sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8= dependencies: http-https "^1.0.0" on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" openzeppelin-solidity@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-1.10.0.tgz#d77eee6653f5958d051318a61ba0b436f92216c0" - integrity sha512-igkrumQQ2lrN2zjeQV4Dnb0GpTBj1fzMcd8HPyBUqwI0hhuscX/HzXiqKT6gFQl1j9Wy/ppVVs9fqL/foF7Gmg== optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= dependencies: minimist "~0.0.1" wordwrap "~0.0.2" @@ -5431,7 +4664,6 @@ optimist@^0.6.1: optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" @@ -5443,29 +4675,24 @@ optionator@^0.8.1, optionator@^0.8.2: original-require@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" - integrity sha1-DxMEcVhM0zURxew4yNWSE/msXiA= os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== dependencies: execa "^0.7.0" lcid "^1.0.0" @@ -5474,12 +4701,10 @@ os-locale@^2.0.0: os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -5487,48 +4712,40 @@ osenv@^0.1.4: p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= dependencies: p-limit "^1.1.0" p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= dependencies: p-finally "^1.0.0" p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" - integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== parse-asn1@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" - integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -5539,7 +4756,6 @@ parse-asn1@^5.0.0: parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= dependencies: glob-base "^0.3.0" is-dotfile "^1.0.0" @@ -5549,7 +4765,6 @@ parse-glob@^3.0.4: parse-headers@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" - integrity sha1-aug6eqJanZtwCswoaYzR8e1+lTY= dependencies: for-each "^0.3.2" trim "0.0.1" @@ -5557,71 +4772,58 @@ parse-headers@^2.0.0: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-parse@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -5630,14 +4832,12 @@ path-type@^1.0.0: path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= dependencies: pify "^2.0.0" pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -5648,119 +4848,116 @@ pbkdf2@^3.0.3: pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" - integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= dependencies: find-up "^1.0.0" +pkginfo@0.3.x: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" + +pkginfo@0.x.x: + version "0.4.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" + pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= pragma-singleton@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pragma-singleton/-/pragma-singleton-1.0.3.tgz#6894317bb8d47157e59de2a4a009db7e6f63e30e" - integrity sha1-aJQxe7jUcVflneKkoAnbfm9j4w4= prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= prettier@^1.14.3: version "1.14.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" - integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg== private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= process@~0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= progress@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= promise-to-callback@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= dependencies: is-fn "^1.0.0" set-immediate-shim "^1.0.1" +prompt@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe" + dependencies: + colors "^1.1.2" + pkginfo "0.x.x" + read "1.0.x" + revalidator "0.1.x" + utile "0.3.x" + winston "2.1.x" + prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" - integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== dependencies: loose-envify "^1.3.1" object-assign "^4.1.1" @@ -5768,7 +4965,6 @@ prop-types@^15.6.2: proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" - integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== dependencies: forwarded "~0.1.2" ipaddr.js "1.8.0" @@ -5776,22 +4972,18 @@ proxy-addr@~2.0.4: prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24: version "1.1.29" resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" - integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -5803,27 +4995,22 @@ public-encrypt@^4.0.0: punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== dependencies: decode-uri-component "^0.2.0" object-assign "^4.1.0" @@ -5832,17 +5019,14 @@ query-string@^5.0.1: querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= randomatic@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116" - integrity sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ== dependencies: is-number "^4.0.0" kind-of "^6.0.0" @@ -5851,14 +5035,12 @@ randomatic@^3.0.0: randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -5866,17 +5048,14 @@ randomfill@^1.0.3: randomhex@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" - integrity sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU= range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== dependencies: bytes "3.0.0" http-errors "1.6.3" @@ -5886,7 +5065,6 @@ raw-body@2.3.3: rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" ini "~1.3.0" @@ -5896,7 +5074,6 @@ rc@^1.2.7: react-dom@^16.2.0: version "16.5.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.5.2.tgz#b69ee47aa20bab5327b2b9d7c1fe2a30f2cfa9d7" - integrity sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5906,7 +5083,6 @@ react-dom@^16.2.0: react@^16.2.0: version "16.5.2" resolved "https://registry.yarnpkg.com/react/-/react-16.5.2.tgz#19f6b444ed139baa45609eee6dc3d318b3895d42" - integrity sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5916,7 +5092,6 @@ react@^16.2.0: read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -5924,7 +5099,6 @@ read-pkg-up@^1.0.1: read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= dependencies: find-up "^2.0.0" read-pkg "^2.0.0" @@ -5932,7 +5106,6 @@ read-pkg-up@^2.0.0: read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" @@ -5941,16 +5114,20 @@ read-pkg@^1.0.0: read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" path-type "^2.0.0" +read@1.0.x: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + dependencies: + mute-stream "~0.0.4" + readable-stream@^1.0.33: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5960,7 +5137,6 @@ readable-stream@^1.0.33: readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -5973,7 +5149,6 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5983,7 +5158,6 @@ readable-stream@~1.0.15: readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" @@ -5992,34 +5166,28 @@ readdirp@^2.0.0: readline-sync@^1.4.9: version "1.4.9" resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.9.tgz#3eda8e65f23cd2a17e61301b1f0003396af5ecda" - integrity sha1-PtqOZfI80qF+YTAbHwADOWr17No= rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" regenerate@^1.2.1: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" @@ -6028,14 +5196,12 @@ regenerator-transform@^0.10.0: regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== dependencies: is-equal-shallow "^0.1.3" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" @@ -6043,12 +5209,10 @@ regex-not@^1.0.0, regex-not@^1.0.2: regexpp@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" - integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= dependencies: regenerate "^1.2.1" regjsgen "^0.2.0" @@ -6057,62 +5221,52 @@ regexpu-core@^2.0.0: regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= regjsparser@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= dependencies: is-finite "^1.0.0" req-cwd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-1.0.1.tgz#0d73aeae9266e697a78f7976019677e76acf0fff" - integrity sha1-DXOurpJm5penj3l2AZZ352rPD/8= dependencies: req-from "^1.0.1" req-from@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-from/-/req-from-1.0.1.tgz#bf81da5147947d32d13b947dc12a58ad4587350e" - integrity sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4= dependencies: resolve-from "^2.0.0" request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" - integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= dependencies: lodash "^4.13.1" request-promise@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" - integrity sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ= dependencies: bluebird "^3.5.0" request-promise-core "1.1.1" @@ -6122,7 +5276,6 @@ request-promise@^4.2.2: request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -6148,22 +5301,18 @@ request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.8 require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" - integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" @@ -6171,41 +5320,34 @@ require-uncached@^1.0.3: resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.1.6, resolve@^1.3.3, resolve@^1.5.0, resolve@^1.6.0: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== dependencies: path-parse "^1.0.5" resolve@~1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" - integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw== dependencies: path-parse "^1.0.5" restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" signal-exit "^3.0.2" @@ -6213,33 +5355,32 @@ restore-cursor@^2.0.0: resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= dependencies: through "~2.3.4" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +revalidator@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1: +rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== dependencies: glob "^7.0.5" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -6247,79 +5388,66 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: rlp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9" - integrity sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA== dependencies: safe-buffer "^5.1.1" run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= dependencies: is-promise "^2.1.0" rustbn.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" - integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== rx-lite-aggregates@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= dependencies: rx-lite "*" rx-lite@*, rx-lite@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-event-emitter@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" - integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== dependencies: events "^3.0.0" safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" safe@^0.4.5: version "0.4.6" resolved "https://registry.yarnpkg.com/safe/-/safe-0.4.6.tgz#1d5580cf2635c5cb940ea48fb5081ae3c25b1be1" - integrity sha1-HVWAzyY1xcuUDqSPtQga48JbG+E= safefs@^3.1.2: version "3.2.2" resolved "https://registry.yarnpkg.com/safefs/-/safefs-3.2.2.tgz#8170c1444d7038e08caea05a374fae2fa349e15c" - integrity sha1-gXDBRE1wOOCMrqBaN0+uL6NJ4Vw= dependencies: graceful-fs "*" "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== scandirectory@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/scandirectory/-/scandirectory-2.5.0.tgz#6ce03f54a090b668e3cbedbf20edf9e310593e72" - integrity sha1-bOA/VKCQtmjjy+2/IO354xBZPnI= dependencies: ignorefs "^1.0.0" safefs "^3.1.2" @@ -6328,24 +5456,20 @@ scandirectory@^2.5.0: schedule@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.5.0.tgz#c128fffa0b402488b08b55ae74bb9df55cc29cc8" - integrity sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw== dependencies: object-assign "^4.1.1" scrypt-async@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-1.3.1.tgz#a11fd6fac981b4b823ee01dee0221169500ddae9" - integrity sha1-oR/W+smBtLgj7gHe4CIRaVAN2uk= scrypt-js@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" - integrity sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q= scrypt.js@0.2.0, scrypt.js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" - integrity sha1-r40UZbcemZARC+38WTuUeeA6ito= dependencies: scrypt "^6.0.2" scryptsy "^1.2.1" @@ -6353,21 +5477,18 @@ scrypt.js@0.2.0, scrypt.js@^0.2.0: scrypt@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" - integrity sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0= dependencies: nan "^2.0.8" scryptsy@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= dependencies: pbkdf2 "^3.0.3" secp256k1@^3.0.1: version "3.5.2" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.2.tgz#f95f952057310722184fe9c914e6b71281f2f2ae" - integrity sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ== dependencies: bindings "^1.2.1" bip66 "^1.1.3" @@ -6381,29 +5502,24 @@ secp256k1@^3.0.1: seek-bzip@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= dependencies: commander "~2.8.1" semaphore@>=1.0.1, semaphore@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== semver@~5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== dependencies: debug "2.6.9" depd "~1.1.2" @@ -6422,7 +5538,6 @@ send@0.16.2: serve-static@1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" @@ -6432,7 +5547,6 @@ serve-static@1.13.2: servify@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== dependencies: body-parser "^1.16.0" cors "^2.8.1" @@ -6443,17 +5557,14 @@ servify@^0.1.12: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6463,7 +5574,6 @@ set-value@^0.4.3: set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6473,22 +5583,18 @@ set-value@^2.0.0: setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -6496,35 +5602,30 @@ sha.js@^2.4.0, sha.js@^2.4.8: sha3@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" - integrity sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k= dependencies: nan "2.10.0" shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shelljs@^0.7.4: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= dependencies: glob "^7.0.0" interpret "^1.0.0" rechoir "^0.6.2" -shelljs@^0.8.1, shelljs@^0.8.2: +shelljs@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" - integrity sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ== dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -6533,17 +5634,14 @@ shelljs@^0.8.1, shelljs@^0.8.2: signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= simple-get@^2.7.0: version "2.8.1" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== dependencies: decompress-response "^3.3.0" once "^1.3.1" @@ -6552,19 +5650,16 @@ simple-get@^2.7.0: slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== dependencies: is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -6573,14 +5668,12 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -6594,22 +5687,18 @@ snapdragon@^0.8.1: sol-digger@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" - integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= sol-explore@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" - integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= sol-explore@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.2.tgz#43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2" - integrity sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI= sol-merger@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-0.1.2.tgz#1f12500f42d427dc0ec8e4c113392acd8a6f62d9" - integrity sha512-12Z84jxeb5VFlQOGS38HOiTrHYohU07oQ5wHOcFJmcRRbaL5kWN7IcldMO1QdW8kONyKdj0xhukzLlN5m5ix4w== dependencies: bluebird "^3.5.0" cli-color "^1.2.0" @@ -6621,7 +5710,6 @@ sol-merger@^0.1.2: solc@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.24.tgz#354f14b269b38cbaa82a47d1ff151723502b954e" - integrity sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -6632,7 +5720,6 @@ solc@0.4.24: solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: version "0.4.25" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.25.tgz#06b8321f7112d95b4b903639b1138a4d292f5faa" - integrity sha512-jU1YygRVy6zatgXrLY2rRm7HW1d7a8CkkEgNJwvH2VLpWhMFsMdWcJn6kUqZwcSz/Vm+w89dy7Z/aB5p6AFTrg== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -6643,7 +5730,6 @@ solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: solidity-coverage@^0.5.11: version "0.5.11" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" - integrity sha512-qikdsSi6+9XbfvwA0aI7HUVpF9fIFNqRWTw23M89GMDY+b6Gj0wWU9IngJS0fimoZIAdEp3bfChxvpfVcrUesg== dependencies: death "^1.1.0" ethereumjs-testrpc-sc "6.1.6" @@ -6659,7 +5745,6 @@ solidity-coverage@^0.5.11: solidity-docgen@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/solidity-docgen/-/solidity-docgen-0.1.0.tgz#f3a56ff074e8c7d832af3a3d462c3b5abf0f64cb" - integrity sha512-F7ufNWmlP5c5hIi66Ijv9tc+HNosyO7ijWq6pRtyBR1WqyJBH/0DJkD6QZI8HkE8p6LEXiPKxGBWbAeVT9Nu9g== dependencies: commander "^2.14.1" lodash "^4.17.5" @@ -6672,7 +5757,6 @@ solidity-docgen@^0.1.0: solidity-parser-sc@0.4.11: version "0.4.11" resolved "https://registry.yarnpkg.com/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz#86734c9205537007f4d6201b57176e41696ee607" - integrity sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw== dependencies: mocha "^4.1.0" pegjs "^0.10.0" @@ -6681,12 +5765,10 @@ solidity-parser-sc@0.4.11: solium-plugin-security@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" - integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== solium@^1.1.6: version "1.1.8" resolved "https://registry.yarnpkg.com/solium/-/solium-1.1.8.tgz#35d30a15c572a233ce8a90226d6cfccb762fadb7" - integrity sha512-fn0lusM6of14CytIDDHK73SGjn6NsVTaCVJjaKCKJyqKhT00rH/hDtvnIeZ2ZTD9z/xaXd4Js2brW3az6AV9RA== dependencies: ajv "^5.2.2" chokidar "^1.6.0" @@ -6704,7 +5786,6 @@ solium@^1.1.6: solparse@2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.5.tgz#72709c867cd6bfc50ec2325f4b81d2b3ea365d99" - integrity sha512-t7tvtR6KU6QfPYLMv1nlCh9DA8HYIu5tbjHpKu0fhGFZ1NuSp0KKDHfFHv07g6v1xgcuUY3rVqNFjZt5b9+5qA== dependencies: mocha "^4.0.1" pegjs "^0.10.0" @@ -6713,17 +5794,14 @@ solparse@2.2.5: sorted-array-functions@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.2.0.tgz#43265b21d6e985b7df31621b1c11cc68d8efc7c3" - integrity sha512-sWpjPhIZJtqO77GN+LD8dDsDKcWZ9GCOJNqKzi1tvtjGIzwfoyuRH8S0psunmc6Z5P+qfDqztSbwYR5X/e1UTg== source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== dependencies: atob "^2.1.1" decode-uri-component "^0.2.0" @@ -6734,14 +5812,12 @@ source-map-resolve@^0.5.0: source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== dependencies: source-map "^0.5.6" source-map-support@^0.5.3: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -6749,29 +5825,24 @@ source-map-support@^0.5.3: source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= dependencies: amdefine ">=0.0.4" spdx-correct@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" - integrity sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -6779,12 +5850,10 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" @@ -6792,29 +5861,24 @@ spdx-expression-parse@^3.0.0: spdx-license-ids@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f" - integrity sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@>=1.0.3: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" - integrity sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw= sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: version "1.15.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2" - integrity sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -6829,12 +5893,10 @@ sshpk@^1.7.0: stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -6842,27 +5904,22 @@ static-extend@^0.1.1: "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== stdio@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/stdio/-/stdio-0.2.7.tgz#a1c57da10fe1cfaa0c3bf683c9d0743d1b660839" - integrity sha1-ocV9oQ/hz6oMO/aDydB0PRtmCDk= stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds= dependencies: inherits "~2.0.1" readable-stream "^2.0.2" @@ -6870,7 +5927,6 @@ stream-browserify@^2.0.1: stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" @@ -6881,22 +5937,10 @@ stream-http@^2.7.2: strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - -string-extended@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/string-extended/-/string-extended-0.0.8.tgz#741957dff487b0272a79eec5a44f239ee6f17ccd" - integrity sha1-dBlX3/SHsCcqee7FpE8jnubxfM0= - dependencies: - array-extended "~0.0.5" - date-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -6905,7 +5949,6 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" @@ -6913,7 +5956,6 @@ string-width@^1.0.1: string.prototype.trim@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" - integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= dependencies: define-properties "^1.1.2" es-abstract "^1.5.0" @@ -6922,109 +5964,92 @@ string.prototype.trim@~1.1.2: string_decoder@^1.0.0, string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== dependencies: is-natural-number "^4.0.1" strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= dependencies: is-hex-prefixed "1.0.0" strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= supports-color@4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== dependencies: has-flag "^2.0.0" supports-color@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== dependencies: has-flag "^3.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" supports-color@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= dependencies: has-flag "^2.0.0" supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" swarm-js@0.1.37: version "0.1.37" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" - integrity sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ== dependencies: bluebird "^3.5.0" buffer "^5.0.5" @@ -7043,7 +6068,6 @@ swarm-js@0.1.37: table@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" - integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== dependencies: ajv "^5.2.3" ajv-keywords "^2.1.0" @@ -7055,12 +6079,10 @@ table@4.0.2: tapable@^0.2.7: version "0.2.8" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" - integrity sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI= tape@^4.4.0, tape@^4.6.3: version "4.9.1" resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9" - integrity sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw== dependencies: deep-equal "~1.0.1" defined "~1.0.0" @@ -7079,7 +6101,6 @@ tape@^4.4.0, tape@^4.6.3: tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== dependencies: bl "^1.0.0" buffer-alloc "^1.2.0" @@ -7092,7 +6113,6 @@ tar-stream@^1.5.2: tar.gz@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" - integrity sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg== dependencies: bluebird "^2.9.34" commander "^2.8.1" @@ -7103,7 +6123,6 @@ tar.gz@^1.0.5: tar@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= dependencies: block-stream "*" fstream "^1.0.2" @@ -7112,7 +6131,6 @@ tar@^2.1.1: tar@^4: version "4.4.6" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" - integrity sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg== dependencies: chownr "^1.0.1" fs-minipass "^1.2.5" @@ -7125,7 +6143,6 @@ tar@^4: taskgroup@^4.0.5, taskgroup@^4.2.0: version "4.3.1" resolved "https://registry.yarnpkg.com/taskgroup/-/taskgroup-4.3.1.tgz#7de193febd768273c457730497024d512c27915a" - integrity sha1-feGT/r12gnPEV3MElwJNUSwnkVo= dependencies: ambi "^2.2.0" csextends "^1.0.3" @@ -7133,43 +6150,36 @@ taskgroup@^4.0.5, taskgroup@^4.2.0: text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= thenify-all@^1.0.0, thenify-all@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.0" resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" - integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= dependencies: any-promise "^1.0.0" through@^2.3.6, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-browserify@^2.0.4: version "2.0.10" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== dependencies: setimmediate "^1.0.4" timers-ext@^0.1.5: version "0.1.7" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" - integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== dependencies: es5-ext "~0.10.46" next-tick "1" @@ -7177,7 +6187,6 @@ timers-ext@^0.1.5: tingodb@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/tingodb/-/tingodb-0.6.1.tgz#f63336259af7dfa6c90dfe2556a0dfb0d4eede59" - integrity sha1-9jM2JZr336bJDf4lVqDfsNTu3lk= dependencies: lodash "^4.17.5" safe "^0.4.5" @@ -7188,36 +6197,30 @@ tingodb@^0.6.1: tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= to-buffer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -7225,7 +6228,6 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" @@ -7235,7 +6237,6 @@ to-regex@^3.0.1, to-regex@^3.0.2: tough-cookie@>=2.3.3, tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: psl "^1.1.24" punycode "^1.4.1" @@ -7243,27 +6244,22 @@ tough-cookie@>=2.3.3, tough-cookie@~2.4.3: tree-kill@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" - integrity sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg== trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= truffle-blockchain-utils@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-blockchain-utils/-/truffle-blockchain-utils-0.0.5.tgz#a4e5c064dadd69f782a137f3d276d21095da7a47" - integrity sha1-pOXAZNrdafeCoTfz0nbSEJXaekc= truffle-contract-schema@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/truffle-contract-schema/-/truffle-contract-schema-2.0.1.tgz#9bf821d32e26e674ba15eb5d40f96b10b1c9d568" - integrity sha1-m/gh0y4m5nS6FetdQPlrELHJ1Wg= dependencies: ajv "^5.1.1" crypto-js "^3.1.9-1" @@ -7272,7 +6268,6 @@ truffle-contract-schema@^2.0.1: truffle-contract@^3.0.4: version "3.0.6" resolved "https://registry.yarnpkg.com/truffle-contract/-/truffle-contract-3.0.6.tgz#2ef6fc32d7faafa9f4aed8e50001a9fdea342192" - integrity sha1-Lvb8Mtf6r6n0rtjlAAGp/eo0IZI= dependencies: ethjs-abi "0.1.8" truffle-blockchain-utils "^0.0.5" @@ -7283,12 +6278,10 @@ truffle-contract@^3.0.4: truffle-error@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/truffle-error/-/truffle-error-0.0.3.tgz#4bf55242e14deee1c7194932709182deff2c97ca" - integrity sha1-S/VSQuFN7uHHGUkycJGC3v8sl8o= truffle-hdwallet-provider-privkey@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider-privkey/-/truffle-hdwallet-provider-privkey-0.1.0.tgz#9417047a74ad37d923df926154b6486ffb57f6c9" - integrity sha512-Vj04yr2d9qLRZspoHztbE/YQnVaoFb90JNZHtggRUm+JFm/NOiSJHLVI63+3mtUIuQ04EuKZ7Df8JQw0Ni7IeA== dependencies: ethereumjs-tx "^1.3.3" ethereumjs-wallet "^0.6.0" @@ -7298,7 +6291,6 @@ truffle-hdwallet-provider-privkey@^0.1.0: truffle-wallet-provider@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-wallet-provider/-/truffle-wallet-provider-0.0.5.tgz#db59ce6fa1c558766011137509a94dfca8d1408e" - integrity sha1-21nOb6HFWHZgERN1CalN/KjRQI4= dependencies: ethereumjs-wallet "^0.6.0" web3 "^0.18.2" @@ -7307,7 +6299,6 @@ truffle-wallet-provider@0.0.5: truffle@^4.1.13: version "4.1.14" resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.14.tgz#8d2c298e29abf9b1e486e44ff9faca6d34bb9030" - integrity sha512-e7tTLvKP3bN9dE7MagfWyFjy4ZgoEGbeujECy1me1ENBzbj/aO/+45gs72qsL3+3IkCNNcWNOJjjrm8BYZZNNg== dependencies: mocha "^4.1.0" original-require "1.0.1" @@ -7316,36 +6307,30 @@ truffle@^4.1.13: tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.13.2.tgz#453161770469d45cd266c36404e2bc99a8fa9944" - integrity sha1-RTFhdwRp1FzSZsNkBOK8maj6mUQ= tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" - integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== dependencies: media-typer "0.3.0" mime-types "~2.1.18" @@ -7353,36 +6338,30 @@ type-is@~1.6.16: typechecker@^2.0.8: version "2.1.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.1.0.tgz#d1c2093a54ff8a19f58cff877eeaa54f2242d383" - integrity sha1-0cIJOlT/ihn1jP+HfuqlTyJC04M= typechecker@^4.3.0: version "4.6.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.6.0.tgz#d245d9c2df21147d5e2a942fff170b68ece73c87" - integrity sha512-83OrXpyP3LNr7aRbLkt2nkjE/d7q8su8/uRvrKxCpswqVCVGOgyaKpaz8/MTjQqBYe4eLNuJ44pNakFZKqyPMA== dependencies: editions "^2.0.2" typechecker@~2.0.1: version "2.0.8" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.0.8.tgz#e83da84bb64c584ccb345838576c40b0337db82e" - integrity sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4= typedarray-to-buffer@^3.1.2: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -7392,7 +6371,6 @@ uglify-js@^2.8.29: uglify-js@^3.1.4: version "3.4.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" - integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== dependencies: commander "~2.17.1" source-map "~0.6.1" @@ -7400,12 +6378,10 @@ uglify-js@^3.1.4: uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= uglifyjs-webpack-plugin@^0.4.6: version "0.4.6" resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" - integrity sha1-uVH0q7a9YX5m9j64kUmOORdj4wk= dependencies: source-map "^0.5.6" uglify-js "^2.8.29" @@ -7414,12 +6390,10 @@ uglifyjs-webpack-plugin@^0.4.6: ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== unbzip2-stream@^1.0.9: version "1.3.1" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" - integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw== dependencies: buffer "^3.0.1" through "^2.3.6" @@ -7427,17 +6401,14 @@ unbzip2-stream@^1.0.9: underscore@1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= underscore@^1.8.3: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -7447,22 +6418,18 @@ union-value@^1.0.0: universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== unorm@^1.3.3: version "1.4.1" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300" - integrity sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA= unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -7470,41 +6437,34 @@ unset-value@^1.0.0: upath@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= dependencies: prepend-http "^1.0.1" url-set-query@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= dependencies: punycode "1.3.2" querystring "0.2.0" @@ -7512,66 +6472,65 @@ url@^0.11.0: use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== utf8@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" - integrity sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g= utf8@^2.1.1, utf8@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" - integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY= utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= dependencies: inherits "2.0.1" util@^0.10.3: version "0.10.4" resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== dependencies: inherits "2.0.3" +utile@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a" + dependencies: + async "~0.9.0" + deep-equal "~0.2.1" + i "0.3.x" + mkdirp "0.x.x" + ncp "1.0.x" + rimraf "2.x.x" + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== valid-url@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" @@ -7579,17 +6538,14 @@ validate-npm-package-license@^3.0.1: varint@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf" - integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8= vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -7598,14 +6554,12 @@ verror@1.10.0: vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= dependencies: indexof "0.0.1" watchpack@^1.4.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== dependencies: chokidar "^2.0.2" graceful-fs "^4.1.2" @@ -7614,7 +6568,6 @@ watchpack@^1.4.0: watchr@~2.4.13: version "2.4.13" resolved "https://registry.yarnpkg.com/watchr/-/watchr-2.4.13.tgz#d74847bb4d6f90f61fe2c74f9f68662aa0e07601" - integrity sha1-10hHu01vkPYf4sdPn2hmKqDgdgE= dependencies: eachr "^2.0.2" extendr "^2.1.0" @@ -7628,7 +6581,6 @@ watchr@~2.4.13: web3-bzz@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.34.tgz#068d37777ab65e5c60f8ec8b9a50cfe45277929c" - integrity sha1-Bo03d3q2Xlxg+OyLmlDP5FJ3kpw= dependencies: got "7.1.0" swarm-js "0.1.37" @@ -7637,7 +6589,6 @@ web3-bzz@1.0.0-beta.34: web3-core-helpers@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz#b168da00d3e19e156bc15ae203203dd4dfee2d03" - integrity sha1-sWjaANPhnhVrwVriAyA91N/uLQM= dependencies: underscore "1.8.3" web3-eth-iban "1.0.0-beta.34" @@ -7646,7 +6597,6 @@ web3-core-helpers@1.0.0-beta.34: web3-core-method@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz#ec163c8a2c490fa02a7ec15559fa7307fc7cc6dd" - integrity sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7657,7 +6607,6 @@ web3-core-method@1.0.0-beta.34: web3-core-promievent@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz#a4f4fa6784bb293e82c60960ae5b56a94cd03edc" - integrity sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw= dependencies: any-promise "1.3.0" eventemitter3 "1.1.1" @@ -7665,7 +6614,6 @@ web3-core-promievent@1.0.0-beta.34: web3-core-requestmanager@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz#01f8f6cf2ae6b6f0b70c38bae1ef741b5bab215c" - integrity sha1-Afj2zyrmtvC3DDi64e90G1urIVw= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7676,7 +6624,6 @@ web3-core-requestmanager@1.0.0-beta.34: web3-core-subscriptions@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz#9fed144033f221c3cf21060302ffdaf5ef2de2de" - integrity sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4= dependencies: eventemitter3 "1.1.1" underscore "1.8.3" @@ -7685,7 +6632,6 @@ web3-core-subscriptions@1.0.0-beta.34: web3-core@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.34.tgz#121be8555e9fb00d2c5d05ddd3381d0c9e46987e" - integrity sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4= dependencies: web3-core-helpers "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7695,7 +6641,6 @@ web3-core@1.0.0-beta.34: web3-eth-abi@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz#034533e3aa2f7e59ff31793eaea685c0ed5af67a" - integrity sha1-A0Uz46ovfln/MXk+rqaFwO1a9no= dependencies: bn.js "4.11.6" underscore "1.8.3" @@ -7705,7 +6650,6 @@ web3-eth-abi@1.0.0-beta.34: web3-eth-accounts@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz#e09142eeecc797ac3459b75e9b23946d3695f333" - integrity sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM= dependencies: any-promise "1.3.0" crypto-browserify "3.12.0" @@ -7721,7 +6665,6 @@ web3-eth-accounts@1.0.0-beta.34: web3-eth-contract@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz#9dbb38fae7643a808427a20180470ec7415c91e6" - integrity sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -7735,7 +6678,6 @@ web3-eth-contract@1.0.0-beta.34: web3-eth-iban@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz#9af458605867ccf74ea979aaf326b38ba6a5ba0c" - integrity sha1-mvRYYFhnzPdOqXmq8yazi6alugw= dependencies: bn.js "4.11.6" web3-utils "1.0.0-beta.34" @@ -7743,7 +6685,6 @@ web3-eth-iban@1.0.0-beta.34: web3-eth-personal@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz#9afba167342ebde5420bcd5895c3f6c34388f205" - integrity sha1-mvuhZzQuveVCC81YlcP2w0OI8gU= dependencies: web3-core "1.0.0-beta.34" web3-core-helpers "1.0.0-beta.34" @@ -7754,7 +6695,6 @@ web3-eth-personal@1.0.0-beta.34: web3-eth@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.34.tgz#74086000850c6fe6f535ef49837d6d4bb6113268" - integrity sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -7772,7 +6712,6 @@ web3-eth@1.0.0-beta.34: web3-net@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.34.tgz#427cea2f431881449c8e38d523290f173f9ff63d" - integrity sha1-QnzqL0MYgUScjjjVIykPFz+f9j0= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7781,7 +6720,6 @@ web3-net@1.0.0-beta.34: web3-provider-engine@^13.6.4: version "13.8.0" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz#4c7c1ad2af5f1fe10343b8a65495879a2f9c00df" - integrity sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ== dependencies: async "^2.5.0" clone "^2.0.0" @@ -7806,7 +6744,6 @@ web3-provider-engine@^13.6.4: web3-provider-engine@^8.4.0: version "8.6.1" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz#4d86e19e30caaf97df351511ec0f60136e5b30eb" - integrity sha1-TYbhnjDKr5ffNRUR7A9gE25bMOs= dependencies: async "^2.1.2" clone "^2.0.0" @@ -7826,7 +6763,6 @@ web3-provider-engine@^8.4.0: web3-providers-http@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz#e561b52bbb43766282007d40285bfe3550c27e7a" - integrity sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno= dependencies: web3-core-helpers "1.0.0-beta.34" xhr2 "0.1.4" @@ -7834,7 +6770,6 @@ web3-providers-http@1.0.0-beta.34: web3-providers-ipc@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz#a1b77f1a306d73649a9c039052e40cb71328d00a" - integrity sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao= dependencies: oboe "2.1.3" underscore "1.8.3" @@ -7843,7 +6778,6 @@ web3-providers-ipc@1.0.0-beta.34: web3-providers-ws@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz#7de70f1b83f2de36476772156becfef6e3516eb3" - integrity sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7852,7 +6786,6 @@ web3-providers-ws@1.0.0-beta.34: web3-shh@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.34.tgz#975061d71eaec42ccee576f7bd8f70f03844afe0" - integrity sha1-l1Bh1x6uxCzO5Xb3vY9w8DhEr+A= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7862,7 +6795,6 @@ web3-shh@1.0.0-beta.34: web3-utils@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.34.tgz#9411fc39aaef39ca4e06169f762297d9ff020970" - integrity sha1-lBH8OarvOcpOBhafdiKX2f8CCXA= dependencies: bn.js "4.11.6" eth-lib "0.1.27" @@ -7875,7 +6807,6 @@ web3-utils@1.0.0-beta.34: web3@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/web3/-/web3-0.19.1.tgz#e763d5b1107c4bc24abd4f8cbee1ba3659e6eb31" - integrity sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE= dependencies: bignumber.js "^4.0.2" crypto-js "^3.1.4" @@ -7886,7 +6817,6 @@ web3@0.19.1: web3@0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.2.tgz#c54dac5fc0e377399c04c1a6ecbb12e4513278d6" - integrity sha1-xU2sX8DjdzmcBMGm7LsS5FEyeNY= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7897,7 +6827,6 @@ web3@0.20.2: web3@0.20.6: version "0.20.6" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.6.tgz#3e97306ae024fb24e10a3d75c884302562215120" - integrity sha1-PpcwauAk+yThCj11yIQwJWIhUSA= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7908,7 +6837,6 @@ web3@0.20.6: web3@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.34.tgz#347e561b784098cb5563315f490479a1d91f2ab1" - integrity sha1-NH5WG3hAmMtVYzFfSQR5odkfKrE= dependencies: web3-bzz "1.0.0-beta.34" web3-core "1.0.0-beta.34" @@ -7921,7 +6849,6 @@ web3@1.0.0-beta.34: web3@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" - integrity sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js#master" crypto-js "^3.1.4" @@ -7931,7 +6858,6 @@ web3@^0.16.0: web3@^0.18.2, web3@^0.18.4: version "0.18.4" resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" - integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" crypto-js "^3.1.4" @@ -7942,7 +6868,6 @@ web3@^0.18.2, web3@^0.18.4: web3@^0.20.5: version "0.20.7" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.7.tgz#1605e6d81399ed6f85a471a4f3da0c8be57df2f7" - integrity sha512-VU6/DSUX93d1fCzBz7WP/SGCQizO1rKZi4Px9j/3yRyfssHyFcZamMw2/sj4E8TlfMXONvZLoforR8B4bRoyTQ== dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7953,7 +6878,6 @@ web3@^0.20.5: webpack-sources@^1.0.1: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" - integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== dependencies: source-list-map "^2.0.0" source-map "~0.6.1" @@ -7961,7 +6885,6 @@ webpack-sources@^1.0.1: webpack@^3.0.0: version "3.12.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.12.0.tgz#3f9e34360370602fcf639e97939db486f4ec0d74" - integrity sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ== dependencies: acorn "^5.0.0" acorn-dynamic-import "^2.0.0" @@ -7998,46 +6921,50 @@ webpack@^3.0.0: whatwg-fetch@>=0.10.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@^1.1.1, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= + +winston@2.1.x: + version "2.1.1" + resolved "http://registry.npmjs.org/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" + dependencies: + async "~1.0.0" + colors "1.0.x" + cycle "1.0.x" + eyes "0.1.x" + isstream "0.1.x" + pkginfo "0.3.x" + stack-trace "0.0.x" winston@^2.3.1: version "2.4.4" resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.4.tgz#a01e4d1d0a103cf4eada6fc1f886b3110d71c34b" - integrity sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q== dependencies: async "~1.0.0" colors "1.0.x" @@ -8049,22 +6976,18 @@ winston@^2.3.1: wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= wordwrap@^1.0.0, wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -8072,19 +6995,16 @@ wrap-ansi@^2.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= dependencies: mkdirp "^0.5.1" ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" @@ -8093,14 +7013,12 @@ ws@^3.0.0: xhr-request-promise@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" - integrity sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0= dependencies: xhr-request "^1.0.1" xhr-request@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== dependencies: buffer-to-arraybuffer "^0.0.5" object-assign "^4.1.1" @@ -8113,19 +7031,16 @@ xhr-request@^1.0.1: xhr2-cookies@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= dependencies: cookiejar "^2.1.1" xhr2@*, xhr2@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" - integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8= xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: version "2.5.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" - integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== dependencies: global "~4.3.0" is-function "^1.0.1" @@ -8135,49 +7050,40 @@ xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: xmlhttprequest@*, xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= xregexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" - integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= dependencies: object-keys "~0.4.0" y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= dependencies: camelcase "^3.0.0" lodash.assign "^4.0.6" @@ -8185,28 +7091,24 @@ yargs-parser@^2.4.1: yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k= dependencies: camelcase "^4.1.0" yargs-parser@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== dependencies: camelcase "^4.1.0" yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= dependencies: camelcase "^4.1.0" yargs@^10.0.3: version "10.1.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" - integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -8224,7 +7126,6 @@ yargs@^10.0.3: yargs@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -8242,7 +7143,6 @@ yargs@^11.0.0: yargs@^4.6.0, yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= dependencies: cliui "^3.2.0" decamelize "^1.1.1" @@ -8262,7 +7162,6 @@ yargs@^4.6.0, yargs@^4.7.1: yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - integrity sha1-YpmpBVsc78lp/355wdkY3Osiw2A= dependencies: camelcase "^4.1.0" cliui "^3.2.0" @@ -8281,7 +7180,6 @@ yargs@^8.0.2: yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= dependencies: camelcase "^1.0.2" cliui "^2.1.0" @@ -8291,7 +7189,6 @@ yargs@~3.10.0: yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" From d0b2aa2e9107d0bcb17188545ae0c71509280261 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 6 Dec 2018 00:53:56 +0530 Subject: [PATCH 335/582] improvements in the update storage --- .../TransferManager/VolumeRestrictionTM.sol | 19 +- test/y_volume_restriction_tm.js | 250 ++++++++++-------- 2 files changed, 153 insertions(+), 116 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 5ee117e35..a79b75771 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -486,7 +486,7 @@ contract VolumeRestrictionTM is ITransferManager { } if (txSumOfDay > 0) { // Total amout that is transacted uptill now for `fromTimestamp` day - txSumOfDay = bucket[_from][lastTradedDayTime] <= bucket[_from][globalLastTradedDayTime]? bucket[_from][lastTradedDayTime] : bucket[_from][globalLastTradedDayTime]; + txSumOfDay = bucket[_from][lastTradedDayTime] >= bucket[_from][globalLastTradedDayTime]? bucket[_from][lastTradedDayTime] : bucket[_from][globalLastTradedDayTime]; // allow modification in storage when `_isTransfer` equals true if (_isTransfer) { // update the storage @@ -516,12 +516,12 @@ contract VolumeRestrictionTM is ITransferManager { uint256 daysCovered; uint256 fromTimestamp; uint256 sumOfLastPeriod = 0; - if (bucketToUser[_from].lastTradedDayTime < globalRestriction.startTime) { + if (bucketToUser[_from].globalLastTradedDayTime < globalRestriction.startTime) { // It will execute when the txn is performed first time after the addition of global restriction fromTimestamp = globalRestriction.startTime; } else { // picking up the preivous timestamp - fromTimestamp = bucketToUser[_from].lastTradedDayTime; + fromTimestamp = bucketToUser[_from].globalLastTradedDayTime; } // Calculating the difference of days uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); @@ -685,14 +685,19 @@ contract VolumeRestrictionTM is ITransferManager { bucketToUser[_from].globalLastTradedDayTime = _globalLastTradedDayTime; } if (_amount != 0) { + if (globalRestriction.endTime >= now && globalRestriction.startTime <= now) { + bucketToUser[_from].globalSumOfLastPeriod = _globalSumOfLastPeriod.add(_amount); + bucketToUser[_from].globalDaysCovered = _globalDaysCovered; + // Increasing the total amount of the day by `_amount` + bucket[_from][_globalLastTradedDayTime] = bucket[_from][_globalLastTradedDayTime].add(_amount); + } if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { bucketToUser[_from].daysCovered = _daysCovered; bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + if (_lastTradedDayTime != _globalLastTradedDayTime) + // Increasing the total amount of the day by `_amount` + bucket[_from][_lastTradedDayTime] = bucket[_from][_lastTradedDayTime].add(_amount); } - bucketToUser[_from].globalSumOfLastPeriod = _globalSumOfLastPeriod.add(_amount); - bucketToUser[_from].globalDaysCovered = _globalDaysCovered; - // Increasing the total amount of the day by `_amount` - bucket[_from][_lastTradedDayTime] = bucket[_from][_lastTradedDayTime].add(_amount); } } diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 10b0e4f5b..85ded68d6 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -84,13 +84,24 @@ contract('VolumeRestrictionTransferManager', accounts => { Global days covered: ${data[3].toNumber()} Global Sum of LastPeriod: ${data[4].dividedBy(new BigNumber(10).pow(18)).toNumber()} Global Latest timestamp: ${data[5].toNumber()} - Individual Total Trade Till now : ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[0])) + Individual Total Trade on latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[0])) .dividedBy(new BigNumber(10).pow(18)).toNumber()} - Global Total Trade Till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[5])) + Global Total Trade on latestTimestamp: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[5])) .dividedBy(new BigNumber(10).pow(18)).toNumber()} `) } + async function calculateSum(rollingPeriod, tempArray) { + let sum = 0; + let start = 0; + if (tempArray.length >= rollingPeriod) + start = tempArray.length - rollingPeriod; + for (let i = start; i < tempArray.length; i++) { + sum += tempArray[i]; + } + return sum; + } + before(async() => { // Accounts setup account_polymath = accounts[0]; @@ -565,13 +576,13 @@ contract('VolumeRestrictionTransferManager', accounts => { await increaseTime(duration.days(5.1)); console.log( - `Estimated gas: + `Estimated gas for addIndividualRestriction: ${await I_VolumeRestrictionTM.addIndividualRestriction.estimateGas( account_investor1, web3.utils.toWei("12"), latestTime() + duration.seconds(2), 3, - latestTime() + duration.days(10), + latestTime() + duration.days(6), 0, { from: token_owner @@ -584,7 +595,7 @@ contract('VolumeRestrictionTransferManager', accounts => { web3.utils.toWei("12"), latestTime() + duration.seconds(2), 3, - latestTime() + duration.days(10), + latestTime() + duration.days(6), 0, { from: token_owner @@ -605,11 +616,10 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should succesfully transact the tokens just after the startTime", async() => { // Check the transfer will be valid or not by calling the verifyTransfer() directly by using _isTransfer = false let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor1, account_investor3, web3.utils.toWei('.3'), "0x0", false); - console.log(result); assert.equal(result.toNumber(), 1); // Perform the transaction - console.log(`Estimated Gas: - ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei('.3'), {from: account_investor1})}` + console.log(` + Gas estimation (Individual): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei('.3'), {from: account_investor1})}` ); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('.3'), {from: account_investor1}); // Check the balance of the investors @@ -631,6 +641,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 0.3); tempArray.push(0.3); + tempArrayGlobal.push(0); }) it("Should successfully add the global restriction", async() => { @@ -653,8 +664,11 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should successfully transact the tokens after 1 and half days", async() => { await increaseTime(duration.days(1.5)); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); - console.log(`Estimated Gas: - ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei("2"), {from: account_investor1})}` + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + let globalStartTime = (await I_VolumeRestrictionTM.globalRestriction.call())[1].toNumber(); + let globalRollingPeriod = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + console.log(` + Gas estimation (Individual + Global): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei("2"), {from: account_investor1})}` ); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); // Check the balance of the investors @@ -662,22 +676,33 @@ contract('VolumeRestrictionTransferManager', accounts => { // Verifying the balances assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 32.7); tempArray.push(2); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + tempArrayGlobal.push(2); + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); await print(data, account_investor1); - assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[tempArray.length - 1]); + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + let globalAmt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[5].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); - assert.equal(data[0].toNumber(), (startTime + duration.days(data[2]))); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 2.3); + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray)); + assert.equal(data[2].toNumber(), 1); + assert.equal(data[3].toNumber(), 1); + assert.equal(data[4].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(globalRollingPeriod, tempArrayGlobal)); + assert.equal(data[5].toNumber(), globalStartTime + duration.days(data[3].toNumber())); + assert.equal(amt, 2); + assert.equal(globalAmt, 2); }); it("Should add the daily restriction successfully", async() => { await I_VolumeRestrictionTM.addDailyGlobalRestriction( web3.utils.toWei("5"), latestTime() + duration.seconds(2), - latestTime() + duration.days(3), + latestTime() + duration.days(1.1), 0, { from: token_owner @@ -689,19 +714,72 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(data[4].toNumber(), 0); }); - it("Should transfer tokens within the daily limit", async() =>{ - console.log(`Estimated Gas: - ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei("2"), {from: account_investor1})}` + it("Should transfer tokens within the daily limit -- falied because of limit failing", async() =>{ + // Transfer the 3.1 tokens to check the daily limit + await increaseTime(5); + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei("3.1"), {from: account_investor1}) + ); + }); + + it("Should transfer the tokens within the daily limit", async() => { + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + let globalStartTime = (await I_VolumeRestrictionTM.globalRestriction.call())[1].toNumber(); + let globalRollingPeriod = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + // Calculate the gas estimation + console.log(` + Gas estimation (Individual + Global + daily): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei("3"), {from: account_investor1})} + `) + // Transfer the 3 tokens + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("3"), {from: account_investor1}); + tempArray[tempArray.length -1] += 3; + tempArrayGlobal[tempArrayGlobal.length -1] += 3; + // getting the data of the bucket + let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + // print the logs + await print(data, account_investor1); + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + let globalAmt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[5].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray)); + assert.equal(data[2].toNumber(), 1); + assert.equal(data[3].toNumber(), 1); + assert.equal(data[4].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArrayGlobal)); + assert.equal(data[5].toNumber(), globalStartTime + duration.days(data[3].toNumber())); + assert.equal(amt, 5); + assert.equal(globalAmt, 5); + }); + + it("Should transfer tokens within the daily limit -- falied because of limit failing", async() =>{ + // Transfer the 0.1 tokens to check the daily limit + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei("0.1"), {from: account_investor1}) ); }); - it.skip("Should successfully transact more tokens on the same day (Fuzz test)", async() => { + it("Should successfully transact tokens on the next day of the rolling period (Fuzz test)", async() => { + // Increase time half day + await increaseTime(duration.days(.52)); // Check the balance of the investors let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + let globalStartTime = (await I_VolumeRestrictionTM.globalRestriction.call())[1].toNumber(); + let globalRollingPeriod = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + let totalAmountTransacted = 0; - for (let i = 0; i < 10; i++) { + // transactions performed + for (let i = 0; i < 5; i++) { let amount = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; + // Calculate the gas estimation + console.log(` + Gas estimation (Individual + Global + daily): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1})} + `) await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); totalAmountTransacted += amount; @@ -711,92 +789,30 @@ contract('VolumeRestrictionTransferManager', accounts => { let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - tempArray[1] = tempArray[1] + totalAmountTransacted; - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - `); - assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 1.3 + totalAmountTransacted, 0.000001); - assert.equal(data[0].length -1, 1); - }); - - it.skip("Should successfully transfer the tokens after half days-- should increase the day covered by 1", async() => { - let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - await increaseTime(duration.days(.5)); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - tempArray.push(2); - - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); - } - - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - `); - assert.equal(data[0].length - 1, 2); - assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), - (oldData[1].plus(new BigNumber(2).times(new BigNumber(10).pow(18)))) - .dividedBy(new BigNumber(10).pow(18)).toNumber()); - }); - - it.skip("Should successfully transfer the tokens in the last day of rolling period", async() => { - // Check the balance of the investors - let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - - let totalAmountTransacted = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(totalAmountTransacted.toString()), {from: account_investor1}); - - // Check the balance of the investors - let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); - // Verifying the balances - assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - tempArray[2] = tempArray[2] + totalAmountTransacted; + tempArray.push(totalAmountTransacted); + tempArrayGlobal.push(totalAmountTransacted); let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.000001); - } - - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - `); - assert.equal(data[0].length - 1, 2); - assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), - oldData[1].dividedBy(new BigNumber(10).pow(18)).toNumber() + totalAmountTransacted, 0.001); - }); - - it.skip("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { + // print the logs + await print(data, account_investor1); + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + let globalAmt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[5].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray), 0.01); + assert.equal(data[2].toNumber(), 2); + assert.equal(data[3].toNumber(), 2); + assert.closeTo(data[4].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArrayGlobal), 0.01); + assert.equal(data[5].toNumber(), globalStartTime + duration.days(data[3].toNumber())); + assert.closeTo(amt, totalAmountTransacted, 0.01); + assert.closeTo(globalAmt, totalAmountTransacted, 0.01); + }); + + it("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { + // Increase the time by 3/5 of the day + await increaseTime(duration.days(.6)); let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); let minimumAmount = new BigNumber(12).times(new BigNumber(10).pow(18)).minus(data[1]); let testAmount = minimumAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))) @@ -805,13 +821,29 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it.skip("Should fail to buy tokens in the new rolling period --failed because amount is more than last two timestamps", async() => { - await increaseTime(duration.days(2)); + it("Should fail to buy tokens in the new rolling period --failed because amount is more than last 1 timestamps", async() => { + await increaseTime(duration.days(1)); await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_investor1}) ); }); + it("Should add the daily restriction again successfully", async() => { + await I_VolumeRestrictionTM.addDailyGlobalRestriction( + web3.utils.toWei("7"), + latestTime() + duration.seconds(2), + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ); + let data = await I_VolumeRestrictionTM.dailyGlobalRestriction.call(); + assert.equal(data[0].dividedBy(new BigNumber(10).pow(18)).toNumber(), 7); + assert.equal(data[2].toNumber(), 1); + assert.equal(data[4].toNumber(), 0); + }); + it.skip("Should transfer the tokens in a new rolling period", async() => { let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); From d156b9963276e83cf7a0ca7715abc734562943fb Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 5 Dec 2018 17:44:27 -0300 Subject: [PATCH 336/582] Fix typo --- CLI/commands/common/common_functions.js | 2 +- CLI/commands/transfer_manager.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index 36bcb5d21..c19834037 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -102,7 +102,7 @@ module.exports = { await checkPermissions(action); options = getFinalOptions(options); - let gasLimit = 8000000//await getGasLimit(options, action); + let gasLimit = await getGasLimit(options, action); console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gasLimit} ----`)); diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 4b88eae92..006ea761c 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -764,7 +764,7 @@ async function blacklistTransferManager() { await manageExistingBlacklist(currentBlacklists[index]); } break; - case 'Remove investors from all blacklists': + case 'Delete investors from all blacklists': let investorsToRemove = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e. addr1,addr2,addr3): `, { limit: function (input) { return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); @@ -775,7 +775,7 @@ async function blacklistTransferManager() { if (investorsToRemove.length === 1) { deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.deleteInvestorFromAllBlacklist(investorsToAdd[0]); } else { - deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.adeleteInvestorFromAllBlacklistMulti(nvestorsToAdd); + deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.deleteInvestorFromAllBlacklistMulti(nvestorsToAdd); } let deleteInvestorFromAllBlacklistReceipt = await common.sendTransaction(deleteInvestorFromAllBlacklistAction); let deleteInvestorFromAllBlacklistEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, deleteInvestorFromAllBlacklistReceipt.logs, 'DeleteInvestorFromBlacklist'); From c41e54cabf698208a81b15f7b47b74de0d3ec795 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 6 Dec 2018 07:53:52 -0300 Subject: [PATCH 337/582] Merged conflicts with master on the CLI --- CLI/commands/ST20Generator.js | 380 +----------- CLI/commands/common/common_functions.js | 93 +-- CLI/commands/common/global.js | 24 +- CLI/commands/strMigrator.js | 791 +++++++++++------------- CLI/package.json | 4 - CLI/polymath-cli.js | 8 +- CLI/yarn.lock | 216 ------- scripts/tokenInfo-v1.js | 13 +- 8 files changed, 391 insertions(+), 1138 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 031814278..689b2b27f 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -29,7 +29,7 @@ async function executeApp(_ticker, _transferOwnership, _name, _details, _divisib try { await step_ticker_registration(_ticker); if (!tokenLaunched) { - await step_transfer_ticker_ownership(_transferOwnership); + await step_transfer_ticker_ownership(_transferOwnership); await step_token_deploy(_name, _details, _divisible); } await tokenManager.executeApp(tokenSymbol); @@ -39,7 +39,7 @@ async function executeApp(_ticker, _transferOwnership, _name, _details, _divisib } }; -async function setup(){ +async function setup() { try { securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -79,7 +79,7 @@ async function step_ticker_registration(_ticker) { available = true; await approvePoly(securityTokenRegistryAddress, regFee); let registerTickerAction = securityTokenRegistry.methods.registerTicker(Issuer.address, tokenSymbol, ""); - await common.sendTransaction(registerTickerAction, {factor: 1.5}); + await common.sendTransaction(registerTickerAction, { factor: 1.5 }); } else if (details[0] == Issuer.address) { // If it has registration date and its owner is Issuer available = true; @@ -107,7 +107,7 @@ async function step_transfer_ticker_ownership(_transferOwnership) { if (newOwner) { let transferTickerOwnershipAction = securityTokenRegistry.methods.transferTickerOwnership(newOwner, tokenSymbol); - let receipt = await common.sendTransaction(transferTickerOwnershipAction, {factor: 1.5}); + let receipt = await common.sendTransaction(transferTickerOwnershipAction, { factor: 1.5 }); let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'ChangeTickerOwnership'); console.log(chalk.green(`Ownership trasferred successfully. The new owner is ${event._newOwner}`)); process.exit(0); @@ -125,7 +125,7 @@ async function step_token_deploy(_name, _details, _divisible) { tokenName = _name; console.log(`Token Name: ${tokenName}`); } else { - tokenName = readlineSync.question('Enter the name for your new token: ', {defaultInput: 'default'}); + tokenName = readlineSync.question('Enter the name for your new token: ', { defaultInput: 'default' }); } let tokenDetails; @@ -145,369 +145,11 @@ async function step_token_deploy(_name, _details, _divisible) { divisibility = (divisible != 'N' && divisible != 'n'); } -<<<<<<< HEAD await approvePoly(securityTokenRegistryAddress, launchFee); let generateSecurityTokenAction = securityTokenRegistry.methods.generateSecurityToken(tokenName, tokenSymbol, tokenDetails, divisibility); let receipt = await common.sendTransaction(generateSecurityTokenAction); let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, receipt.logs, 'NewSecurityToken'); console.log(chalk.green(`Security Token has been successfully deployed at address ${event._securityTokenAddress}`)); -======= - return limits; -} - -async function usdTieredSTO_launch() { - console.log("\n"); - console.log('\x1b[34m%s\x1b[0m',"Token Creation - USD Tiered STO"); - - let stoFee = usdTieredSTOFee; - let contractBalance = await polyToken.methods.balanceOf(securityToken._address).call(); - let requiredAmount = web3.utils.toWei(stoFee.toString(), "ether"); - if (new web3.utils.BN(contractBalance).lt(new web3.utils.BN(requiredAmount))) { - let transferAmount = (new web3.utils.BN(requiredAmount)).sub(new web3.utils.BN(contractBalance)); - let ownerBalance = new web3.utils.BN(await polyToken.methods.balanceOf(Issuer.address).call()); - if (ownerBalance.lt(transferAmount)) { - console.log(chalk.red(`\n**************************************************************************************************************************************************`)); - console.log(chalk.red(`Not enough balance to pay the ${selectedSTO} fee, Requires ${web3.utils.fromWei(transferAmount)} POLY but have ${web3.utils.fromWei(ownerBalance)} POLY. Access POLY faucet to get the POLY to complete this txn`)); - console.log(chalk.red(`**************************************************************************************************************************************************\n`)); - process.exit(0); - } else { - let transferAction = polyToken.methods.transfer(securityToken._address, transferAmount); - let receipt = await common.sendTransaction(Issuer, transferAction, defaultGasPrice, 0, 2); - let event = common.getEventFromLogs(polyToken._jsonInterface, receipt.logs, 'Transfer'); - console.log(`Number of POLY sent: ${web3.utils.fromWei(new web3.utils.BN(event._value))}`) - } - } - - let funding = fundingConfigUSDTieredSTO(); - let addresses = addressesConfigUSDTieredSTO(funding.raiseType.includes(FUND_RAISE_TYPES.DAI)); - let tiers = tiersConfigUSDTieredSTO(funding.raiseType.includes(FUND_RAISE_TYPES.POLY)); - let limits = limitsConfigUSDTieredSTO(); - let times = timesConfigUSDTieredSTO(); - let bytesSTO = web3.eth.abi.encodeFunctionCall( { - name: 'configure', - type: 'function', - inputs: [ - { - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256[]', - name: '_ratePerTier' - },{ - type: 'uint256[]', - name: '_ratePerTierDiscountPoly' - },{ - type: 'uint256[]', - name: '_tokensPerTier' - },{ - type: 'uint256[]', - name: '_tokensPerTierDiscountPoly' - },{ - type: 'uint256', - name: '_nonAccreditedLimitUSD' - },{ - type: 'uint256', - name: '_minimumInvestmentUSD' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes' - },{ - type: 'address', - name: '_wallet' - },{ - type: 'address', - name: '_reserveWallet' - },{ - type: 'address', - name: '_usdToken' - } - ] - }, [times.startTime, - times.endTime, - tiers.ratePerTier, - tiers.ratePerTierDiscountPoly, - tiers.tokensPerTier, - tiers.tokensPerTierDiscountPoly, - limits.nonAccreditedLimitUSD, - limits.minimumInvestmentUSD, - funding.raiseType, - addresses.wallet, - addresses.reserveWallet, - addresses.usdToken - ]); - - let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, MODULES_TYPES.STO, 'USDTieredSTO'); - let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, new BigNumber(stoFee).times(new BigNumber(10).pow(18)), 0); - let receipt = await common.sendTransaction(Issuer, addModuleAction, defaultGasPrice); - let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); - console.log(`STO deployed at address: ${event._module}`); - - STO_Address = event._module; - let usdTieredSTOABI = abis.usdTieredSTO(); - currentSTO = new web3.eth.Contract(usdTieredSTOABI,STO_Address); -} - -async function usdTieredSTO_status() { - let displayStartTime = await currentSTO.methods.startTime().call(); - let displayEndTime = await currentSTO.methods.endTime().call(); - let displayCurrentTier = parseInt(await currentSTO.methods.currentTier().call()) + 1; - let displayNonAccreditedLimitUSD = web3.utils.fromWei(await currentSTO.methods.nonAccreditedLimitUSD().call()); - let displayMinimumInvestmentUSD = web3.utils.fromWei(await currentSTO.methods.minimumInvestmentUSD().call()); - let displayWallet = await currentSTO.methods.wallet().call(); - let displayReserveWallet = await currentSTO.methods.reserveWallet().call(); - let displayTokensSold = web3.utils.fromWei(await currentSTO.methods.getTokensSold().call()); - let displayInvestorCount = await currentSTO.methods.investorCount().call(); - let displayIsFinalized = await currentSTO.methods.isFinalized().call() ? "YES" : "NO"; - let displayTokenSymbol = await securityToken.methods.symbol().call(); - - let tiersLength = await currentSTO.methods.getNumberOfTiers().call();; - - let raiseTypes = []; - for (const fundType in FUND_RAISE_TYPES) { - if (await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES[fundType]).call()) { - raiseTypes.push(fundType); - } - } - - let displayTiers = ""; - let displayMintedPerTier = ""; - for (let t = 0; t < tiersLength; t++) { - let ratePerTier = await currentSTO.methods.ratePerTier(t).call(); - let tokensPerTierTotal = await currentSTO.methods.tokensPerTierTotal(t).call(); - let mintedPerTierTotal = await currentSTO.methods.mintedPerTierTotal(t).call(); - - let displayMintedPerTierPerType = ""; - let displayDiscountTokens = ""; - for (const type of raiseTypes) { - let displayDiscountMinted = ""; - if (type == 'POLY') { - let tokensPerTierDiscountPoly = await currentSTO.methods.tokensPerTierDiscountPoly(t).call(); - if (tokensPerTierDiscountPoly > 0) { - let ratePerTierDiscountPoly = await currentSTO.methods.ratePerTierDiscountPoly(t).call(); - let mintedPerTierDiscountPoly = await currentSTO.methods.mintedPerTierDiscountPoly(t).call(); - displayDiscountTokens = ` - Tokens at discounted rate: ${web3.utils.fromWei(tokensPerTierDiscountPoly)} ${displayTokenSymbol} - Discounted rate: ${web3.utils.fromWei(ratePerTierDiscountPoly, 'ether')} USD per Token`; - - displayDiscountMinted = `(${web3.utils.fromWei(mintedPerTierDiscountPoly)} ${displayTokenSymbol} at discounted rate)`; - } - } - - let mintedPerTier = await currentSTO.methods.mintedPerTier(FUND_RAISE_TYPES[type], t).call(); - displayMintedPerTierPerType += ` - Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; - } - - displayTiers += ` - - Tier ${t+1}: - Tokens: ${web3.utils.fromWei(tokensPerTierTotal)} ${displayTokenSymbol} - Rate: ${web3.utils.fromWei(ratePerTier)} USD per Token` - + displayDiscountTokens; - - displayMintedPerTier += ` - - Tokens minted in Tier ${t+1}: ${web3.utils.fromWei(mintedPerTierTotal)} ${displayTokenSymbol}` - + displayMintedPerTierPerType; - } - - let displayFundsRaisedUSD = web3.utils.fromWei(await currentSTO.methods.fundsRaisedUSD().call()); - - let displayWalletBalancePerType = ''; - let displayReserveWalletBalancePerType = ''; - let displayFundsRaisedPerType = ''; - let displayTokensSoldPerType = ''; - for (const type of raiseTypes) { - let balance = await getBalance(displayWallet, type); - let walletBalance = web3.utils.fromWei(balance); - let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(FUND_RAISE_TYPES[type], balance).call()); - displayWalletBalancePerType += ` - Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; - - balance = await getBalance(displayReserveWallet, type); - let reserveWalletBalance = web3.utils.fromWei(balance); - let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(FUND_RAISE_TYPES[type], balance).call()); - displayReserveWalletBalancePerType += ` - Balance ${type}:\t\t ${reserveWalletBalance} ${type} (${reserveWalletBalanceUSD} USD)`; - - let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(FUND_RAISE_TYPES[type]).call()); - displayFundsRaisedPerType += ` - ${type}:\t\t\t ${fundsRaised} ${type}`; - - //Only show sold for if more than one raise type are allowed - if (raiseTypes.length > 1) { - let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(FUND_RAISE_TYPES[type]).call()); - displayTokensSoldPerType += ` - Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; - } - } - - let displayRaiseType = raiseTypes.join(' - '); - - let now = Math.floor(Date.now()/1000); - let timeTitle; - let timeRemaining; - if (now < displayStartTime) { - timeTitle = "STO starts in: "; - timeRemaining = displayStartTime - now; - } else { - timeTitle = "Time remaining:"; - timeRemaining = displayEndTime - now; - } - - timeRemaining = common.convertToDaysRemaining(timeRemaining); - - console.log(` - ****************** STO Information ****************** - - Address: ${STO_Address} - - Start Time: ${new Date(displayStartTime * 1000)} - - End Time: ${new Date(displayEndTime * 1000)} - - Raise Type: ${displayRaiseType} - - Tiers: ${tiersLength}` - + displayTiers + ` - - Minimum Investment: ${displayMinimumInvestmentUSD} USD - - Non Accredited Limit: ${displayNonAccreditedLimitUSD} USD - - Wallet: ${displayWallet}` - + displayWalletBalancePerType + ` - - Reserve Wallet: ${displayReserveWallet}` - + displayReserveWalletBalancePerType + ` - - -------------------------------------- - - ${timeTitle} ${timeRemaining} - - Is Finalized: ${displayIsFinalized} - - Tokens Sold: ${displayTokensSold} ${displayTokenSymbol}` - + displayTokensSoldPerType + ` - - Current Tier: ${displayCurrentTier}` - + displayMintedPerTier + ` - - Investor count: ${displayInvestorCount} - - Funds Raised` - + displayFundsRaisedPerType + ` - USD: ${displayFundsRaisedUSD} USD - `); - - console.log(chalk.green(`\n${(await currentBalance(Issuer.address))} POLY balance remaining at issuer address ${Issuer.address}`)); -} - -async function usdTieredSTO_configure() { - console.log("\n"); - console.log('\x1b[34m%s\x1b[0m',"STO Configuration - USD Tiered STO"); - - let isFinalized = await currentSTO.methods.isFinalized().call(); - if (isFinalized) { - console.log(chalk.red(`STO is finalized`)); - } else { - let options = []; - options.push('Finalize STO', - 'Change accredited account', 'Change accredited in batch', - 'Change non accredited limit for an account', 'Change non accredited limits in batch'); - - // If STO is not started, you can modify configuration - let now = Math.floor(Date.now() / 1000); - let startTime = await currentSTO.methods.startTime().call.call(); - if (now < startTime) { - options.push('Modify times configuration', 'Modify tiers configuration', 'Modify addresses configuration', - 'Modify limits configuration', 'Modify funding configuration'); - } - - if (typeof _stoConfig === 'undefined') { - let index = readlineSync.keyInSelect(options, 'What do you want to do?'); - switch (index) { - case 0: - let reserveWallet = await currentSTO.methods.reserveWallet().call(); - let isVerified = await securityToken.methods.verifyTransfer("0x0000000000000000000000000000000000000000", reserveWallet, 0, web3.utils.fromAscii("")).call(); - if (isVerified) { - if (readlineSync.keyInYNStrict()) { - let finalizeAction = currentSTO.methods.finalize(); - await common.sendTransaction(Issuer, finalizeAction, defaultGasPrice); - } - } else { - console.log(chalk.red(`Reserve wallet (${reserveWallet}) is not able to receive remaining tokens. Check if this address is whitelisted.`)); - } - break; - case 1: - let investor = readlineSync.question('Enter the address to change accreditation: '); - let isAccredited = readlineSync.keyInYNStrict(`Is ${investor} accredited?`); - let investors = [investor]; - let accredited = [isAccredited]; - let changeAccreditedAction = currentSTO.methods.changeAccredited(investors, accredited); - // 2 GAS? - await common.sendTransaction(Issuer, changeAccreditedAction, defaultGasPrice); - break; - case 2: - shell.exec(`${__dirname}/scripts/script.sh Accredit ${tokenSymbol} 75 ${network}`); - break; - case 3: - let account = readlineSync.question('Enter the address to change non accredited limit: '); - let limit = readlineSync.question(`Enter the limit in USD: `); - let accounts = [account]; - let limits = [web3.utils.toWei(limit)]; - let changeNonAccreditedLimitAction = currentSTO.methods.changeNonAccreditedLimit(accounts, limits); - // 2 GAS? - await common.sendTransaction(Issuer, changeNonAccreditedLimitAction, defaultGasPrice); - break; - case 4: - shell.exec(`${__dirname}/scripts/script.sh NonAccreditedLimit ${tokenSymbol} 75 ${network}`); - break; - case 5: - await modfifyTimes(); - await usdTieredSTO_status(); - break; - case 6: - await modfifyTiers(); - await usdTieredSTO_status(); - break; - case 7: - await modfifyAddresses(); - await usdTieredSTO_status(); - break; - case 8: - await modfifyLimits(); - await usdTieredSTO_status(); - break; - case 9: - await modfifyFunding(); - await usdTieredSTO_status(); - break; - } - } - } -} - -async function modfifyTimes() { - let times = timesConfigUSDTieredSTO(); - let modifyTimesAction = currentSTO.methods.modifyTimes(times.startTime, times.endTime); - await common.sendTransaction(Issuer, modifyTimesAction, defaultGasPrice); -} - -async function modfifyLimits() { - let limits = limitsConfigUSDTieredSTO(); - let modifyLimitsAction = currentSTO.methods.modifyLimits(limits.nonAccreditedLimitUSD, limits.minimumInvestmentUSD); - await common.sendTransaction(Issuer, modifyLimitsAction, defaultGasPrice); -} - -async function modfifyFunding() { - let funding = fundingConfigUSDTieredSTO(); - let modifyFundingAction = currentSTO.methods.modifyFunding(funding.raiseType); - await common.sendTransaction(Issuer, modifyFundingAction, defaultGasPrice); -} - -async function modfifyAddresses() { - let addresses = addressesConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.DAI).call()); - let modifyAddressesAction = currentSTO.methods.modifyAddresses(addresses.wallet, addresses.reserveWallet, addresses.usdToken); - await common.sendTransaction(Issuer, modifyAddressesAction, defaultGasPrice); -} - -async function modfifyTiers() { - let tiers = tiersConfigUSDTieredSTO(await currentSTO.methods.fundRaiseTypes(FUND_RAISE_TYPES.POLY).call()); - let modifyTiersAction = currentSTO.methods.modifyTiers( - tiers.ratePerTier, - tiers.ratePerTierDiscountPoly, - tiers.tokensPerTier, - tiers.tokensPerTierDiscountPoly, - ); - await common.sendTransaction(Issuer, modifyTiersAction, defaultGasPrice); ->>>>>>> master-dev-2.1 } ////////////////////// @@ -553,16 +195,16 @@ async function approvePoly(spender, fee) { await common.sendTransaction(approveAction); } } else { - let requiredBalance = parseInt(requiredAmount) - parseInt(polyBalance); - console.log(chalk.red(`\n*****************************************************************************************************************************************`)); - console.log(chalk.red(`Not enough balance to Pay the Fee, Require ${(new BigNumber(requiredBalance).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY but have ${(new BigNumber(polyBalance).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY. Access POLY faucet to get the POLY to complete this txn`)); - console.log(chalk.red(`******************************************************************************************************************************************\n`)); - process.exit(0); + let requiredBalance = parseInt(requiredAmount) - parseInt(polyBalance); + console.log(chalk.red(`\n*****************************************************************************************************************************************`)); + console.log(chalk.red(`Not enough balance to Pay the Fee, Require ${(new BigNumber(requiredBalance).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY but have ${(new BigNumber(polyBalance).dividedBy(new BigNumber(10).pow(18))).toNumber()} POLY. Access POLY faucet to get the POLY to complete this txn`)); + console.log(chalk.red(`******************************************************************************************************************************************\n`)); + process.exit(0); } } module.exports = { - executeApp: async function(ticker, transferOwnership, name, details, divisible) { + executeApp: async function (ticker, transferOwnership, name, details, divisible) { return executeApp(ticker, transferOwnership, name, details, divisible); } } diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index 5b57a8fb1..fb3db68b7 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -34,13 +34,14 @@ function getFinalOptions(options) { from: Issuer, gasPrice: defaultGasPrice, value: undefined, - factor: 1.2 + factor: 1.2, + minNonce: 0 } return Object.assign(defaultOptions, options) }; async function getGasLimit(options, action) { - let block = await web3.eth.getBlock("latest"); + let block = await web3.eth.getBlock('latest'); let networkGasLimit = block.gasLimit; let gas = Math.round(options.factor * (await action.estimateGas({ from: options.from.address, value: options.value }))); return (gas > networkGasLimit) ? networkGasLimit : gas; @@ -98,101 +99,21 @@ module.exports = { %%%. `); }, -<<<<<<< HEAD + getNonce: async function (from) { + return (await web3.eth.getTransactionCount(from.address, "pending")); + }, sendTransaction: async function (action, options) { await checkPermissions(action); options = getFinalOptions(options); let gasLimit = await getGasLimit(options, action); -======= - getNonce: async function(from) { - return (await web3.eth.getTransactionCount(from.address, "pending")); - }, - sendTransaction: async function (from, action, gasPrice, value, factor) { - let contractRegistry = await connect(action._parent.options.jsonInterface, action._parent._address); - - //NOTE this is a condition to verify if the transaction comes from a module or not. - if (contractRegistry.methods.hasOwnProperty('factory')) { - let moduleAddress = await contractRegistry.methods.factory().call(); - let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress) - let parentModule = await moduleRegistry.methods.getName().call(); - let result = await checkPermission(web3.utils.hexToUtf8(parentModule), action._method.name, contractRegistry); - if (!result) { - console.log("You haven't the right permissions to execute this method."); - process.exit(0); - } - } - - if (typeof factor === 'undefined') factor = 1.2; - - let block = await web3.eth.getBlock("latest"); - let networkGasLimit = block.gasLimit; - let gas = Math.round(factor * (await action.estimateGas({ from: from.address, value: value}))); - if (gas > networkGasLimit) gas = networkGasLimit; - - console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gas} ----`)); - - let nonce = await web3.eth.getTransactionCount(from.address); - let abi = action.encodeABI(); - let parameter = { - from: from.address, - to: action._parent._address, - data: abi, - gasLimit: gas, - gasPrice: gasPrice, - nonce: nonce, - value: web3.utils.toHex(value) - }; - - const transaction = new Tx(parameter); - transaction.sign(Buffer.from(from.privateKey.replace('0x', ''), 'hex')); - return await web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex')) - .on('transactionHash', function(hash){ - console.log(` - Your transaction is being processed. Please wait... - TxHash: ${hash}` - ); - }) - .on('receipt', function(receipt){ - console.log(` - Congratulations! The transaction was successfully completed. - Gas used: ${receipt.gasUsed} - Gas spent: ${web3.utils.fromWei((new web3.utils.BN(gasPrice)).mul(new web3.utils.BN(receipt.gasUsed)))} Ether - Review it on Etherscan. - TxHash: ${receipt.transactionHash}\n` - ); - }); - }, - sendTransactionWithNonce: async function (from, action, gasPrice, minNonce, value, factor) { - let contractRegistry = await connect(action._parent.options.jsonInterface, action._parent._address); - - //NOTE this is a condition to verify if the transaction comes from a module or not. - if (contractRegistry.methods.hasOwnProperty('factory')) { - let moduleAddress = await contractRegistry.methods.factory().call(); - let moduleRegistry = await connect(abis.moduleFactory(), moduleAddress) - let parentModule = await moduleRegistry.methods.getName().call(); - let result = await checkPermission(web3.utils.hexToUtf8(parentModule), action._method.name, contractRegistry); - if (!result) { - console.log("You haven't the right permissions to execute this method."); - process.exit(0); - } - } - if (typeof factor === 'undefined') factor = 1.2; - - let block = await web3.eth.getBlock("latest"); - let networkGasLimit = block.gasLimit; ->>>>>>> master-dev-2.1 console.log(chalk.black.bgYellowBright(`---- Transaction executed: ${action._method.name} - Gas limit provided: ${gasLimit} ----`)); -<<<<<<< HEAD let nonce = await web3.eth.getTransactionCount(options.from.address); -======= - let nonce = await web3.eth.getTransactionCount(from.address); - - if (nonce < minNonce) { + if (nonce < options.minNonce) { nonce = minNonce; } ->>>>>>> master-dev-2.1 let abi = action.encodeABI(); let parameter = { from: options.from.address, diff --git a/CLI/commands/common/global.js b/CLI/commands/common/global.js index 4e0804c7f..51972ea92 100644 --- a/CLI/commands/common/global.js +++ b/CLI/commands/common/global.js @@ -3,8 +3,7 @@ const constants = require('./constants'); global.web3, global.Issuer, global.defaultGasPrice, global.remoteNetwork; -function getGasPrice (networkId) { -<<<<<<< HEAD +function getGasPrice(networkId) { let gasPrice; switch (networkId) { case 1: //Mainnet @@ -24,25 +23,6 @@ function getGasPrice (networkId) { } return gasPrice; } -======= - let gasPrice; - switch (networkId) { - case 1: //Mainnet - gasPrice = 20000000000; - break; - case 3: //Ropsten - gasPrice = 50000000000; - break; - case 15: //Ganache - gasPrice = 50000000000; - break; - case 42: //Kovan - gasPrice = 5000000000; - break; - default: - throw new Error('Network ID not identified'); - } ->>>>>>> master-dev-2.1 function providerValidator(url) { var expression = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g; @@ -56,7 +36,7 @@ async function httpProvider(url, file) { } module.exports = { - initialize: async function(network) { + initialize: async function (network) { remoteNetwork = network; if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { if (typeof remoteNetwork !== 'undefined') { diff --git a/CLI/commands/strMigrator.js b/CLI/commands/strMigrator.js index d88ce9b72..4a8dabfe0 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -6,417 +6,369 @@ var contracts = require('./helpers/contract_addresses'); var common = require('./common/common_functions'); var gbl = require('./common/global'); -<<<<<<< HEAD -async function executeApp(toStrAddress, fromTrAddress, fromStrAddress) { -======= let network; let minNonce; async function executeApp(toStrAddress, fromTrAddress, fromStrAddress, singleTicker, tokenAddress, onlyTickers, remoteNetwork) { - network = remoteNetwork; - await global.initialize(remoteNetwork); ->>>>>>> master-dev-2.1 - - common.logAsciiBull(); - console.log("****************************************"); - console.log("Welcome to the Command-Line STR Migrator"); - console.log("****************************************"); - console.log("The following script will migrate tokens from old STR to new one."); - console.log("Issuer Account: " + Issuer.address + "\n"); - - try { - minNonce = await common.getNonce(Issuer); - let toSecurityTokenRegistry = await step_instance_toSTR(toStrAddress); - if (typeof tokenAddress === 'undefined') { - let fromTickerRegistry = await step_instance_fromTR(fromTrAddress); - let tickers = await step_get_registered_tickers(fromTickerRegistry, singleTicker, onlyTickers); - await step_register_tickers(tickers, toSecurityTokenRegistry); - } - if (typeof onlyTickers === 'undefined') { - let fromSecurityTokenRegistry = await step_instance_fromSTR(fromStrAddress); - let tokens = await step_get_deployed_tokens(fromSecurityTokenRegistry, singleTicker); - await step_launch_STs(tokens, toSecurityTokenRegistry, tokenAddress); - } - } catch (err) { - console.log(err); - return; + network = remoteNetwork; + await global.initialize(remoteNetwork); + + common.logAsciiBull(); + console.log("****************************************"); + console.log("Welcome to the Command-Line STR Migrator"); + console.log("****************************************"); + console.log("The following script will migrate tokens from old STR to new one."); + console.log("Issuer Account: " + Issuer.address + "\n"); + + try { + minNonce = await common.getNonce(Issuer); + let toSecurityTokenRegistry = await step_instance_toSTR(toStrAddress); + if (typeof tokenAddress === 'undefined') { + let fromTickerRegistry = await step_instance_fromTR(fromTrAddress); + let tickers = await step_get_registered_tickers(fromTickerRegistry, singleTicker, onlyTickers); + await step_register_tickers(tickers, toSecurityTokenRegistry); } + if (typeof onlyTickers === 'undefined') { + let fromSecurityTokenRegistry = await step_instance_fromSTR(fromStrAddress); + let tokens = await step_get_deployed_tokens(fromSecurityTokenRegistry, singleTicker); + await step_launch_STs(tokens, toSecurityTokenRegistry, tokenAddress); + } + } catch (err) { + console.log(err); + return; + } } -async function step_instance_toSTR(toStrAddress){ - let _toStrAddress; - if (typeof toStrAddress !== 'undefined') { - if (web3.utils.isAddress(toStrAddress)) { - _toStrAddress = toStrAddress; - } else { - console.log(chalk.red("Entered toStrAddress is not a valid address.")); - return; - } +async function step_instance_toSTR(toStrAddress) { + let _toStrAddress; + if (typeof toStrAddress !== 'undefined') { + if (web3.utils.isAddress(toStrAddress)) { + _toStrAddress = toStrAddress; } else { - // _toStrAddress = readlineSync.question('Enter the new SecurityTokenRegistry address to migrate TO: ', { - // limit: function(input) { - // return web3.utils.isAddress(input); - // }, - // limitMessage: "Must be a valid address" - // }); - _toStrAddress = "0x240f9f86b1465bf1b8eb29bc88cbf65573dfdd97"; + console.log(chalk.red("Entered toStrAddress is not a valid address.")); + return; } - - console.log(`Creating SecurityTokenRegistry contract instance of address: ${_toStrAddress}...`); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - let toSTR = new web3.eth.Contract(securityTokenRegistryABI, _toStrAddress); - toSTR.setProvider(web3.currentProvider); - - return toSTR; + } else { + // _toStrAddress = readlineSync.question('Enter the new SecurityTokenRegistry address to migrate TO: ', { + // limit: function(input) { + // return web3.utils.isAddress(input); + // }, + // limitMessage: "Must be a valid address" + // }); + _toStrAddress = "0x240f9f86b1465bf1b8eb29bc88cbf65573dfdd97"; + } + + console.log(`Creating SecurityTokenRegistry contract instance of address: ${_toStrAddress}...`); + let securityTokenRegistryABI = abis.securityTokenRegistry(); + let toSTR = new web3.eth.Contract(securityTokenRegistryABI, _toStrAddress); + toSTR.setProvider(web3.currentProvider); + + return toSTR; } -async function step_instance_fromTR(fromTrAddress){ - let _fromTrAddress; - if (typeof fromTrAddress !== 'undefined') { - if (web3.utils.isAddress(fromTrAddress)) { - _fromTrAddress = fromTrAddress; - } else { - console.log(chalk.red("Entered fromTrAddress is not a valid address.")); - return; - } +async function step_instance_fromTR(fromTrAddress) { + let _fromTrAddress; + if (typeof fromTrAddress !== 'undefined') { + if (web3.utils.isAddress(fromTrAddress)) { + _fromTrAddress = fromTrAddress; } else { - // _fromTrAddress = readlineSync.question('Enter the old TikcerRegistry address to migrate FROM: ', { - // limit: function(input) { - // return web3.utils.isAddress(input); - // }, - // limitMessage: "Must be a valid address" - // }); - _fromTrAddress = "0xc31714e6759a1ee26db1d06af1ed276340cd4233"; + console.log(chalk.red("Entered fromTrAddress is not a valid address.")); + return; } - - console.log(`Creating TickerRegistry contract instance of address: ${_fromTrAddress}...`); - let tickerRegistryABI = await getABIfromEtherscan(_fromTrAddress); - let fromTR = new web3.eth.Contract(tickerRegistryABI, _fromTrAddress); - fromTR.setProvider(web3.currentProvider); - - return fromTR; + } else { + // _fromTrAddress = readlineSync.question('Enter the old TikcerRegistry address to migrate FROM: ', { + // limit: function(input) { + // return web3.utils.isAddress(input); + // }, + // limitMessage: "Must be a valid address" + // }); + _fromTrAddress = "0xc31714e6759a1ee26db1d06af1ed276340cd4233"; + } + + console.log(`Creating TickerRegistry contract instance of address: ${_fromTrAddress}...`); + let tickerRegistryABI = await getABIfromEtherscan(_fromTrAddress); + let fromTR = new web3.eth.Contract(tickerRegistryABI, _fromTrAddress); + fromTR.setProvider(web3.currentProvider); + + return fromTR; } async function step_get_registered_tickers(tickerRegistry, singleTicker, onlyTickers) { - let tickers = []; - let expiryTime = await tickerRegistry.methods.expiryLimit().call(); - - let logs = await getLogsFromEtherscan(tickerRegistry.options.address, 0, 'latest', 'LogRegisterTicker(address,string,string,bytes32,uint256)'); - if (logs.length == 0) { - console.log("No ticker registration events were emitted."); - } else { - for (let log of logs) { - let event = common.getEventFromLogs(tickerRegistry._jsonInterface, [log], 'LogRegisterTicker'); - if (typeof singleTicker === 'undefined' || event._symbol == singleTicker) { - let details = await tickerRegistry.methods.getDetails(event._symbol).call(); - let _status = details[4]; - if (typeof onlyTickers === 'undefined' || (onlyTickers && !_status)) { - let expiredTicker = details[0] == '0x0000000000000000000000000000000000000000'; - let _symbol = event._symbol; - let _owner = expiredTicker ? event._owner : details[0]; - let _name = expiredTicker ? event._name : details[2]; - let _registrationDate = expiredTicker ? event._timestamp : details[1]; - - - console.log(`------------ Ticker Registered ------------`); - console.log(`Ticker: ${_symbol}`); - console.log(`Owner: ${_owner}`); - console.log(`Token name: ${_name}`); - console.log(`Timestamp: ${_registrationDate}`); - console.log(`Transaction hash: ${log.transactionHash}`); - console.log(`-------------------------------------------`); - console.log(`\n`); - - tickers.push({ - ticker: _symbol, - owner: _owner, - name: _name, - registrationDate: new web3.utils.BN(_registrationDate), - expiryDate: new web3.utils.BN(_registrationDate).add(new web3.utils.BN(expiryTime)), - status: _status - }); - } - } + let tickers = []; + let expiryTime = await tickerRegistry.methods.expiryLimit().call(); + + let logs = await getLogsFromEtherscan(tickerRegistry.options.address, 0, 'latest', 'LogRegisterTicker(address,string,string,bytes32,uint256)'); + if (logs.length == 0) { + console.log("No ticker registration events were emitted."); + } else { + for (let log of logs) { + let event = common.getEventFromLogs(tickerRegistry._jsonInterface, [log], 'LogRegisterTicker'); + if (typeof singleTicker === 'undefined' || event._symbol == singleTicker) { + let details = await tickerRegistry.methods.getDetails(event._symbol).call(); + let _status = details[4]; + if (typeof onlyTickers === 'undefined' || (onlyTickers && !_status)) { + let expiredTicker = details[0] == '0x0000000000000000000000000000000000000000'; + let _symbol = event._symbol; + let _owner = expiredTicker ? event._owner : details[0]; + let _name = expiredTicker ? event._name : details[2]; + let _registrationDate = expiredTicker ? event._timestamp : details[1]; + + + console.log(`------------ Ticker Registered ------------`); + console.log(`Ticker: ${_symbol}`); + console.log(`Owner: ${_owner}`); + console.log(`Token name: ${_name}`); + console.log(`Timestamp: ${_registrationDate}`); + console.log(`Transaction hash: ${log.transactionHash}`); + console.log(`-------------------------------------------`); + console.log(`\n`); + + tickers.push({ + ticker: _symbol, + owner: _owner, + name: _name, + registrationDate: new web3.utils.BN(_registrationDate), + expiryDate: new web3.utils.BN(_registrationDate).add(new web3.utils.BN(expiryTime)), + status: _status + }); } + } } + } - console.log(chalk.yellow(`${tickers.length} tickers found!`)); - return tickers; + console.log(chalk.yellow(`${tickers.length} tickers found!`)); + return tickers; } async function step_register_tickers(tickers, securityTokenRegistry) { - if (tickers.length == 0) { - console.log(chalk.yellow(`There are no tickers to migrate!`)); -} else /*if (readlineSync.keyInYNStrict(`Do you want to migrate ${tickers.length} Tickers?`)) */{ - let i = 0; - let succeed = []; - let failed = []; - let totalGas = new web3.utils.BN(0); - let migrateAll = false; - for (const t of tickers) { -<<<<<<< HEAD - console.log(`\n`); - console.log(`-------- Migrating ticker No ${++i}--------`); - console.log(`Ticker: ${t.ticker}`); - console.log(``); - try { - let modifyTickerAction = securityTokenRegistry.methods.modifyTicker(t.owner, t.ticker, t.name, t.registrationDate, t.expiryDate, false); - let receipt = await common.sendTransaction(modifyTickerAction); - totalGas = totalGas.add(new web3.utils.BN(receipt.gasUsed)); - succeed.push(t); - } catch (error) { - failed.push(t); - console.log(chalk.red(`Transaction failed!!! `)) - console.log(error); -======= - if (migrateAll || readlineSync.keyInYNStrict(`Do you want to migrate ${t.ticker}?`)) { - if (!migrateAll) { - migrateAll = readlineSync.keyInYNStrict(`Do you want to migrate all tickers from here?`) - } - console.log(`\n`); - console.log(`-------- Migrating ticker No ${++i}--------`); - console.log(`Ticker: ${t.ticker}`); - console.log(``); - try { - let modifyTickerAction = securityTokenRegistry.methods.modifyTicker(t.owner, t.ticker, t.name, t.registrationDate, t.expiryDate, false); - let receipt = await common.sendTransactionWithNonce(Issuer, modifyTickerAction, defaultGasPrice, minNonce); - console.log(minNonce); - minNonce = minNonce + 1; - //totalGas = totalGas.add(new web3.utils.BN(receipt.gasUsed)); - succeed.push(t); - } catch (error) { - failed.push(t); - console.log(chalk.red(`Transaction failed!!! `)) - console.log(error); - } ->>>>>>> master-dev-2.1 - } + if (tickers.length == 0) { + console.log(chalk.yellow(`There are no tickers to migrate!`)); + } else /*if (readlineSync.keyInYNStrict(`Do you want to migrate ${tickers.length} Tickers?`)) */ { + let i = 0; + let succeed = []; + let failed = []; + let totalGas = new web3.utils.BN(0); + let migrateAll = false; + for (const t of tickers) { + if (migrateAll || readlineSync.keyInYNStrict(`Do you want to migrate ${t.ticker}?`)) { + if (!migrateAll) { + migrateAll = readlineSync.keyInYNStrict(`Do you want to migrate all tickers from here?`) } - - logTickerResults(succeed, failed, totalGas); + console.log(`\n`); + console.log(`-------- Migrating ticker No ${++i}--------`); + console.log(`Ticker: ${t.ticker}`); + console.log(``); + try { + let modifyTickerAction = securityTokenRegistry.methods.modifyTicker(t.owner, t.ticker, t.name, t.registrationDate, t.expiryDate, false); + let receipt = await common.sendTransaction(modifyTickerAction, { minNonce: minNonce }); + console.log(minNonce); + minNonce = minNonce + 1; + //totalGas = totalGas.add(new web3.utils.BN(receipt.gasUsed)); + succeed.push(t); + } catch (error) { + failed.push(t); + console.log(chalk.red(`Transaction failed!!! `)) + console.log(error); + } + } } + + logTickerResults(succeed, failed, totalGas); + } } -async function step_instance_fromSTR(fromStrAddress){ - let _fromStrAddress; - if (typeof fromStrAddress !== 'undefined') { - if (web3.utils.isAddress(fromStrAddress)) { - _fromStrAddress = fromStrAddress; - } else { - console.log(chalk.red("Entered fromStrAddress is not a valid address.")); - return; - } +async function step_instance_fromSTR(fromStrAddress) { + let _fromStrAddress; + if (typeof fromStrAddress !== 'undefined') { + if (web3.utils.isAddress(fromStrAddress)) { + _fromStrAddress = fromStrAddress; } else { - // _fromStrAddress = readlineSync.question('Enter the old SecurityTokenRegistry address to migrate FROM: ', { - // limit: function(input) { - // return web3.utils.isAddress(input); - // }, - // limitMessage: "Must be a valid address" - // }); - _fromStrAddress = "0xef58491224958d978facf55d2120c55a24516b98"; + console.log(chalk.red("Entered fromStrAddress is not a valid address.")); + return; } - - console.log(`Creating SecurityTokenRegistry contract instance of address: ${_fromStrAddress}...`); - let securityTokenRegistryABI = await getABIfromEtherscan(_fromStrAddress); - let fromSTR = new web3.eth.Contract(securityTokenRegistryABI, _fromStrAddress); - fromSTR.setProvider(web3.currentProvider); - - return fromSTR; + } else { + // _fromStrAddress = readlineSync.question('Enter the old SecurityTokenRegistry address to migrate FROM: ', { + // limit: function(input) { + // return web3.utils.isAddress(input); + // }, + // limitMessage: "Must be a valid address" + // }); + _fromStrAddress = "0xef58491224958d978facf55d2120c55a24516b98"; + } + + console.log(`Creating SecurityTokenRegistry contract instance of address: ${_fromStrAddress}...`); + let securityTokenRegistryABI = await getABIfromEtherscan(_fromStrAddress); + let fromSTR = new web3.eth.Contract(securityTokenRegistryABI, _fromStrAddress); + fromSTR.setProvider(web3.currentProvider); + + return fromSTR; } async function step_get_deployed_tokens(securityTokenRegistry, singleTicker) { - let tokens = []; - - //let events = await securityTokenRegistry.getPastEvents('LogNewSecurityToken', { fromBlock: 0}); - let logs = await getLogsFromEtherscan(securityTokenRegistry.options.address, 0, 'latest', 'LogNewSecurityToken(string,address,address)'); - if (logs.length == 0) { - console.log("No security token events were emitted."); - } else { - for (let log of logs) { - let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, [log], 'LogNewSecurityToken'); - if (typeof singleTicker === 'undefined' || event._ticker == singleTicker) { - let tokenAddress = event._securityTokenAddress; - let securityTokenABI = JSON.parse(require('fs').readFileSync('./CLI/data/SecurityToken1-4-0.json').toString()).abi; - console.log(`Creating SecurityToken contract instance of address: ${tokenAddress}...`); - let token = new web3.eth.Contract(securityTokenABI, tokenAddress); - token.setProvider(web3.currentProvider); - - let tokenName = await token.methods.name().call(); - let tokenSymbol = await token.methods.symbol().call(); - let tokenOwner = await token.methods.owner().call(); - let tokenDetails = await token.methods.tokenDetails().call(); - let tokenDivisible = await token.methods.granularity().call() == 1; - let tokenDeployedAt = (await getBlockfromEtherscan(web3.utils.hexToNumber(log.blockNumber))).timeStamp; - - - let gmtAddress = (await token.methods.getModule(2, 0).call())[1]; - let gtmABI = JSON.parse(require('fs').readFileSync('./CLI/data/GeneralTransferManager1-4-0.json').toString()).abi; - let gmt = new web3.eth.Contract(gtmABI, gmtAddress); - //let gtmEvents = await gmt.getPastEvents('LogModifyWhitelist', { fromBlock: event.blockNumber}); - let gtmLogs = await getLogsFromEtherscan(gmt.options.address, 0, 'latest', 'LogModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)'); - let gtmEvents = common.getMultipleEventsFromLogs(gmt._jsonInterface, gtmLogs, 'LogModifyWhitelist'); - - let mintedEvents = []; - if (gtmEvents.length > 0) { - //mintedEvents = await token.getPastEvents('Minted', { fromBlock: event.blockNumber}); - let mintedLogs = await getLogsFromEtherscan(token.options.address, 0, 'latest', 'Minted(address,uint256)'); - mintedEvents = common.getMultipleEventsFromLogs(token._jsonInterface, mintedLogs, 'Minted'); - } - - console.log(`--------- SecurityToken launched ---------`); - console.log(`Token address: ${event._securityTokenAddress}`); - console.log(`Symbol: ${tokenSymbol}`); - console.log(`Name: ${tokenName}`); - console.log(`Owner: ${tokenOwner}`); - console.log(`Details: ${tokenDetails}`); - console.log(`Divisble: ${tokenDivisible}`); - console.log(`Deployed at: ${tokenDeployedAt}`); - console.log(`Transaction hash: ${log.transactionHash}`); - console.log(`------------------------------------------`); - console.log(``); - - - tokens.push({ - name: tokenName, - ticker: tokenSymbol, - owner: tokenOwner, - details: tokenDetails, - address: tokenAddress, - deployedAt: tokenDeployedAt, - divisble: tokenDivisible, - gmtEvents: gtmEvents, - mintedEvents: mintedEvents - }); - } + let tokens = []; + + //let events = await securityTokenRegistry.getPastEvents('LogNewSecurityToken', { fromBlock: 0}); + let logs = await getLogsFromEtherscan(securityTokenRegistry.options.address, 0, 'latest', 'LogNewSecurityToken(string,address,address)'); + if (logs.length == 0) { + console.log("No security token events were emitted."); + } else { + for (let log of logs) { + let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, [log], 'LogNewSecurityToken'); + if (typeof singleTicker === 'undefined' || event._ticker == singleTicker) { + let tokenAddress = event._securityTokenAddress; + let securityTokenABI = JSON.parse(require('fs').readFileSync('./CLI/data/SecurityToken1-4-0.json').toString()).abi; + console.log(`Creating SecurityToken contract instance of address: ${tokenAddress}...`); + let token = new web3.eth.Contract(securityTokenABI, tokenAddress); + token.setProvider(web3.currentProvider); + + let tokenName = await token.methods.name().call(); + let tokenSymbol = await token.methods.symbol().call(); + let tokenOwner = await token.methods.owner().call(); + let tokenDetails = await token.methods.tokenDetails().call(); + let tokenDivisible = await token.methods.granularity().call() == 1; + let tokenDeployedAt = (await getBlockfromEtherscan(web3.utils.hexToNumber(log.blockNumber))).timeStamp; + + + let gmtAddress = (await token.methods.getModule(2, 0).call())[1]; + let gtmABI = JSON.parse(require('fs').readFileSync('./CLI/data/GeneralTransferManager1-4-0.json').toString()).abi; + let gmt = new web3.eth.Contract(gtmABI, gmtAddress); + //let gtmEvents = await gmt.getPastEvents('LogModifyWhitelist', { fromBlock: event.blockNumber}); + let gtmLogs = await getLogsFromEtherscan(gmt.options.address, 0, 'latest', 'LogModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)'); + let gtmEvents = common.getMultipleEventsFromLogs(gmt._jsonInterface, gtmLogs, 'LogModifyWhitelist'); + + let mintedEvents = []; + if (gtmEvents.length > 0) { + //mintedEvents = await token.getPastEvents('Minted', { fromBlock: event.blockNumber}); + let mintedLogs = await getLogsFromEtherscan(token.options.address, 0, 'latest', 'Minted(address,uint256)'); + mintedEvents = common.getMultipleEventsFromLogs(token._jsonInterface, mintedLogs, 'Minted'); } + + console.log(`--------- SecurityToken launched ---------`); + console.log(`Token address: ${event._securityTokenAddress}`); + console.log(`Symbol: ${tokenSymbol}`); + console.log(`Name: ${tokenName}`); + console.log(`Owner: ${tokenOwner}`); + console.log(`Details: ${tokenDetails}`); + console.log(`Divisble: ${tokenDivisible}`); + console.log(`Deployed at: ${tokenDeployedAt}`); + console.log(`Transaction hash: ${log.transactionHash}`); + console.log(`------------------------------------------`); + console.log(``); + + + tokens.push({ + name: tokenName, + ticker: tokenSymbol, + owner: tokenOwner, + details: tokenDetails, + address: tokenAddress, + deployedAt: tokenDeployedAt, + divisble: tokenDivisible, + gmtEvents: gtmEvents, + mintedEvents: mintedEvents + }); + } } + } - console.log(chalk.yellow(`${tokens.length} security tokens found!`)); - return tokens; + console.log(chalk.yellow(`${tokens.length} security tokens found!`)); + return tokens; } async function step_launch_STs(tokens, securityTokenRegistry, tokenAddress) { - if (tokens.length == 0) { - console.log(chalk.yellow(`There are no security tokens to migrate!`)); -} else /*if (readlineSync.keyInYNStrict(`Do you want to migrate ${tokens.length} Security Tokens?`))*/ { - let i = 0; - let succeed = []; - let failed = []; - let totalGas = new web3.utils.BN(0); - let polymathRegistryAddress = await contracts.polymathRegistry(); - let STFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/STFactory.json').toString()).abi; - let STFactoryAddress = await securityTokenRegistry.methods.getSTFactoryAddress().call(); - let STFactory = new web3.eth.Contract(STFactoryABI, STFactoryAddress); - for (const t of tokens) { - console.log(`\n`); - console.log(`-------- Migrating token No ${++i}--------`); - console.log(`Token symbol: ${t.ticker}`); - console.log(`Token old address: ${t.address}`); - console.log(``); - try { - // Deploying 2.0.0 Token -<<<<<<< HEAD - let deployTokenAction = STFactory.methods.deployToken(t.name, t.ticker, 18, t.details, Issuer.address, t.divisble, polymathRegistryAddress) - let deployTokenReceipt = await common.sendTransaction(deployTokenAction); - // Instancing Security Token - let newTokenAddress = deployTokenReceipt.logs[deployTokenReceipt.logs.length -1].address; //Last log is the ST creation -======= - let newTokenAddress; - if (tokens.length == 1 && typeof tokenAddress !== 'undefined') { - if (web3.utils.isAddress(tokenAddress)) { - newTokenAddress = tokenAddress; - } else { - console.log(chalk.red('Given tokenAddress is not an address!!')); - process.exit(0); - } - } else { - let deployTokenAction = STFactory.methods.deployToken(t.name, t.ticker, 18, t.details, Issuer.address, t.divisble, polymathRegistryAddress) - let deployTokenReceipt = await common.sendTransactionWithNonce(Issuer, deployTokenAction, 25000000000, minNonce); - minNonce = minNonce + 1; - // Instancing Security Token - newTokenAddress = deployTokenReceipt.logs[deployTokenReceipt.logs.length -1].address; //Last log is the ST creation - } - console.log(chalk.green(`The migrated to 2.0.0 Security Token address is ${newTokenAddress}`)); ->>>>>>> master-dev-2.1 - let newTokenABI = abis.securityToken(); - let newToken = new web3.eth.Contract(newTokenABI, newTokenAddress); - - // Checking if the old Security Token has activity - if (t.gmtEvents.length > 0) { - // Instancing GeneralTransferManager - let gmtABI = abis.generalTransferManager(); - let gmtAddress = (await newToken.methods.getModulesByName(web3.utils.toHex("GeneralTransferManager")).call())[0]; - let gmt = new web3.eth.Contract(gmtABI, gmtAddress); - // Whitelisting investors - for (const gmtEvent of t.gmtEvents) { - let modifyWhitelistAction = gmt.methods.modifyWhitelist( - gmtEvent._investor, - new web3.utils.BN(gmtEvent._fromTime), - new web3.utils.BN(gmtEvent._toTime), - new web3.utils.BN(gmtEvent._expiryTime), - gmtEvent._canBuyFromSTO - ); -<<<<<<< HEAD - let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); - totalGas = totalGas.add(new web3.utils.BN(modifyWhitelistReceipt.gasUsed)); - } - // Minting tokens - for (const mintedEvent of t.mintedEvents) { - let mintAction = newToken.methods.mint(mintedEvent.returnValues.to, new web3.utils.BN(mintedEvent.returnValues.value)); - let mintReceipt = await common.sendTransaction(mintAction); - totalGas = totalGas.add(new web3.utils.BN(mintReceipt.gasUsed)); -======= - let modifyWhitelistReceipt = await common.sendTransactionWithNonce(Issuer, modifyWhitelistAction, defaultGasPrice, minNonce); - minNonce = minNonce + 1; - //totalGas = totalGas.add(new web3.utils.BN(modifyWhitelistReceipt.gasUsed)); - } - // Minting tokens - for (const mintedEvent of t.mintedEvents) { - let mintAction = newToken.methods.mint(mintedEvent.to, new web3.utils.BN(mintedEvent.amount)); - let mintReceipt = await common.sendTransactionWithNonce(Issuer, mintAction, defaultGasPrice, minNonce); - minNonce = minNonce + 1; - //totalGas = totalGas.add(new web3.utils.BN(mintReceipt.gasUsed)); ->>>>>>> master-dev-2.1 - } - } - - // Transferring onweship to the original owner - let transferOwnershipAction = newToken.methods.transferOwnership(t.owner); -<<<<<<< HEAD - let transferOwnershipReceipt = await common.sendTransaction(transferOwnershipAction); - totalGas = totalGas.add(new web3.utils.BN(transferOwnershipReceipt.gasUsed)); - - // Adding 2.0.0 Security Token to SecurityTokenRegistry - let modifySecurityTokenAction = securityTokenRegistry.methods.modifySecurityToken(t.name, t.ticker, t.owner, newTokenAddress, t.details, t.deployedAt); - let modifySecurityTokenReceipt = await common.sendTransaction(modifySecurityTokenAction); - totalGas = totalGas.add(new web3.utils.BN(modifySecurityTokenReceipt.gasUsed)); -======= - let transferOwnershipReceipt = await common.sendTransactionWithNonce(Issuer, transferOwnershipAction, defaultGasPrice, minNonce); - minNonce = minNonce + 1; - //totalGas = totalGas.add(new web3.utils.BN(transferOwnershipReceipt.gasUsed)); - - // Adding 2.0.0 Security Token to SecurityTokenRegistry - let modifySecurityTokenAction = securityTokenRegistry.methods.modifySecurityToken(t.name, t.ticker, t.owner, newTokenAddress, t.details, t.deployedAt); - let modifySecurityTokenReceipt = await common.sendTransactionWithNonce(Issuer, modifySecurityTokenAction, defaultGasPrice, minNonce); - minNonce = minNonce + 1; - //totalGas = totalGas.add(new web3.utils.BN(modifySecurityTokenReceipt.gasUsed)); ->>>>>>> master-dev-2.1 - - succeed.push(t); - console.log('done'); - } catch (error) { - failed.push(t); - console.log(chalk.red(`Transaction failed!!! `)) - console.log(error); - } + if (tokens.length == 0) { + console.log(chalk.yellow(`There are no security tokens to migrate!`)); + } else /*if (readlineSync.keyInYNStrict(`Do you want to migrate ${tokens.length} Security Tokens?`))*/ { + let i = 0; + let succeed = []; + let failed = []; + let totalGas = new web3.utils.BN(0); + let polymathRegistryAddress = await contracts.polymathRegistry(); + let STFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/STFactory.json').toString()).abi; + let STFactoryAddress = await securityTokenRegistry.methods.getSTFactoryAddress().call(); + let STFactory = new web3.eth.Contract(STFactoryABI, STFactoryAddress); + for (const t of tokens) { + console.log(`\n`); + console.log(`-------- Migrating token No ${++i}--------`); + console.log(`Token symbol: ${t.ticker}`); + console.log(`Token old address: ${t.address}`); + console.log(``); + try { + // Deploying 2.0.0 Token + let newTokenAddress; + if (tokens.length == 1 && typeof tokenAddress !== 'undefined') { + if (web3.utils.isAddress(tokenAddress)) { + newTokenAddress = tokenAddress; + } else { + console.log(chalk.red('Given tokenAddress is not an address!!')); + process.exit(0); + } + } else { + let deployTokenAction = STFactory.methods.deployToken(t.name, t.ticker, 18, t.details, Issuer.address, t.divisble, polymathRegistryAddress) + let deployTokenReceipt = await common.sendTransaction(deployTokenAction, { minNonce: minNonce }); + minNonce = minNonce + 1; + // Instancing Security Token + newTokenAddress = deployTokenReceipt.logs[deployTokenReceipt.logs.length - 1].address; //Last log is the ST creation + } + console.log(chalk.green(`The migrated to 2.0.0 Security Token address is ${newTokenAddress}`)); + let newTokenABI = abis.securityToken(); + let newToken = new web3.eth.Contract(newTokenABI, newTokenAddress); + + // Checking if the old Security Token has activity + if (t.gmtEvents.length > 0) { + // Instancing GeneralTransferManager + let gmtABI = abis.generalTransferManager(); + let gmtAddress = (await newToken.methods.getModulesByName(web3.utils.toHex("GeneralTransferManager")).call())[0]; + let gmt = new web3.eth.Contract(gmtABI, gmtAddress); + // Whitelisting investors + for (const gmtEvent of t.gmtEvents) { + let modifyWhitelistAction = gmt.methods.modifyWhitelist( + gmtEvent._investor, + new web3.utils.BN(gmtEvent._fromTime), + new web3.utils.BN(gmtEvent._toTime), + new web3.utils.BN(gmtEvent._expiryTime), + gmtEvent._canBuyFromSTO + ); + let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction, { minNonce: minNonce }); + minNonce = minNonce + 1; + //totalGas = totalGas.add(new web3.utils.BN(modifyWhitelistReceipt.gasUsed)); + } + // Minting tokens + for (const mintedEvent of t.mintedEvents) { + let mintAction = newToken.methods.mint(mintedEvent.to, new web3.utils.BN(mintedEvent.amount)); + let mintReceipt = await common.sendTransaction(mintAction, { minNonce: minNonce }); + minNonce = minNonce + 1; + //totalGas = totalGas.add(new web3.utils.BN(mintReceipt.gasUsed)); + } } - logTokenResults(succeed, failed, totalGas); + // Transferring onweship to the original owner + let transferOwnershipAction = newToken.methods.transferOwnership(t.owner); + let transferOwnershipReceipt = await common.sendTransaction(transferOwnershipAction, { minNonce: minNonce }); + minNonce = minNonce + 1; + //totalGas = totalGas.add(new web3.utils.BN(transferOwnershipReceipt.gasUsed)); + + // Adding 2.0.0 Security Token to SecurityTokenRegistry + let modifySecurityTokenAction = securityTokenRegistry.methods.modifySecurityToken(t.name, t.ticker, t.owner, newTokenAddress, t.details, t.deployedAt); + let modifySecurityTokenReceipt = await common.sendTransaction(modifySecurityTokenAction, { minNonce: minNonce }); + minNonce = minNonce + 1; + //totalGas = totalGas.add(new web3.utils.BN(modifySecurityTokenReceipt.gasUsed)); + + succeed.push(t); + console.log('done'); + } catch (error) { + failed.push(t); + console.log(chalk.red(`Transaction failed!!! `)) + console.log(error); + } } + + logTokenResults(succeed, failed, totalGas); + } } function logTokenResults(succeed, failed, totalGas) { - console.log(` + console.log(` -------------------------------------------- --------- Token Migration Results ---------- -------------------------------------------- @@ -430,7 +382,7 @@ ${failed.map(token => chalk.red(`${token.symbol} at ${token.address}`)).join('\n } function logTickerResults(succeed, failed, totalGas) { - console.log(` + console.log(` -------------------------------------------- --------- Ticker Migration Results --------- -------------------------------------------- @@ -444,66 +396,61 @@ ${failed.map(ticker => chalk.red(`${ticker.ticker}`)).join('\n')} } async function getLogsFromEtherscan(_address, _fromBlock, _toBlock, _eventSignature) { - let urlDomain = network == 'kovan' ? 'api-kovan' : 'api'; - const options = { - url: `https://${urlDomain}.etherscan.io/api`, - qs: { - module: 'logs', - action: 'getLogs', - fromBlock: _fromBlock, - toBlock: _toBlock, - address: _address, - topic0: web3.utils.sha3(_eventSignature), - apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' - }, - method: 'GET', - json: true - }; - let data = await request(options); - return data.result; + let urlDomain = network == 'kovan' ? 'api-kovan' : 'api'; + const options = { + url: `https://${urlDomain}.etherscan.io/api`, + qs: { + module: 'logs', + action: 'getLogs', + fromBlock: _fromBlock, + toBlock: _toBlock, + address: _address, + topic0: web3.utils.sha3(_eventSignature), + apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' + }, + method: 'GET', + json: true + }; + let data = await request(options); + return data.result; } async function getABIfromEtherscan(_address) { - let urlDomain = remoteNetwork == 'kovan' ? 'api-kovan' : 'api'; - const options = { - url: `https://${urlDomain}.etherscan.io/api`, - qs: { - module: 'contract', - action: 'getabi', - address: _address, - apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' - }, - method: 'GET', - json: true - }; - let data = await request(options); - return JSON.parse(data.result); + let urlDomain = remoteNetwork == 'kovan' ? 'api-kovan' : 'api'; + const options = { + url: `https://${urlDomain}.etherscan.io/api`, + qs: { + module: 'contract', + action: 'getabi', + address: _address, + apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' + }, + method: 'GET', + json: true + }; + let data = await request(options); + return JSON.parse(data.result); } async function getBlockfromEtherscan(_blockNumber) { - let urlDomain = network == 'kovan' ? 'api-kovan' : 'api'; - const options = { - url: `https://${urlDomain}.etherscan.io/api`, - qs: { - module: 'block', - action: 'getblockreward', - blockno: _blockNumber, - apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' - }, - method: 'GET', - json: true - }; - let data = await request(options); - return data.result; + let urlDomain = network == 'kovan' ? 'api-kovan' : 'api'; + const options = { + url: `https://${urlDomain}.etherscan.io/api`, + qs: { + module: 'block', + action: 'getblockreward', + blockno: _blockNumber, + apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' + }, + method: 'GET', + json: true + }; + let data = await request(options); + return data.result; } module.exports = { -<<<<<<< HEAD - executeApp: async function(toStrAddress, fromTrAddress, fromStrAddress) { - return executeApp(toStrAddress, fromTrAddress, fromStrAddress); -======= - executeApp: async function(toStrAddress, fromTrAddress, fromStrAddress, singleTicker, tokenAddress, onlyTickers, remoteNetwork) { - return executeApp(toStrAddress, fromTrAddress, fromStrAddress, singleTicker, tokenAddress, onlyTickers, remoteNetwork); ->>>>>>> master-dev-2.1 - } + executeApp: async function (toStrAddress, fromTrAddress, fromStrAddress, singleTicker, tokenAddress, onlyTickers, remoteNetwork) { + return executeApp(toStrAddress, fromTrAddress, fromStrAddress, singleTicker, tokenAddress, onlyTickers, remoteNetwork); + } }; \ No newline at end of file diff --git a/CLI/package.json b/CLI/package.json index febf2e6df..4dfcbf3a4 100644 --- a/CLI/package.json +++ b/CLI/package.json @@ -17,11 +17,7 @@ "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", -<<<<<<< HEAD "table": "^5.1.1", "web3": "1.0.0-beta.35" -======= - "web3": "1.0.0-beta.34" ->>>>>>> master-dev-2.1 } } diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 693c041ac..f0a010c97 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -140,14 +140,8 @@ program .option('-ot, --onlyTickers', 'Only migrate tickers without a launched token') .alias('str') .description('Runs STR Migrator') -<<<<<<< HEAD - .action(async function (toStrAddress, fromTrAddress, fromStrAddress) { - await gbl.initialize(program.remoteNode); - await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress); -======= - .action(async function(toStrAddress, fromTrAddress, fromStrAddress, cmd) { + .action(async function (toStrAddress, fromTrAddress, fromStrAddress, cmd) { await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress, cmd.singleTicker, cmd.tokenAddress, cmd.onlyTickers, program.remoteNode); ->>>>>>> master-dev-2.1 }); program diff --git a/CLI/yarn.lock b/CLI/yarn.lock index 7e9fd8c58..82d60b57f 100644 --- a/CLI/yarn.lock +++ b/CLI/yarn.lock @@ -2,14 +2,11 @@ # yarn lockfile v1 -<<<<<<< HEAD "@types/node@^10.3.2": version "10.12.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.0.tgz#ea6dcbddbc5b584c83f06c60e82736d8fbb0c235" integrity sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ== -======= ->>>>>>> master-dev-2.1 accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" @@ -651,7 +648,6 @@ eth-lib@0.2.7: elliptic "^6.4.0" xhr-request-promise "^0.1.2" -<<<<<<< HEAD ethers@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.7.tgz#8c653618077a1fc60c5c1b2575da03561f0039f4" @@ -668,8 +664,6 @@ ethers@^4.0.7: uuid "2.0.1" xmlhttprequest "1.8.0" -======= ->>>>>>> master-dev-2.1 ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -1108,14 +1102,11 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -<<<<<<< HEAD js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= -======= ->>>>>>> master-dev-2.1 js-sha3@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" @@ -1652,14 +1643,11 @@ safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, s resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -<<<<<<< HEAD scrypt-js@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== -======= ->>>>>>> master-dev-2.1 scrypt.js@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" @@ -2072,23 +2060,15 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -<<<<<<< HEAD web3-bzz@1.0.0-beta.35: version "1.0.0-beta.35" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.35.tgz#9d5e1362b3db2afd77d65619b7cd46dd5845c192" integrity sha512-BhAU0qhlr8zltm4gs/+P1gki2VkxHJaM2Rrh4DGesDW0lzwufRoNvWFlwx1bKHoFPWNbSmm9PRkHOYOINL/Tgw== -======= -web3-bzz@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.34.tgz#068d37777ab65e5c60f8ec8b9a50cfe45277929c" - integrity sha1-Bo03d3q2Xlxg+OyLmlDP5FJ3kpw= ->>>>>>> master-dev-2.1 dependencies: got "7.1.0" swarm-js "0.1.37" underscore "1.8.3" -<<<<<<< HEAD web3-core-helpers@1.0.0-beta.35: version "1.0.0-beta.35" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.35.tgz#d681d218a0c6e3283ee1f99a078ab9d3eef037f1" @@ -2113,37 +2093,10 @@ web3-core-promievent@1.0.0-beta.35: version "1.0.0-beta.35" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.35.tgz#4f1b24737520fa423fee3afee110fbe82bcb8691" integrity sha512-GvqXqKq07OmHuVi5uNRg6k79a1/CI0ViCC+EtNv4CORHtDRmYEt5Bvdv6z6FJEiaaQkD0lKbFwNhLxutx7HItw== -======= -web3-core-helpers@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz#b168da00d3e19e156bc15ae203203dd4dfee2d03" - integrity sha1-sWjaANPhnhVrwVriAyA91N/uLQM= - dependencies: - underscore "1.8.3" - web3-eth-iban "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" - -web3-core-method@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz#ec163c8a2c490fa02a7ec15559fa7307fc7cc6dd" - integrity sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0= - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.34" - web3-core-promievent "1.0.0-beta.34" - web3-core-subscriptions "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" - -web3-core-promievent@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz#a4f4fa6784bb293e82c60960ae5b56a94cd03edc" - integrity sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw= ->>>>>>> master-dev-2.1 dependencies: any-promise "1.3.0" eventemitter3 "1.1.1" -<<<<<<< HEAD web3-core-requestmanager@1.0.0-beta.35: version "1.0.0-beta.35" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.35.tgz#2b77cbf6303720ad68899b39fa7f584dc03dbc8f" @@ -2188,52 +2141,6 @@ web3-eth-accounts@1.0.0-beta.35: version "1.0.0-beta.35" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.35.tgz#7d0e5a69f510dc93874471599eb7abfa9ddf3e63" integrity sha512-duIgRsfht/0kAW/eQ0X9lKtVIykbETrnM2H7EnvplCzPHtQLodpib4o9JXfh9n6ZDgdDC7cuJoiVB9QJg089ew== -======= -web3-core-requestmanager@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz#01f8f6cf2ae6b6f0b70c38bae1ef741b5bab215c" - integrity sha1-Afj2zyrmtvC3DDi64e90G1urIVw= - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.34" - web3-providers-http "1.0.0-beta.34" - web3-providers-ipc "1.0.0-beta.34" - web3-providers-ws "1.0.0-beta.34" - -web3-core-subscriptions@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz#9fed144033f221c3cf21060302ffdaf5ef2de2de" - integrity sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4= - dependencies: - eventemitter3 "1.1.1" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.34" - -web3-core@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.34.tgz#121be8555e9fb00d2c5d05ddd3381d0c9e46987e" - integrity sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4= - dependencies: - web3-core-helpers "1.0.0-beta.34" - web3-core-method "1.0.0-beta.34" - web3-core-requestmanager "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" - -web3-eth-abi@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz#034533e3aa2f7e59ff31793eaea685c0ed5af67a" - integrity sha1-A0Uz46ovfln/MXk+rqaFwO1a9no= - dependencies: - bn.js "4.11.6" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" - -web3-eth-accounts@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz#e09142eeecc797ac3459b75e9b23946d3695f333" - integrity sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM= ->>>>>>> master-dev-2.1 dependencies: any-promise "1.3.0" crypto-browserify "3.12.0" @@ -2241,7 +2148,6 @@ web3-eth-accounts@1.0.0-beta.34: scrypt.js "0.2.0" underscore "1.8.3" uuid "2.0.1" -<<<<<<< HEAD web3-core "1.0.0-beta.35" web3-core-helpers "1.0.0-beta.35" web3-core-method "1.0.0-beta.35" @@ -2347,113 +2253,6 @@ web3-utils@1.0.0-beta.35: version "1.0.0-beta.35" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.35.tgz#ced9e1df47c65581c441c5f2af76b05a37a273d7" integrity sha512-Dq6f0SOKj3BDFRgOPnE6ALbzBDCKVIW8mKWVf7tGVhTDHf+wQaWwQSC3aArFSqdExB75BPBPyDpuMTNszhljpA== -======= - web3-core "1.0.0-beta.34" - web3-core-helpers "1.0.0-beta.34" - web3-core-method "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" - -web3-eth-contract@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz#9dbb38fae7643a808427a20180470ec7415c91e6" - integrity sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY= - dependencies: - underscore "1.8.3" - web3-core "1.0.0-beta.34" - web3-core-helpers "1.0.0-beta.34" - web3-core-method "1.0.0-beta.34" - web3-core-promievent "1.0.0-beta.34" - web3-core-subscriptions "1.0.0-beta.34" - web3-eth-abi "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" - -web3-eth-iban@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz#9af458605867ccf74ea979aaf326b38ba6a5ba0c" - integrity sha1-mvRYYFhnzPdOqXmq8yazi6alugw= - dependencies: - bn.js "4.11.6" - web3-utils "1.0.0-beta.34" - -web3-eth-personal@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz#9afba167342ebde5420bcd5895c3f6c34388f205" - integrity sha1-mvuhZzQuveVCC81YlcP2w0OI8gU= - dependencies: - web3-core "1.0.0-beta.34" - web3-core-helpers "1.0.0-beta.34" - web3-core-method "1.0.0-beta.34" - web3-net "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" - -web3-eth@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.34.tgz#74086000850c6fe6f535ef49837d6d4bb6113268" - integrity sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg= - dependencies: - underscore "1.8.3" - web3-core "1.0.0-beta.34" - web3-core-helpers "1.0.0-beta.34" - web3-core-method "1.0.0-beta.34" - web3-core-subscriptions "1.0.0-beta.34" - web3-eth-abi "1.0.0-beta.34" - web3-eth-accounts "1.0.0-beta.34" - web3-eth-contract "1.0.0-beta.34" - web3-eth-iban "1.0.0-beta.34" - web3-eth-personal "1.0.0-beta.34" - web3-net "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" - -web3-net@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.34.tgz#427cea2f431881449c8e38d523290f173f9ff63d" - integrity sha1-QnzqL0MYgUScjjjVIykPFz+f9j0= - dependencies: - web3-core "1.0.0-beta.34" - web3-core-method "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" - -web3-providers-http@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz#e561b52bbb43766282007d40285bfe3550c27e7a" - integrity sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno= - dependencies: - web3-core-helpers "1.0.0-beta.34" - xhr2 "0.1.4" - -web3-providers-ipc@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz#a1b77f1a306d73649a9c039052e40cb71328d00a" - integrity sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao= - dependencies: - oboe "2.1.3" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.34" - -web3-providers-ws@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz#7de70f1b83f2de36476772156becfef6e3516eb3" - integrity sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM= - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.34" - websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" - -web3-shh@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.34.tgz#975061d71eaec42ccee576f7bd8f70f03844afe0" - integrity sha1-l1Bh1x6uxCzO5Xb3vY9w8DhEr+A= - dependencies: - web3-core "1.0.0-beta.34" - web3-core-method "1.0.0-beta.34" - web3-core-subscriptions "1.0.0-beta.34" - web3-net "1.0.0-beta.34" - -web3-utils@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.34.tgz#9411fc39aaef39ca4e06169f762297d9ff020970" - integrity sha1-lBH8OarvOcpOBhafdiKX2f8CCXA= ->>>>>>> master-dev-2.1 dependencies: bn.js "4.11.6" eth-lib "0.1.27" @@ -2463,7 +2262,6 @@ web3-utils@1.0.0-beta.34: underscore "1.8.3" utf8 "2.1.1" -<<<<<<< HEAD web3@1.0.0-beta.35: version "1.0.0-beta.35" resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.35.tgz#6475095bd451a96e50a32b997ddee82279292f11" @@ -2476,20 +2274,6 @@ web3@1.0.0-beta.35: web3-net "1.0.0-beta.35" web3-shh "1.0.0-beta.35" web3-utils "1.0.0-beta.35" -======= -web3@1.0.0-beta.34: - version "1.0.0-beta.34" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.34.tgz#347e561b784098cb5563315f490479a1d91f2ab1" - integrity sha1-NH5WG3hAmMtVYzFfSQR5odkfKrE= - dependencies: - web3-bzz "1.0.0-beta.34" - web3-core "1.0.0-beta.34" - web3-eth "1.0.0-beta.34" - web3-eth-personal "1.0.0-beta.34" - web3-net "1.0.0-beta.34" - web3-shh "1.0.0-beta.34" - web3-utils "1.0.0-beta.34" ->>>>>>> master-dev-2.1 "websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": version "1.0.26" diff --git a/scripts/tokenInfo-v1.js b/scripts/tokenInfo-v1.js index 7edfa804e..ea14a7efe 100644 --- a/scripts/tokenInfo-v1.js +++ b/scripts/tokenInfo-v1.js @@ -6,25 +6,14 @@ const securityTokenABI = JSON.parse(require('fs').readFileSync('../CLI/data/Secu const generalTransferManagerABI = JSON.parse(require('fs').readFileSync('../CLI/data/GeneralTransferManager1-4-0.json').toString()).abi; async function getTokens() { -<<<<<<< HEAD:scripts/tokenInfo.js - let strEvents = await web3.eth.getPastLogs({fromBlock:'0x5C5C18', address:securityTokenRegistry.address, topics: ["0x2510d802a0818e71139a7680a6388bcffcd3fa686e02a0f7319488c5bdb38fcb"]}); - for (let i = 0; i < strEvents.length; i++) { - let tokenAddress = '0x' + strEvents[i].topics[1].slice(26,66) - try { - await getInfo(tokenAddress); - } catch(exception) { - console.log('Failed to load info of', tokenAddress, exception); - } -======= const securityTokenRegistryAddress = "0xEf58491224958d978fACF55D2120c55A24516B98"; const securityTokenRegistryABI = await getABIfromEtherscan(securityTokenRegistryAddress); const securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); let logs = await getLogsFromEtherscan(securityTokenRegistry.options.address, web3.utils.hexToNumber('0x5C5C18'), 'latest', 'LogNewSecurityToken(string,address,address)'); for (let i = 0; i < logs.length; i++) { - let tokenAddress = '0x' + logs[i].topics[1].slice(26,66) + let tokenAddress = '0x' + logs[i].topics[1].slice(26, 66) await getInfo(tokenAddress); ->>>>>>> master-dev-2.1:scripts/tokenInfo-v1.js } } From 3f256b840d8b84af246f8b73ff10be18309f5dcb Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 6 Dec 2018 17:12:06 +0530 Subject: [PATCH 338/582] changes in the business logic --- .../TransferManager/VolumeRestrictionTM.sol | 424 ++++++++---------- 1 file changed, 199 insertions(+), 225 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index a79b75771..1f400e9ef 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -26,25 +26,25 @@ contract VolumeRestrictionTM is ITransferManager { struct BucketDetails { uint256 lastTradedDayTime; - uint256 globalLastTradedDayTime; - uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays - uint256 globalSumOfLastPeriod; + uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays uint256 daysCovered; // No of days covered till (from the startTime of VolumeRestriction) - uint256 globalDaysCovered; + uint256 dailyLastTradedDayTime; } // Global restriction that applies to all token holders - VolumeRestriction public globalRestriction; + VolumeRestriction public defaultRestriction; // Daily global restriction that applies to all token holders (Total ST traded daily is restricted) - VolumeRestriction public dailyGlobalRestriction; - // Variable stores the data matrix for the globa restrictions - BucketDetails internal globalBucketDetails; + VolumeRestriction public defaultDailyRestriction; // Restriction stored corresponds to a particular token holder mapping(address => VolumeRestriction) public individualRestriction; + // Daily restriction stored corresponds to a particular token holder + mapping(address => VolumeRestriction) public individualDailyRestriction; // Storing _from => day's timestamp => total amount transact in a day --individual mapping(address => mapping(uint256 => uint256)) internal bucket; // Storing the information that used to validate the transaction mapping(address => BucketDetails) internal bucketToUser; + // Storing the information related to default restriction + mapping(address => BucketDetails) internal defaultBucketToUser; // List of wallets that are exempted from all the restrictions applied by the this contract mapping(address => bool) public exemptList; @@ -69,31 +69,31 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _typeOfRestriction ); // Emit when the new global restriction is added - event AddGlobalRestriction( + event AddDefaultRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, uint256 _typeOfRestriction ); - // Emit when the new daily (global) restriction is added - event AddDailyGlobalRestriction( + // Emit when the new daily (Default) restriction is added + event AddDefaultDailyRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, uint256 _typeOfRestriction ); - // Emit when global restriction get modified - event ModifyGlobalRestriction( + // Emit when default restriction get modified + event ModifyDefaultRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, uint256 _typeOfRestriction ); - // Emit when daily global restriction get modified - event ModifyDailyGlobalRestriction( + // Emit when daily default restriction get modified + event ModifyDefaultDailyRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _rollingPeriodInDays, @@ -102,10 +102,10 @@ contract VolumeRestrictionTM is ITransferManager { ); // Emit when the individual restriction gets removed event IndividualRestrictionRemoved(address _user); - // Emit when the global restriction gets removed - event GlobalRestrictionRemoved(); - // Emit when the daily global restriction gets removed - event DailyGlobalRestrictionRemoved(); + // Emit when the default restriction gets removed + event DefaultRestrictionRemoved(); + // Emit when the daily default restriction gets removed + event DefaultDailyRestrictionRemoved(); /** * @notice Constructor @@ -131,7 +131,17 @@ contract VolumeRestrictionTM is ITransferManager { if (!paused && _from != address(0) && !exemptList[_from]) { // Function must only be called by the associated security token if _isTransfer == true require(msg.sender == securityToken || !_isTransfer); - return _restrictionCheck(_from, _amount, _isTransfer); + // Checking the individual restriction if the `_from` comes in the individual category + if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now + || individualDailyRestriction[_from].endTime >= now && individualDailyRestriction[_from].startTime <= now) { + + return _individualRestrictionCheck(_from, _amount, _isTransfer); + // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically + } else if (defaultRestriction.endTime >= now && defaultRestriction.startTime <= now + || defaultDailyRestriction.endTime >= now && defaultDailyRestriction.startTime <= now) { + + return _defaultRestrictionCheck(_from, _amount, _isTransfer); + } } return Result.NA; } @@ -212,14 +222,14 @@ contract VolumeRestrictionTM is ITransferManager { } /** - * @notice Use to add the new global restriction for all token holder + * @notice Use to add the new default restriction for all token holder * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _startTime Unix timestamp at which restriction get into effect * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ - function addGlobalRestriction( + function addDefaultRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _rollingPeriodInDays, @@ -230,21 +240,18 @@ contract VolumeRestrictionTM is ITransferManager { withPerm(ADMIN) { require( - globalRestriction.endTime < now, + defaultRestriction.endTime < now, "Not allowed" ); _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - if (globalRestriction.endTime != 0) { - removeGlobalRestriction(); - } - globalRestriction = VolumeRestriction( + defaultRestriction = VolumeRestriction( _allowedTokens, _startTime, _rollingPeriodInDays, _endTime, RestrictionType(_restrictionType) ); - emit AddGlobalRestriction( + emit AddDefaultRestriction( _allowedTokens, _startTime, _rollingPeriodInDays, @@ -254,13 +261,13 @@ contract VolumeRestrictionTM is ITransferManager { } /** - * @notice Use to add the new global daily restriction for all token holder + * @notice Use to add the new default daily restriction for all token holder * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ - function addDailyGlobalRestriction( + function addDefaultDailyRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, @@ -270,18 +277,18 @@ contract VolumeRestrictionTM is ITransferManager { withPerm(ADMIN) { require( - dailyGlobalRestriction.endTime < now, + defaultDailyRestriction.endTime < now, "Not Allowed" ); _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); - dailyGlobalRestriction = VolumeRestriction( + defaultDailyRestriction = VolumeRestriction( _allowedTokens, _startTime, 1, _endTime, RestrictionType(_restrictionType) ); - emit AddDailyGlobalRestriction( + emit AddDefaultDailyRestriction( _allowedTokens, _startTime, 1, @@ -309,24 +316,21 @@ contract VolumeRestrictionTM is ITransferManager { } /** - * @notice Use to remove the global restriction + * @notice Use to remove the default restriction */ - function removeGlobalRestriction() public withPerm(ADMIN) { - require(globalRestriction.endTime != 0); - globalRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - globalBucketDetails.lastTradedDayTime = 0; - globalBucketDetails.sumOfLastPeriod = 0; - globalBucketDetails.daysCovered = 0; - emit GlobalRestrictionRemoved(); + function removeDefaultRestriction() public withPerm(ADMIN) { + require(defaultRestriction.endTime != 0); + defaultRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + emit DefaultRestrictionRemoved(); } /** - * @notice Use to remove the daily global restriction + * @notice Use to remove the daily default restriction */ - function removeDailyGlobalRestriction() external withPerm(ADMIN) { - require(dailyGlobalRestriction.endTime != 0); - dailyGlobalRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - emit DailyGlobalRestrictionRemoved(); + function removeDefaultDailyRestriction() external withPerm(ADMIN) { + require(defaultDailyRestriction.endTime != 0); + defaultDailyRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + emit DefaultDailyRestrictionRemoved(); } /** @@ -401,7 +405,7 @@ contract VolumeRestrictionTM is ITransferManager { * @param _endTime Unix timestamp at which restriction effects will gets end. * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ - function modifyGlobalRestriction( + function modifyDefaultRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _rollingPeriodInDays, @@ -411,16 +415,16 @@ contract VolumeRestrictionTM is ITransferManager { external withPerm(ADMIN) { - require(globalRestriction.startTime > now, "Not allowed"); + require(defaultRestriction.startTime > now, "Not allowed"); _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - globalRestriction = VolumeRestriction( + defaultRestriction = VolumeRestriction( _allowedTokens, _startTime, _rollingPeriodInDays, _endTime, RestrictionType(_restrictionType) ); - emit ModifyGlobalRestriction( + emit ModifyDefaultRestriction( _allowedTokens, _startTime, _rollingPeriodInDays, @@ -430,13 +434,13 @@ contract VolumeRestrictionTM is ITransferManager { } /** - * @notice Use to modify the daily global restriction for all token holder + * @notice Use to modify the daily default restriction for all token holder * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) */ - function modifyDailyGlobalRestriction( + function modifyDefaultDailyRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, @@ -445,16 +449,16 @@ contract VolumeRestrictionTM is ITransferManager { external withPerm(ADMIN) { - require(dailyGlobalRestriction.startTime > now, "Not allowed"); + require(defaultDailyRestriction.startTime > now, "Not allowed"); _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); - dailyGlobalRestriction = VolumeRestriction( + defaultDailyRestriction = VolumeRestriction( _allowedTokens, _startTime, 1, _endTime, RestrictionType(_restrictionType) ); - emit ModifyDailyGlobalRestriction( + emit ModifyDefaultDailyRestriction( _allowedTokens, _startTime, 1, @@ -464,116 +468,132 @@ contract VolumeRestrictionTM is ITransferManager { } /** - * @notice Internal function have a logic to validate the txn amount with global restriction - */ - function _restrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { - uint256 sumOfLastPeriod = 0; - uint256 daysCovered = 0; - uint256 lastTradedDayTime = 0; - uint256 globalLastTradedDayTime = 0; - uint256 globalSumOfLastPeriod = 0; - uint256 globalDaysCovered = 0; - bool validIR = true; - bool validGR = true; - uint256 txSumOfDay = 0; - if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { - (validIR, sumOfLastPeriod, lastTradedDayTime, daysCovered) = _individualRestrictionCheck(_from, _amount); - txSumOfDay = txSumOfDay + 1; - } - if (globalRestriction.endTime >= now && globalRestriction.startTime <= now) { - (validGR, globalSumOfLastPeriod, globalLastTradedDayTime, globalDaysCovered) = _globalRestrictionCheck(_from, _amount); - txSumOfDay = txSumOfDay + 1; - } - if (txSumOfDay > 0) { - // Total amout that is transacted uptill now for `fromTimestamp` day - txSumOfDay = bucket[_from][lastTradedDayTime] >= bucket[_from][globalLastTradedDayTime]? bucket[_from][lastTradedDayTime] : bucket[_from][globalLastTradedDayTime]; - // allow modification in storage when `_isTransfer` equals true - if (_isTransfer) { - // update the storage - _updateStorage( - _from, - _amount, - lastTradedDayTime, - sumOfLastPeriod, - globalSumOfLastPeriod, - daysCovered, - globalDaysCovered, - globalLastTradedDayTime - ); + * @notice Internal function used to validate the transaction for a given address + * If it validates then it also update the storage corressponds to the default restriction + */ + function _defaultRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + // using the variable to avoid stack too deep error + uint256 daysCovered = defaultRestriction.rollingPeriodInDays; + uint256 fromTimestamp = 0; + uint256 sumOfLastPeriod = 0; + uint256 dailyTime = 0; + bool allowedDefault = true; + bool allowedDaily; + if (defaultRestriction.endTime >= now && defaultRestriction.startTime <= now) { + if (defaultBucketToUser[_from].lastTradedDayTime < defaultRestriction.startTime) { + // It will execute when the txn is performed first time after the addition of individual restriction + fromTimestamp = defaultRestriction.startTime; + } else { + // Picking up the last timestamp + fromTimestamp = defaultBucketToUser[_from].lastTradedDayTime; + } + + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod + // re-using the local variables to avoid the stack too deep error. + (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( + fromTimestamp, + BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now), + _from, + daysCovered, + defaultBucketToUser[_from] + ); + // validation of the transaction amount + if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, defaultRestriction)) { + allowedDefault == false; } - if (validGR && validIR && _dailyTxCheck(txSumOfDay, _amount)) - return Result.NA; - else - return Result.INVALID; } - return Result.NA; - } - - /** - * @notice Internal function have a logic to validate the txn amount with global restriction - */ - function _globalRestrictionCheck(address _from, uint256 _amount) internal view returns (bool, uint256, uint256, uint256) { - uint256 daysCovered; - uint256 fromTimestamp; - uint256 sumOfLastPeriod = 0; - if (bucketToUser[_from].globalLastTradedDayTime < globalRestriction.startTime) { - // It will execute when the txn is performed first time after the addition of global restriction - fromTimestamp = globalRestriction.startTime; - } else { - // picking up the preivous timestamp - fromTimestamp = bucketToUser[_from].globalLastTradedDayTime; + (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, defaultBucketToUser[_from].dailyLastTradedDayTime, defaultDailyRestriction); + + if (_isTransfer) { + _updateStorage( + _from, + _amount, + fromTimestamp, + sumOfLastPeriod, + daysCovered, + dailyTime, + defaultBucketToUser[_from] + ); } - // Calculating the difference of days - uint256 diffDays = BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now); - // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod - // re-using the local variables to avoid the stack too deep error. - (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( - fromTimestamp, - diffDays, - _from, - bucketToUser[_from], - true, - globalRestriction.rollingPeriodInDays - ); - // validation of the transaction amount - if (_checkValidAmountToTransact(sumOfLastPeriod, _amount, globalRestriction)) { - return (true, sumOfLastPeriod, fromTimestamp, daysCovered); - } - return (false, sumOfLastPeriod, fromTimestamp, daysCovered); + return ((allowedDaily && allowedDefault) == true ? Result.NA : Result.INVALID); } /** * @notice Internal function used to validate the transaction for a given address * If it validates then it also update the storage corressponds to the individual restriction */ - function _individualRestrictionCheck(address _from, uint256 _amount) internal view returns (bool, uint256, uint256, uint256) { + function _individualRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { // using the variable to avoid stack too deep error uint256 daysCovered = individualRestriction[_from].rollingPeriodInDays; - uint256 fromTimestamp; + uint256 fromTimestamp = 0; uint256 sumOfLastPeriod = 0; - if (bucketToUser[_from].lastTradedDayTime < individualRestriction[_from].startTime) { - // It will execute when the txn is performed first time after the addition of individual restriction - fromTimestamp = individualRestriction[_from].startTime; - } else { - // Picking up the last timestamp - fromTimestamp = bucketToUser[_from].lastTradedDayTime; + uint256 dailyTime = 0; + bool allowedIndividual = true; + bool allowedDaily; + if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { + if (bucketToUser[_from].lastTradedDayTime < individualRestriction[_from].startTime) { + // It will execute when the txn is performed first time after the addition of individual restriction + fromTimestamp = individualRestriction[_from].startTime; + } else { + // Picking up the last timestamp + fromTimestamp = bucketToUser[_from].lastTradedDayTime; + } + + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod + // re-using the local variables to avoid the stack too deep error. + (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( + fromTimestamp, + BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now), + _from, + daysCovered, + bucketToUser[_from] + ); + // validation of the transaction amount + if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, individualRestriction[_from])) { + allowedIndividual == false; + } } - - // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod - // re-using the local variables to avoid the stack too deep error. - (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( - fromTimestamp, - BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now), - _from, - bucketToUser[_from], - false, - daysCovered - ); - // validation of the transaction amount - if (_checkValidAmountToTransact(sumOfLastPeriod, _amount, individualRestriction[_from])) { - return (true, sumOfLastPeriod, fromTimestamp, daysCovered); - } - return (false, sumOfLastPeriod, fromTimestamp, daysCovered); + (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, bucketToUser[_from].dailyLastTradedDayTime, individualDailyRestriction[_from]); + + if (_isTransfer) { + _updateStorage( + _from, + _amount, + fromTimestamp, + sumOfLastPeriod, + daysCovered, + dailyTime, + bucketToUser[_from] + ); + } + + return ((allowedDaily && allowedIndividual) == true ? Result.NA : Result.INVALID); + } + + function _dailyTxCheck( + address from, + uint256 amount, + uint256 fromTimestamp, + uint256 dailyLastTradedDayTime, + VolumeRestriction restriction + ) + internal + view + returns(bool, uint256) + { + // Checking whether the daily restriction is added or not if yes then calculate + // the total amount get traded on a particular day (~ _fromTime) + if ( now <= restriction.endTime && now >= restriction.startTime) { + uint256 txSumOfDay = 0; + if (now.sub(dailyLastTradedDayTime) < 1 days || dailyLastTradedDayTime == 0) { + txSumOfDay = bucket[from][dailyLastTradedDayTime] >= bucket[from][fromTimestamp] ? bucket[from][dailyLastTradedDayTime] : bucket[from][fromTimestamp]; + } else { + txSumOfDay = 0; + dailyLastTradedDayTime = now; + } + return (_checkValidAmountToTransact(txSumOfDay, amount, restriction), dailyLastTradedDayTime); + } + return (true, dailyLastTradedDayTime); } /// Internal function for the bucket check @@ -581,21 +601,16 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _fromTime, uint256 _diffDays, address _from, - BucketDetails memory _bucketDetails, - bool _isGlobal, - uint256 _rollingPeriodInDays + uint256 _rollingPeriodInDays, + BucketDetails memory _bucketDetails ) internal view returns (uint256, uint256, uint256) { - uint256 counter = _bucketDetails.globalDaysCovered; - uint256 sumOfLastPeriod = _bucketDetails.globalSumOfLastPeriod; + uint256 counter = _bucketDetails.daysCovered; + uint256 sumOfLastPeriod = _bucketDetails.sumOfLastPeriod; uint256 i = 0; - if (!_isGlobal) { - counter = _bucketDetails.daysCovered; - sumOfLastPeriod = _bucketDetails.sumOfLastPeriod; - } if (_diffDays >= _rollingPeriodInDays) { // If the difference of days is greater than the rollingPeriod then sumOfLastPeriod will always be zero sumOfLastPeriod = 0; @@ -623,24 +638,6 @@ contract VolumeRestrictionTM is ITransferManager { return (sumOfLastPeriod, _fromTime, counter); } - function _dailyTxCheck( - uint256 _dailyAmount, - uint256 _amount - ) - internal - view - returns(bool) - { - // Checking whether the global day restriction is added or not if yes then calculate - // the total amount get traded on a particular day (~ _fromTime) - if ( now <= dailyGlobalRestriction.endTime && now >= dailyGlobalRestriction.startTime) - { - if (!_checkValidAmountToTransact(_dailyAmount, _amount, dailyGlobalRestriction)) - return false; - } - return true; - } - function _checkValidAmountToTransact( uint256 _sumOfLastPeriod, uint256 _amountToTransact, @@ -657,11 +654,7 @@ contract VolumeRestrictionTM is ITransferManager { _allowedAmount = _restriction.allowedTokens; } // Validation on the amount to transact - if (_allowedAmount >= _sumOfLastPeriod.add(_amountToTransact)) { - return true; - } else { - return false; - } + return (_allowedAmount >= _sumOfLastPeriod.add(_amountToTransact)); } function _updateStorage( @@ -669,37 +662,33 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _amount, uint256 _lastTradedDayTime, uint256 _sumOfLastPeriod, - uint256 _globalSumOfLastPeriod, uint256 _daysCovered, - uint256 _globalDaysCovered, - uint256 _globalLastTradedDayTime + uint256 _dailyLastTradedDayTime, + BucketDetails storage _details ) internal - { - if (bucketToUser[_from].lastTradedDayTime != _lastTradedDayTime) { + { + // Cheap storage technique + if (_details.lastTradedDayTime != _lastTradedDayTime) { // Assigning the latest transaction timestamp of the day - bucketToUser[_from].lastTradedDayTime = _lastTradedDayTime; + _details.lastTradedDayTime = _lastTradedDayTime; } - if (bucketToUser[_from].globalLastTradedDayTime != _globalLastTradedDayTime) { + if (_lastTradedDayTime != 0 && _lastTradedDayTime != _dailyLastTradedDayTime) { + // Assigning the latest transaction timestamp of the day + _details.dailyLastTradedDayTime = _lastTradedDayTime; + } else if (_details.dailyLastTradedDayTime != _dailyLastTradedDayTime) { // Assigning the latest transaction timestamp of the day - bucketToUser[_from].globalLastTradedDayTime = _globalLastTradedDayTime; + _details.dailyLastTradedDayTime = _dailyLastTradedDayTime; } - if (_amount != 0) { - if (globalRestriction.endTime >= now && globalRestriction.startTime <= now) { - bucketToUser[_from].globalSumOfLastPeriod = _globalSumOfLastPeriod.add(_amount); - bucketToUser[_from].globalDaysCovered = _globalDaysCovered; - // Increasing the total amount of the day by `_amount` - bucket[_from][_globalLastTradedDayTime] = bucket[_from][_globalLastTradedDayTime].add(_amount); - } - if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { - bucketToUser[_from].daysCovered = _daysCovered; - bucketToUser[_from].sumOfLastPeriod = _sumOfLastPeriod.add(_amount); - if (_lastTradedDayTime != _globalLastTradedDayTime) - // Increasing the total amount of the day by `_amount` - bucket[_from][_lastTradedDayTime] = bucket[_from][_lastTradedDayTime].add(_amount); - } + if (_details.daysCovered != _daysCovered) { + _details.daysCovered = _daysCovered; } - + if (_amount != 0) { + _details.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + _dailyLastTradedDayTime = _details.dailyLastTradedDayTime; + // Increasing the total amount of the day by `_amount` + bucket[_from][_dailyLastTradedDayTime] = bucket[_from][_dailyLastTradedDayTime].add(_amount); + } } function _removeIndividualRestriction(address _user) internal { @@ -830,14 +819,11 @@ contract VolumeRestrictionTM is ITransferManager { * @return uint256 sumOfLastPeriod * @return uint256 days covered */ - function getBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256, uint256, uint256) { + function getBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256) { return( bucketToUser[_user].lastTradedDayTime, bucketToUser[_user].sumOfLastPeriod, - bucketToUser[_user].daysCovered, - bucketToUser[_user].globalDaysCovered, - bucketToUser[_user].globalSumOfLastPeriod, - bucketToUser[_user].globalLastTradedDayTime + bucketToUser[_user].daysCovered ); } @@ -850,18 +836,6 @@ contract VolumeRestrictionTM is ITransferManager { return bucket[_user][_at]; } - /** - * @notice Use to get the global bucket details - * @return uint256 lastTradedDayTime - * @return uint256 sumOfLastPeriod - */ - function getGlobalBucketDetails() external view returns(uint256, uint256) { - return( - globalBucketDetails.lastTradedDayTime, - globalBucketDetails.sumOfLastPeriod - ); - } - /** * @notice This function returns the signature of configure function */ @@ -878,4 +852,4 @@ contract VolumeRestrictionTM is ITransferManager { return allPermissions; } -} +} \ No newline at end of file From f3a872234cec43574b3777bb0fbca384111dae27 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 6 Dec 2018 19:57:23 +0530 Subject: [PATCH 339/582] Merge fix --- contracts/modules/STO/CappedSTO.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 5b37b5437..af091dacf 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -275,7 +275,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { uint256 granularity = ISecurityToken(securityToken).granularity(); _tokens = _tokens.div(granularity); _tokens = _tokens.mul(granularity); - _refund = _investedAmount.sub(_tokens.div(rate)); + _refund = _investedAmount.sub((_tokens.mul(uint256(10) ** 18)).div(rate)); } /** From 6bbe51dd77962385f368e6d81447b516a2308325 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 6 Dec 2018 20:12:33 +0530 Subject: [PATCH 340/582] add functions for the individual daily restrictions --- .../TransferManager/VolumeRestrictionTM.sol | 251 ++++++++++++++++-- 1 file changed, 227 insertions(+), 24 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 1f400e9ef..d80ab217e 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -84,6 +84,15 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _endTime, uint256 _typeOfRestriction ); + // Emit when the new daily (Individual) restriction is added + event AddIndividualDailyRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); // Emit when default restriction get modified event ModifyDefaultRestriction( uint256 _allowedTokens, @@ -187,6 +196,69 @@ contract VolumeRestrictionTM is ITransferManager { ); } + /** + * @notice Use to add the new individual daily restriction for all token holder + * @param _holder Address of the token holder, whom restriction will be implied + * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + */ + function addIndividualDailyRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + _addIndividualDailyRestriction( + _holder, + _allowedTokens, + _startTime, + _endTime, + _restrictionType + ); + } + + /** + * @notice Use to add the new individual daily restriction for multiple token holders + * @param _holders Array of address of the token holders, whom restriction will be implied + * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. + * @param _startTimes Array of unix timestamps at which restrictions get into effect + * @param _endTimes Array of unix timestamps at which restriction effects will gets end. + * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + */ + function addIndividualDailyRestrictionMulti( + address[] _holders, + uint256[] _allowedTokens, + uint256[] _startTimes, + uint256[] _endTimes, + uint256[] _restrictionTypes + ) + public + withPerm(ADMIN) + { + require( + _allowedTokens.length == _startTimes.length && + _startTimes.length == _holders.length && + _holders.length == _endTimes.length && + _endTimes.length == _restrictionTypes.length, + "Array length mismatch" + ); + for (uint256 i = 0; i < _holders.length; i++) { + _addIndividualDailyRestriction( + _holders[i], + _allowedTokens[i], + _startTimes[i], + _endTimes[i], + _restrictionTypes[i] + ); + } + } + /** * @notice Use to add the new individual restriction for multiple token holders * @param _holders Array of address of the token holders, whom restriction will be implied @@ -363,6 +435,70 @@ contract VolumeRestrictionTM is ITransferManager { ); } + /** + * @notice Use to modify the existing individual daily restriction for a given token holder + * @param _holder Address of the token holder, whom restriction will be implied + * @param _allowedTokens Amount of tokens allowed to be trade for a given address. + * @param _startTime Unix timestamp at which restriction get into effect + * @param _endTime Unix timestamp at which restriction effects will gets end. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + */ + function modifyIndividualDailyRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + _modifyIndividualDailyRestriction( + _holder, + _allowedTokens, + _startTime, + _endTime, + _restrictionType + ); + } + + /** + * @notice Use to modify the existing individual daily restriction for multiple token holders + * @param _holders Array of address of the token holders, whom restriction will be implied + * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. + * @param _startTimes Array of unix timestamps at which restrictions get into effect + * @param _endTimes Array of unix timestamps at which restriction effects will gets end. + * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + */ + function modifyIndividualDailyRestrictionMulti( + address[] _holders, + uint256[] _allowedTokens, + uint256[] _startTimes, + uint256[] _endTimes, + uint256[] _restrictionTypes + ) + public + withPerm(ADMIN) + { + require( + _allowedTokens.length == _startTimes.length && + _startTimes.length == _holders.length && + _holders.length == _endTimes.length && + _endTimes.length == _restrictionTypes.length, + "Array length mismatch" + ); + require(_holders.length == _allowedTokens.length, "Length mismatch"); + for (uint256 i = 0; i < _holders.length; i++) { + _modifyIndividualDailyRestriction( + _holders[i], + _allowedTokens[i], + _startTimes[i], + _endTimes[i], + _restrictionTypes[i] + ); + } + } + /** * @notice Use to modify the existing individual restriction for multiple token holders * @param _holders Array of address of the token holders, whom restriction will be implied @@ -473,6 +609,7 @@ contract VolumeRestrictionTM is ITransferManager { */ function _defaultRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { // using the variable to avoid stack too deep error + BucketDetails memory bucketDetails = defaultBucketToUser[_from]; uint256 daysCovered = defaultRestriction.rollingPeriodInDays; uint256 fromTimestamp = 0; uint256 sumOfLastPeriod = 0; @@ -480,12 +617,12 @@ contract VolumeRestrictionTM is ITransferManager { bool allowedDefault = true; bool allowedDaily; if (defaultRestriction.endTime >= now && defaultRestriction.startTime <= now) { - if (defaultBucketToUser[_from].lastTradedDayTime < defaultRestriction.startTime) { + if (bucketDetails.lastTradedDayTime < defaultRestriction.startTime) { // It will execute when the txn is performed first time after the addition of individual restriction fromTimestamp = defaultRestriction.startTime; } else { // Picking up the last timestamp - fromTimestamp = defaultBucketToUser[_from].lastTradedDayTime; + fromTimestamp = bucketDetails.lastTradedDayTime; } // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod @@ -495,14 +632,14 @@ contract VolumeRestrictionTM is ITransferManager { BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now), _from, daysCovered, - defaultBucketToUser[_from] + bucketDetails ); // validation of the transaction amount if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, defaultRestriction)) { allowedDefault == false; } } - (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, defaultBucketToUser[_from].dailyLastTradedDayTime, defaultDailyRestriction); + (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, bucketDetails.dailyLastTradedDayTime, defaultDailyRestriction); if (_isTransfer) { _updateStorage( @@ -512,7 +649,7 @@ contract VolumeRestrictionTM is ITransferManager { sumOfLastPeriod, daysCovered, dailyTime, - defaultBucketToUser[_from] + true ); } return ((allowedDaily && allowedDefault) == true ? Result.NA : Result.INVALID); @@ -522,21 +659,24 @@ contract VolumeRestrictionTM is ITransferManager { * @notice Internal function used to validate the transaction for a given address * If it validates then it also update the storage corressponds to the individual restriction */ - function _individualRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + function _individualRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) private returns (Result) { // using the variable to avoid stack too deep error + BucketDetails memory bucketDetails = bucketToUser[_from]; + VolumeRestriction memory dailyRestriction = individualDailyRestriction[_from]; + VolumeRestriction memory restriction = individualRestriction[_from]; uint256 daysCovered = individualRestriction[_from].rollingPeriodInDays; uint256 fromTimestamp = 0; uint256 sumOfLastPeriod = 0; uint256 dailyTime = 0; bool allowedIndividual = true; bool allowedDaily; - if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) { - if (bucketToUser[_from].lastTradedDayTime < individualRestriction[_from].startTime) { + if (restriction.endTime >= now && restriction.startTime <= now) { + if (bucketDetails.lastTradedDayTime < restriction.startTime) { // It will execute when the txn is performed first time after the addition of individual restriction - fromTimestamp = individualRestriction[_from].startTime; + fromTimestamp = restriction.startTime; } else { // Picking up the last timestamp - fromTimestamp = bucketToUser[_from].lastTradedDayTime; + fromTimestamp = bucketDetails.lastTradedDayTime; } // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod @@ -546,14 +686,14 @@ contract VolumeRestrictionTM is ITransferManager { BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now), _from, daysCovered, - bucketToUser[_from] + bucketDetails ); // validation of the transaction amount - if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, individualRestriction[_from])) { + if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, restriction)) { allowedIndividual == false; } } - (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, bucketToUser[_from].dailyLastTradedDayTime, individualDailyRestriction[_from]); + (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, bucketDetails.dailyLastTradedDayTime, dailyRestriction); if (_isTransfer) { _updateStorage( @@ -563,7 +703,7 @@ contract VolumeRestrictionTM is ITransferManager { sumOfLastPeriod, daysCovered, dailyTime, - bucketToUser[_from] + false ); } @@ -664,28 +804,33 @@ contract VolumeRestrictionTM is ITransferManager { uint256 _sumOfLastPeriod, uint256 _daysCovered, uint256 _dailyLastTradedDayTime, - BucketDetails storage _details + bool isDefault ) internal { + BucketDetails storage details; + if (isDefault) + details = defaultBucketToUser[_from]; + else + details = bucketToUser[_from]; // Cheap storage technique - if (_details.lastTradedDayTime != _lastTradedDayTime) { + if (details.lastTradedDayTime != _lastTradedDayTime) { // Assigning the latest transaction timestamp of the day - _details.lastTradedDayTime = _lastTradedDayTime; + details.lastTradedDayTime = _lastTradedDayTime; } if (_lastTradedDayTime != 0 && _lastTradedDayTime != _dailyLastTradedDayTime) { // Assigning the latest transaction timestamp of the day - _details.dailyLastTradedDayTime = _lastTradedDayTime; - } else if (_details.dailyLastTradedDayTime != _dailyLastTradedDayTime) { + details.dailyLastTradedDayTime = _lastTradedDayTime; + } else if (details.dailyLastTradedDayTime != _dailyLastTradedDayTime) { // Assigning the latest transaction timestamp of the day - _details.dailyLastTradedDayTime = _dailyLastTradedDayTime; + details.dailyLastTradedDayTime = _dailyLastTradedDayTime; } - if (_details.daysCovered != _daysCovered) { - _details.daysCovered = _daysCovered; + if (details.daysCovered != _daysCovered) { + details.daysCovered = _daysCovered; } if (_amount != 0) { - _details.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); - _dailyLastTradedDayTime = _details.dailyLastTradedDayTime; + details.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + _dailyLastTradedDayTime = details.dailyLastTradedDayTime; // Increasing the total amount of the day by `_amount` bucket[_from][_dailyLastTradedDayTime] = bucket[_from][_dailyLastTradedDayTime].add(_amount); } @@ -768,6 +913,64 @@ contract VolumeRestrictionTM is ITransferManager { ); } + function _addIndividualDailyRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + internal + { + require( + individualDailyRestriction[_holder].endTime < now, + "Not Allowed" + ); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); + individualDailyRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddIndividualDailyRestriction( + _holder, + _allowedTokens, + _startTime, + 1, + _endTime, + _restrictionType + ); + } + + function _modifyIndividualDailyRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + internal + { + require(individualDailyRestriction[_holder].startTime > now, "Not allowed"); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); + individualDailyRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyDefaultDailyRestriction( + _allowedTokens, + _startTime, + 1, + _endTime, + _restrictionType + ); + } + function _checkInputParams( uint256 _allowedTokens, uint256 _startTime, From 3b983b5eeee2a1c59dec41c28bc22318c3f850db Mon Sep 17 00:00:00 2001 From: shuffledex Date: Thu, 6 Dec 2018 13:10:57 -0300 Subject: [PATCH 341/582] code advances --- CLI/commands/investor_portal.js | 101 ++++++++++++++++++++++++-------- CLI/commands/sto_manager.js | 3 +- package.json | 1 + 3 files changed, 77 insertions(+), 28 deletions(-) diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 4b01705b3..54aba70c4 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -10,6 +10,8 @@ var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); const STO_KEY = 3; +const ETH = 'ETH'; +const POLY = 'POLY'; const STABLE = 'STABLE'; let securityTokenRegistry; @@ -17,7 +19,6 @@ let securityToken; let selectedSTO; let currentSTO; let polyToken; -let usdToken; let generalTransferManager; let raiseTypes = []; @@ -90,10 +91,6 @@ async function setup() { let polytokenABI = abis.polyToken(); polyToken = new web3.eth.Contract(polytokenABI, polytokenAddress); polyToken.setProvider(web3.currentProvider); - - let usdTokenAddress = await contracts.usdToken(); - usdToken = new web3.eth.Contract(polytokenABI, usdTokenAddress); - usdToken.setProvider(web3.currentProvider); } catch (err) { console.log(err); console.log(chalk.red(`There was a problem getting the contracts. Make sure they are deployed to the selected network.`)); @@ -155,6 +152,8 @@ async function showTokenInfo() { // Show info async function showUserInfo(_user) { + let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); + console.log(` ******************* User Information ******************** - Address: ${_user}`); @@ -165,7 +164,10 @@ async function showUserInfo(_user) { console.log(` - ETH balance:\t ${web3.utils.fromWei(await web3.eth.getBalance(_user))}`); } if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.STABLE).call()) { - console.log(` - DAI balance:\t ${await usdBalance(_user)}`); + let stableSymbolsAndBalance = await processAddressWithBalance(listOfStableCoins); + stableSymbolsAndBalance.forEach(stable => { + console.log(` - ${stable.symbol} balance:\t ${web3.utils.fromWei(stable.balance)}`); + }); } } @@ -238,6 +240,16 @@ async function showCappedSTOInfo() { } } +async function processAddressWithBalance(array) { + let list = []; + for (const address of array) { + let symbol = await checkSymbol(address); + let balance = await checkBalance(address); + list.push({'address': address, 'symbol': symbol, 'balance': balance}) + } + return list +} + async function processAddress(array) { let list = []; for (const address of array) { @@ -256,11 +268,19 @@ async function checkSymbol(address) { } } +async function checkBalance(address) { + let stableCoin = common.connect(abis.erc20(), address); + try { + return await stableCoin.methods.balanceOf(User.address).call(); + } catch (e) { + return "" + } +} + async function showUserInfoForUSDTieredSTO() { let stableSymbols = []; - //REMOVE ONCE SMART CONTRACT SUPPORT METHOD TO GET STABLE COIN ADDRESSES - let listOfStableCoins = ["0xa016B2ae79436E20FBe22Bf230a92A5Fb055762F", "0xae794d38cb481868a8CB19b9d7A5073851bC6dB7"]; + let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); for (const fundType in gbl.constants.FUND_RAISE_TYPES) { if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { @@ -311,8 +331,7 @@ async function showUSDTieredSTOInfo() { let displayTokenSymbol = await securityToken.methods.symbol().call(); let tiersLength = await currentSTO.methods.getNumberOfTiers().call(); let stableSymbols = []; - //REMOVE ONCE SMART CONTRACT SUPPORT METHOD TO GET STABLE COIN ADDRESSES - let listOfStableCoins = ["0xa016B2ae79436E20FBe22Bf230a92A5Fb055762F", "0xae794d38cb481868a8CB19b9d7A5073851bC6dB7"]; + let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); for (const fundType in gbl.constants.FUND_RAISE_TYPES) { if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES[fundType]).call()) { @@ -496,7 +515,11 @@ async function investCappedSTO(currency, amount) { // Allow investor to buy tokens. async function investUsdTieredSTO(currency, amount) { + let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); + let stableSymbols = await processAddress(listOfStableCoins); + let raiseType; + if (typeof currency !== 'undefined') { if (!raiseTypes.inlcudes(currency)) { console.log(chalk.red(`${currency} is not allowed for current STO`)); @@ -507,9 +530,20 @@ async function investUsdTieredSTO(currency, amount) { } else { for (const type of raiseTypes) { let displayPrice = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], web3.utils.toWei("1")).call()); - console.log(chalk.green(` Current ${type} price:\t\t ${displayPrice} USD`)); + if ((type == STABLE) && (stableSymbols.length)) { + console.log(chalk.green(` Current ${stableSymbols.toString()} price:\t\t ${displayPrice} USD`)); + } else { + console.log(chalk.green(` Current ${type} price:\t\t ${displayPrice} USD`)); + } } if (raiseTypes.length > 1) { + const stableIndex = raiseTypes.indexOf(STABLE); + if (stableIndex > -1) { + raiseTypes.splice(stableIndex, 1) + stableSymbols.forEach((symbol) => { + raiseTypes.push(symbol) + }) + } let index = readlineSync.keyInSelect(raiseTypes, 'Choose one of the allowed raise types: ', { cancel: false }); raiseType = raiseTypes[index]; } else { @@ -522,7 +556,15 @@ async function investUsdTieredSTO(currency, amount) { if (typeof amount === 'undefined') { let investorInvestedUSD = web3.utils.fromWei(await currentSTO.methods.investorInvestedUSD(User.address).call()); let minimumInvestmentUSD = await currentSTO.methods.minimumInvestmentUSD().call(); - let minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(gbl.constants.FUND_RAISE_TYPES[raiseType], minimumInvestmentUSD).call(); + let minimumInvestmentRaiseType; + + // if raiseType is different than ETH or POLY, we assume is STABLE + if ((raiseType != ETH) && (raiseType != POLY)) { + minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(gbl.constants.FUND_RAISE_TYPES[STABLE], minimumInvestmentUSD).call(); + } else { + minimumInvestmentRaiseType = await currentSTO.methods.convertFromUSD(gbl.constants.FUND_RAISE_TYPES[raiseType], minimumInvestmentUSD).call(); + } + cost = readlineSync.question(chalk.yellow(`Enter the amount of ${raiseType} you would like to invest or press 'Enter' to exit: `), { limit: function (input) { return investorInvestedUSD != 0 || parseInt(input) > parseInt(web3.utils.fromWei(minimumInvestmentRaiseType)); @@ -536,7 +578,14 @@ async function investUsdTieredSTO(currency, amount) { let costWei = web3.utils.toWei(cost.toString()); - let tokensToBuy = await currentSTO.methods.buyTokensView(User.address, costWei, gbl.constants.FUND_RAISE_TYPES[raiseType]).call(); + let tokensToBuy; + // if raiseType is different than ETH or POLY, we assume is STABLE + if ((raiseType != ETH) && (raiseType != POLY)) { + tokensToBuy = await currentSTO.methods.buyTokensView(User.address, costWei, gbl.constants.FUND_RAISE_TYPES[STABLE]).call(); + } else { + tokensToBuy = await currentSTO.methods.buyTokensView(User.address, costWei, gbl.constants.FUND_RAISE_TYPES[raiseType]).call(); + } + let minTokenToBuy = tokensToBuy.tokensMinted; console.log(chalk.yellow(`You are going to spend ${web3.utils.fromWei(tokensToBuy.spentValue)} ${raiseType} (${web3.utils.fromWei(tokensToBuy.spentUSD)} USD) to buy ${web3.utils.fromWei(minTokenToBuy)} ${STSymbol} approx.`)); console.log(chalk.yellow(`Due to ${raiseType} price changes and network delays, it is possible that the final amount of purchased tokens is lower.`)); @@ -544,7 +593,7 @@ async function investUsdTieredSTO(currency, amount) { minTokenToBuy = 0; } - if (raiseType == 'POLY') { + if (raiseType == POLY) { let userBalance = await polyBalance(User.address); if (parseInt(userBalance) >= parseInt(cost)) { let allowance = await polyToken.methods.allowance(STOAddress, User.address).call(); @@ -560,19 +609,24 @@ async function investUsdTieredSTO(currency, amount) { console.log(chalk.red(`Please purchase a smaller amount of tokens or access the POLY faucet to get the POLY to complete this txn.`)); process.exit(); } - } else if (raiseType == 'DAI') { - let userBalance = await usdBalance(User.address); - if (parseInt(userBalance) >= parseInt(cost)) { - let allowance = await usdToken.methods.allowance(STOAddress, User.address).call(); + } else if ((raiseType != POLY) && (raiseType != ETH)) { + + let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); + let stableSymbolsAndBalance = await processAddressWithBalance(listOfStableCoins); + let stableInfo = stableSymbolsAndBalance.find(o => o.symbol === raiseType); + + if (parseInt(stableInfo.balance) >= parseInt(cost)) { + let stableCoin = common.connect(abis.erc20(), stableInfo.address); + let allowance = await stableCoin.methods.allowance(STOAddress, User.address).call(); if (allowance < costWei) { - let approveAction = usdToken.methods.approve(STOAddress, costWei); + let approveAction = stableCoin.methods.approve(STOAddress, costWei); await common.sendTransaction(approveAction, { from: User }); } - let actionBuyWithUSD = currentSTO.methods.buyWithUSDRateLimited(User.address, costWei, minTokenToBuy); + let actionBuyWithUSD = currentSTO.methods.buyWithUSDRateLimited(User.address, costWei, minTokenToBuy, stableInfo.address); let receipt = await common.sendTransaction(actionBuyWithUSD, { from: User, factor: 1.5 }); logTokensPurchasedUSDTieredSTO(receipt); } else { - console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} DAI but have ${userBalance} DAI.`)); + console.log(chalk.red(`Not enough balance to Buy tokens, Require ${cost} ${stableInfo.symbol} but have ${stableInfo.balance} ${stableInfo.symbol}.`)); console.log(chalk.red(`Please purchase a smaller amount of tokens.`)); process.exit(); } @@ -591,11 +645,6 @@ async function polyBalance(_user) { return web3.utils.fromWei(balance); } -async function usdBalance(_user) { - let balance = await usdToken.methods.balanceOf(_user).call(); - return web3.utils.fromWei(balance); -} - function logTokensPurchasedUSDTieredSTO(receipt) { console.log(chalk.green(`Congratulations! The token purchase was successfully completed.`)); let events = common.getMultipleEventsFromLogs(currentSTO._jsonInterface, receipt.logs, 'TokenPurchase'); diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 316bdceb7..d9e95f723 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -577,8 +577,7 @@ async function usdTieredSTO_status(currentSTO) { let displayIsFinalized = await currentSTO.methods.isFinalized().call() ? "YES" : "NO"; let displayTokenSymbol = await securityToken.methods.symbol().call(); let tiersLength = await currentSTO.methods.getNumberOfTiers().call(); - //REMOVE ONCE SMART CONTRACT SUPPORT METHOD TO GET STABLE COIN ADDRESSES - let listOfStableCoins = ["0xa016B2ae79436E20FBe22Bf230a92A5Fb055762F", "0xae794d38cb481868a8CB19b9d7A5073851bC6dB7"]; + let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); let raiseTypes = []; let stableSymbols = []; diff --git a/package.json b/package.json index ef2d76c38..7341ea9da 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "bignumber.js": "^5.0.0", "chalk": "^2.4.1", "coveralls": "^3.0.1", + "csv-parse": "^4.0.1", "ethereumjs-testrpc": "^6.0.3", "ethers": "^3.0.15", "fs": "0.0.1-security", From 429b7e870c5e3bfb1c9aa62e3391db504320886a Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 6 Dec 2018 23:45:51 +0530 Subject: [PATCH 342/582] change the type of proxy deployment for USDTieredSTO --- CHANGELOG.md | 1 + contracts/interfaces/IBoot.sol | 10 +++ contracts/modules/STO/ISTO.sol | 18 +--- contracts/modules/STO/ISTOStorage.sol | 24 +++++ .../ProxyFactory/USDTieredSTOProxyFactory.sol | 33 ------- contracts/modules/STO/USDTieredSTO.sol | 89 +++---------------- contracts/modules/STO/USDTieredSTOFactory.sol | 16 ++-- contracts/modules/STO/USDTieredSTOStorage.sol | 82 +++++++++++++++++ contracts/proxy/USDTieredSTOProxy.sol | 32 +++++++ migrations/2_deploy_contracts.js | 13 +-- test/helpers/createInstances.js | 7 +- 11 files changed, 180 insertions(+), 145 deletions(-) create mode 100644 contracts/interfaces/IBoot.sol create mode 100644 contracts/modules/STO/ISTOStorage.sol delete mode 100644 contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol create mode 100644 contracts/modules/STO/USDTieredSTOStorage.sol create mode 100644 contracts/proxy/USDTieredSTOProxy.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 562d7c4f4..f41982216 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. * Added `buyWithETHRateLimited`, `buyWithPOLYRateLimited` and `buyWithUSDRateLimited` to USDTSTO. * Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. * Removed individual mappings for tier data removed in UDSTSTO. +* Removed the old Proxy deployment method of USDTieredSTO and adopt the new inherited proxy deployment approach. ## GeneralTransferManager * `getInvestors`, `getAllInvestorsData`, `getInvestorsData` added to GTM to allow easy data queries. diff --git a/contracts/interfaces/IBoot.sol b/contracts/interfaces/IBoot.sol new file mode 100644 index 000000000..db29dc319 --- /dev/null +++ b/contracts/interfaces/IBoot.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.4.24; + +interface IBoot { + + /** + * @notice This function returns the signature of configure function + * @return bytes4 Configure function signature + */ + function getInitFunction() external pure returns(bytes4); +} \ No newline at end of file diff --git a/contracts/modules/STO/ISTO.sol b/contracts/modules/STO/ISTO.sol index 6ed1d5ba1..7c8e45852 100644 --- a/contracts/modules/STO/ISTO.sol +++ b/contracts/modules/STO/ISTO.sol @@ -3,30 +3,16 @@ pragma solidity ^0.4.24; import "../../Pausable.sol"; import "../Module.sol"; import "../../interfaces/IERC20.sol"; +import "./ISTOStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Interface to be implemented by all STO modules */ -contract ISTO is Module, Pausable { +contract ISTO is ISTOStorage, Module, Pausable { using SafeMath for uint256; enum FundRaiseType { ETH, POLY, DAI } - mapping (uint8 => bool) public fundRaiseTypes; - mapping (uint8 => uint256) public fundsRaised; - - // Start time of the STO - uint256 public startTime; - // End time of the STO - uint256 public endTime; - // Time STO was paused - uint256 public pausedTime; - // Number of individual investors - uint256 public investorCount; - // Address where ETH & POLY funds are delivered - address public wallet; - // Final amount of tokens sold - uint256 public totalTokensSold; // Event event SetFundRaiseTypes(FundRaiseType[] _fundRaiseTypes); diff --git a/contracts/modules/STO/ISTOStorage.sol b/contracts/modules/STO/ISTOStorage.sol new file mode 100644 index 000000000..b808c98b4 --- /dev/null +++ b/contracts/modules/STO/ISTOStorage.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.4.24; + +/** + * @title Storage layout for the ISTO contract + */ +contract ISTOStorage { + + mapping (uint8 => bool) public fundRaiseTypes; + mapping (uint8 => uint256) public fundsRaised; + + // Start time of the STO + uint256 public startTime; + // End time of the STO + uint256 public endTime; + // Time STO was paused + uint256 public pausedTime; + // Number of individual investors + uint256 public investorCount; + // Address where ETH & POLY funds are delivered + address public wallet; + // Final amount of tokens sold + uint256 public totalTokensSold; + +} \ No newline at end of file diff --git a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol deleted file mode 100644 index d9a48b87d..000000000 --- a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma solidity ^0.4.24; - -import "../USDTieredSTO.sol"; -import "../../../interfaces/IUSDTieredSTOProxy.sol"; - -contract USDTieredSTOProxyFactory is IUSDTieredSTOProxy { - - constructor() public { - - } - - /** - * @notice Deploys the STO. - * @param _securityToken Contract address of the securityToken - * @param _polyAddress Contract address of the PolyToken. - * @param _factoryAddress Contract address of the factory - * @return address Address of the deployed STO - */ - function deploySTO(address _securityToken, address _polyAddress, address _factoryAddress) external returns (address) { - address newSecurityTokenAddress = new USDTieredSTO(_securityToken, _polyAddress, _factoryAddress); - return newSecurityTokenAddress; - } - - /** - * @notice Used to get the init function signature - * @param _contractAddress Address of the STO contract - * @return bytes4 - */ - function getInitFunction(address _contractAddress) external returns (bytes4) { - return USDTieredSTO(_contractAddress).getInitFunction(); - } - -} diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index baba70472..825df2122 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -7,86 +7,16 @@ import "../../RegistryUpdater.sol"; import "../../libraries/DecimalMath.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; +import "./USDTieredSTOStorage.sol"; /** * @title STO module for standard capped crowdsale */ -contract USDTieredSTO is ISTO, ReentrancyGuard { +contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { using SafeMath for uint256; - ///////////// - // Storage // - ///////////// - struct Tier { - // How many token units a buyer gets per USD in this tier (multiplied by 10**18) - uint256 rate; - - // How many token units a buyer gets per USD in this tier (multiplied by 10**18) when investing in POLY up to tokensDiscountPoly - uint256 rateDiscountPoly; - - // How many tokens are available in this tier (relative to totalSupply) - uint256 tokenTotal; - - // How many token units are available in this tier (relative to totalSupply) at the ratePerTierDiscountPoly rate - uint256 tokensDiscountPoly; - - // How many tokens have been minted in this tier (relative to totalSupply) - uint256 mintedTotal; - - // How many tokens have been minted in this tier (relative to totalSupply) for each fund raise type - mapping (uint8 => uint256) minted; - - // How many tokens have been minted in this tier (relative to totalSupply) at discounted POLY rate - uint256 mintedDiscountPoly; - } - - string public POLY_ORACLE = "PolyUsdOracle"; - string public ETH_ORACLE = "EthUsdOracle"; - mapping (bytes32 => mapping (bytes32 => string)) oracleKeys; - - IERC20 public usdToken; - - // Determine whether users can invest on behalf of a beneficiary - bool public allowBeneficialInvestments = false; - - // Whether or not the STO has been finalized - bool public isFinalized; - - // Address where ETH, POLY & DAI funds are delivered - address public wallet; - - // Address of issuer reserve wallet for unsold tokens - address public reserveWallet; - - // Current tier - uint256 public currentTier; - - // Amount of USD funds raised - uint256 public fundsRaisedUSD; - - // Amount in USD invested by each address - mapping (address => uint256) public investorInvestedUSD; - - // Amount in fund raise type invested by each investor - mapping (address => mapping (uint8 => uint256)) public investorInvested; - - // List of accredited investors - mapping (address => bool) public accredited; - - // Default limit in USD for non-accredited investors multiplied by 10**18 - uint256 public nonAccreditedLimitUSD; - - // Overrides for default limit in USD for non-accredited investors multiplied by 10**18 - mapping (address => uint256) public nonAccreditedLimitUSDOverride; - - // Minimum investable amount in USD - uint256 public minimumInvestmentUSD; - - // Final amount of tokens returned to issuer - uint256 public finalAmountReturned; - - // Array of Tiers - Tier[] public tiers; + string public constant POLY_ORACLE = "PolyUsdOracle"; + string public constant ETH_ORACLE = "EthUsdOracle"; //////////// // Events // @@ -158,11 +88,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // STO Configuration // /////////////////////// - constructor (address _securityToken, address _polyAddress, address _factory) public Module(_securityToken, _polyAddress) { - require(_factory != address(0), "Invalid factory"); - oracleKeys[bytes32("ETH")][bytes32("USD")] = ETH_ORACLE; - oracleKeys[bytes32("POLY")][bytes32("USD")] = POLY_ORACLE; - factory = _factory; //Explicitly setting factory as we are using proxy deployment for this module + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { } /** @@ -192,6 +121,8 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { address _reserveWallet, address _usdToken ) public onlyFactory { + oracleKeys[bytes32("ETH")][bytes32("USD")] = ETH_ORACLE; + oracleKeys[bytes32("POLY")][bytes32("USD")] = POLY_ORACLE; require(endTime == 0, "Already configured"); _modifyTimes(_startTime, _endTime); _modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index adc3ba628..fee9eebb6 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -1,6 +1,7 @@ pragma solidity ^0.4.24; -import "../../interfaces/IUSDTieredSTOProxy.sol"; +import "../../interfaces/IBoot.sol"; +import "../../proxy/USDTieredSTOProxy.sol"; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; @@ -9,17 +10,17 @@ import "../../libraries/Util.sol"; */ contract USDTieredSTOFactory is ModuleFactory { - address public USDTieredSTOProxyAddress; + address public logicContract; /** * @notice Constructor * @param _polyAddress Address of the polytoken */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _proxyFactoryAddress) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - require(_proxyFactoryAddress != address(0), "0x address is not allowed"); - USDTieredSTOProxyAddress = _proxyFactoryAddress; + require(_logicContract != address(0), "0x address is not allowed"); + logicContract = _logicContract; version = "1.0.0"; name = "USDTieredSTO"; title = "USD Tiered STO"; @@ -36,11 +37,10 @@ contract USDTieredSTOFactory is ModuleFactory { function deploy(bytes _data) external returns(address) { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Sufficent Allowance is not provided"); - require(USDTieredSTOProxyAddress != address(0), "Proxy contract should be pre-set"); //Check valid bytes - can only call module init function - address usdTieredSTO = IUSDTieredSTOProxy(USDTieredSTOProxyAddress).deploySTO(msg.sender, address(polyToken), address(this)); + address usdTieredSTO = new USDTieredSTOProxy(msg.sender, address(polyToken), logicContract); //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == IUSDTieredSTOProxy(USDTieredSTOProxyAddress).getInitFunction(usdTieredSTO), "Invalid data"); + require(Util.getSig(_data) == IBoot(usdTieredSTO).getInitFunction(), "Invalid data"); /*solium-disable-next-line security/no-low-level-calls*/ require(address(usdTieredSTO).call(_data), "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ diff --git a/contracts/modules/STO/USDTieredSTOStorage.sol b/contracts/modules/STO/USDTieredSTOStorage.sol new file mode 100644 index 000000000..031792f42 --- /dev/null +++ b/contracts/modules/STO/USDTieredSTOStorage.sol @@ -0,0 +1,82 @@ +pragma solidity ^0.4.24; + +import "../../interfaces/IERC20.sol"; + +/** + * @title Contract used to store layout for the USDTieredSTO storage + */ +contract USDTieredSTOStorage { + + ///////////// + // Storage // + ///////////// + struct Tier { + // How many token units a buyer gets per USD in this tier (multiplied by 10**18) + uint256 rate; + + // How many token units a buyer gets per USD in this tier (multiplied by 10**18) when investing in POLY up to tokensDiscountPoly + uint256 rateDiscountPoly; + + // How many tokens are available in this tier (relative to totalSupply) + uint256 tokenTotal; + + // How many token units are available in this tier (relative to totalSupply) at the ratePerTierDiscountPoly rate + uint256 tokensDiscountPoly; + + // How many tokens have been minted in this tier (relative to totalSupply) + uint256 mintedTotal; + + // How many tokens have been minted in this tier (relative to totalSupply) for each fund raise type + mapping (uint8 => uint256) minted; + + // How many tokens have been minted in this tier (relative to totalSupply) at discounted POLY rate + uint256 mintedDiscountPoly; + } + + mapping (bytes32 => mapping (bytes32 => string)) oracleKeys; + + IERC20 public usdToken; + + // Determine whether users can invest on behalf of a beneficiary + bool public allowBeneficialInvestments = false; + + // Whether or not the STO has been finalized + bool public isFinalized; + + // Address where ETH, POLY & DAI funds are delivered + address public wallet; + + // Address of issuer reserve wallet for unsold tokens + address public reserveWallet; + + // Current tier + uint256 public currentTier; + + // Amount of USD funds raised + uint256 public fundsRaisedUSD; + + // Amount in USD invested by each address + mapping (address => uint256) public investorInvestedUSD; + + // Amount in fund raise type invested by each investor + mapping (address => mapping (uint8 => uint256)) public investorInvested; + + // List of accredited investors + mapping (address => bool) public accredited; + + // Default limit in USD for non-accredited investors multiplied by 10**18 + uint256 public nonAccreditedLimitUSD; + + // Overrides for default limit in USD for non-accredited investors multiplied by 10**18 + mapping (address => uint256) public nonAccreditedLimitUSDOverride; + + // Minimum investable amount in USD + uint256 public minimumInvestmentUSD; + + // Final amount of tokens returned to issuer + uint256 public finalAmountReturned; + + // Array of Tiers + Tier[] public tiers; + +} \ No newline at end of file diff --git a/contracts/proxy/USDTieredSTOProxy.sol b/contracts/proxy/USDTieredSTOProxy.sol new file mode 100644 index 000000000..12cf8fdb1 --- /dev/null +++ b/contracts/proxy/USDTieredSTOProxy.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.4.24; + +import "../modules/STO/USDTieredSTOStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; +import "../modules/STO/ISTOStorage.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title USDTiered STO module Proxy + */ +contract USDTieredSTOProxy is USDTieredSTOStorage, ISTOStorage, ModuleStorage, Pausable, ReentrancyGuard, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + +} diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index f25cfab35..88883d5a2 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -3,7 +3,7 @@ const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManage const GeneralTransferManagerLogic = artifacts.require('./GeneralTransferManager.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') -const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); +const USDTieredSTOLogic = artifacts.require('./USDTieredSTO.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') const EtherDividendCheckpointLogic = artifacts.require('./EtherDividendCheckpoint.sol') const ERC20DividendCheckpointLogic = artifacts.require('./ERC20DividendCheckpoint.sol') @@ -160,6 +160,10 @@ module.exports = function (deployer, network, accounts) { // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) return deployer.deploy(EtherDividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the USDTieredSTOLogic Contract (Factory used to generate the USDTieredSTO contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(USDTieredSTOLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); }).then(() => { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) @@ -286,12 +290,9 @@ module.exports = function (deployer, network, accounts) { // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(CappedSTOFactory.address, true, {from: PolymathAccount}) - }).then(() => { - // Deploy the proxy factory - return deployer.deploy(USDTieredSTOProxyFactory, {from: PolymathAccount}); }).then(() => { // H) Deploy the USDTieredSTOFactory (Use to generate the USDTieredSTOFactory contract which will used to collect the funds ). - return deployer.deploy(USDTieredSTOFactory, PolyToken, usdTieredSTOSetupCost, 0, 0, USDTieredSTOProxyFactory.address, {from: PolymathAccount}) + return deployer.deploy(USDTieredSTOFactory, PolyToken, usdTieredSTOSetupCost, 0, 0, USDTieredSTOLogic.address, {from: PolymathAccount}) }).then(() => { // I) Register the USDTieredSTOFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the USDTieredSTOFactory contract. @@ -324,7 +325,7 @@ module.exports = function (deployer, network, accounts) { CappedSTOFactory: ${CappedSTOFactory.address} USDTieredSTOFactory: ${USDTieredSTOFactory.address} - USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} + USDTieredSTOLogic: ${USDTieredSTOLogic.address} CountTransferManagerFactory: ${CountTransferManagerFactory.address} PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 81ee9606b..77c7a5e5d 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -17,7 +17,7 @@ const TrackedRedemptionFactory = artifacts.require("./TrackedRedemptionFactory.s const PercentageTransferManagerFactory = artifacts.require("./PercentageTransferManagerFactory.sol"); const ScheduledCheckpointFactory = artifacts.require('./ScheduledCheckpointFactory.sol'); const USDTieredSTOFactory = artifacts.require("./USDTieredSTOFactory.sol"); -const USDTieredSTOProxyFactory = artifacts.require("./USDTieredSTOProxyFactory"); +const USDTieredSTO = artifacts.require("./USDTieredSTO"); const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); const FeatureRegistry = artifacts.require("./FeatureRegistry.sol"); const STFactory = artifacts.require("./STFactory.sol"); @@ -65,6 +65,7 @@ let I_SecurityToken; let I_DummySTOFactory; let I_PolyToken; let I_STFactory; +let I_USDTieredSTOLogic; let I_PolymathRegistry; let I_SecurityTokenRegistryProxy; let I_STRProxied; @@ -343,9 +344,9 @@ export async function deployPresaleSTOAndVerified(accountPolymath, MRProxyInstan } export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({from: accountPolymath}); + I_USDTieredSTOLogic = await USDTieredSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(polyToken, setupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: accountPolymath }); + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(polyToken, setupCost, 0, 0, I_USDTieredSTOLogic.address, { from: accountPolymath }); assert.notEqual( I_USDTieredSTOFactory.address.valueOf(), From 265ef4a7cddae71c0bee68eabb640b397168cfb7 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 6 Dec 2018 18:40:33 -0300 Subject: [PATCH 343/582] Time travel on development network --- CLI/commands/helpers/time.js | 59 ++++++++++++++++++++++++++++++++++++ CLI/polymath-cli.js | 48 ++++++++++++++++++++--------- 2 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 CLI/commands/helpers/time.js diff --git a/CLI/commands/helpers/time.js b/CLI/commands/helpers/time.js new file mode 100644 index 000000000..3c5e2ce3c --- /dev/null +++ b/CLI/commands/helpers/time.js @@ -0,0 +1,59 @@ +const moment = require('moment'); +const chalk = require('chalk'); + +function jumpToTime(timestamp) { + const id = Date.now(); + + return new Promise((resolve, reject) => { + web3.currentProvider.send( + { + jsonrpc: "2.0", + method: "evm_mine", + params: [timestamp], + id: id + }, + (err, res) => { + return err ? reject(err) : resolve(res); + } + ); + }); +} + +async function increaseTimeByDate(toTime) { + if (await web3.eth.net.getId() === 15) { + if (toTime.isValid()) { + let currentTime = (await web3.eth.getBlock('latest')).timestamp; + if (toTime.unix() > currentTime) { + await jumpToTime(toTime.unix()); + currentTime = (await web3.eth.getBlock('latest')).timestamp; + console.log(chalk.gree(`Current datetime is ${currentTime} or ${moment.unix(currentTime).format("MM/DD/YYYY HH:mm:ss")}`)); + } else { + console.log(chalk.red(`It is not possible to go back in time. Please try again with a time in the future to travel to`)); + } + } else { + console.log(chalk.red(`Date format is not valid. Please use a valid Unix epoch time`)); + } + } else { + console.log(chalk.red(`Time traveling is only possible over develpment network`)); + } +} + +async function increaseTimeByDuration(duration) { + let blockTimestamp = moment.unix((await web3.eth.getBlock('latest')).timestamp); + let toTime = blockTimestamp.add(duration, "seconds"); + return increaseTimeByDate(toTime); +} + +function increaseTimeToDate(date) { + var toDate = moment(date, ['MM-DD-YYYY', 'MM-DD-YYYY HH:mm:ss']); + return increaseTimeByDate(toDate); +} + +function increaseTimeToEpochDate(epochDate) { + var toTime = moment.unix(epochDate); + return increaseTimeByDate(toTime); +} + +module.exports = { increaseTimeByDuration, increaseTimeToDate, increaseTimeToEpochDate }; + + diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 2ce101a4d..1a423385b 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -1,19 +1,21 @@ #!/usr/bin/env node -var faucet = require('./commands/faucet'); -var investor_portal = require('./commands/investor_portal'); -var token_manager = require('./commands/token_manager'); -var st20generator = require('./commands/ST20Generator'); -var sto_manager = require('./commands/sto_manager'); -var transfer = require('./commands/transfer'); -var transfer_ownership = require('./commands/transfer_ownership'); -var dividends_manager = require('./commands/dividends_manager'); -var transfer_manager = require('./commands/transfer_manager'); -var contract_manager = require('./commands/contract_manager'); -var strMigrator = require('./commands/strMigrator'); -var permission_manager = require('./commands/permission_manager'); -var program = require('commander'); -var gbl = require('./commands/common/global'); +const faucet = require('./commands/faucet'); +const investor_portal = require('./commands/investor_portal'); +const token_manager = require('./commands/token_manager'); +const st20generator = require('./commands/ST20Generator'); +const sto_manager = require('./commands/sto_manager'); +const transfer = require('./commands/transfer'); +const transfer_ownership = require('./commands/transfer_ownership'); +const dividends_manager = require('./commands/dividends_manager'); +const transfer_manager = require('./commands/transfer_manager'); +const contract_manager = require('./commands/contract_manager'); +const strMigrator = require('./commands/strMigrator'); +const permission_manager = require('./commands/permission_manager'); +const time = require('./commands/helpers/time') +const gbl = require('./commands/common/global'); +const program = require('commander'); +const moment = require('moment'); const yaml = require('js-yaml'); const fs = require('fs'); @@ -151,6 +153,24 @@ program await permission_manager.executeApp(); }); +program + .command('time_travel') + .alias('tt') + .option('-p, --period ', 'Period of time in seconds to increase') + .option('-d, --toDate ', 'Human readable date ("MM/DD/YY [HH:mm:ss]") to travel to') + .option('-e, --toEpochTime ', 'Unix Epoch time to travel to') + .description('Increases time on EVM according to given value.') + .action(async function (cmd) { + await gbl.initialize(program.remoteNode); + if (cmd.period) { + await time.increaseTimeByDuration(parseInt(cmd.period)); + } else if (cmd.toDate) { + await time.increaseTimeToDate(cmd.toDate); + } else if (cmd.toEpochTime) { + await time.increaseTimeToEpochDate(cmd.toEpochTime); + } + }); + program.parse(process.argv); if (typeof program.commands.length == 0) { From c9fae08b6e276a15d1a3c5c8e2b51892a3fe7747 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 6 Dec 2018 18:49:41 -0300 Subject: [PATCH 344/582] Fix jump a period of time --- CLI/commands/helpers/time.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CLI/commands/helpers/time.js b/CLI/commands/helpers/time.js index 3c5e2ce3c..dd244d04e 100644 --- a/CLI/commands/helpers/time.js +++ b/CLI/commands/helpers/time.js @@ -38,9 +38,9 @@ async function increaseTimeByDate(toTime) { } } -async function increaseTimeByDuration(duration) { - let blockTimestamp = moment.unix((await web3.eth.getBlock('latest')).timestamp); - let toTime = blockTimestamp.add(duration, "seconds"); +function increaseTimeByDuration(duration) { + let currentTime = moment().unix(); + let toTime = currentTime.add(duration, "seconds"); return increaseTimeByDate(toTime); } From e14a18e71a761d69c21e773c78907885f50843c5 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Thu, 6 Dec 2018 18:51:43 -0300 Subject: [PATCH 345/582] final code --- CLI/commands/investor_portal.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 54aba70c4..bbebc003c 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -59,17 +59,18 @@ async function executeApp(investorAddress, investorPrivKey, symbol, currency, am try { await inputSymbol(symbol); - await showUserInfo(User.address); switch (selectedSTO) { case 'CappedSTO': let cappedSTOABI = abis.cappedSTO(); currentSTO = new web3.eth.Contract(cappedSTOABI, STOAddress); + await showUserInfo(User.address); await showCappedSTOInfo(); await investCappedSTO(currency, amount); break; case 'USDTieredSTO': let usdTieredSTOABI = abis.usdTieredSTO(); currentSTO = new web3.eth.Contract(usdTieredSTOABI, STOAddress); + await showUserInfo(User.address); await showUserInfoForUSDTieredSTO(); await showUSDTieredSTOInfo(); await investUsdTieredSTO(currency, amount) From e9a46364bca02e5940c84cdd9f4bf83d5c137a2f Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 7 Dec 2018 10:34:30 +0530 Subject: [PATCH 346/582] VRTM smart contract completion --- .../TransferManager/VolumeRestrictionTM.sol | 367 +++++++++--------- .../VolumeRestrictionTMFactory.sol | 16 +- .../VolumeRestrictionTMStorage.sol | 45 +++ contracts/proxy/VolumeRestrictionTMProxy.sol | 30 ++ migrations/2_deploy_contracts.js | 8 +- test/helpers/createInstances.js | 6 +- test/y_volume_restriction_tm.js | 22 +- 7 files changed, 301 insertions(+), 193 deletions(-) create mode 100644 contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol create mode 100644 contracts/proxy/VolumeRestrictionTMProxy.sol diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index d80ab217e..3b481d00b 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -1,53 +1,17 @@ pragma solidity ^0.4.24; import "./ITransferManager.sol"; +import "./VolumeRestrictionTMStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../../libraries/BokkyPooBahsDateTimeLibrary.sol"; -contract VolumeRestrictionTM is ITransferManager { +contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { using SafeMath for uint256; // permission definition bytes32 public constant ADMIN = "ADMIN"; - enum RestrictionType { Fixed, Percentage } - - struct VolumeRestriction { - // If typeOfRestriction is `Percentage` then allowedTokens will be in - // the % (w.r.t to totalSupply) with a multiplier of 10**16 . else it - // will be fixed amount of tokens - uint256 allowedTokens; - uint256 startTime; - uint256 rollingPeriodInDays; - uint256 endTime; - RestrictionType typeOfRestriction; - } - - struct BucketDetails { - uint256 lastTradedDayTime; - uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays - uint256 daysCovered; // No of days covered till (from the startTime of VolumeRestriction) - uint256 dailyLastTradedDayTime; - } - - // Global restriction that applies to all token holders - VolumeRestriction public defaultRestriction; - // Daily global restriction that applies to all token holders (Total ST traded daily is restricted) - VolumeRestriction public defaultDailyRestriction; - // Restriction stored corresponds to a particular token holder - mapping(address => VolumeRestriction) public individualRestriction; - // Daily restriction stored corresponds to a particular token holder - mapping(address => VolumeRestriction) public individualDailyRestriction; - // Storing _from => day's timestamp => total amount transact in a day --individual - mapping(address => mapping(uint256 => uint256)) internal bucket; - // Storing the information that used to validate the transaction - mapping(address => BucketDetails) internal bucketToUser; - // Storing the information related to default restriction - mapping(address => BucketDetails) internal defaultBucketToUser; - // List of wallets that are exempted from all the restrictions applied by the this contract - mapping(address => bool) public exemptList; - // Emit when the token holder is added/removed from the exemption list event ChangedExemptWalletList(address indexed _wallet, bool _change); // Emit when the new individual restriction is added corresponds to new token holders @@ -111,6 +75,8 @@ contract VolumeRestrictionTM is ITransferManager { ); // Emit when the individual restriction gets removed event IndividualRestrictionRemoved(address _user); + // Emit when individual daily restriction removed + event IndividualDailyRestrictionRemoved(address _user); // Emit when the default restriction gets removed event DefaultRestrictionRemoved(); // Emit when the daily default restriction gets removed @@ -196,6 +162,44 @@ contract VolumeRestrictionTM is ITransferManager { ); } + /// @notice Internal function to facilitate the addition of individual restriction + function _addIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + internal + { + require( + individualRestriction[_holder].endTime < now, + "Already present" + ); + require(_holder != address(0) && !exemptList[_holder], "Invalid address"); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + + if (individualRestriction[_holder].endTime != 0) { + _removeIndividualRestriction(_holder); + } + individualRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddNewIndividualRestriction( + _holder, + _allowedTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + /** * @notice Use to add the new individual daily restriction for all token holder * @param _holder Address of the token holder, whom restriction will be implied @@ -223,6 +227,38 @@ contract VolumeRestrictionTM is ITransferManager { ); } + /// @notice Internal function to facilitate the addition of individual daily restriction + function _addIndividualDailyRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + internal + { + require( + individualDailyRestriction[_holder].endTime < now, + "Not Allowed" + ); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); + individualDailyRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddIndividualDailyRestriction( + _holder, + _allowedTokens, + _startTime, + 1, + _endTime, + _restrictionType + ); + } + /** * @notice Use to add the new individual daily restriction for multiple token holders * @param _holders Array of address of the token holders, whom restriction will be implied @@ -377,6 +413,17 @@ contract VolumeRestrictionTM is ITransferManager { _removeIndividualRestriction(_user); } + /// @notice Internal function to facilitate the removal of individual restriction + function _removeIndividualRestriction(address _user) internal { + require(_user != address(0), "Invalid address"); + require(individualRestriction[_user].endTime != 0, "Not present"); + individualRestriction[_user] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + bucketToUser[_user].lastTradedDayTime = 0; + bucketToUser[_user].sumOfLastPeriod = 0; + bucketToUser[_user].daysCovered = 0; + emit IndividualRestrictionRemoved(_user); + } + /** * @notice use to remove the individual restriction for a given address * @param _users Array of address of the user @@ -387,6 +434,33 @@ contract VolumeRestrictionTM is ITransferManager { } } + /** + * @notice use to remove the individual daily restriction for a given address + * @param _user Address of the user + */ + function removeIndividualDailyRestriction(address _user) external withPerm(ADMIN) { + _removeIndividualDailyRestriction(_user); + } + + /// @notice Internal function to facilitate the removal of individual daily restriction + function _removeIndividualDailyRestriction(address _user) internal { + require(_user != address(0), "Invalid address"); + require(individualDailyRestriction[_user].endTime != 0, "Not present"); + individualDailyRestriction[_user] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + bucketToUser[_user].dailyLastTradedDayTime = 0; + emit IndividualDailyRestrictionRemoved(_user); + } + + /** + * @notice use to remove the individual daily restriction for a given address + * @param _users Array of address of the user + */ + function removeIndividualDailyRestrictionMulti(address[] _users) external withPerm(ADMIN) { + for (uint256 i = 0; i < _users.length; i++) { + _removeIndividualDailyRestriction(_users[i]); + } + } + /** * @notice Use to remove the default restriction */ @@ -435,6 +509,37 @@ contract VolumeRestrictionTM is ITransferManager { ); } + /// @notice Internal function to facilitate the modification of individual restriction + function _modifyIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + internal + { + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + require(individualRestriction[_holder].startTime > now, "Not allowed"); + + individualRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyIndividualRestriction( + _holder, + _allowedTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + /** * @notice Use to modify the existing individual daily restriction for a given token holder * @param _holder Address of the token holder, whom restriction will be implied @@ -462,6 +567,34 @@ contract VolumeRestrictionTM is ITransferManager { ); } + /// @notice Internal function to facilitate the modification of individual daily restriction + function _modifyIndividualDailyRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + internal + { + require(individualDailyRestriction[_holder].startTime > now, "Not allowed"); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); + individualDailyRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyDefaultDailyRestriction( + _allowedTokens, + _startTime, + 1, + _endTime, + _restrictionType + ); + } + /** * @notice Use to modify the existing individual daily restriction for multiple token holders * @param _holders Array of address of the token holders, whom restriction will be implied @@ -836,141 +969,6 @@ contract VolumeRestrictionTM is ITransferManager { } } - function _removeIndividualRestriction(address _user) internal { - require(_user != address(0), "Invalid address"); - require(individualRestriction[_user].endTime != 0, "Not present"); - individualRestriction[_user] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - bucketToUser[_user].lastTradedDayTime = 0; - bucketToUser[_user].sumOfLastPeriod = 0; - bucketToUser[_user].daysCovered = 0; - emit IndividualRestrictionRemoved(_user); - } - - function _modifyIndividualRestriction( - address _holder, - uint256 _allowedTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _restrictionType - ) - internal - { - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - require(individualRestriction[_holder].startTime > now, "Not allowed"); - - individualRestriction[_holder] = VolumeRestriction( - _allowedTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - RestrictionType(_restrictionType) - ); - emit ModifyIndividualRestriction( - _holder, - _allowedTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - _restrictionType - ); - } - - function _addIndividualRestriction( - address _holder, - uint256 _allowedTokens, - uint256 _startTime, - uint256 _rollingPeriodInDays, - uint256 _endTime, - uint256 _restrictionType - ) - internal - { - require( - individualRestriction[_holder].endTime < now, - "Already present" - ); - require(_holder != address(0) && !exemptList[_holder], "Invalid address"); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); - - if (individualRestriction[_holder].endTime != 0) { - _removeIndividualRestriction(_holder); - } - individualRestriction[_holder] = VolumeRestriction( - _allowedTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - RestrictionType(_restrictionType) - ); - emit AddNewIndividualRestriction( - _holder, - _allowedTokens, - _startTime, - _rollingPeriodInDays, - _endTime, - _restrictionType - ); - } - - function _addIndividualDailyRestriction( - address _holder, - uint256 _allowedTokens, - uint256 _startTime, - uint256 _endTime, - uint256 _restrictionType - ) - internal - { - require( - individualDailyRestriction[_holder].endTime < now, - "Not Allowed" - ); - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); - individualDailyRestriction[_holder] = VolumeRestriction( - _allowedTokens, - _startTime, - 1, - _endTime, - RestrictionType(_restrictionType) - ); - emit AddIndividualDailyRestriction( - _holder, - _allowedTokens, - _startTime, - 1, - _endTime, - _restrictionType - ); - } - - function _modifyIndividualDailyRestriction( - address _holder, - uint256 _allowedTokens, - uint256 _startTime, - uint256 _endTime, - uint256 _restrictionType - ) - internal - { - require(individualDailyRestriction[_holder].startTime > now, "Not allowed"); - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); - individualDailyRestriction[_holder] = VolumeRestriction( - _allowedTokens, - _startTime, - 1, - _endTime, - RestrictionType(_restrictionType) - ); - emit ModifyDefaultDailyRestriction( - _allowedTokens, - _startTime, - 1, - _endTime, - _restrictionType - ); - } - function _checkInputParams( uint256 _allowedTokens, uint256 _startTime, @@ -1021,12 +1019,31 @@ contract VolumeRestrictionTM is ITransferManager { * @return uint256 lastTradedDayTime * @return uint256 sumOfLastPeriod * @return uint256 days covered + * @return uint256 24h lastTradedDayTime */ - function getBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256) { + function getIndividualBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { return( bucketToUser[_user].lastTradedDayTime, bucketToUser[_user].sumOfLastPeriod, - bucketToUser[_user].daysCovered + bucketToUser[_user].daysCovered, + bucketToUser[_user].dailyLastTradedDayTime + ); + } + + /** + * @notice Use to get the bucket details for a given address + * @param _user Address of the token holder for whom the bucket details has queried + * @return uint256 lastTradedDayTime + * @return uint256 sumOfLastPeriod + * @return uint256 days covered + * @return uint256 24h lastTradedDayTime + */ + function getDefaultBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { + return( + defaultBucketToUser[_user].lastTradedDayTime, + defaultBucketToUser[_user].sumOfLastPeriod, + defaultBucketToUser[_user].daysCovered, + defaultBucketToUser[_user].dailyLastTradedDayTime ); } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol index 9ac511183..7d2e27cc0 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol @@ -1,25 +1,30 @@ pragma solidity ^0.4.24; -import "./VolumeRestrictionTM.sol"; +import "../../proxy/VolumeRestrictionTMProxy.sol"; import "../ModuleFactory.sol"; /** * @title Factory for deploying VolumeRestrictionTM module */ contract VolumeRestrictionTMFactory is ModuleFactory { + + address public logicContract; + /** * @notice Constructor * @param _polyAddress Address of the polytoken */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { + { + require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; name = "VolumeRestrictionTM"; title = "Volume Restriction Transfer Manager"; description = "Manage transfers based on the volume of tokens that needs to be transact"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } @@ -30,7 +35,7 @@ contract VolumeRestrictionTMFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent Allowance"); - address volumeRestrictionTransferManager = new VolumeRestrictionTM(msg.sender, address(polyToken)); + address volumeRestrictionTransferManager = new VolumeRestrictionTMProxy(msg.sender, address(polyToken), logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(volumeRestrictionTransferManager, getName(), address(this), msg.sender, setupCost, now); return volumeRestrictionTransferManager; @@ -58,11 +63,12 @@ contract VolumeRestrictionTMFactory is ModuleFactory { * @notice Get the tags related to the module factory */ function getTags() public view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](4); + bytes32[] memory availableTags = new bytes32[](5); availableTags[0] = "Maximum Volume"; availableTags[1] = "Transfer Restriction"; availableTags[2] = "Daily Restriction"; availableTags[3] = "Individual Restriction"; + availableTags[4] = "Default Restriction"; return availableTags; } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol new file mode 100644 index 000000000..9e614213a --- /dev/null +++ b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol @@ -0,0 +1,45 @@ +pragma solidity ^0.4.24; + +/** + * @title Storage layout for VolumeRestrictionTM + */ +contract VolumeRestrictionTMStorage { + + enum RestrictionType { Fixed, Percentage } + + struct VolumeRestriction { + // If typeOfRestriction is `Percentage` then allowedTokens will be in + // the % (w.r.t to totalSupply) with a multiplier of 10**16 . else it + // will be fixed amount of tokens + uint256 allowedTokens; + uint256 startTime; + uint256 rollingPeriodInDays; + uint256 endTime; + RestrictionType typeOfRestriction; + } + + struct BucketDetails { + uint256 lastTradedDayTime; + uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays + uint256 daysCovered; // No of days covered till (from the startTime of VolumeRestriction) + uint256 dailyLastTradedDayTime; + } + + // Global restriction that applies to all token holders + VolumeRestriction public defaultRestriction; + // Daily global restriction that applies to all token holders (Total ST traded daily is restricted) + VolumeRestriction public defaultDailyRestriction; + // Restriction stored corresponds to a particular token holder + mapping(address => VolumeRestriction) public individualRestriction; + // Daily restriction stored corresponds to a particular token holder + mapping(address => VolumeRestriction) public individualDailyRestriction; + // Storing _from => day's timestamp => total amount transact in a day --individual + mapping(address => mapping(uint256 => uint256)) internal bucket; + // Storing the information that used to validate the transaction + mapping(address => BucketDetails) internal bucketToUser; + // Storing the information related to default restriction + mapping(address => BucketDetails) internal defaultBucketToUser; + // List of wallets that are exempted from all the restrictions applied by the this contract + mapping(address => bool) public exemptList; + +} \ No newline at end of file diff --git a/contracts/proxy/VolumeRestrictionTMProxy.sol b/contracts/proxy/VolumeRestrictionTMProxy.sol new file mode 100644 index 000000000..e8c24e6be --- /dev/null +++ b/contracts/proxy/VolumeRestrictionTMProxy.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../modules/TransferManager/VolumeRestrictionTMStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract VolumeRestrictionTMProxy is VolumeRestrictionTMStorage, ModuleStorage, Pausable, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor (address _securityToken, address _polyAddress, address _implementation) + public + ModuleStorage(_securityToken, _polyAddress) + { + require( + _implementation != address(0), + "Implementation address should not be 0x" + ); + __implementation = _implementation; + } + +} diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 2a1a02905..61b13f38e 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -17,6 +17,7 @@ const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol') const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol') const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol') const VolumeRestrictionTMFactory = artifacts.require('./VolumeRestrictionTMFactory.sol') +const VolumeRestrictionTMLogic = artifacts.require('./VolumeRestrictionTM.sol'); const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') const STFactory = artifacts.require('./tokens/STFactory.sol') const DevPolyToken = artifacts.require('./helpers/PolyTokenFaucet.sol') @@ -161,6 +162,10 @@ module.exports = function (deployer, network, accounts) { // B) Deploy the GeneralTransferManagerLogic Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) return deployer.deploy(EtherDividendCheckpointLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the VolumeRestrictionTMLogic Contract (Factory used to generate the VolumeRestrictionTM contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(VolumeRestrictionTMLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); }).then(() => { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) @@ -188,7 +193,7 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // D) Deploy the VolumeRestrictionTMFactory Contract (Factory used to generate the VolumeRestrictionTM contract use // to provide the functionality of restricting the token volume) - return deployer.deploy(VolumeRestrictionTMFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(VolumeRestrictionTMFactory, PolyToken, 0, 0, 0, VolumeRestrictionTMLogic.address, {from: PolymathAccount}); }).then(() => { // D) Deploy the ManualApprovalTransferManagerFactory Contract (Factory used to generate the ManualApprovalTransferManager contract use // to manual approve the transfer that will overcome the other transfer restrictions) @@ -348,6 +353,7 @@ module.exports = function (deployer, network, accounts) { EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} VolumeRestrictionTMFactory: ${VolumeRestrictionTMFactory.address} + VolumeRestrictionTMLogic: ${VolumeRestrictionTMLogic.address} --------------------------------------------------------------------------------- `); console.log('\n'); diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index d76ac82c9..9b138ef15 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -33,6 +33,7 @@ const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); const VolumeRestrictionTMFactory = artifacts.require("./VolumeRestrictionTMFactory.sol"); +const VolumeRestrictionTM = artifacts.require("./VolumeRestrictionTM.sol"); const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port @@ -57,6 +58,7 @@ let I_GeneralPermissionManagerFactory; let I_GeneralTransferManagerLogic; let I_GeneralTransferManagerFactory; let I_GeneralTransferManager; +let I_VolumeRestrictionTMLogic; let I_ModuleRegistryProxy; let I_PreSaleSTOFactory; let I_ModuleRegistry; @@ -227,7 +229,9 @@ export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, pol } export async function deployVRTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_VolumeRestrictionTMFactory = await VolumeRestrictionTMFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_VolumeRestrictionTMLogic = await VolumeRestrictionTM.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + + I_VolumeRestrictionTMFactory = await VolumeRestrictionTMFactory.new(polyToken, setupCost, 0, 0, I_VolumeRestrictionTMLogic.address, { from: accountPolymath }); assert.notEqual( I_VolumeRestrictionTMFactory.address.valueOf(), diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 85ded68d6..87020a170 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -613,7 +613,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should succesfully transact the tokens just after the startTime", async() => { + it.skip("Should succesfully transact the tokens just after the startTime", async() => { // Check the transfer will be valid or not by calling the verifyTransfer() directly by using _isTransfer = false let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor1, account_investor3, web3.utils.toWei('.3'), "0x0", false); assert.equal(result.toNumber(), 1); @@ -644,7 +644,7 @@ contract('VolumeRestrictionTransferManager', accounts => { tempArrayGlobal.push(0); }) - it("Should successfully add the global restriction", async() => { + it.skip("Should successfully add the global restriction", async() => { await I_VolumeRestrictionTM.addGlobalRestriction( web3.utils.toWei("15"), latestTime() + duration.seconds(2), @@ -661,7 +661,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(data[2].toNumber(), 5); }); - it("Should successfully transact the tokens after 1 and half days", async() => { + it.skip("Should successfully transact the tokens after 1 and half days", async() => { await increaseTime(duration.days(1.5)); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); @@ -698,7 +698,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(globalAmt, 2); }); - it("Should add the daily restriction successfully", async() => { + it.skip("Should add the daily restriction successfully", async() => { await I_VolumeRestrictionTM.addDailyGlobalRestriction( web3.utils.toWei("5"), latestTime() + duration.seconds(2), @@ -714,7 +714,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(data[4].toNumber(), 0); }); - it("Should transfer tokens within the daily limit -- falied because of limit failing", async() =>{ + it.skip("Should transfer tokens within the daily limit -- falied because of limit failing", async() =>{ // Transfer the 3.1 tokens to check the daily limit await increaseTime(5); await catchRevert( @@ -722,7 +722,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should transfer the tokens within the daily limit", async() => { + it.skip("Should transfer the tokens within the daily limit", async() => { let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); let globalStartTime = (await I_VolumeRestrictionTM.globalRestriction.call())[1].toNumber(); @@ -755,14 +755,14 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(globalAmt, 5); }); - it("Should transfer tokens within the daily limit -- falied because of limit failing", async() =>{ + it.skip("Should transfer tokens within the daily limit -- falied because of limit failing", async() =>{ // Transfer the 0.1 tokens to check the daily limit await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei("0.1"), {from: account_investor1}) ); }); - it("Should successfully transact tokens on the next day of the rolling period (Fuzz test)", async() => { + it.skip("Should successfully transact tokens on the next day of the rolling period (Fuzz test)", async() => { // Increase time half day await increaseTime(duration.days(.52)); // Check the balance of the investors @@ -810,7 +810,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.closeTo(globalAmt, totalAmountTransacted, 0.01); }); - it("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { + it.skip("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { // Increase the time by 3/5 of the day await increaseTime(duration.days(.6)); let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); @@ -821,14 +821,14 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should fail to buy tokens in the new rolling period --failed because amount is more than last 1 timestamps", async() => { + it.skip("Should fail to buy tokens in the new rolling period --failed because amount is more than last 1 timestamps", async() => { await increaseTime(duration.days(1)); await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_investor1}) ); }); - it("Should add the daily restriction again successfully", async() => { + it.skip("Should add the daily restriction again successfully", async() => { await I_VolumeRestrictionTM.addDailyGlobalRestriction( web3.utils.toWei("7"), latestTime() + duration.seconds(2), From aa6e8a1c552486262e58442174cd0d022a48da7f Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 7 Dec 2018 15:45:35 +0530 Subject: [PATCH 347/582] reinvent test cases --- .../TransferManager/VolumeRestrictionTM.sol | 20 +- test/y_volume_restriction_tm.js | 209 +++++++++++++++++- 2 files changed, 211 insertions(+), 18 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 3b481d00b..2f8d1868d 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -107,13 +107,13 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Function must only be called by the associated security token if _isTransfer == true require(msg.sender == securityToken || !_isTransfer); // Checking the individual restriction if the `_from` comes in the individual category - if (individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now - || individualDailyRestriction[_from].endTime >= now && individualDailyRestriction[_from].startTime <= now) { + if ((individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) + || (individualDailyRestriction[_from].endTime >= now && individualDailyRestriction[_from].startTime <= now)) { return _individualRestrictionCheck(_from, _amount, _isTransfer); // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically - } else if (defaultRestriction.endTime >= now && defaultRestriction.startTime <= now - || defaultDailyRestriction.endTime >= now && defaultDailyRestriction.startTime <= now) { + } else if ((defaultRestriction.endTime >= now && defaultRestriction.startTime <= now) + || (defaultDailyRestriction.endTime >= now && defaultDailyRestriction.startTime <= now)) { return _defaultRestrictionCheck(_from, _amount, _isTransfer); } @@ -769,7 +769,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ); // validation of the transaction amount if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, defaultRestriction)) { - allowedDefault == false; + allowedDefault = false; } } (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, bucketDetails.dailyLastTradedDayTime, defaultDailyRestriction); @@ -823,7 +823,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ); // validation of the transaction amount if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, restriction)) { - allowedIndividual == false; + allowedIndividual = false; } } (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, bucketDetails.dailyLastTradedDayTime, dailyRestriction); @@ -840,7 +840,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ); } - return ((allowedDaily && allowedIndividual) == true ? Result.NA : Result.INVALID); + return ((allowedDaily && allowedIndividual) ? Result.NA : Result.INVALID); } function _dailyTxCheck( @@ -860,6 +860,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 txSumOfDay = 0; if (now.sub(dailyLastTradedDayTime) < 1 days || dailyLastTradedDayTime == 0) { txSumOfDay = bucket[from][dailyLastTradedDayTime] >= bucket[from][fromTimestamp] ? bucket[from][dailyLastTradedDayTime] : bucket[from][fromTimestamp]; + if (dailyLastTradedDayTime == 0) + dailyLastTradedDayTime = now; } else { txSumOfDay = 0; dailyLastTradedDayTime = now; @@ -962,7 +964,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { details.daysCovered = _daysCovered; } if (_amount != 0) { - details.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + if (_lastTradedDayTime !=0) { + details.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + } _dailyLastTradedDayTime = details.dailyLastTradedDayTime; // Increasing the total amount of the day by `_amount` bucket[_from][_dailyLastTradedDayTime] = bucket[_from][_dailyLastTradedDayTime].add(_amount); diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 87020a170..f6fd60de8 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -81,13 +81,11 @@ contract('VolumeRestrictionTransferManager', accounts => { Latest timestamp: ${data[0].toNumber()} SumOfLastPeriod: ${data[1].dividedBy(new BigNumber(10).pow(18)).toNumber()} Days Covered: ${data[2].toNumber()} - Global days covered: ${data[3].toNumber()} - Global Sum of LastPeriod: ${data[4].dividedBy(new BigNumber(10).pow(18)).toNumber()} - Global Latest timestamp: ${data[5].toNumber()} + Latest timestamp daily: ${data[3].toNumber()} Individual Total Trade on latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[0])) .dividedBy(new BigNumber(10).pow(18)).toNumber()} - Global Total Trade on latestTimestamp: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[5])) - .dividedBy(new BigNumber(10).pow(18)).toNumber()} + Individual Total Trade on daily latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[3])) + .dividedBy(new BigNumber(10).pow(18)).toNumber()} `) } @@ -215,6 +213,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // Mint some tokens and transferred to whitelisted addresses await I_SecurityToken.mint(account_investor1, web3.utils.toWei("40", "ether"), {from: token_owner}); await I_SecurityToken.mint(account_investor2, web3.utils.toWei("30", "ether"), {from: token_owner}); + await I_SecurityToken.mint(account_investor3, web3.utils.toWei("30", "ether"), {from: token_owner}); // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); @@ -229,7 +228,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('5', 'ether'), { from: account_investor1 }); let bal1 = await I_SecurityToken.balanceOf.call(account_investor3); // Verifying the balances - assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 5); + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 35); }); }) @@ -613,7 +612,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it.skip("Should succesfully transact the tokens just after the startTime", async() => { + it("Should succesfully transact the tokens just after the startTime", async() => { // Check the transfer will be valid or not by calling the verifyTransfer() directly by using _isTransfer = false let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor1, account_investor3, web3.utils.toWei('.3'), "0x0", false); assert.equal(result.toNumber(), 1); @@ -627,7 +626,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // Verifying the balances assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 34.7); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor1); await print(data, account_investor1); assert.equal( @@ -641,9 +640,199 @@ contract('VolumeRestrictionTransferManager', accounts => { ); assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 0.3); tempArray.push(0.3); - tempArrayGlobal.push(0); + }); + + it("Should fail to add the individual daily restriction -- Bad msg.sender", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + web3.utils.toWei("6"), + latestTime() + duration.seconds(1), + latestTime() + duration.days(4), + 0, + { + from: account_investor1 + } + ) + ); + }) + + it("Should fail to add the individual daily restriction -- Bad params value", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + web3.utils.toWei("6"), + latestTime() + duration.seconds(1), + latestTime() + duration.days(4), + 1, + { + from: token_owner + } + ) + ); }) + it("Should fail to add the individual daily restriction -- Bad params value", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + 0, + latestTime() + duration.seconds(1), + latestTime() + duration.days(4), + 0, + { + from: token_owner + } + ) + ); + }) + + it("Should fail to add the individual daily restriction -- Bad params value", async() => { + await catchRevert( + I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + web3.utils.toWei("6"), + latestTime() + duration.days(5), + latestTime() + duration.days(4), + 0, + { + from: token_owner + } + ) + ); + }) + + it("Should add the individual daily default restriction", async() => { + let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + web3.utils.toWei("6"), + latestTime() + duration.seconds(1), + latestTime() + duration.days(4), + 0, + { + from: token_owner + } + ); + + assert.equal(tx.logs[0].args._holder, account_investor3); + assert.equal(tx.logs[0].args._typeOfRestriction, 0); + assert.equal((tx.logs[0].args._allowedTokens).toNumber(), web3.utils.toWei("6")); + let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3); + console.log(` + *** Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(18)).toNumber()} + StartTime : ${dataRestriction[1].toNumber()} + Rolling Period in days : ${dataRestriction[2].toNumber()} + EndTime : ${dataRestriction[3].toNumber()} + Type of Restriction: ${dataRestriction[4].toNumber()} + `); + }); + + it("Should transfer the tokens within the individual daily restriction limits", async() => { + // transfer 2 tokens as per the limit + let txTime = latestTime(); + console.log(` + Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), {from: account_investor3})} + `) + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + await increaseTime(duration.minutes(15)); + + console.log(` + Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("4"), {from: account_investor3})} + `) + // transfer the 4 tokens which is under the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_investor3}); + let newData = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(newData, account_investor3); + + assert.equal(newData[3].toNumber(), data[3].toNumber()); + assert.closeTo(data[3].toNumber(), txTime, 2); + assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[3])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), 6); + }); + + it("Should fail to transfer more tokens --because of the above limit", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei(".1"), {from: account_investor3}) + ); + }); + + it("Should try to send after the one day completion", async() => { + // increase the EVM time by one day + await increaseTime(duration.days(1)); + + let txTime = latestTime(); + console.log(` + Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), {from: account_investor3})} + `) + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + assert.closeTo(data[3].toNumber(), txTime, 2); + assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[3])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(), 2); + }); + + it("Should add the daily restriction on the investor 1", async() => { + let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor1, + web3.utils.toWei("5"), + latestTime() + duration.seconds(1), + latestTime() + duration.days(4), + 0, + { + from: token_owner + } + ); + + assert.equal(tx.logs[0].args._holder, account_investor1); + assert.equal(tx.logs[0].args._typeOfRestriction, 0); + assert.equal((tx.logs[0].args._allowedTokens).toNumber(), web3.utils.toWei("5")); + let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor1); + console.log(` + *** Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(18)).toNumber()} + StartTime : ${dataRestriction[1].toNumber()} + Rolling Period in days : ${dataRestriction[2].toNumber()} + EndTime : ${dataRestriction[3].toNumber()} + Type of Restriction: ${dataRestriction[4].toNumber()} + `); + }); + + it("Should transfer tokens on the 2 day by investor1 (Individual + Individual daily)", async() => { + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); + + console.log(` + Gas estimation (Individual + Individual daily): ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), {from: account_investor1})}` + ); + + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor1}); + // Check the balance of the investors + let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); + // Verifying the balances + assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 32.7); + tempArray.push(2); + + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor1); + await print(data, account_investor1); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray)); + assert.equal(data[2].toNumber(), 1); + assert.equal(data[3].toNumber(), data[0].toNumber()); + assert.equal(amt, 2); + }); + it.skip("Should successfully add the global restriction", async() => { await I_VolumeRestrictionTM.addGlobalRestriction( web3.utils.toWei("15"), @@ -1581,7 +1770,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should get the tags of the factory", async() => { let tags = await I_VolumeRestrictionTMFactory.getTags.call(); - assert.equal(tags.length, 4); + assert.equal(tags.length, 5); assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Maximum Volume"); }); }); From eb0d081ae44172883f6d9a003432c29db583a143 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 7 Dec 2018 17:01:59 +0530 Subject: [PATCH 348/582] bump the version --- CHANGELOG.md | 3 ++- contracts/modules/STO/USDTieredSTOFactory.sol | 2 +- test/p_usd_tiered_sto.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f41982216..2fa488501 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file. # CappedSTO 2.0.1 * `rate` is now accepted as multiplied by 10^18 to allow settting higher price than 1ETH/POLY per token. -## USDTieredSTO 2.0.1 +## USDTieredSTO 2.1.0 * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. * Added `getSTODetails` to USDTSTO. * Added an Array of Tiers that will hold data about every tier in USDTSTO. @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. * Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO. * Removed individual mappings for tier data removed in UDSTSTO. * Removed the old Proxy deployment method of USDTieredSTO and adopt the new inherited proxy deployment approach. +* Bump the version to `2.1.0` ## GeneralTransferManager * `getInvestors`, `getAllInvestorsData`, `getInvestorsData` added to GTM to allow easy data queries. diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index fee9eebb6..3263a4fa7 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -21,7 +21,7 @@ contract USDTieredSTOFactory is ModuleFactory { { require(_logicContract != address(0), "0x address is not allowed"); logicContract = _logicContract; - version = "1.0.0"; + version = "2.1.0"; name = "USDTieredSTO"; title = "USD Tiered STO"; /*solium-disable-next-line max-len*/ diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 1bec3697f..22172c7a4 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -4569,7 +4569,7 @@ contract("USDTieredSTO", accounts => { "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.title.call(), "USD Tiered STO", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.getInstructions.call(), "Initialises a USD tiered STO.", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.version.call(), "1.0.0"); + assert.equal(await I_USDTieredSTOFactory.version.call(), "2.1.0"); let tags = await I_USDTieredSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "USD"); assert.equal(web3.utils.hexToString(tags[1]), "Tiered"); From e4ba72959d32778ed14bc5946b484a21ddcf1499 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 7 Dec 2018 17:32:18 -0300 Subject: [PATCH 349/582] CLI permission list updated --- CLI/commands/common/permissions_list.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/CLI/commands/common/permissions_list.js b/CLI/commands/common/permissions_list.js index 4d2b58cf7..e0cf2664d 100644 --- a/CLI/commands/common/permissions_list.js +++ b/CLI/commands/common/permissions_list.js @@ -94,12 +94,28 @@ function getPermissionList() { setTransferLimitInPercentageMulti: "ADMIN", removeTransferLimitInTokensMulti: "ADMIN", removeTransferLimitInPercentageMulti: "ADMIN" + }, + BlacklistTransferManager: { + addBlacklistType: "ADMIN", + addBlacklistTypeMulti: "ADMIN", + modifyBlacklistType: "ADMIN", + modifyBlacklistTypeMulti: "ADMIN", + deleteBlacklistType: "ADMIN", + deleteBlacklistTypeMulti: "ADMIN", + addInvestorToBlacklist: "ADMIN", + addInvestorToBlacklistMulti: "ADMIN", + addMultiInvestorToBlacklistMulti: "ADMIN", + addInvestorToNewBlacklist: "ADMIN", + deleteInvestorFromAllBlacklist: "ADMIN", + deleteInvestorFromAllBlacklistMulti: "ADMIN", + deleteInvestorFromBlacklist: "ADMIN", + deleteMultiInvestorsFromBlacklistMulti: "ADMIN", } } } module.exports = { - verifyPermission: function(contractName, functionName) { + verifyPermission: function (contractName, functionName) { let list = getPermissionList(); try { return list[contractName][functionName] From 24e1369980ee4485c4e082f1f88e0760a33d9881 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 7 Dec 2018 18:20:44 -0300 Subject: [PATCH 350/582] Check if blacklist is empty before delete it --- CLI/commands/transfer_manager.js | 41 ++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 1ac315946..ff760f63a 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1045,7 +1045,24 @@ async function manageExistingBlacklist(blacklistName) { console.log(chalk.green(`${deleteInvestorFromBlacklistEvent._investor} has been removed from ${web3.utils.hexToUtf8(deleteInvestorFromBlacklistEvent._blacklistName)} successfully!`)); break; case "Delete this blacklist type": - if (readlineSync.keyInYNStrict()) { + let isEmpty = investors.length === 0; + if (!isEmpty) { + console.log(chalk.yellow(`This blacklist have investors added on it. To delete it you must remove them first.`)); + if (readlineSync.keyInYNStrict(`Do you want to remove them? `)) { + let data = investors.map(i => [i, blacklistName]) + let batches = common.splitIntoBatches(data, gbl.constants.DEFAULT_BATCH_SIZE); + let [investorArray, blacklistNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to remove the following investors:\n\n`, investorArray[batch], '\n'); + let action = currentTransferManager.methods.deleteMultiInvestorsFromBlacklistMulti(investorArray[batch], blacklistNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Remove investors from multiple blacklists transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } + isEmpty = true; + } + } + if (isEmpty) { let deleteBlacklistTypeAction = currentTransferManager.methods.deleteBlacklistType(blacklistName); let deleteBlacklistTypeReceipt = await common.sendTransaction(deleteBlacklistTypeAction); let deleteBlacklistTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, deleteBlacklistTypeReceipt.logs, 'DeleteBlacklistType'); @@ -1171,7 +1188,20 @@ async function deleteBlacklistsInBatch() { if (invalidRows.length > 0) { console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); } - let batches = common.splitIntoBatches(validData, batchSize); + + let verifiedData = []; + let unverifiedData = []; + for (const row of validData) { + let blacklistName = row[0]; + let verifiedTransaction = (await currentTransferManager.methods.getListOfAddresses(web3.utils.toHex(blacklistName)).call()).length === 0; + if (verifiedTransaction) { + verifiedData.push(row); + } else { + unverifiedData.push(row); + } + } + + let batches = common.splitIntoBatches(verifiedData, batchSize); let [blacklistNameArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { console.log(`Batch ${batch + 1} - Attempting to delete the following blacklists:\n\n`, blacklistNameArray[batch], '\n'); @@ -1181,6 +1211,13 @@ async function deleteBlacklistsInBatch() { console.log(chalk.green('Delete multiple blacklists transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } + + if (unverifiedData.length > 0) { + console.log("*****************************************************************************************************************"); + console.log('The following data would failed as these blacklists have investors. They must be empty to be able to delete them.\n'); + console.log(chalk.red(unverifiedData.map(d => `${d[0]}`).join('\n'))); + console.log("*****************************************************************************************************************"); + } } async function addInvestorsToBlacklistsInBatch() { From befe46d57fc7c027c08e6b4b7edb8ffb6276c405 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 7 Dec 2018 19:14:50 -0300 Subject: [PATCH 351/582] CLI flow fix for TM modules --- CLI/commands/transfer_manager.js | 268 +++++++++++++++++-------------- 1 file changed, 146 insertions(+), 122 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index ff760f63a..47ff236ac 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -25,97 +25,95 @@ let securityTokenRegistry; let currentTransferManager; async function executeApp() { - let exit = false; - while (!exit) { - console.log('\n', chalk.blue('Transfer Manager - Main Menu', '\n')); - - let tmModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.TRANSFER); - let nonArchivedModules = tmModules.filter(m => !m.archived); - if (nonArchivedModules.length > 0) { - console.log(`Transfer Manager modules attached:`); - nonArchivedModules.map(m => console.log(`- ${m.name} at ${m.address}`)) - } else { - console.log(`There are no Transfer Manager modules attached`); - } + console.log('\n', chalk.blue('Transfer Manager - Main Menu', '\n')); - let options = ['Verify transfer', 'Transfer']; - let forcedTransferDisabled = await securityToken.methods.controllerDisabled().call(); - if (!forcedTransferDisabled) { - options.push('Forced transfers'); - } - if (nonArchivedModules.length > 0) { - options.push('Config existing modules'); - } - options.push('Add new Transfer Manager module'); - - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Exit' }); - let optionSelected = index != -1 ? options[index] : 'Exit'; - console.log('Selected:', optionSelected, '\n'); - switch (optionSelected) { - case 'Verify transfer': - let verifyTransferFrom = readlineSync.question(`Enter the sender account (${Issuer.address}): `, { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - defaultInput: Issuer.address - }); - let verifyFromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferFrom).call()); - console.log(chalk.yellow(`Balance of ${verifyTransferFrom}: ${verifyFromBalance} ${tokenSymbol}`)); - let verifyTransferTo = readlineSync.question('Enter the receiver account: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - }); - let verifyToBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferTo).call()); - console.log(chalk.yellow(`Balance of ${verifyTransferTo}: ${verifyToBalance} ${tokenSymbol}`)); - let verifyTransferAmount = readlineSync.question('Enter amount of tokens to verify: '); - let isVerified = await securityToken.methods.verifyTransfer(verifyTransferFrom, verifyTransferTo, web3.utils.toWei(verifyTransferAmount), web3.utils.fromAscii("")).call(); - if (isVerified) { - console.log(chalk.green(`\n${verifyTransferAmount} ${tokenSymbol} can be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); - } else { - console.log(chalk.red(`\n${verifyTransferAmount} ${tokenSymbol} can't be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); - } - break; - case 'Transfer': - let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call()); - console.log(chalk.yellow(`Balance of ${Issuer.address}: ${fromBalance} ${tokenSymbol}`)); - let transferTo = readlineSync.question('Enter beneficiary of tranfer: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let toBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call()); - console.log(chalk.yellow(`Balance of ${transferTo}: ${toBalance} ${tokenSymbol}`)); - let transferAmount = readlineSync.question('Enter amount of tokens to transfer: '); - let isTranferVerified = await securityToken.methods.verifyTransfer(Issuer.address, transferTo, web3.utils.toWei(transferAmount), web3.utils.fromAscii("")).call(); - if (isTranferVerified) { - let transferAction = securityToken.methods.transfer(transferTo, web3.utils.toWei(transferAmount)); - let receipt = await common.sendTransaction(transferAction); - let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); - console.log(chalk.green(`${event.from} transferred ${web3.utils.fromWei(event.value)} ${tokenSymbol} to ${event.to} successfully!`)); - console.log(`Balance of ${Issuer.address} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call())} ${tokenSymbol}`); - console.log(`Balance of ${transferTo} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call())} ${tokenSymbol}`); - } else { - console.log(chalk.red(`Transfer failed at verification. Please review the transfer restrictions.`)); - } - break; - case 'Forced transfers': - await forcedTransfers(); - break; - case 'Config existing modules': - await configExistingModules(nonArchivedModules); - break; - case 'Add new Transfer Manager module': - await addTransferManagerModule(); - break; - case 'Exit': - exit = true; - break - } + let tmModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.TRANSFER); + let nonArchivedModules = tmModules.filter(m => !m.archived); + if (nonArchivedModules.length > 0) { + console.log(`Transfer Manager modules attached:`); + nonArchivedModules.map(m => console.log(`- ${m.name} at ${m.address}`)) + } else { + console.log(`There are no Transfer Manager modules attached`); + } + + let options = ['Verify transfer', 'Transfer']; + let forcedTransferDisabled = await securityToken.methods.controllerDisabled().call(); + if (!forcedTransferDisabled) { + options.push('Forced transfers'); + } + if (nonArchivedModules.length > 0) { + options.push('Config existing modules'); } + options.push('Add new Transfer Manager module'); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'EXIT' }); + let optionSelected = index !== -1 ? options[index] : 'EXIT'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Verify transfer': + let verifyTransferFrom = readlineSync.question(`Enter the sender account (${Issuer.address}): `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: Issuer.address + }); + let verifyFromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferFrom).call()); + console.log(chalk.yellow(`Balance of ${verifyTransferFrom}: ${verifyFromBalance} ${tokenSymbol}`)); + let verifyTransferTo = readlineSync.question('Enter the receiver account: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + }); + let verifyToBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferTo).call()); + console.log(chalk.yellow(`Balance of ${verifyTransferTo}: ${verifyToBalance} ${tokenSymbol}`)); + let verifyTransferAmount = readlineSync.question('Enter amount of tokens to verify: '); + let isVerified = await securityToken.methods.verifyTransfer(verifyTransferFrom, verifyTransferTo, web3.utils.toWei(verifyTransferAmount), web3.utils.fromAscii("")).call(); + if (isVerified) { + console.log(chalk.green(`\n${verifyTransferAmount} ${tokenSymbol} can be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); + } else { + console.log(chalk.red(`\n${verifyTransferAmount} ${tokenSymbol} can't be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); + } + break; + case 'Transfer': + let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call()); + console.log(chalk.yellow(`Balance of ${Issuer.address}: ${fromBalance} ${tokenSymbol}`)); + let transferTo = readlineSync.question('Enter beneficiary of tranfer: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let toBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call()); + console.log(chalk.yellow(`Balance of ${transferTo}: ${toBalance} ${tokenSymbol}`)); + let transferAmount = readlineSync.question('Enter amount of tokens to transfer: '); + let isTranferVerified = await securityToken.methods.verifyTransfer(Issuer.address, transferTo, web3.utils.toWei(transferAmount), web3.utils.fromAscii("")).call(); + if (isTranferVerified) { + let transferAction = securityToken.methods.transfer(transferTo, web3.utils.toWei(transferAmount)); + let receipt = await common.sendTransaction(transferAction); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); + console.log(chalk.green(`${event.from} transferred ${web3.utils.fromWei(event.value)} ${tokenSymbol} to ${event.to} successfully!`)); + console.log(`Balance of ${Issuer.address} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call())} ${tokenSymbol}`); + console.log(`Balance of ${transferTo} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call())} ${tokenSymbol}`); + } else { + console.log(chalk.red(`Transfer failed at verification. Please review the transfer restrictions.`)); + } + break; + case 'Forced transfers': + await forcedTransfers(); + break; + case 'Config existing modules': + await configExistingModules(nonArchivedModules); + break; + case 'Add new Transfer Manager module': + await addTransferManagerModule(); + break; + case 'EXIT': + return; + } + + await executeApp(); } async function forcedTransfers() { @@ -124,8 +122,8 @@ async function forcedTransfers() { if (controller == Issuer.address) { options.push('Force Transfer'); } - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = index != -1 ? options[index] : 'Return'; + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Disable controller': @@ -184,14 +182,18 @@ async function forcedTransfers() { console.log(`Balance of ${from} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(from).call())} ${tokenSymbol}`); console.log(`Balance of ${to} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(to).call())} ${tokenSymbol}`); break; + case 'RETURN': + return; } + + await forcedTransfers(); } async function configExistingModules(tmModules) { let options = tmModules.map(m => `${m.name} at ${m.address}`); - let index = readlineSync.keyInSelect(options, 'Which module do you want to config? ', { cancel: 'Return' }); - console.log('Selected:', index != -1 ? options[index] : 'Return', '\n'); - let moduleNameSelected = index != -1 ? tmModules[index].name : 'Return'; + let index = readlineSync.keyInSelect(options, 'Which module do you want to config? ', { cancel: 'RETURN' }); + console.log('Selected:', index !== -1 ? options[index] : 'RETURN', '\n'); + let moduleNameSelected = index !== -1 ? tmModules[index].name : 'RETURN'; switch (moduleNameSelected) { case 'GeneralTransferManager': @@ -251,7 +253,7 @@ async function addTransferManagerModule() { //'LookupVolumeRestrictionTM'*/ ]; - let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', { cancel: 'Return' }); + let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', { cancel: 'RETURN' }); if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { let bytes = web3.utils.fromAscii('', 16); switch (options[index]) { @@ -383,9 +385,9 @@ async function generalTransferManager() { options.push('Allow all burn transfers'); } - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case `Show investors`: console.log('***** List of investors on whitelist *****'); @@ -525,7 +527,11 @@ async function generalTransferManager() { console.log(chalk.green(`The burning mechanism is deactivated!`)); } break; + case 'RETURN': + return; } + + await generalTransferManager(); } function showWhitelistTable(investorsArray, fromTimeArray, toTimeArray, expiryTimeArray, canBuyFromSTOArray) { @@ -583,9 +589,9 @@ async function manualApprovalTransferManager() { let options = ['Check manual approval', 'Add manual approval', 'Revoke manual approval', 'Check manual blocking', 'Add manual blocking', 'Revoke manual blocking']; - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); let from; let to; switch (optionSelected) { @@ -727,7 +733,10 @@ async function manualApprovalTransferManager() { console.log(chalk.red(`Manual blocking from ${from} to ${to} does not exist.`)); } break; + case 'RETURN': + return; } + await manualApprovalTransferManager(); } async function getManualApproval(_from, _to) { @@ -761,9 +770,9 @@ async function countTransferManager() { console.log(`- Max holder count: ${displayMaxHolderCount}`); let options = ['Change max holder count'] - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Change max holder count': let maxHolderCount = readlineSync.question('Enter the maximum no. of holders the SecurityToken is allowed to have: '); @@ -772,7 +781,11 @@ async function countTransferManager() { let changeHolderCountEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeHolderCountReceipt.logs, 'ModifyHolderCount'); console.log(chalk.green(`Max holder count has been set to ${changeHolderCountEvent._newHolderCount} sucessfully!`)); break; + case 'RETURN': + return; } + + await countTransferManager(); } async function percentageTransferManager() { @@ -791,9 +804,9 @@ async function percentageTransferManager() { } else { options.push('Allow primary issuance'); } - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Change max holder percentage': let maxHolderPercentage = toWeiPercentage(readlineSync.question('Enter the maximum amount of tokens in percentage that an investor can hold: ', { @@ -876,8 +889,11 @@ async function percentageTransferManager() { console.log(chalk.green(`Transactions which are part of the primary issuance will NOT be ignored!`)); } break; - + case 'RETURN': + return; } + + await percentageTransferManager(); } async function blacklistTransferManager() { @@ -892,8 +908,8 @@ async function blacklistTransferManager() { } options.push('Delete investors from all blacklists', 'Operate with multiple blacklists'); - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: "Return" }); - let optionSelected = index !== -1 ? options[index] : 'Return'; + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: "RETURN" }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Add new blacklist': @@ -936,8 +952,8 @@ async function blacklistTransferManager() { break; case 'Manage existing blacklist': let options = currentBlacklists.map(b => web3.utils.hexToUtf8(b)); - let index = readlineSync.keyInSelect(options, 'Which blacklist type do you want to manage? ', { cancel: "Return" }); - let optionSelected = index !== -1 ? options[index] : 'Return'; + let index = readlineSync.keyInSelect(options, 'Which blacklist type do you want to manage? ', { cancel: "RETURN" }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; console.log('Selected:', optionSelected, '\n'); if (index !== -1) { await manageExistingBlacklist(currentBlacklists[index]); @@ -963,7 +979,11 @@ async function blacklistTransferManager() { case 'Operate with multiple blacklists': await operateWithMultipleBlacklists(currentBlacklists); break; + case 'RETURN': + return; } + + await blacklistTransferManager(); } async function manageExistingBlacklist(blacklistName) { @@ -987,8 +1007,8 @@ async function manageExistingBlacklist(blacklistName) { "Delete this blacklist type" ]; - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = index !== -1 ? options[index] : 'Return'; + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Modify properties': @@ -1068,8 +1088,12 @@ async function manageExistingBlacklist(blacklistName) { let deleteBlacklistTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, deleteBlacklistTypeReceipt.logs, 'DeleteBlacklistType'); console.log(chalk.green(`${web3.utils.hexToUtf8(deleteBlacklistTypeEvent._blacklistName)} blacklist type has been deleted successfully!`)); } - break; + return; + case 'RETURN': + return; } + + await manageExistingBlacklist(blacklistName); } async function operateWithMultipleBlacklists(currentBlacklists) { @@ -1083,8 +1107,8 @@ async function operateWithMultipleBlacklists(currentBlacklists) { 'Remove investors from multiple blacklists' ); - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = index !== -1 ? options[index] : 'Return'; + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Add multiple blacklists': @@ -1316,9 +1340,9 @@ async function singleTradeVolumeRestrictionTM() { 'Set tokens transfer limit per account', 'Remove tokens transfer limit per account'); } - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Allow primary issuance': case 'Disallow primary issuance': @@ -1567,8 +1591,8 @@ async function selectToken() { }); options.push('Enter token symbol manually'); - let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); - let selected = index != -1 ? options[index] : 'Exit'; + let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'EXIT' }); + let selected = index !== -1 ? options[index] : 'EXIT'; switch (selected) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); From 0db70686999a9566cef0b116a1cee39f23dc1d09 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 7 Dec 2018 20:48:45 -0300 Subject: [PATCH 352/582] Show total investors and current percentage ownership at transfer --- CLI/commands/transfer_manager.js | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 4d551e05c..d35cf273e 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -48,6 +48,8 @@ async function executeApp() { console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Verify transfer': + let verifyTotalSupply = web3.utils.fromWei(await securityToken.methods.totalSupply().call()); + await logTotalInvestors(); let verifyTransferFrom = readlineSync.question(`Enter the sender account (${Issuer.address}): `, { limit: function (input) { return web3.utils.isAddress(input); @@ -55,16 +57,14 @@ async function executeApp() { limitMessage: "Must be a valid address", defaultInput: Issuer.address }); - let verifyFromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferFrom).call()); - console.log(chalk.yellow(`Balance of ${verifyTransferFrom}: ${verifyFromBalance} ${tokenSymbol}`)); + await logBalance(verifyTransferFrom, verifyTotalSupply); let verifyTransferTo = readlineSync.question('Enter the receiver account: ', { limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address", }); - let verifyToBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferTo).call()); - console.log(chalk.yellow(`Balance of ${verifyTransferTo}: ${verifyToBalance} ${tokenSymbol}`)); + await logBalance(verifyTransferTo, verifyTotalSupply); let verifyTransferAmount = readlineSync.question('Enter amount of tokens to verify: '); let isVerified = await securityToken.methods.verifyTransfer(verifyTransferFrom, verifyTransferTo, web3.utils.toWei(verifyTransferAmount), web3.utils.fromAscii("")).call(); if (isVerified) { @@ -74,16 +74,16 @@ async function executeApp() { } break; case 'Transfer': - let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call()); - console.log(chalk.yellow(`Balance of ${Issuer.address}: ${fromBalance} ${tokenSymbol}`)); + let totalSupply = web3.utils.fromWei(await securityToken.methods.totalSupply().call()); + await logTotalInvestors(); + await logBalance(Issuer.address, totalSupply); let transferTo = readlineSync.question('Enter beneficiary of tranfer: ', { limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" }); - let toBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call()); - console.log(chalk.yellow(`Balance of ${transferTo}: ${toBalance} ${tokenSymbol}`)); + await logBalance(transferTo, totalSupply); let transferAmount = readlineSync.question('Enter amount of tokens to transfer: '); let isTranferVerified = await securityToken.methods.verifyTransfer(Issuer.address, transferTo, web3.utils.toWei(transferAmount), web3.utils.fromAscii("")).call(); if (isTranferVerified) { @@ -91,8 +91,9 @@ async function executeApp() { let receipt = await common.sendTransaction(transferAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(chalk.green(`${event.from} transferred ${web3.utils.fromWei(event.value)} ${tokenSymbol} to ${event.to} successfully!`)); - console.log(`Balance of ${Issuer.address} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call())} ${tokenSymbol}`); - console.log(`Balance of ${transferTo} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call())} ${tokenSymbol}`); + await logTotalInvestors(); + await logBalance(Issuer.address, totalSupply); + await logBalance(transferTo, totalSupply); } else { console.log(chalk.red(`Transfer failed at verification. Please review the transfer restrictions.`)); } @@ -1171,6 +1172,17 @@ async function selectToken() { return result; } +async function logTotalInvestors() { + let investorsCount = await securityToken.methods.getInvestorCount().call(); + console.log(chalk.yellow(`Total investors at the moment: ${investorsCount}`)); +} + +async function logBalance(from, totalSupply) { + let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(from).call()); + let percentage = totalSupply != '0' ? ` - ${parseFloat(fromBalance) / parseFloat(totalSupply) * 100}% of total supply` : ''; + console.log(chalk.yellow(`Balance of ${from}: ${fromBalance} ${tokenSymbol}${percentage}`)); +} + module.exports = { executeApp: async function (_tokenSymbol) { await initialize(_tokenSymbol); From c5e70c1485299a7854462b41f0205233144ca2e0 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 7 Dec 2018 22:50:20 -0300 Subject: [PATCH 353/582] CLI - Removed blocking functions --- CLI/commands/transfer_manager.js | 86 ++------------------------------ 1 file changed, 5 insertions(+), 81 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 4d551e05c..621702cf8 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -569,8 +569,11 @@ async function modifyWhitelistInBatch() { async function manualApprovalTransferManager() { console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address} `), '\n'); - let options = ['Check manual approval', 'Add manual approval', 'Revoke manual approval', - 'Check manual blocking', 'Add manual blocking', 'Revoke manual blocking']; + let options = [ + 'Check manual approval', + 'Add manual approval', + 'Revoke manual approval' + ]; let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); let optionSelected = options[index]; @@ -648,74 +651,6 @@ async function manualApprovalTransferManager() { console.log(chalk.red(`Manual approval from ${from} to ${to} does not exist.`)); } break; - case 'Check manual blocking': - from = readlineSync.question('Enter the address from which transfers would be blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers would be blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - console.log(); - let manualBlocking = await getManualBlocking(from, to); - if (manualBlocking) { - console.log(`Manual blocking found!`); - console.log(`Expiry time: ${moment.unix(manualBlocking).format('MMMM Do YYYY, HH:mm:ss')}; `) - } else { - console.log(chalk.yellow(`There are no manual blockings from ${from} to ${to}.`)); - } - break; - case 'Add manual blocking': - from = readlineSync.question('Enter the address from which transfers will be blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers will be blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - if (!await getManualBlocking(from, to)) { - let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is blocked(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); - let addManualBlockingAction = currentTransferManager.methods.addManualBlocking(from, to, expiryTime); - let addManualBlockingReceipt = await common.sendTransaction(addManualBlockingAction); - let addManualBlockingEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualBlockingReceipt.logs, 'AddManualBlocking'); - console.log(chalk.green(`Manual blocking has been added successfully!`)); - } else { - console.log(chalk.red(`A manual blocking already exists from ${from} to ${to}.Revoke it first if you want to add a new one.`)); - } - break; - case 'Revoke manual blocking': - from = readlineSync.question('Enter the address from which transfers were blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers were blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - if (await getManualBlocking(from, to)) { - let revokeManualBlockingAction = currentTransferManager.methods.revokeManualBlocking(from, to); - let revokeManualBlockingReceipt = await common.sendTransaction(revokeManualBlockingAction); - let revokeManualBlockingEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, revokeManualBlockingReceipt.logs, 'RevokeManualBlocking'); - console.log(chalk.green(`Manual blocking has been revoked successfully!`)); - } else { - console.log(chalk.red(`Manual blocking from ${from} to ${to} does not exist.`)); - } - break; } } @@ -730,17 +665,6 @@ async function getManualApproval(_from, _to) { return result; } -async function getManualBlocking(_from, _to) { - let result = null; - - let manualBlocking = await currentTransferManager.methods.manualBlockings(_from, _to).call(); - if (manualBlocking !== "0") { - result = manualBlocking; - } - - return result; -} - async function countTransferManager() { console.log(chalk.blue(`Count Transfer Manager at ${currentTransferManager.options.address}`), '\n'); From b894a0c48b91a53dc66ff0baa200ffcdf3375374 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 7 Dec 2018 22:54:14 -0300 Subject: [PATCH 354/582] Updated permission document --- CLI/commands/common/permissions_list.js | 4 +--- docs/permissions_list.md | 10 ++-------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/CLI/commands/common/permissions_list.js b/CLI/commands/common/permissions_list.js index 4d2b58cf7..2afdccfa2 100644 --- a/CLI/commands/common/permissions_list.js +++ b/CLI/commands/common/permissions_list.js @@ -60,9 +60,7 @@ function getPermissionList() { }, ManualApprovalTransferManager: { addManualApproval: "TRANSFER_APPROVAL", - addManualBlocking: "TRANSFER_APPROVAL", revokeManualApproval: "TRANSFER_APPROVAL", - revokeManualBlocking: "TRANSFER_APPROVAL" }, PercentageTransferManager: { modifyWhitelist: "WHITELIST", @@ -99,7 +97,7 @@ function getPermissionList() { } module.exports = { - verifyPermission: function(contractName, functionName) { + verifyPermission: function (contractName, functionName) { let list = getPermissionList(); try { return list[contractName][functionName] diff --git a/docs/permissions_list.md b/docs/permissions_list.md index b49c95a0e..f75e9389c 100644 --- a/docs/permissions_list.md +++ b/docs/permissions_list.md @@ -176,19 +176,13 @@ modifyWhitelistMulti() - ManualApprovalTransferManager + ManualApprovalTransferManager addManualApproval() - withPerm(TRANSFER_APPROVAL) - - - addManualBlocking() + withPerm(TRANSFER_APPROVAL) revokeManualApproval() - - revokeManualBlocking() - PercentageTransferManager modifyWhitelist() From 31e12695401bd54efcfda0d86af49544c59986a1 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 7 Dec 2018 23:16:59 -0300 Subject: [PATCH 355/582] Modules available are read from ModuleRegistry --- CLI/commands/sto_manager.js | 13 ++++++++++++- CLI/commands/transfer_manager.js | 20 ++++++++++++-------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 2123c8706..4f19df76b 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -18,6 +18,7 @@ let tokenSymbol; //////////////////////// // Artifacts let securityTokenRegistry; +let moduleRegistry; let polyToken; let usdToken; let securityToken; @@ -118,7 +119,12 @@ async function addSTOModule(stoConfig) { let optionSelected; if (typeof stoConfig === 'undefined') { - let options = ['CappedSTO', 'USDTieredSTO']; + let availableModules = await moduleRegistry.methods.getModulesByTypeAndToken(gbl.constants.MODULES_TYPES.STO, securityToken.options.address).call(); + let options = await Promise.all(availableModules.map(async function (m) { + let moduleFactoryABI = abis.moduleFactory(); + let moduleFactory = new web3.eth.Contract(moduleFactoryABI, m); + return web3.utils.hexToUtf8(await moduleFactory.methods.name().call()); + })); let index = readlineSync.keyInSelect(options, 'What type of STO do you want?', { cancel: 'Return' }); optionSelected = index != -1 ? options[index] : 'Return'; } else { @@ -899,6 +905,11 @@ async function setup() { securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); securityTokenRegistry.setProvider(web3.currentProvider); + let moduleRegistryAddress = await contracts.moduleRegistry(); + let moduleRegistryABI = abis.moduleRegistry(); + moduleRegistry = new web3.eth.Contract(moduleRegistryABI, moduleRegistryAddress); + moduleRegistry.setProvider(web3.currentProvider); + let polytokenAddress = await contracts.polyToken(); let polytokenABI = abis.polyToken(); polyToken = new web3.eth.Contract(polytokenABI, polytokenAddress); diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index d35cf273e..16af0e34e 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -17,6 +17,7 @@ const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelis let tokenSymbol; let securityToken; let securityTokenRegistry; +let moduleRegistry; let currentTransferManager; async function executeApp() { @@ -232,14 +233,12 @@ async function configExistingModules(tmModules) { } async function addTransferManagerModule() { - let options = [ - 'GeneralTransferManager', - 'ManualApprovalTransferManager', - 'CountTransferManager', - 'PercentageTransferManager', - //'SingleTradeVolumeRestrictionTM', - //'LookupVolumeRestrictionTM'*/ - ]; + let availableModules = await moduleRegistry.methods.getModulesByTypeAndToken(gbl.constants.MODULES_TYPES.TRANSFER, securityToken.options.address).call(); + let options = await Promise.all(availableModules.map(async function (m) { + let moduleFactoryABI = abis.moduleFactory(); + let moduleFactory = new web3.eth.Contract(moduleFactoryABI, m); + return web3.utils.hexToUtf8(await moduleFactory.methods.name().call()); + })); let index = readlineSync.keyInSelect(options, 'Which Transfer Manager module do you want to add? ', { cancel: 'Return' }); if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module?`)) { @@ -1135,6 +1134,11 @@ async function setup() { let securityTokenRegistryABI = abis.securityTokenRegistry(); securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); securityTokenRegistry.setProvider(web3.currentProvider); + + let moduleRegistryAddress = await contracts.moduleRegistry(); + let moduleRegistryABI = abis.moduleRegistry(); + moduleRegistry = new web3.eth.Contract(moduleRegistryABI, moduleRegistryAddress); + moduleRegistry.setProvider(web3.currentProvider); } catch (err) { console.log(err) console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); From 40eac85d36891e71ec512bbe7d6349d7eb4d7017 Mon Sep 17 00:00:00 2001 From: satyam Date: Sat, 8 Dec 2018 22:56:35 +0530 Subject: [PATCH 356/582] contract fully tested with different scenarios of selling of tokens --- .../TransferManager/VolumeRestrictionTM.sol | 213 ++-- test/y_volume_restriction_tm.js | 1064 ++++++----------- 2 files changed, 479 insertions(+), 798 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 2f8d1868d..04240ea35 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -74,9 +74,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _typeOfRestriction ); // Emit when the individual restriction gets removed - event IndividualRestrictionRemoved(address _user); + event IndividualRestrictionRemoved(address _holder); // Emit when individual daily restriction removed - event IndividualDailyRestrictionRemoved(address _user); + event IndividualDailyRestrictionRemoved(address _holder); // Emit when the default restriction gets removed event DefaultRestrictionRemoved(); // Emit when the daily default restriction gets removed @@ -173,19 +173,25 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) internal { + + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } require( individualRestriction[_holder].endTime < now, "Already present" ); require(_holder != address(0) && !exemptList[_holder], "Invalid address"); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + require(startTime >= now, "Invalid startTime"); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType); if (individualRestriction[_holder].endTime != 0) { _removeIndividualRestriction(_holder); } individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, RestrictionType(_restrictionType) @@ -193,7 +199,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddNewIndividualRestriction( _holder, _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -237,14 +243,20 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) internal { + + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } require( individualDailyRestriction[_holder].endTime < now, "Not Allowed" ); - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); + require(startTime >= now, "Invalid startTime"); + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, RestrictionType(_restrictionType) @@ -252,7 +264,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddIndividualDailyRestriction( _holder, _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -347,21 +359,26 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { external withPerm(ADMIN) { + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } require( defaultRestriction.endTime < now, "Not allowed" ); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + require(startTime >= now, "Invalid startTime"); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType); defaultRestriction = VolumeRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, RestrictionType(_restrictionType) ); emit AddDefaultRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -384,21 +401,26 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { external withPerm(ADMIN) { + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } require( defaultDailyRestriction.endTime < now, "Not Allowed" ); - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); + require(startTime >= now, "Invalid startTime"); + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); defaultDailyRestriction = VolumeRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, RestrictionType(_restrictionType) ); emit AddDefaultDailyRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -407,57 +429,57 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice use to remove the individual restriction for a given address - * @param _user Address of the user + * @param _holder Address of the user */ - function removeIndividualRestriction(address _user) external withPerm(ADMIN) { - _removeIndividualRestriction(_user); + function removeIndividualRestriction(address _holder) external withPerm(ADMIN) { + _removeIndividualRestriction(_holder); } /// @notice Internal function to facilitate the removal of individual restriction - function _removeIndividualRestriction(address _user) internal { - require(_user != address(0), "Invalid address"); - require(individualRestriction[_user].endTime != 0, "Not present"); - individualRestriction[_user] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - bucketToUser[_user].lastTradedDayTime = 0; - bucketToUser[_user].sumOfLastPeriod = 0; - bucketToUser[_user].daysCovered = 0; - emit IndividualRestrictionRemoved(_user); + function _removeIndividualRestriction(address _holder) internal { + require(_holder != address(0), "Invalid address"); + require(individualRestriction[_holder].endTime != 0, "Not present"); + individualRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + bucketToUser[_holder].lastTradedDayTime = 0; + bucketToUser[_holder].sumOfLastPeriod = 0; + bucketToUser[_holder].daysCovered = 0; + emit IndividualRestrictionRemoved(_holder); } /** * @notice use to remove the individual restriction for a given address - * @param _users Array of address of the user + * @param _holders Array of address of the user */ - function removeIndividualRestrictionMulti(address[] _users) external withPerm(ADMIN) { - for (uint256 i = 0; i < _users.length; i++) { - _removeIndividualRestriction(_users[i]); + function removeIndividualRestrictionMulti(address[] _holders) external withPerm(ADMIN) { + for (uint256 i = 0; i < _holders.length; i++) { + _removeIndividualRestriction(_holders[i]); } } /** * @notice use to remove the individual daily restriction for a given address - * @param _user Address of the user + * @param _holder Address of the user */ - function removeIndividualDailyRestriction(address _user) external withPerm(ADMIN) { - _removeIndividualDailyRestriction(_user); + function removeIndividualDailyRestriction(address _holder) external withPerm(ADMIN) { + _removeIndividualDailyRestriction(_holder); } /// @notice Internal function to facilitate the removal of individual daily restriction - function _removeIndividualDailyRestriction(address _user) internal { - require(_user != address(0), "Invalid address"); - require(individualDailyRestriction[_user].endTime != 0, "Not present"); - individualDailyRestriction[_user] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - bucketToUser[_user].dailyLastTradedDayTime = 0; - emit IndividualDailyRestrictionRemoved(_user); + function _removeIndividualDailyRestriction(address _holder) internal { + require(_holder != address(0), "Invalid address"); + require(individualDailyRestriction[_holder].endTime != 0, "Not present"); + individualDailyRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + bucketToUser[_holder].dailyLastTradedDayTime = 0; + emit IndividualDailyRestrictionRemoved(_holder); } /** * @notice use to remove the individual daily restriction for a given address - * @param _users Array of address of the user + * @param _holders Array of address of the user */ - function removeIndividualDailyRestrictionMulti(address[] _users) external withPerm(ADMIN) { - for (uint256 i = 0; i < _users.length; i++) { - _removeIndividualDailyRestriction(_users[i]); + function removeIndividualDailyRestrictionMulti(address[] _holders) external withPerm(ADMIN) { + for (uint256 i = 0; i < _holders.length; i++) { + _removeIndividualDailyRestriction(_holders[i]); } } @@ -520,12 +542,16 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) internal { - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } require(individualRestriction[_holder].startTime > now, "Not allowed"); - + require(startTime >= now, "Invalid startTime"); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType); individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, RestrictionType(_restrictionType) @@ -533,7 +559,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit ModifyIndividualRestriction( _holder, _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -542,6 +568,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice Use to modify the existing individual daily restriction for a given token holder + * @dev It is possible to intialize the dailyLatestTradedTime by 0 for the given holder then + * changing of startTime will affect the 24 hrs span. i.e if in earlier restriction days start with + * morning and end on midnight while after the change day may start with afternoon and end with other day afternoon * @param _holder Address of the token holder, whom restriction will be implied * @param _allowedTokens Amount of tokens allowed to be trade for a given address. * @param _startTime Unix timestamp at which restriction get into effect @@ -576,19 +605,24 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _restrictionType ) internal - { - require(individualDailyRestriction[_holder].startTime > now, "Not allowed"); - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); + { + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); + // Initializing the value with 0 to allow the trade with new startTime of the restriction + bucketToUser[_holder].dailyLastTradedDayTime = 0; individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, RestrictionType(_restrictionType) ); emit ModifyDefaultDailyRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -684,18 +718,23 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { external withPerm(ADMIN) { - require(defaultRestriction.startTime > now, "Not allowed"); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType); + require(defaultRestriction.startTime > now, "Not allowed"); + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } + require(startTime >= now, "Invalid startTime"); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType); defaultRestriction = VolumeRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, RestrictionType(_restrictionType) ); emit ModifyDefaultRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -704,6 +743,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice Use to modify the daily default restriction for all token holder + * @dev If the start time is modified then it only affect the startTime of the restriction + * while it may carries the earlier dailyLatestStartDayTime value. Not possible to initialize the value + * of dailyLatestStartDayTime for every holder to 0. * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. @@ -718,18 +760,21 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { external withPerm(ADMIN) { - require(defaultDailyRestriction.startTime > now, "Not allowed"); - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType); + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); defaultDailyRestriction = VolumeRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, RestrictionType(_restrictionType) ); emit ModifyDefaultDailyRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -772,7 +817,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { allowedDefault = false; } } - (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, bucketDetails.dailyLastTradedDayTime, defaultDailyRestriction); + (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, bucketDetails.dailyLastTradedDayTime, defaultDailyRestriction); if (_isTransfer) { _updateStorage( @@ -782,6 +827,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { sumOfLastPeriod, daysCovered, dailyTime, + defaultDailyRestriction.endTime, true ); } @@ -792,7 +838,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @notice Internal function used to validate the transaction for a given address * If it validates then it also update the storage corressponds to the individual restriction */ - function _individualRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) private returns (Result) { + function _individualRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { // using the variable to avoid stack too deep error BucketDetails memory bucketDetails = bucketToUser[_from]; VolumeRestriction memory dailyRestriction = individualDailyRestriction[_from]; @@ -826,7 +872,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { allowedIndividual = false; } } - (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, fromTimestamp, bucketDetails.dailyLastTradedDayTime, dailyRestriction); + (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, bucketDetails.dailyLastTradedDayTime, dailyRestriction); if (_isTransfer) { _updateStorage( @@ -836,6 +882,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { sumOfLastPeriod, daysCovered, dailyTime, + dailyRestriction.endTime, false ); } @@ -846,7 +893,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { function _dailyTxCheck( address from, uint256 amount, - uint256 fromTimestamp, uint256 dailyLastTradedDayTime, VolumeRestriction restriction ) @@ -858,14 +904,13 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // the total amount get traded on a particular day (~ _fromTime) if ( now <= restriction.endTime && now >= restriction.startTime) { uint256 txSumOfDay = 0; - if (now.sub(dailyLastTradedDayTime) < 1 days || dailyLastTradedDayTime == 0) { - txSumOfDay = bucket[from][dailyLastTradedDayTime] >= bucket[from][fromTimestamp] ? bucket[from][dailyLastTradedDayTime] : bucket[from][fromTimestamp]; - if (dailyLastTradedDayTime == 0) - dailyLastTradedDayTime = now; - } else { - txSumOfDay = 0; - dailyLastTradedDayTime = now; - } + if (dailyLastTradedDayTime == 0) + // This if condition will be executed when the individual daily restriction executed first time + dailyLastTradedDayTime = restriction.startTime.add(BokkyPooBahsDateTimeLibrary.diffDays(restriction.startTime, now).mul(1 days)); + else if (now.sub(dailyLastTradedDayTime) >= 1 days) + dailyLastTradedDayTime = dailyLastTradedDayTime.add(BokkyPooBahsDateTimeLibrary.diffDays(dailyLastTradedDayTime, now).mul(1 days)); + // Assgining total sum traded on dailyLastTradedDayTime timestamp + txSumOfDay = bucket[from][dailyLastTradedDayTime]; return (_checkValidAmountToTransact(txSumOfDay, amount, restriction), dailyLastTradedDayTime); } return (true, dailyLastTradedDayTime); @@ -897,7 +942,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (counter >= _rollingPeriodInDays) { // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod sumOfLastPeriod = sumOfLastPeriod. - sub(bucket[_from][_bucketDetails.lastTradedDayTime.sub((counter.sub(_rollingPeriodInDays)).mul(1 days))]); + sub(bucket[_from][_bucketDetails.lastTradedDayTime. + sub((_bucketDetails.daysCovered.sub(counter.sub(_rollingPeriodInDays))).mul(1 days))]); } // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand // the alogrithm @@ -939,6 +985,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _sumOfLastPeriod, uint256 _daysCovered, uint256 _dailyLastTradedDayTime, + uint256 _endTime, bool isDefault ) internal @@ -953,10 +1000,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Assigning the latest transaction timestamp of the day details.lastTradedDayTime = _lastTradedDayTime; } - if (_lastTradedDayTime != 0 && _lastTradedDayTime != _dailyLastTradedDayTime) { - // Assigning the latest transaction timestamp of the day - details.dailyLastTradedDayTime = _lastTradedDayTime; - } else if (details.dailyLastTradedDayTime != _dailyLastTradedDayTime) { + if (details.dailyLastTradedDayTime != _dailyLastTradedDayTime) { // Assigning the latest transaction timestamp of the day details.dailyLastTradedDayTime = _dailyLastTradedDayTime; } @@ -966,10 +1010,13 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (_amount != 0) { if (_lastTradedDayTime !=0) { details.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + // Increasing the total amount of the day by `_amount` + bucket[_from][_lastTradedDayTime] = bucket[_from][_lastTradedDayTime].add(_amount); + } + if ((_dailyLastTradedDayTime != _lastTradedDayTime) && _dailyLastTradedDayTime != 0 && now <= _endTime) { + // Increasing the total amount of the day by `_amount` + bucket[_from][_dailyLastTradedDayTime] = bucket[_from][_dailyLastTradedDayTime].add(_amount); } - _dailyLastTradedDayTime = details.dailyLastTradedDayTime; - // Increasing the total amount of the day by `_amount` - bucket[_from][_dailyLastTradedDayTime] = bucket[_from][_dailyLastTradedDayTime].add(_amount); } } @@ -981,7 +1028,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _restrictionType ) internal - view + pure { require(_restrictionType == 0 || _restrictionType == 1, "Invalid type"); if (_restrictionType == uint256(RestrictionType.Fixed)) { @@ -992,10 +1039,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { "Percentage is not within (0,100]" ); } - require(_startTime >= now && _endTime > _startTime); + require(_endTime > _startTime, "Invalid times"); // Maximum limit for the rollingPeriod is 365 days - require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365); - require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays); + require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365, "Invalid rollingperiod"); + require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays, "Invalid start & end time"); } function _checkLengthOfArray( diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index f6fd60de8..115bfed7a 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -70,7 +70,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tempAmount = new BigNumber(0); let tempArray = new Array(); - let tempArrayVariable = new Array(); + let tempArray3 = new Array(); let tempArrayGlobal = new Array(); // Initial fee for ticker registry and security token registry @@ -571,7 +571,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ) }); - it("Should add the restriction succesfully after the expiry of previous one", async() => { + it("Should add the restriction succesfully after the expiry of previous one for investor 1", async() => { await increaseTime(duration.days(5.1)); console.log( @@ -612,7 +612,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should succesfully transact the tokens just after the startTime", async() => { + it("Should succesfully transact the tokens by investor 1 just after the startTime", async() => { // Check the transfer will be valid or not by calling the verifyTransfer() directly by using _isTransfer = false let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor1, account_investor3, web3.utils.toWei('.3'), "0x0", false); assert.equal(result.toNumber(), 1); @@ -702,7 +702,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should add the individual daily default restriction", async() => { + it("Should add the individual daily restriction for investor 3", async() => { let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor3, web3.utils.toWei("6"), @@ -730,7 +730,8 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should transfer the tokens within the individual daily restriction limits", async() => { // transfer 2 tokens as per the limit - let txTime = latestTime(); + await increaseTime(5); // increase 5 seconds to layoff the time gap + let startTime = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); console.log(` Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), {from: account_investor3})} `) @@ -749,7 +750,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(newData, account_investor3); assert.equal(newData[3].toNumber(), data[3].toNumber()); - assert.closeTo(data[3].toNumber(), txTime, 2); + assert.equal(data[3].toNumber(), startTime); assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[3])) .dividedBy(new BigNumber(10).pow(18)).toNumber(), 6); }); @@ -764,7 +765,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // increase the EVM time by one day await increaseTime(duration.days(1)); - let txTime = latestTime(); + let startTime = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); console.log(` Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), {from: account_investor3})} `) @@ -772,7 +773,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - assert.closeTo(data[3].toNumber(), txTime, 2); + assert.equal(data[3].toNumber(), startTime + duration.days(1)); assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[3])) .dividedBy(new BigNumber(10).pow(18)).toNumber(), 2); }); @@ -780,22 +781,22 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should add the daily restriction on the investor 1", async() => { let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor1, - web3.utils.toWei("5"), - latestTime() + duration.seconds(1), - latestTime() + duration.days(4), + new BigNumber(5).times(new BigNumber(10).pow(16)), 0, + latestTime() + duration.days(4), + 1, { from: token_owner } ); assert.equal(tx.logs[0].args._holder, account_investor1); - assert.equal(tx.logs[0].args._typeOfRestriction, 0); - assert.equal((tx.logs[0].args._allowedTokens).toNumber(), web3.utils.toWei("5")); + assert.equal((tx.logs[0].args._typeOfRestriction).toNumber(), 1); + assert.equal((tx.logs[0].args._allowedTokens).dividedBy(new BigNumber(10).pow(16)).toNumber(), 5); let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor1); console.log(` *** Individual Daily restriction data *** - Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(18)).toNumber()} + Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(16)).toNumber()} % of TotalSupply StartTime : ${dataRestriction[1].toNumber()} Rolling Period in days : ${dataRestriction[2].toNumber()} EndTime : ${dataRestriction[3].toNumber()} @@ -803,7 +804,7 @@ contract('VolumeRestrictionTransferManager', accounts => { `); }); - it("Should transfer tokens on the 2 day by investor1 (Individual + Individual daily)", async() => { + it("Should transfer tokens on the 2nd day by investor1 (Individual + Individual daily)", async() => { let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); @@ -829,778 +830,423 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray)); assert.equal(data[2].toNumber(), 1); - assert.equal(data[3].toNumber(), data[0].toNumber()); + assert.equal(data[3].toNumber(), + (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor1))[1].toNumber()); assert.equal(amt, 2); }); - it.skip("Should successfully add the global restriction", async() => { - await I_VolumeRestrictionTM.addGlobalRestriction( - web3.utils.toWei("15"), + it("Should fail to transfer by investor 1 -- because voilating the individual daily", async() => { + // transfer 4 tokens -- voilate the daily restriction + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_investor1}) + ); + }); + + it("Should add the individual restriction to investor 3", async() => { + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor3, + new BigNumber(15.36).times(new BigNumber(10).pow(16)), // 15.36 tokens as totalsupply is 1000 latestTime() + duration.seconds(2), - 5, - latestTime() + duration.days(10), - 0, + 6, + latestTime() + duration.days(15), + 1, { from: token_owner } ); - - let data = await I_VolumeRestrictionTM.globalRestriction.call(); - assert.equal(data[0].toNumber(), web3.utils.toWei("15")); - assert.equal(data[2].toNumber(), 5); + + assert.equal(tx.logs[0].args._holder, account_investor3); + assert.equal(tx.logs[0].args._typeOfRestriction, 1); }); - it.skip("Should successfully transact the tokens after 1 and half days", async() => { - await increaseTime(duration.days(1.5)); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); - let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - let globalStartTime = (await I_VolumeRestrictionTM.globalRestriction.call())[1].toNumber(); - let globalRollingPeriod = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); + it("Should transfer the token by the investor 3 with in the (Individual + Individual daily limit)", async() => { + await increaseTime(4); + // Allowed 4 tokens to transfer + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); + let startTimeDaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); console.log(` - Gas estimation (Individual + Global): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei("2"), {from: account_investor1})}` + Gas estimation (Individual + Individual daily): ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("4"), {from: account_investor3})}` ); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor1}); // Check the balance of the investors - let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); + let bal1 = await I_SecurityToken.balanceOf.call(account_investor3); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_investor3}); + tempArray3.push(4); + // Check the balance of the investors + let bal2 = await I_SecurityToken.balanceOf.call(account_investor3); // Verifying the balances - assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 32.7); - tempArray.push(2); - tempArrayGlobal.push(2); + assert.equal(web3.utils.fromWei(((bal1.minus(bal2)).toNumber()).toString()), 4); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - await print(data, account_investor1); + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); - let globalAmt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[5].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); - assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray)); - assert.equal(data[2].toNumber(), 1); - assert.equal(data[3].toNumber(), 1); - assert.equal(data[4].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(globalRollingPeriod, tempArrayGlobal)); - assert.equal(data[5].toNumber(), globalStartTime + duration.days(data[3].toNumber())); - assert.equal(amt, 2); - assert.equal(globalAmt, 2); - }); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 4); + assert.equal(data[2].toNumber(), 0); + assert.equal(data[3].toNumber(), startTimeDaily + duration.days(1)); + assert.equal(amt, 4); - it.skip("Should add the daily restriction successfully", async() => { - await I_VolumeRestrictionTM.addDailyGlobalRestriction( - web3.utils.toWei("5"), - latestTime() + duration.seconds(2), - latestTime() + duration.days(1.1), - 0, - { - from: token_owner - } - ); - let data = await I_VolumeRestrictionTM.dailyGlobalRestriction.call(); - assert.equal(data[0].dividedBy(new BigNumber(10).pow(18)).toNumber(), 5); - assert.equal(data[2].toNumber(), 1); - assert.equal(data[4].toNumber(), 0); }); - it.skip("Should transfer tokens within the daily limit -- falied because of limit failing", async() =>{ - // Transfer the 3.1 tokens to check the daily limit - await increaseTime(5); + it("Should fail during transferring more tokens by investor3 -- Voilating the daily Limit", async() => { await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei("3.1"), {from: account_investor1}) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1"), {from: account_investor3}) ); }); - it.skip("Should transfer the tokens within the daily limit", async() => { - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); - let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - let globalStartTime = (await I_VolumeRestrictionTM.globalRestriction.call())[1].toNumber(); - let globalRollingPeriod = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - // Calculate the gas estimation - console.log(` - Gas estimation (Individual + Global + daily): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei("3"), {from: account_investor1})} - `) - // Transfer the 3 tokens - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("3"), {from: account_investor1}); - tempArray[tempArray.length -1] += 3; - tempArrayGlobal[tempArrayGlobal.length -1] += 3; - // getting the data of the bucket - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - // print the logs - await print(data, account_investor1); - // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); - let globalAmt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[5].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); - // Verify the storage changes - assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); - assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray)); - assert.equal(data[2].toNumber(), 1); - assert.equal(data[3].toNumber(), 1); - assert.equal(data[4].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArrayGlobal)); - assert.equal(data[5].toNumber(), globalStartTime + duration.days(data[3].toNumber())); - assert.equal(amt, 5); - assert.equal(globalAmt, 5); - }); - - it.skip("Should transfer tokens within the daily limit -- falied because of limit failing", async() =>{ - // Transfer the 0.1 tokens to check the daily limit + it("Should remove the daily individual limit and transfer more tokens on a same day -- failed because of bad owner", async() => { + // remove the Individual daily restriction await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei("0.1"), {from: account_investor1}) + I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, {from: account_investor4}) ); - }); + }) + + it("Should remove the daily individual limit and transfer more tokens on a same day", async() => { + // remove the Individual daily restriction + let tx = await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, {from: token_owner}); + assert.equal(tx.logs[0].args._holder, account_investor3); + + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); + + // transfer more tokens on the same day + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_investor3}); + tempArray3[tempArray3.length -1] += 4; + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); - it.skip("Should successfully transact tokens on the next day of the rolling period (Fuzz test)", async() => { - // Increase time half day - await increaseTime(duration.days(.52)); - // Check the balance of the investors - let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); - let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - let globalStartTime = (await I_VolumeRestrictionTM.globalRestriction.call())[1].toNumber(); - let globalRollingPeriod = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - - let totalAmountTransacted = 0; - // transactions performed - for (let i = 0; i < 5; i++) { - let amount = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; - // Calculate the gas estimation - console.log(` - Gas estimation (Individual + Global + daily): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1})} - `) - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor1}); - console.log(`${i}: Restricted investor 1 able to transact ${amount} tokens to investor 3`); - totalAmountTransacted += amount; - } - - // Check the balance of the investors - let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); - // Verifying the balances - assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - tempArray.push(totalAmountTransacted); - tempArrayGlobal.push(totalAmountTransacted); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - // print the logs - await print(data, account_investor1); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); - let globalAmt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[5].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); + // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); - assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray), 0.01); - assert.equal(data[2].toNumber(), 2); - assert.equal(data[3].toNumber(), 2); - assert.closeTo(data[4].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArrayGlobal), 0.01); - assert.equal(data[5].toNumber(), globalStartTime + duration.days(data[3].toNumber())); - assert.closeTo(amt, totalAmountTransacted, 0.01); - assert.closeTo(globalAmt, totalAmountTransacted, 0.01); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 8); + assert.equal(data[2].toNumber(), 0); + assert.equal(data[3].toNumber(), 0); + assert.equal(amt, 8); }); - it.skip("Should fail to transact the tokens more than the allowed tokens in a rolling period", async() => { - // Increase the time by 3/5 of the day - await increaseTime(duration.days(.6)); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - let minimumAmount = new BigNumber(12).times(new BigNumber(10).pow(18)).minus(data[1]); - let testAmount = minimumAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))) - await catchRevert( - I_SecurityToken.transfer(account_investor3, testAmount, {from: account_investor1}) - ); - }); - - it.skip("Should fail to buy tokens in the new rolling period --failed because amount is more than last 1 timestamps", async() => { - await increaseTime(duration.days(1)); - await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_investor1}) - ); - }); - - it.skip("Should add the daily restriction again successfully", async() => { - await I_VolumeRestrictionTM.addDailyGlobalRestriction( - web3.utils.toWei("7"), - latestTime() + duration.seconds(2), - latestTime() + duration.days(10), + it("Should add the new Individual daily restriction and transact the tokens", async() => { + // add new restriction + let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + web3.utils.toWei("2"), + latestTime() + duration.days(1), + latestTime() + duration.days(4), 0, { from: token_owner } ); - let data = await I_VolumeRestrictionTM.dailyGlobalRestriction.call(); - assert.equal(data[0].dividedBy(new BigNumber(10).pow(18)).toNumber(), 7); - assert.equal(data[2].toNumber(), 1); - assert.equal(data[4].toNumber(), 0); - }); - - it.skip("Should transfer the tokens in a new rolling period", async() => { - let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - let firstDayAmount; - tempAmount = new BigNumber(0); - for (let i = 0; i < oldData[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${oldData[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - if (i != 2) { - firstDayAmount = await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][0]); - tempAmount = tempAmount.plus(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, oldData[0][i])); - } - } + assert.equal(tx.logs[0].args._holder, account_investor3); + assert.equal(tx.logs[0].args._typeOfRestriction, 0); + assert.equal((tx.logs[0].args._allowedTokens).toNumber(), web3.utils.toWei("2")); + let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3); console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((oldData[1].toNumber()).toString())} - Last Timestamp Index : ${oldData[0].length -1} + *** Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(18)).toNumber()} + StartTime : ${dataRestriction[1].toNumber()} + Rolling Period in days : ${dataRestriction[2].toNumber()} + EndTime : ${dataRestriction[3].toNumber()} + Type of Restriction: ${dataRestriction[4].toNumber()} `); - let currentDayAmount = firstDayAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))); - let tx = await I_SecurityToken.transfer(account_investor3, currentDayAmount, {from: account_investor1}); - tempAmount = tempAmount.minus(currentDayAmount); - tempArray.push(0); - tempArray.push(currentDayAmount.dividedBy(new BigNumber(10).pow(18)).toNumber()); - console.log('\n'); - let newData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - for (let i = 2; i < newData[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${newData[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(newData[0][i].toNumber(), startTime + duration.days(i)) - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, newData[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((newData[1].toNumber()).toString())} - Last Timestamp Index : ${newData[0].length -1} - `); - }); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); + // Increase the time by one day + await increaseTime(duration.days(1.1)); - it.skip("Should transfer the more tokens on the same day", async() => { - // Check the balance of the investors - let balBefore = await I_SecurityToken.balanceOf.call(account_investor1); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); - await I_SecurityToken.transfer(account_investor3, tempAmount, {from: account_investor1}); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); + tempArray3.push(2); - // Check the balance of the investors - let balAfter = await I_SecurityToken.balanceOf.call(account_investor1); - // Verifying the balances - assert.closeTo( - (balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), - tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(), - 0.01 + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 1); + assert.equal(data[3].toNumber(), dataRestriction[1].toNumber()); + assert.equal(amt, 2); + + // Fail to sell more tokens than the limit + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}) ); - tempArray[tempArray.length -1] = tempArray[tempArray.length -1] + tempAmount.dividedBy(new BigNumber(10).pow(18)).toNumber(); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor1); - for (let i = 2; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArray[i], 0.001); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length -1} - `); - let sumOflastperiod = 0; - for (let i = tempArray.length - 1; i >= tempArray.length - 3; i--) { - sumOflastperiod += tempArray[i]; - } - assert.equal(data[0].length - 1, 4); - assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), sumOflastperiod, 0.001); }); - }); - describe.skip("Test case for the variable individual restriction", async() => { - it("Should add the restriction succesfully", async() => { - let tx = await I_VolumeRestrictionTM.addIndividualRestriction( - account_investor2, + it("Should fail to modify the individual daily restriction -- bad owner", async() => { + await catchRevert( + I_VolumeRestrictionTM.modifyIndividualDailyRestriction( + account_investor3, + web3.utils.toWei('3'), + latestTime(), + latestTime() + duration.days(5), 0, - new BigNumber(20).times(new BigNumber(10).pow(16)), - latestTime() + duration.seconds(2), - 3, - latestTime() + duration.days(10), - 1, { - from: token_owner + from: account_polymath } - ); - - assert.equal(tx.logs[0].args._holder, account_investor2); - assert.equal(tx.logs[0].args._typeOfRestriction, 1); - }); - - it("Should not successfully transact the tokens -- failed because volume is above the limit", async() => { - await increaseTime(duration.seconds(10)); - await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei("15"), { from: account_investor2}) + ) ); }); + + it("Should modify the individual daily restriction", async() => { + await I_VolumeRestrictionTM.modifyIndividualDailyRestriction( + account_investor3, + web3.utils.toWei('3'), + 0, + latestTime() + duration.days(5), + 0, + { + from: token_owner + } + ); - it("Should succesfully transact the tokens just after the starttime", async() => { - // Check the transfer will be valid or not by calling the verifyTransfer() directly by using _isTransfer = false - let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor2, account_investor3, web3.utils.toWei('.3'), "0x0", false); - console.log(result); - assert.equal(result.toNumber(), 1); - // Perform the transaction - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('.3'), {from: account_investor2}); - // Check the balance of the investors - let bal1 = await I_SecurityToken.balanceOf.call(account_investor2); - // Verifying the balances - assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 29.7); - - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); - console.log('\n'); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), 0.3); - assert.equal(data[0][i].toNumber(), (await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber()) - } + let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3); console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length -1} + *** Modify Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(18)).toNumber()} + StartTime : ${dataRestriction[1].toNumber()} + Rolling Period in days : ${dataRestriction[2].toNumber()} + EndTime : ${dataRestriction[3].toNumber()} + Type of Restriction: ${dataRestriction[4].toNumber()} `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 0.3); - assert.equal(data[0].length -1, 0); - tempArrayVariable.push(0.3); }); - it("Should successfully transact the tokens after 1 and half days", async() => { - await increaseTime(duration.days(1.5)); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor2}); - // Check the balance of the investors - let bal1 = await I_SecurityToken.balanceOf.call(account_investor2); - // Verifying the balances - assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 28.7); - tempArrayVariable.push(1); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayVariable[i]); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length -1} - `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1.3); - assert.equal(data[0].length -1, 1); - }); + it("Should allow to sell to transfer more tokens by investor3", async() => { + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); + let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), {from: account_investor3}); + tempArray3[tempArray3.length -1] += 3; - it("Should successfully transact more tokens on the same day (Fuzz test)", async() => { - // Check the balance of the investors - let balBefore = await I_SecurityToken.balanceOf.call(account_investor2); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(); - let totalAmountTransacted = 0; - for (let i = 0; i < 10; i++) { - let amount = Math.floor(Math.random() * (1000 - 100) + 100) / 1000; - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(amount.toString()), {from: account_investor2}); - console.log(`${i}: Restricted investor 2 able to transact ${amount} tokens to investor 3`); - totalAmountTransacted += amount; - } - - // Check the balance of the investors - let balAfter = await I_SecurityToken.balanceOf.call(account_investor2); - tempArrayVariable[1] = tempArrayVariable[1] + totalAmountTransacted; - // Verifying the balances - assert.closeTo((balBefore.minus(balAfter).dividedBy(new BigNumber(10).pow(18))).toNumber(), totalAmountTransacted, 0.01); - - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayVariable[i], 0.000001); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - `); - assert.closeTo(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), 1.3 + totalAmountTransacted, 0.000001); - assert.equal(data[0].length -1, 1); - }); + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); - it("Should successfully transfer the tokens after half days-- should increase the day covered by 1", async() => { - let oldData = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); - let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(); - await increaseTime(duration.days(.5)); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2"), {from: account_investor2}); - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); - tempArrayVariable.push(2); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)) - assert.closeTo((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor2, data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayVariable[i], 0.000001); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - `); - assert.equal(data[0].length - 1, 2); - assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), - (oldData[1].plus(new BigNumber(2).times(new BigNumber(10).pow(18)))) - .dividedBy(new BigNumber(10).pow(18)).toNumber()); + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 1); + assert.equal(data[3].toNumber(), startTimedaily); + assert.equal(amt, 5); }); - it("Should fail to transfer the tokens on third day -- because it is more than the rolling period allowed", async() => { - let data = await I_VolumeRestrictionTM.getBucketDetailsToUser.call(account_investor2); - let res = await I_VolumeRestrictionTM.individualRestriction.call(account_investor2); - let allowedAmount = (res[1].mul(await I_SecurityToken.totalSupply.call())).dividedBy(new BigNumber(10).pow(18)); - let remainingAmount = allowedAmount.minus(data[1]); + it("Should allow to transact the tokens on the other day", async() => { + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); + let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); - await catchRevert( - I_SecurityToken.transfer( - account_investor3, - remainingAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))), - { - from: account_investor2 - } - ) - ); - tempAmount = remainingAmount; + await increaseTime(duration.days(1)); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2.36"), {from: account_investor3}); + tempArray3.push(2.36); + + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 2); + assert.equal(data[3].toNumber(), startTimedaily + duration.days(1)); + assert.equal(amt, 2.36); }); - it("Should successfully transfer tokens more than the allowed as totalsupply get increased", async() => { - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("10"), { from: token_owner }); - - await I_SecurityToken.transfer( - account_investor3, - tempAmount.plus(new BigNumber(1).times(new BigNumber(10).pow(18))), - { - from: account_investor2 - } + it("Should fail to transfer the tokens after completion of the total amount", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("0.3"), {from: account_investor3}) ); - }); - }); + }) - describe.skip("Add the test cases for global restriction", async() => { + it("Should sell more tokens on the same day after changing the total supply", async() => { + await I_SecurityToken.mint(account_investor3, web3.utils.toWei("10"), {from: token_owner}); - it("Should successfully add the global restriction", async() => { - await I_VolumeRestrictionTM.addGlobalRestriction( - web3.utils.toWei("20"), - 0, - latestTime() + duration.seconds(2), - 3, - latestTime() + duration.days(10), - 0, - { - from: token_owner - } - ); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); + let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); - let data = await I_VolumeRestrictionTM.globalRestriction.call(); - assert.equal(data[0], web3.utils.toWei("20")); - assert.equal(data[3], 3); - }); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei(".50"), {from: account_investor3}); + tempArray3[tempArray3.length -1] += .50; - it("Should successfully add the 2 more address in the whitelist", async() => { - await I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor4, account_delegate3], - [latestTime(), latestTime()], - [latestTime(), latestTime()], - [latestTime() + duration.days(30), latestTime() + duration.days(30)], - [true, true], - { - from: token_owner - } - ); + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); - // Mint some tokens and transferred to whitelisted addresses - await I_SecurityToken.mint(account_investor4, web3.utils.toWei("40", "ether"), {from: token_owner}); - await I_SecurityToken.mint(account_delegate3, web3.utils.toWei("30", "ether"), {from: token_owner}); - - // Check the balance of the investors - let bal1 = await I_SecurityToken.balanceOf.call(account_investor4); - let bal2 = await I_SecurityToken.balanceOf.call(account_delegate3); - // Verifying the balances - assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 40); - assert.equal(web3.utils.fromWei((bal2.toNumber()).toString()), 30); + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 2); + assert.equal(data[3].toNumber(), startTimedaily + duration.days(1)); + assert.equal(amt, 2.86); }); - it("Should successfully transfer the tokens with in the global range", async() => { - let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor4}); - let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); - let latestTimestamp = 0; - tempArrayGlobal.push(1); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); + it("Should fail to transact tokens more than the allowed in the second rolling period", async() => { + await increaseTime(duration.days(5)); + let i + for (i = 0; i < 3; i++) { + tempArray3.push(0); } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 1); - assert.equal(data[0].length - 1, 0); - - console.log(`Transfer the tokens from the another investor comes under the global category`); - await increaseTime(duration.minutes(10)); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4"), {from: account_delegate3}); - tempArrayGlobal[tempArrayGlobal.length - 1] += 4; - data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); + let allowedAmount = (tempArray3[0] + 1.1); + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei(allowedAmount.toString()), {from: account_investor3}) + ); + }) + + it("Should successfully to transact tokens in the second rolling period", async() => { + // Should transact freely tokens daily limit is also ended + + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); + let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); + let allowedAmount = (tempArray3[0] + 1); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei(allowedAmount.toString()), {from: account_investor3}); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); - latestTimestamp = data[0][i]; - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} - `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 5); - assert.equal(data[0].length - 1, 0); - assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 5); - }); + tempArray3.push(allowedAmount); + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); - it("Should transfer the tokens on the another day", async() => { - await increaseTime(duration.days(1.2)); - let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("5"), { from: account_investor3}); - tempArrayGlobal.push(5); - let latestTimestamp = 0; - let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); - latestTimestamp = data[0][i]; - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} - `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 10); - assert.equal(data[0].length - 1, 1); - assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 5); + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 7); + assert.equal(data[3].toNumber(), startTimedaily + duration.days(1)); + assert.equal(amt, allowedAmount); }); - it("Should transfer tokens on the third day of rolling period", async() => { - await increaseTime(duration.days(1)); - let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("6"), {from: account_investor4}); - let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); - tempArrayGlobal.push(6); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} - `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 16); - assert.equal(data[0].length - 1, 2); - assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 6); - - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4"), {from: account_delegate3}); - data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); - tempArrayGlobal[tempArrayGlobal.length -1] += 4; - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} - `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 20); - assert.equal(data[0].length - 1, 2); - assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 10); + it("Should sell more tokens on the net day of rolling period", async() => { + await increaseTime(duration.days(3)); + + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); + let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); + + tempArray3.push(0); + tempArray3.push(0); + + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("7"), {from: account_investor3}); + + tempArray3.push(7) + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 10); + assert.equal(data[3].toNumber(), startTimedaily + duration.days(1)); + assert.equal(amt, 7); }) - it("Should transfer of tokens get failed - limit of global token txn get reached", async() => { - let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); - let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - let latestTimestamp = 0; - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - latestTimestamp = data[0][i]; + it("Should transfer after the 5 days", async() => { + await increaseTime(duration.days(4.5)); + + for (let i = 0; i <3; i++) { + tempArray3.push(0); } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} - `); - // Already 20 tokens transferred - await catchRevert( - I_SecurityToken.transfer(account_delegate3, web3.utils.toWei("5"), {from: account_investor3}) - ); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); + let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("25"), {from: account_investor2}); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("8"), {from: account_investor3}); + tempArray3.push(8); + + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 14); + assert.equal(data[3].toNumber(), startTimedaily + duration.days(1)); + assert.equal(amt, 8); }); - it("Should allow to transact on the next rolling period", async() => { - await increaseTime(duration.days(1.7)); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("1"), {from: account_investor4}); - let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); - let latestTimestamp = 0; - tempArrayGlobal.push(1); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); - latestTimestamp = data[0][i]; - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} - `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 16); - assert.equal(data[0].length - 1, 3); - assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 1); + it("Should freely transfer the tokens after one day (completion of individual restriction)", async() => { + // increase one time + await increaseTime(duration.days(1)); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("17"), {from: account_investor3}); }); + }); - it("Should add the daily restriction successfully", async() => { - await I_VolumeRestrictionTM.addDailyGlobalRestriction( - web3.utils.toWei("5"), - 0, + describe("Should add the Default restriction", async() => { + + it("Should successfully add the default restriction", async() => { + await I_VolumeRestrictionTM.addDefaultRestriction( + web3.utils.toWei("10"), latestTime() + duration.seconds(2), - latestTime() + duration.days(3), + 5, + latestTime() + duration.days(10), 0, { from: token_owner } ); - let data = await I_VolumeRestrictionTM.dailyGlobalRestriction.call(); - assert.equal(data[0].dividedBy(new BigNumber(10).pow(18)).toNumber(), 5); - assert.equal(data[1].toNumber(), 0); - assert.equal(data[5].toNumber(), 0); - }); - it("Should failed to transact tokens -- failed because amount of tx is more than the daily limit",async() => { - let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - await increaseTime(duration.days(2)); - // Failed because amount of tokens is greater than the daily limit - await catchRevert( - I_SecurityToken.transfer(account_delegate3, web3.utils.toWei("5.1"), {from: account_investor4}) - ); + let data = await I_VolumeRestrictionTM.defaultRestriction.call(); + assert.equal(data[0].toNumber(), web3.utils.toWei("10")); + assert.equal(data[2].toNumber(), 5); }); - it("Should transfer the tokens with in the daily limit", async() => { - let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - await I_SecurityToken.transfer(account_delegate3, web3.utils.toWei("4.9"), {from: account_investor4}); - tempArrayGlobal.push(0); - tempArrayGlobal.push(4.9); - let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} - `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 5.9); - assert.equal(data[0].length - 1, 5); - assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 4.9); + it("Should add the investor 4 in the whitelist", async() => { + await I_GeneralTransferManager.modifyWhitelist( + account_investor4, + latestTime(), + latestTime(), + latestTime() + duration.days(30), + true, + { + from: token_owner + } + ); }); - it("Should transact the tokens more than the daily limit because daily limit restriction is ended", async() => { - let startTime = (await I_VolumeRestrictionTM.globalRestriction.call())[2].toNumber(); - await increaseTime(duration.days(1)); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("10"), {from: account_delegate3}); - tempArrayGlobal.push(10); - let data = await I_VolumeRestrictionTM.getGlobalBucketDetails.call(); - for (let i = 0; i < data[0].length; i++) { - console.log(` - Timestamps array index ${i}: ${data[0][i].toNumber()} - Total Trade till now: ${(await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18))} - `); - assert.equal(data[0][i].toNumber(), startTime + duration.days(i)); - assert.equal((await I_VolumeRestrictionTM.globalBucket.call(data[0][i])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), tempArrayGlobal[i]); - } - console.log(` - SumOfLastPeriod : ${web3.utils.fromWei((data[1].toNumber()).toString())} - Last Timestamp Index : ${data[0].length - 1} - Total amount traded in a day: ${web3.utils.fromWei((data[2].toNumber()).toString())} - `); - assert.equal(web3.utils.fromWei((data[1].toNumber()).toString()), 14.9); - assert.equal(data[0].length - 1, 6); - assert.equal(web3.utils.fromWei((data[2].toNumber()).toString()), 10); + it("Should mint some tokens to investor 4", async() => { + await I_SecurityToken.mint(account_investor4, web3.utils.toWei("15"), {from: token_owner}); }); }) - describe.skip("Test for the exemptlist", async() => { + describe("Test for the exemptlist", async() => { it("Should add the token holder in the exemption list -- failed because of bad owner", async() => { await catchRevert( @@ -1618,13 +1264,12 @@ contract('VolumeRestrictionTransferManager', accounts => { }); }); - describe.skip("Test for modify functions", async() => { + describe("Test for modify functions", async() => { - it("Should not able to modify the already started restrictions --global", async() =>{ + it.skip("Should not able to modify the already started restrictions --global", async() =>{ await catchRevert( - I_VolumeRestrictionTM.modifyGlobalRestriction( + I_VolumeRestrictionTM.modifyDefaultDailyRestriction( web3.utils.toWei("50"), - 0, latestTime() + duration.seconds(50), 10, latestTime() + duration.days(20), @@ -1636,11 +1281,10 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should not able to modify the already started restrictions -- daily global", async() =>{ + it.skip("Should not able to modify the already started restrictions -- daily global", async() =>{ await catchRevert( - I_VolumeRestrictionTM.modifyDailyGlobalRestriction( + I_VolumeRestrictionTM.modifyDefaultDailyRestriction( web3.utils.toWei("50"), - 0, latestTime() + duration.seconds(50), latestTime() + duration.days(20), 0, @@ -1651,12 +1295,11 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should not able to modify the already started restrictions -- Individual", async() =>{ + it.skip("Should not able to modify the already started restrictions -- Individual", async() =>{ await catchRevert( I_VolumeRestrictionTM.modifyIndividualRestriction( account_investor2, web3.utils.toWei("50"), - 0, latestTime() + duration.seconds(50), 10, latestTime() + duration.days(20), @@ -1668,12 +1311,11 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should not able to modify the already started transaction -- multi Individuals", async() => { + it.skip("Should not able to modify the already started transaction -- multi Individuals", async() => { await catchRevert( I_VolumeRestrictionTM.modifyIndividualRestrictionMulti( [account_investor2, account_investor1], [web3.utils.toWei("50"), web3.utils.toWei("50")], - [0, 0], [latestTime() + duration.seconds(50), latestTime() + duration.seconds(50)], [10, 20], [latestTime() + duration.days(20), latestTime() + duration.days(50)], @@ -1688,8 +1330,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should add the individual restriction for multiple investor", async() => { await I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor3, account_delegate3], - [web3.utils.toWei("15"), 0], - [0, new BigNumber(12.78).times(new BigNumber(10).pow(16))], + [web3.utils.toWei("15"), new BigNumber(12.78).times(new BigNumber(10).pow(16))], [latestTime() + duration.days(1), latestTime() + duration.days(2)], [15, 20], [latestTime() + duration.days(40), latestTime() + duration.days(60)], @@ -1703,23 +1344,19 @@ contract('VolumeRestrictionTransferManager', accounts => { let indi2 = await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3); assert.equal(indi1[0].dividedBy(new BigNumber(10).pow(18)), 15); - assert.equal(indi2[0].dividedBy(new BigNumber(10).pow(18)), 0); + assert.equal(indi2[0].dividedBy(new BigNumber(10).pow(16)), 12.78); - assert.equal(indi1[1].dividedBy(new BigNumber(10).pow(18)), 0); - assert.equal(indi2[1].dividedBy(new BigNumber(10).pow(16)), 12.78); + assert.equal(indi1[2].toNumber(), 15); + assert.equal(indi2[2].toNumber(), 20); - assert.equal(indi1[3].toNumber(), 15); - assert.equal(indi2[3].toNumber(), 20); - - assert.equal(indi1[5].toNumber(), 0); - assert.equal(indi2[5].toNumber(), 1); + assert.equal(indi1[4].toNumber(), 0); + assert.equal(indi2[4].toNumber(), 1); }); it("Should modify the details before the starttime passed", async() => { await I_VolumeRestrictionTM.modifyIndividualRestrictionMulti( [account_investor3, account_delegate3], - [0, web3.utils.toWei("15")], - [new BigNumber(12.78).times(new BigNumber(10).pow(16)), 0], + [new BigNumber(12.78).times(new BigNumber(10).pow(16)), web3.utils.toWei("15")], [latestTime() + duration.days(1), latestTime() + duration.days(2)], [20, 15], [latestTime() + duration.days(40), latestTime() + duration.days(60)], @@ -1733,16 +1370,13 @@ contract('VolumeRestrictionTransferManager', accounts => { let indi2 = await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3); assert.equal(indi2[0].dividedBy(new BigNumber(10).pow(18)), 15); - assert.equal(indi1[0].dividedBy(new BigNumber(10).pow(18)), 0); - - assert.equal(indi2[1].dividedBy(new BigNumber(10).pow(18)), 0); - assert.equal(indi1[1].dividedBy(new BigNumber(10).pow(16)), 12.78); + assert.equal(indi1[0].dividedBy(new BigNumber(10).pow(16)), 12.78); - assert.equal(indi2[3].toNumber(), 15); - assert.equal(indi1[3].toNumber(), 20); + assert.equal(indi2[2].toNumber(), 15); + assert.equal(indi1[2].toNumber(), 20); - assert.equal(indi2[5].toNumber(), 0); - assert.equal(indi1[5].toNumber(), 1); + assert.equal(indi2[4].toNumber(), 0); + assert.equal(indi1[4].toNumber(), 1); }); }); From 97fe1cfee07065ef88e11f66b15a11f1076bbaa9 Mon Sep 17 00:00:00 2001 From: satyam Date: Sun, 9 Dec 2018 16:35:24 +0530 Subject: [PATCH 357/582] more test cases and fix bug in algo --- .../TransferManager/VolumeRestrictionTM.sol | 4 +- test/y_volume_restriction_tm.js | 300 +++++++++++++----- 2 files changed, 224 insertions(+), 80 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 04240ea35..e525d81b8 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -934,8 +934,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (_diffDays >= _rollingPeriodInDays) { // If the difference of days is greater than the rollingPeriod then sumOfLastPeriod will always be zero sumOfLastPeriod = 0; + counter = counter.add(_diffDays); } else { for (i = 0; i < _diffDays; i++) { + counter++; // This condition is to check whether the first rolling period is covered or not // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting // the earlier value at that index @@ -948,8 +950,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand // the alogrithm //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); - // Storing all those timestamps whose total transacted value is 0 - counter++; } } // calculating the timestamp that will used as an index of the next bucket diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 115bfed7a..cfd955a91 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -203,7 +203,7 @@ contract('VolumeRestrictionTransferManager', accounts => { [account_investor1, account_investor2, account_investor3], [latestTime(), latestTime(), latestTime()], [latestTime(), latestTime(), latestTime()], - [latestTime() + duration.days(30), latestTime() + duration.days(30), latestTime() + duration.days(30)], + [latestTime() + duration.days(60), latestTime() + duration.days(60), latestTime() + duration.days(60)], [true, true, true], { from: token_owner @@ -1105,11 +1105,12 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should fail to transact tokens more than the allowed in the second rolling period", async() => { - await increaseTime(duration.days(5)); + await increaseTime(duration.days(4)); let i for (i = 0; i < 3; i++) { tempArray3.push(0); } + console.log(`Diff Days: ${(latestTime() - ((await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3))[0]).toNumber()) / 86400}`); let allowedAmount = (tempArray3[0] + 1.1); await catchRevert( I_SecurityToken.transfer(account_investor2, web3.utils.toWei(allowedAmount.toString()), {from: account_investor3}) @@ -1137,7 +1138,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); - assert.equal(data[2].toNumber(), 7); + assert.equal(data[2].toNumber(), 6); assert.equal(data[3].toNumber(), startTimedaily + duration.days(1)); assert.equal(amt, allowedAmount); }); @@ -1166,7 +1167,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); - assert.equal(data[2].toNumber(), 10); + assert.equal(data[2].toNumber(), 9); assert.equal(data[3].toNumber(), startTimedaily + duration.days(1)); assert.equal(amt, 7); }) @@ -1197,24 +1198,98 @@ contract('VolumeRestrictionTransferManager', accounts => { // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); - assert.equal(data[2].toNumber(), 14); + assert.equal(data[2].toNumber(), 13); assert.equal(data[3].toNumber(), startTimedaily + duration.days(1)); assert.equal(amt, 8); }); it("Should freely transfer the tokens after one day (completion of individual restriction)", async() => { // increase one time - await increaseTime(duration.days(1)); + await increaseTime(duration.days(2)); await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("17"), {from: account_investor3}); }); }); - describe("Should add the Default restriction", async() => { + describe("Test cases for the Default restrictions", async() => { + + it("Should add the investor 4 in the whitelist", async() => { + await I_GeneralTransferManager.modifyWhitelist( + account_investor4, + latestTime(), + latestTime(), + latestTime() + duration.days(30), + true, + { + from: token_owner + } + ); + }); + + it("Should mint some tokens to investor 4", async() => { + await I_SecurityToken.mint(account_investor4, web3.utils.toWei("20"), {from: token_owner}); + }); + + it("Should add the default daily restriction successfully", async() => { + await I_VolumeRestrictionTM.addDefaultDailyRestriction( + new BigNumber(2.75).times(new BigNumber(10).pow(16)), + 0, + latestTime() + duration.days(3), + 1, + { + from: token_owner + } + ); + + let dataRestriction = await I_VolumeRestrictionTM.defaultDailyRestriction.call(); + console.log(` + *** Add Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(16)).toNumber()} % of TotalSupply + StartTime : ${dataRestriction[1].toNumber()} + Rolling Period in days : ${dataRestriction[2].toNumber()} + EndTime : ${dataRestriction[3].toNumber()} + Type of Restriction: ${dataRestriction[4].toNumber()} + `); + }); + + it("Should fail to transfer above the daily limit", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei("5"), {from: account_investor4}) + ) + }) + + it("Should transfer the token by investor 4", async() => { + let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3.57"), {from: account_investor4}); + + let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor4); + await print(data, account_investor3); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor4, data[3].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), 0); + assert.equal(data[1].toNumber(), 0); + assert.equal(data[2].toNumber(), 0); + assert.equal(data[3].toNumber(), startTimedaily); + assert.equal(amt, 3.57); + }); + + it("Should transfer the tokens freely after ending the default daily restriction", async() => { + await increaseTime(duration.days(3)); + //sell tokens upto the limit + let tx = await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), {from: account_investor4}); + assert.equal((tx.logs[0].args.value).toNumber(), web3.utils.toWei("5")); + // Transfer the tokens again to investor 3 + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("40"), {from: account_investor2}); + }) it("Should successfully add the default restriction", async() => { await I_VolumeRestrictionTM.addDefaultRestriction( web3.utils.toWei("10"), - latestTime() + duration.seconds(2), + 0, 5, latestTime() + duration.days(10), 0, @@ -1226,23 +1301,153 @@ contract('VolumeRestrictionTransferManager', accounts => { let data = await I_VolumeRestrictionTM.defaultRestriction.call(); assert.equal(data[0].toNumber(), web3.utils.toWei("10")); assert.equal(data[2].toNumber(), 5); + let dataRestriction = await I_VolumeRestrictionTM.defaultRestriction.call(); + console.log(` + *** Add Individual restriction data *** + Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(18)).toNumber()} + StartTime : ${dataRestriction[1].toNumber()} + Rolling Period in days : ${dataRestriction[2].toNumber()} + EndTime : ${dataRestriction[3].toNumber()} + Type of Restriction: ${dataRestriction[4].toNumber()} + `); }); - it("Should add the investor 4 in the whitelist", async() => { - await I_GeneralTransferManager.modifyWhitelist( - account_investor4, - latestTime(), - latestTime(), - latestTime() + duration.days(30), - true, + it("Should transfer tokens on by investor 3 (comes under the Default restriction)", async() => { + tempArray3.length = 0; + let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); + let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), {from: account_investor3}); + tempArray3.push(5); + + let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 0); + assert.equal(data[3].toNumber(), 0); + assert.equal(amt, 5); + + // Transfer tokens on another day + + await increaseTime(duration.days(1)); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), {from: account_investor3}); + tempArray3.push(3); + + data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + // get the trade amount using the timestamp + amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 1); + assert.equal(data[3].toNumber(), 0); + assert.equal(amt, 3); + }); + + it("Should fail to transfer more tokens than the available default limit", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), {from: account_investor3}) + ); + }); + + it("Should able to transfer tokens in the next rolling period", async() => { + await increaseTime(duration.days(4.1)); + console.log(`Diff days: ${(latestTime() - ((await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3))[0]).toNumber()) / 86400}`) + for (let i = 0; i < 3; i++) { + tempArray3.push(0); + } + + let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); + let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); + + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("7"), {from: account_investor3}); + tempArray3.push(7); + + let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 5); + assert.equal(data[3].toNumber(), 0); + assert.equal(amt, 7); + + // Try to transact more on the same day but fail + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1"), {from: account_investor3}) + ); + }); + + it("Should add the daily default restriction again", async() => { + await I_VolumeRestrictionTM.addDefaultDailyRestriction( + web3.utils.toWei("2"), + 0, + latestTime() + duration.days(3), + 0, { from: token_owner } ); + + let dataRestriction = await I_VolumeRestrictionTM.defaultDailyRestriction.call(); + console.log(` + *** Add Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(16)).toNumber()} + StartTime : ${dataRestriction[1].toNumber()} + Rolling Period in days : ${dataRestriction[2].toNumber()} + EndTime : ${dataRestriction[3].toNumber()} + Type of Restriction: ${dataRestriction[4].toNumber()} + `); + }); + + it("Should not able to transfer tokens more than the default daily restriction", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), {from: account_investor3}) + ); }); - it("Should mint some tokens to investor 4", async() => { - await I_SecurityToken.mint(account_investor4, web3.utils.toWei("15"), {from: token_owner}); + it("Should able to transfer tokens within the limit of (daily default + default) restriction", async() => { + await increaseTime(duration.days(1)); + let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); + let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); + tempArray3[tempArray3.length -1] += 2; + + let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); + await print(data, account_investor3); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toNumber(), 5); + assert.equal(data[3].toNumber(), startTimedaily); + assert.equal(amt, 2); }); }) @@ -1266,67 +1471,6 @@ contract('VolumeRestrictionTransferManager', accounts => { describe("Test for modify functions", async() => { - it.skip("Should not able to modify the already started restrictions --global", async() =>{ - await catchRevert( - I_VolumeRestrictionTM.modifyDefaultDailyRestriction( - web3.utils.toWei("50"), - latestTime() + duration.seconds(50), - 10, - latestTime() + duration.days(20), - 0, - { - from: token_owner - } - ) - ); - }); - - it.skip("Should not able to modify the already started restrictions -- daily global", async() =>{ - await catchRevert( - I_VolumeRestrictionTM.modifyDefaultDailyRestriction( - web3.utils.toWei("50"), - latestTime() + duration.seconds(50), - latestTime() + duration.days(20), - 0, - { - from: token_owner - } - ) - ); - }); - - it.skip("Should not able to modify the already started restrictions -- Individual", async() =>{ - await catchRevert( - I_VolumeRestrictionTM.modifyIndividualRestriction( - account_investor2, - web3.utils.toWei("50"), - latestTime() + duration.seconds(50), - 10, - latestTime() + duration.days(20), - 0, - { - from: token_owner - } - ) - ); - }); - - it.skip("Should not able to modify the already started transaction -- multi Individuals", async() => { - await catchRevert( - I_VolumeRestrictionTM.modifyIndividualRestrictionMulti( - [account_investor2, account_investor1], - [web3.utils.toWei("50"), web3.utils.toWei("50")], - [latestTime() + duration.seconds(50), latestTime() + duration.seconds(50)], - [10, 20], - [latestTime() + duration.days(20), latestTime() + duration.days(50)], - [0, 0], - { - from: token_owner - } - ) - ); - }); - it("Should add the individual restriction for multiple investor", async() => { await I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor3, account_delegate3], From 7447fb6d66b584d0162914d19b5a2efcc3cabbc7 Mon Sep 17 00:00:00 2001 From: satyam Date: Sun, 9 Dec 2018 16:52:12 +0530 Subject: [PATCH 358/582] CLI & CountTransferManager changes readded --- CLI/commands/helpers/time.js | 50 ++++++++ CLI/polymath-cli.js | 47 +++++--- .../TransferManager/CountTransferManager.sol | 8 +- .../CountTransferManagerFactory.sol | 2 +- test/d_count_transfer_manager.js | 107 ++++++++++++++++++ 5 files changed, 196 insertions(+), 18 deletions(-) create mode 100644 CLI/commands/helpers/time.js diff --git a/CLI/commands/helpers/time.js b/CLI/commands/helpers/time.js new file mode 100644 index 000000000..68477a554 --- /dev/null +++ b/CLI/commands/helpers/time.js @@ -0,0 +1,50 @@ +const moment = require('moment'); +const chalk = require('chalk'); + function jumpToTime(timestamp) { + const id = Date.now(); + return new Promise((resolve, reject) => { + web3.currentProvider.send( + { + jsonrpc: "2.0", + method: "evm_mine", + params: [timestamp], + id: id + }, + (err, res) => { + return err ? reject(err) : resolve(res); + } + ); + }); +} + async function increaseTimeByDate(toTime) { + if (await web3.eth.net.getId() === 15) { + if (toTime.isValid()) { + let currentTime = (await web3.eth.getBlock('latest')).timestamp; + if (toTime.unix() > currentTime) { + await jumpToTime(toTime.unix()); + currentTime = (await web3.eth.getBlock('latest')).timestamp; + console.log(chalk.gree(`Current datetime is ${currentTime} or ${moment.unix(currentTime).format("MM/DD/YYYY HH:mm:ss")}`)); + } else { + console.log(chalk.red(`It is not possible to go back in time. Please try again with a time in the future to travel to`)); + } + } else { + console.log(chalk.red(`Date format is not valid. Please use a valid Unix epoch time`)); + } + } else { + console.log(chalk.red(`Time traveling is only possible over develpment network`)); + } +} + function increaseTimeByDuration(duration) { + let currentTime = moment().unix(); + let toTime = currentTime.add(duration, "seconds"); + return increaseTimeByDate(toTime); +} + function increaseTimeToDate(date) { + var toDate = moment(date, ['MM-DD-YYYY', 'MM-DD-YYYY HH:mm:ss']); + return increaseTimeByDate(toDate); +} + function increaseTimeToEpochDate(epochDate) { + var toTime = moment.unix(epochDate); + return increaseTimeByDate(toTime); +} + module.exports = { increaseTimeByDuration, increaseTimeToDate, increaseTimeToEpochDate }; \ No newline at end of file diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 2ce101a4d..d3394c8eb 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -1,19 +1,21 @@ #!/usr/bin/env node -var faucet = require('./commands/faucet'); -var investor_portal = require('./commands/investor_portal'); -var token_manager = require('./commands/token_manager'); -var st20generator = require('./commands/ST20Generator'); -var sto_manager = require('./commands/sto_manager'); -var transfer = require('./commands/transfer'); -var transfer_ownership = require('./commands/transfer_ownership'); -var dividends_manager = require('./commands/dividends_manager'); -var transfer_manager = require('./commands/transfer_manager'); -var contract_manager = require('./commands/contract_manager'); -var strMigrator = require('./commands/strMigrator'); -var permission_manager = require('./commands/permission_manager'); -var program = require('commander'); -var gbl = require('./commands/common/global'); +const faucet = require('./commands/faucet'); +const investor_portal = require('./commands/investor_portal'); +const token_manager = require('./commands/token_manager'); +const st20generator = require('./commands/ST20Generator'); +const sto_manager = require('./commands/sto_manager'); +const transfer = require('./commands/transfer'); +const transfer_ownership = require('./commands/transfer_ownership'); +const dividends_manager = require('./commands/dividends_manager'); +const transfer_manager = require('./commands/transfer_manager'); +const contract_manager = require('./commands/contract_manager'); +const strMigrator = require('./commands/strMigrator'); +const permission_manager = require('./commands/permission_manager'); +const time = require('./commands/helpers/time'); +const gbl = require('./commands/common/global'); +const program = require('commander'); +const moment = require('moment'); const yaml = require('js-yaml'); const fs = require('fs'); @@ -151,6 +153,23 @@ program await permission_manager.executeApp(); }); + program + .command('time_travel') + .alias('tt') + .option('-p, --period ', 'Period of time in seconds to increase') + .option('-d, --toDate ', 'Human readable date ("MM/DD/YY [HH:mm:ss]") to travel to') + .option('-e, --toEpochTime ', 'Unix Epoch time to travel to') + .description('Increases time on EVM according to given value.') + .action(async function (cmd) { + await gbl.initialize(program.remoteNode); + if (cmd.period) { + await time.increaseTimeByDuration(parseInt(cmd.period)); + } else if (cmd.toDate) { + await time.increaseTimeToDate(cmd.toDate); + } else if (cmd.toEpochTime) { + await time.increaseTimeToEpochDate(cmd.toEpochTime); + } + }); program.parse(process.argv); if (typeof program.commands.length == 0) { diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index b54870251..86a537ebe 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -26,12 +26,14 @@ contract CountTransferManager is ITransferManager { } /** @notice Used to verify the transfer transaction and prevent a transfer if it passes the allowed amount of token holders + * @param _from Address of the sender * @param _to Address of the receiver + * @param _amount Amount to send */ function verifyTransfer( - address /* _from */, + address _from, address _to, - uint256 /* _amount */, + uint256 _amount, bytes /* _data */, bool /* _isTransfer */ ) @@ -41,7 +43,7 @@ contract CountTransferManager is ITransferManager { if (!paused) { if (maxHolderCount < ISecurityToken(securityToken).getInvestorCount()) { // Allow transfers to existing maxHolders - if (ISecurityToken(securityToken).balanceOf(_to) != 0) { + if (ISecurityToken(securityToken).balanceOf(_to) != 0 || ISecurityToken(securityToken).balanceOf(_from) == _amount) { return Result.NA; } return Result.INVALID; diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index d9b1328f7..c42cebc61 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -16,7 +16,7 @@ contract CountTransferManagerFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + version = "2.1.0"; name = "CountTransferManager"; title = "Count Transfer Manager"; description = "Restrict the number of investors"; diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 1a1e7717a..3107c4bf7 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -39,7 +39,9 @@ contract("CountTransferManager", accounts => { let I_CountTransferManagerFactory; let I_GeneralPermissionManager; let I_CountTransferManager; + let I_CountTransferManager2; let I_GeneralTransferManager; + let I_GeneralTransferManager2; let I_ExchangeTransferManager; let I_ModuleRegistry; let I_ModuleRegistryProxy; @@ -49,12 +51,14 @@ contract("CountTransferManager", accounts => { let I_SecurityTokenRegistry; let I_STFactory; let I_SecurityToken; + let I_SecurityToken2; let I_PolyToken; let I_PolymathRegistry; // SecurityToken Details const name = "Team"; const symbol = "sap"; + const symbol2 = "sapp"; const tokenDetails = "This is equity type of issuance"; const decimals = 18; const contact = "team@polymath.network"; @@ -81,6 +85,7 @@ contract("CountTransferManager", accounts => { account_investor1 = accounts[7]; account_investor2 = accounts[8]; account_investor3 = accounts[9]; + account_investor4 = accounts[6]; // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -347,6 +352,108 @@ contract("CountTransferManager", accounts => { let perm = await I_CountTransferManager.getPermissions.call(); assert.equal(perm.length, 1); }); + describe("Test cases for adding and removing acc holder at the same time", async () => { + it("deploy a new token & auto attach modules", async () => { + + //register ticker and deploy token + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol2, contact, { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx2 = await I_STRProxied.generateSecurityToken(name, symbol2, tokenDetails, false, { from: token_owner }); + + I_SecurityToken2 = SecurityToken.at(tx2.logs[1].args._securityTokenAddress); + let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + }); + it("add 3 holders to the token", async () => { + await I_GeneralTransferManager2.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + await I_GeneralTransferManager2.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + await I_GeneralTransferManager2.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + + await I_GeneralTransferManager2.modifyWhitelist( + account_investor4, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + + // Jump time + await increaseTime(5000); + // Add 3 holders to the token + await I_SecurityToken2.mint(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_SecurityToken2.mint(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_SecurityToken2.mint(account_investor3, web3.utils.toWei("1", "ether"), { from: token_owner }); + assert.equal((await I_SecurityToken2.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + }); + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + }); + it("Should successfully attach the CountTransferManager factory with the security token", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await catchRevert( + I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + from: token_owner + }) + ); + }); + it("Should successfully attach the CountTransferManager with the security token and set max holder to 2", async () => { + const tx = await I_SecurityToken2.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "CountTransferManager", + "CountTransferManager module was not added" + ); + I_CountTransferManager2 = CountTransferManager.at(tx.logs[2].args._module); + await I_CountTransferManager2.changeHolderCount(2, {from: token_owner}); + console.log('current max holder number is '+ await I_CountTransferManager2.maxHolderCount({from: token_owner})); + }); + it("Should allow add a new token holder while transfer all the tokens at one go", async () => { + let amount = (await I_SecurityToken2.balanceOf(account_investor2)).toNumber(); + let investorCount = await I_SecurityToken2.getInvestorCount({from: account_investor2 }); + console.log("current investor count is " + investorCount); + await I_SecurityToken2.transfer(account_investor4, amount, { from: account_investor2 }); + assert((await I_SecurityToken2.balanceOf(account_investor4)).toNumber(), amount, {from: account_investor2 }); + assert(await I_SecurityToken2.getInvestorCount({from: account_investor2 }), investorCount); + }); + }); describe("Test cases for the factory", async () => { it("should get the exact details of the factory", async () => { From f03b5f7c06557cea01f4477bfae69c1acb10d64a Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Sun, 9 Dec 2018 20:05:29 +0100 Subject: [PATCH 359/582] finished MATM function changes --- .../ManualApprovalTransferManager.sol | 85 ++++++++++++++++++- test/j_manual_approval_transfer_manager.js | 44 +++++++++- 2 files changed, 126 insertions(+), 3 deletions(-) diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index fd25ab43d..bea99f672 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -19,13 +19,19 @@ contract ManualApprovalTransferManager is ITransferManager { //Manual approval is an allowance (that has been approved) with an expiry time struct ManualApproval { + address from; + address to; uint256 allowance; uint256 expiryTime; + bytes32 description; } //Store mappings of address => address with ManualApprovals mapping (address => mapping (address => ManualApproval)) public manualApprovals; + //An array to track all current active approvals + ManualApproval[] public activeManualApprovals; + event AddManualApproval( address indexed _from, address indexed _to, @@ -34,6 +40,13 @@ contract ManualApprovalTransferManager is ITransferManager { address indexed _addedBy ); + event EditManualApproval( + address indexed _from, + address indexed _to, + uint256 _expiryTime, + address indexed _edittedBy + ); + event RevokeManualApproval( address indexed _from, address indexed _to, @@ -86,14 +99,47 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _allowance is the approved amount of tokens * @param _expiryTime is the time until which the transfer is allowed */ - function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { + function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime, bytes32 _description) public withPerm(TRANSFER_APPROVAL) { require(_to != address(0), "Invalid to address"); require(_expiryTime > now, "Invalid expiry time"); require(manualApprovals[_from][_to].allowance == 0, "Approval already exists"); - manualApprovals[_from][_to] = ManualApproval(_allowance, _expiryTime); + manualApprovals[_from][_to] = ManualApproval(_from, _to, _allowance, _expiryTime, _description); + activeManualApprovals.push(ManualApproval(_from, _to, _allowance, _expiryTime, _description)); + emit AddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender); } + + /** + * @notice Adds mutiple manual approvals in batch + * @param _from is the address array from which transfers are approved + * @param _to is the address array to which transfers are approved + * @param _allowance is the array of approved amounts + * @param _expiryTime is the array of the times until which eath transfer is allowed + * @param _description is the description array for these manual approvals + */ + function addManualApprovalMulti(address[] _from, address[] _to, uint256[] _allowance, uint256[] _expiryTime, bytes32[] _description) public withPerm(TRANSFER_APPROVAL) { + require(_from.length == _to.length && _to.length == _allowance.length && _allowance.length == _expiryTime.length && _expiryTime.length == _description.length, "input array numbers not matching"); + for(uint8 i=0; i<_from.length; i++){ + addManualApproval(_from[i], _to[i], _allowance[i], _expiryTime[i], _description[i]); + } + } + + /** + * @notice Edit an existing manual approvals + * @param _from is the new address from which transfers are approved + * @param _to is the new address to which transfers are approved + * @param _expiryTime is the new time until which the transfer is allowed + */ + function updateManualApproval(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { + require(_to != address(0), "Invalid to address"); + /*solium-disable-next-line security/no-block-members*/ + require(_expiryTime > now, "Invalid expiry time"); + require(manualApprovals[_from][_to].allowance != 0, "Approval does not exists"); + manualApprovals[_from][_to].expiryTime = _expiryTime; + emit EditManualApproval(_from, _to, _expiryTime, msg.sender); + } + /** * @notice Removes a pairs of addresses from manual approvals * @param _from is the address from which transfers are approved @@ -102,9 +148,44 @@ contract ManualApprovalTransferManager is ITransferManager { function revokeManualApproval(address _from, address _to) public withPerm(TRANSFER_APPROVAL) { require(_to != address(0), "Invalid to address"); delete manualApprovals[_from][_to]; + + //find the record in active approvals array & delete it + uint256 index; + for(uint256 i = 0; i < activeManualApprovals.length; i++){ + if (activeManualApprovals[i].from == _from && activeManualApprovals[i].to == _to){ + index = i; + } + } + + for(uint256 j = index; j < activeManualApprovals.length-1; j++){ + activeManualApprovals[j] = activeManualApprovals[j+1]; + } + + delete activeManualApprovals[activeManualApprovals.length-1]; + activeManualApprovals.length--; + emit RevokeManualApproval(_from, _to, msg.sender); } + /** + * @notice Removes mutiple pairs of addresses from manual approvals + * @param _from is the address array from which transfers are approved + * @param _to is the address array to which transfers are approved + */ + function revokeManualApprovalMulti(address[] _from, address[] _to) public withPerm(TRANSFER_APPROVAL) { + require(_from.length == _to.length, "input array numbers not matching"); + for(uint8 i=0; i<_from.length; i++){ + revokeManualApproval(_from[i], _to[i]); + } + } + + /** + * @notice Returns the current number of active approvals + */ + function getActiveApprovalsLength() public view returns(uint256) { + return activeManualApprovals.length; + } + /** * @notice Returns the permissions flag that are associated with ManualApproval transfer manager */ diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 11f22bb8c..7e799872c 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -328,6 +328,7 @@ contract("ManualApprovalTransferManager", accounts => { "", web3.utils.toWei("2", "ether"), latestTime() + duration.days(1), + "DESCRIPTION", { from: token_owner } ) ); @@ -340,27 +341,66 @@ contract("ManualApprovalTransferManager", accounts => { account_investor4, web3.utils.toWei("2", "ether"), 99999, + "DESCRIPTION", { from: token_owner } ) ); }); - it("Add a manual approval for a 4th investor", async () => { + it("Add a manual approval for a 4th investor & return correct length", async () => { await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, web3.utils.toWei("2", "ether"), latestTime() + duration.days(1), + "DESCRIPTION", + { from: token_owner } + ); + + assert(await I_ManualApprovalTransferManager.getActiveApprovalsLength({ from: token_owner }), 1); + }); + + it("Should update the manual approval expiry time for 4th investor", async () => { + await I_ManualApprovalTransferManager.updateManualApproval( + account_investor1, + account_investor4, + latestTime() + duration.days(2), { from: token_owner } ); }); + it("Add multiple manual approvals", async () => { + await I_ManualApprovalTransferManager.addManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + [web3.utils.toWei("2", "ether"), web3.utils.toWei("2", "ether")], + [latestTime() + duration.days(1),latestTime() + duration.days(1)], + ["DESCRIPTION", "DESCRIPTION"], + { from: token_owner } + ); + + assert(await I_ManualApprovalTransferManager.getActiveApprovalsLength({ from: token_owner }), 3); + }); + + it("Revoke multiple manual approvals", async () => { + await I_ManualApprovalTransferManager.revokeManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + { from: token_owner } + ); + + assert(await I_ManualApprovalTransferManager.getActiveApprovalsLength({ from: token_owner }), 1); + }); + + + it("Add a manual approval for a 5th investor from issuance", async () => { await I_ManualApprovalTransferManager.addManualApproval( "", account_investor5, web3.utils.toWei("2", "ether"), latestTime() + duration.days(1), + "DESCRIPTION", { from: token_owner } ); }); @@ -372,6 +412,7 @@ contract("ManualApprovalTransferManager", accounts => { account_investor4, web3.utils.toWei("2", "ether"), latestTime() + duration.days(5), + "DESCRIPTION", { from: token_owner } ) ); @@ -393,6 +434,7 @@ contract("ManualApprovalTransferManager", accounts => { account_investor4, web3.utils.toWei("2", "ether"), latestTime() + duration.days(1), + "DESCRIPTION", { from: token_owner } ); }); From 57bde3a81ba6fd4753f3b3f0da7fdbe1764b80bc Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 10 Dec 2018 11:32:35 +0530 Subject: [PATCH 360/582] minor fix in test case --- test/y_volume_restriction_tm.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index cfd955a91..260df3ef4 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -1433,7 +1433,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); //sell tokens upto the limit await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); - tempArray3[tempArray3.length -1] += 2; + tempArray3.push(2); let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); @@ -1445,8 +1445,8 @@ contract('VolumeRestrictionTransferManager', accounts => { // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray3)); - assert.equal(data[2].toNumber(), 5); - assert.equal(data[3].toNumber(), startTimedaily); + assert.equal(data[2].toNumber(), 6); + assert.equal(data[3].toNumber(), startTimedaily + duration.days(1)); assert.equal(amt, 2); }); }) From 74c3c4fc0a59b9b87e3bca35c38b291c2b679e81 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 13:54:36 +0530 Subject: [PATCH 361/582] Increase Travis test timeout to 25 minutes --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2265b2d88..520c82130 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ jobs: - stage: Tests and Coverage after_install: wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js before_script: truffle version - script: npm run test + script: travis_wait 25 npm run test - stage: Docs env: 'TASK=docs' before_install: @@ -24,4 +24,4 @@ jobs: script: npm run docs notifications: slack: - secure: W4FZSabLrzF74f317hutolEHnlq2GBlQxU6b85L5XymrjgLEhlgE16c5Qz7Emoyt6le6PXL+sfG2ujJc3XYys/6hppgrHSAasuJnKCdQNpmMZ9BNyMs6WGkmB3enIf3K/FLXb26AQdwpQdIXuOeJUTf879u+YoiZV0eZH8d3+fsIOyovq9N6X5pKOpDM9iT8gGB4t7fie7xf51s+iUaHxyO9G7jDginZ4rBXHcU7mxCub9z+Z1H8+kCTnPWaF+KKVEXx4Z0nI3+urboD7E4OIP02LwrThQls2CppA3X0EoesTcdvj/HLErY/JvsXIFiFEEHZzB1Wi+k2TiOeLcYwEuHIVij+HPxxlJNX/j8uy01Uk8s4rd+0EhvfdKHJqUKqxH4YN2npcKfHEss7bU3y7dUinXQfYShW5ZewHdvc7pnnxBTfhvmdi64HdNrXAPq+s1rhciH7MmnU+tsm4lhrpr+FBuHzUMA9fOCr7b0SQytZEgWpiUls88gdbh3yG8TjyZxmZJGx09cwEP0q7VoH0UwFh7mIu5XmYdd5tWUhavTiO7YV8cUPn7MvwMsTltB3YBpF/fB26L7ka8zBhCsjm9prW6SVYU/dyO3m91VeZtO/zJFHRDA6Q58JGVW2rgzO39z193qC1EGRXqTie96VwAAtNg8+hRb+bI/CWDVzSPc= \ No newline at end of file + secure: W4FZSabLrzF74f317hutolEHnlq2GBlQxU6b85L5XymrjgLEhlgE16c5Qz7Emoyt6le6PXL+sfG2ujJc3XYys/6hppgrHSAasuJnKCdQNpmMZ9BNyMs6WGkmB3enIf3K/FLXb26AQdwpQdIXuOeJUTf879u+YoiZV0eZH8d3+fsIOyovq9N6X5pKOpDM9iT8gGB4t7fie7xf51s+iUaHxyO9G7jDginZ4rBXHcU7mxCub9z+Z1H8+kCTnPWaF+KKVEXx4Z0nI3+urboD7E4OIP02LwrThQls2CppA3X0EoesTcdvj/HLErY/JvsXIFiFEEHZzB1Wi+k2TiOeLcYwEuHIVij+HPxxlJNX/j8uy01Uk8s4rd+0EhvfdKHJqUKqxH4YN2npcKfHEss7bU3y7dUinXQfYShW5ZewHdvc7pnnxBTfhvmdi64HdNrXAPq+s1rhciH7MmnU+tsm4lhrpr+FBuHzUMA9fOCr7b0SQytZEgWpiUls88gdbh3yG8TjyZxmZJGx09cwEP0q7VoH0UwFh7mIu5XmYdd5tWUhavTiO7YV8cUPn7MvwMsTltB3YBpF/fB26L7ka8zBhCsjm9prW6SVYU/dyO3m91VeZtO/zJFHRDA6Q58JGVW2rgzO39z193qC1EGRXqTie96VwAAtNg8+hRb+bI/CWDVzSPc= From e44af3d7c6e487bb3db273d24379803d8946dd63 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 14:17:17 +0530 Subject: [PATCH 362/582] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 520c82130..91a00c5ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ jobs: - stage: Tests and Coverage after_install: wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js before_script: truffle version - script: travis_wait 25 npm run test + script: travis_wait 120 sleep infinity & npm run test - stage: Docs env: 'TASK=docs' before_install: From e5799470f3a5e64e272f779202048b27c7238711 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 10 Dec 2018 16:56:35 +0530 Subject: [PATCH 363/582] minor fix in the naming convention --- .../TransferManager/VolumeRestrictionTM.sol | 34 +++++++++---------- .../VolumeRestrictionTMStorage.sol | 4 +-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index e525d81b8..fff5f71f4 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -440,9 +440,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_holder != address(0), "Invalid address"); require(individualRestriction[_holder].endTime != 0, "Not present"); individualRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - bucketToUser[_holder].lastTradedDayTime = 0; - bucketToUser[_holder].sumOfLastPeriod = 0; - bucketToUser[_holder].daysCovered = 0; + userToBucket[_holder].lastTradedDayTime = 0; + userToBucket[_holder].sumOfLastPeriod = 0; + userToBucket[_holder].daysCovered = 0; emit IndividualRestrictionRemoved(_holder); } @@ -469,7 +469,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_holder != address(0), "Invalid address"); require(individualDailyRestriction[_holder].endTime != 0, "Not present"); individualDailyRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - bucketToUser[_holder].dailyLastTradedDayTime = 0; + userToBucket[_holder].dailyLastTradedDayTime = 0; emit IndividualDailyRestrictionRemoved(_holder); } @@ -612,7 +612,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); // Initializing the value with 0 to allow the trade with new startTime of the restriction - bucketToUser[_holder].dailyLastTradedDayTime = 0; + userToBucket[_holder].dailyLastTradedDayTime = 0; individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, startTime, @@ -787,7 +787,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { */ function _defaultRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { // using the variable to avoid stack too deep error - BucketDetails memory bucketDetails = defaultBucketToUser[_from]; + BucketDetails memory bucketDetails = defaultUserToBucket[_from]; uint256 daysCovered = defaultRestriction.rollingPeriodInDays; uint256 fromTimestamp = 0; uint256 sumOfLastPeriod = 0; @@ -840,7 +840,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { */ function _individualRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { // using the variable to avoid stack too deep error - BucketDetails memory bucketDetails = bucketToUser[_from]; + BucketDetails memory bucketDetails = userToBucket[_from]; VolumeRestriction memory dailyRestriction = individualDailyRestriction[_from]; VolumeRestriction memory restriction = individualRestriction[_from]; uint256 daysCovered = individualRestriction[_from].rollingPeriodInDays; @@ -992,9 +992,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { { BucketDetails storage details; if (isDefault) - details = defaultBucketToUser[_from]; + details = defaultUserToBucket[_from]; else - details = bucketToUser[_from]; + details = userToBucket[_from]; // Cheap storage technique if (details.lastTradedDayTime != _lastTradedDayTime) { // Assigning the latest transaction timestamp of the day @@ -1074,10 +1074,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { */ function getIndividualBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { return( - bucketToUser[_user].lastTradedDayTime, - bucketToUser[_user].sumOfLastPeriod, - bucketToUser[_user].daysCovered, - bucketToUser[_user].dailyLastTradedDayTime + userToBucket[_user].lastTradedDayTime, + userToBucket[_user].sumOfLastPeriod, + userToBucket[_user].daysCovered, + userToBucket[_user].dailyLastTradedDayTime ); } @@ -1091,10 +1091,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { */ function getDefaultBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { return( - defaultBucketToUser[_user].lastTradedDayTime, - defaultBucketToUser[_user].sumOfLastPeriod, - defaultBucketToUser[_user].daysCovered, - defaultBucketToUser[_user].dailyLastTradedDayTime + defaultUserToBucket[_user].lastTradedDayTime, + defaultUserToBucket[_user].sumOfLastPeriod, + defaultUserToBucket[_user].daysCovered, + defaultUserToBucket[_user].dailyLastTradedDayTime ); } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol index 9e614213a..e995676a0 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol @@ -36,9 +36,9 @@ contract VolumeRestrictionTMStorage { // Storing _from => day's timestamp => total amount transact in a day --individual mapping(address => mapping(uint256 => uint256)) internal bucket; // Storing the information that used to validate the transaction - mapping(address => BucketDetails) internal bucketToUser; + mapping(address => BucketDetails) internal userToBucket; // Storing the information related to default restriction - mapping(address => BucketDetails) internal defaultBucketToUser; + mapping(address => BucketDetails) internal defaultUserToBucket; // List of wallets that are exempted from all the restrictions applied by the this contract mapping(address => bool) public exemptList; From 2c91d2741c829754414b0033f31667231f8f06db Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 17:10:48 +0530 Subject: [PATCH 364/582] Removed sim and fuzz tests from coverage --- .solcover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.solcover.js b/.solcover.js index 23ac4d3ef..dacedf1f1 100644 --- a/.solcover.js +++ b/.solcover.js @@ -2,7 +2,7 @@ module.exports = { norpc: true, port: 8545, copyPackages: ['openzeppelin-solidity'], - testCommand: 'node ../node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js` --network coverage', + testCommand: 'node ../node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js -and ! -name q_usd_tiered_sto_sim.js -and ! -name z_general_permission_manager_fuzzer.js` --network coverage', deepSkip: true, skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'storage', 'modules/Experimental'], forceParse: ['mocks', 'oracles', 'modules/Experimental'] From 32c16f0b8bd7cedb9d712edc82efb66d10ea4a8d Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 17:49:20 +0530 Subject: [PATCH 365/582] Initial circleci script --- .circleci/config.yml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..86bb215de --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,39 @@ +version: 2 +jobs: + test: + docker: + - image: circleci/node:8 + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package.json" }} + - run: + - yarn + - node --version + - truffle version + - npm run test + - save_cache: + key: dependency-cache-{{ checksum "package.json" }} + paths: + - node_modules + docs: + docker: + - image: circleci/node:8 + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package.json" }} + - run: + - yarn + - npm run docs + - save_cache: + key: dependency-cache-{{ checksum "package.json" }} + paths: + - node_modules +workflows: + version: 2 + test_and_docs: + jobs: + - test + - docs + \ No newline at end of file From a6a60ee5589a8aefb32f28c2c3dba24f415ab93a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 17:56:30 +0530 Subject: [PATCH 366/582] circle ci run fixed --- .circleci/config.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 86bb215de..41ac6838b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,11 +7,10 @@ jobs: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - - run: - - yarn - - node --version - - truffle version - - npm run test + - run: yarn + - run: node --version + - run: truffle version + - run: npm run test - save_cache: key: dependency-cache-{{ checksum "package.json" }} paths: @@ -23,9 +22,10 @@ jobs: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - - run: - - yarn - - npm run docs + - run: yarn + - run: node --version + - run: truffle version + - run: npm run docs - save_cache: key: dependency-cache-{{ checksum "package.json" }} paths: From b71f8186056524d51adabf0cd1b912364aab1f65 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:00:25 +0530 Subject: [PATCH 367/582] Added global truffle installation --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 41ac6838b..feb53b66e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,6 +8,7 @@ jobs: - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - run: yarn + - run: npm i truffle -g - run: node --version - run: truffle version - run: npm run test @@ -23,6 +24,7 @@ jobs: - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - run: yarn + - run: npm i truffle -g - run: node --version - run: truffle version - run: npm run docs From d5dfc62a45a5b7058a5cfa5c876a1abeb8bd4723 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:03:13 +0530 Subject: [PATCH 368/582] Added sudo to global install --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index feb53b66e..f69a20ced 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ jobs: - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - run: yarn - - run: npm i truffle -g + - run: sudo npm i truffle -g - run: node --version - run: truffle version - run: npm run test @@ -24,7 +24,7 @@ jobs: - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - run: yarn - - run: npm i truffle -g + - run: sudo npm i truffle -g - run: node --version - run: truffle version - run: npm run docs From 4d9af7b243f5fce5f89c6b9e02ddd0ecfd6592fd Mon Sep 17 00:00:00 2001 From: shuffledex Date: Mon, 10 Dec 2018 09:42:47 -0300 Subject: [PATCH 369/582] PR fixes --- CLI/commands/sto_manager.js | 93 +++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index d9e95f723..796f7387f 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -295,60 +295,65 @@ function fundingConfigUSDTieredSTO() { } async function addressesConfigUSDTieredSTO(usdTokenRaise) { - let addresses = {}; - addresses.wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - defaultInput: Issuer.address - }); - if (addresses.wallet == "") addresses.wallet = Issuer.address; + let addresses, menu; - addresses.reserveWallet = readlineSync.question('Enter the address that will receive remaining tokens in the case the cap is not met (' + Issuer.address + '): ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - defaultInput: Issuer.address - }); - if (addresses.reserveWallet == "") addresses.reserveWallet = Issuer.address; + do { - let listOfAddress; + addresses = {}; - if (usdTokenRaise) { - addresses.usdToken = readlineSync.question('Enter the address (or many addresses that you want separated by comma) of the USD Token or stable coin (' + usdToken.options.address + '): ', { + addresses.wallet = readlineSync.question('Enter the address that will receive the funds from the STO (' + Issuer.address + '): ', { limit: function (input) { - listOfAddress = input.split(','); - let response = true - listOfAddress.forEach((addr) => { - if (!web3.utils.isAddress(addr)) { - response = false - } - }) - return response + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: Issuer.address + }); + if (addresses.wallet == "") addresses.wallet = Issuer.address; + + addresses.reserveWallet = readlineSync.question('Enter the address that will receive remaining tokens in the case the cap is not met (' + Issuer.address + '): ', { + limit: function (input) { + return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address", - defaultInput: usdToken.options.address + defaultInput: Issuer.address }); - if (addresses.usdToken == "") { - listOfAddress = [usdToken.options.address] - addresses.usdToken = [usdToken.options.address]; + if (addresses.reserveWallet == "") addresses.reserveWallet = Issuer.address; + + let listOfAddress; + + if (usdTokenRaise) { + addresses.usdToken = readlineSync.question('Enter the address (or many addresses that you want separated by comma) of the USD Token or stable coin (' + usdToken.options.address + '): ', { + limit: function (input) { + listOfAddress = input.split(','); + return listOfAddress.every((addr) => { + return web3.utils.isAddress(addr) + }) + }, + limitMessage: "Must be a valid address", + defaultInput: usdToken.options.address + }); + if (addresses.usdToken == "") { + listOfAddress = [usdToken.options.address] + addresses.usdToken = [usdToken.options.address]; + } + } else { + listOfAddress = ['0x0000000000000000000000000000000000000000'] + addresses.usdToken = ['0x0000000000000000000000000000000000000000']; + } + + if (!await processArray(listOfAddress)) { + console.log(chalk.yellow(`\nPlease, verify your stable coins addresses to continue with this process.\n`)) + menu = true; + } else { + menu = false; + } + + if (typeof addresses.usdToken === 'string') { + addresses.usdToken = addresses.usdToken.split(",") } - } else { - listOfAddress = ['0x0000000000000000000000000000000000000000'] - addresses.usdToken = ['0x0000000000000000000000000000000000000000']; - } - - if (!await processArray(listOfAddress)) { - console.log(`Please, verify your stable coins addresses to continue with this process.`) - process.exit(0) - } - if (typeof addresses.usdToken === 'string') { - addresses.usdToken = addresses.usdToken.split(",") - } + } while (menu); return addresses; } From 9f096a981c36edbc4c5a384e93be6d9537456e00 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:23:20 +0530 Subject: [PATCH 370/582] Added coverage, parallelism --- .circleci/config.yml | 49 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f69a20ced..00b97d3ce 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,8 +1,26 @@ version: 2 jobs: + build: + docker: + - image: circleci/node:8 + parallelism: 4 + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package.json" }} + - run: yarn + - run: sudo npm i truffle -g + - run: node --version + - run: truffle version + - run: truffle compile + - save_cache: + key: dependency-cache-{{ checksum "package.json" }} + paths: + - node_modules test: docker: - image: circleci/node:8 + parallelism: 4 steps: - checkout - restore_cache: @@ -16,6 +34,23 @@ jobs: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules + coverage: + docker: + - image: circleci/node:8 + parallelism: 4 + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package.json" }} + - run: yarn + - run: sudo npm i truffle -g + - run: node --version + - run: truffle version + - run: npm run coverage + - save_cache: + key: dependency-cache-{{ checksum "package.json" }} + paths: + - node_modules docs: docker: - image: circleci/node:8 @@ -34,8 +69,16 @@ jobs: - node_modules workflows: version: 2 - test_and_docs: + build-test-coverage-docs: jobs: - - test - - docs + - build + - test: + - requires: + - build + - coverage: + - requires: + - test + - docs: + - requires: + - coverage \ No newline at end of file From c9b622afe761f8279dcdc07f4ebe2881b6b7cdd3 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:27:16 +0530 Subject: [PATCH 371/582] Workflow fixed --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 00b97d3ce..2714ad01e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -73,12 +73,12 @@ workflows: jobs: - build - test: - - requires: - - build + requires: + - build - coverage: - - requires: - - test + requires: + - test - docs: - - requires: - - coverage + requires: + - coverage \ No newline at end of file From 63f2c8f3e1dddf6e93ea48dfac500d28d499d7c8 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:41:25 +0530 Subject: [PATCH 372/582] Removed parallelism --- .circleci/config.yml | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2714ad01e..26383b3bd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,6 @@ jobs: build: docker: - image: circleci/node:8 - parallelism: 4 steps: - checkout - restore_cache: @@ -20,7 +19,6 @@ jobs: test: docker: - image: circleci/node:8 - parallelism: 4 steps: - checkout - restore_cache: @@ -37,7 +35,6 @@ jobs: coverage: docker: - image: circleci/node:8 - parallelism: 4 steps: - checkout - restore_cache: @@ -72,13 +69,6 @@ workflows: build-test-coverage-docs: jobs: - build - - test: - requires: - - build - - coverage: - requires: - - test - - docs: - requires: - - coverage - \ No newline at end of file + - test + - coverage + - docs \ No newline at end of file From 35a4d176a73b68c7b8a51c77746aba7c9eef9d81 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 10 Dec 2018 10:28:37 -0300 Subject: [PATCH 373/582] Time traveling fixes --- CLI/commands/helpers/time.js | 47 ++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/CLI/commands/helpers/time.js b/CLI/commands/helpers/time.js index dd244d04e..720e25d41 100644 --- a/CLI/commands/helpers/time.js +++ b/CLI/commands/helpers/time.js @@ -1,6 +1,35 @@ const moment = require('moment'); const chalk = require('chalk'); +function increaseTime(duration) { + const id = Date.now(); + + return new Promise((resolve, reject) => { + web3.currentProvider.send( + { + jsonrpc: "2.0", + method: "evm_increaseTime", + params: [duration], + id: id + }, + err1 => { + if (err1) return reject(err1); + + web3.currentProvider.send( + { + jsonrpc: "2.0", + method: "evm_mine", + id: id + 1 + }, + (err2, res) => { + return err2 ? reject(err2) : resolve(res); + } + ); + } + ); + }); +} + function jumpToTime(timestamp) { const id = Date.now(); @@ -26,7 +55,7 @@ async function increaseTimeByDate(toTime) { if (toTime.unix() > currentTime) { await jumpToTime(toTime.unix()); currentTime = (await web3.eth.getBlock('latest')).timestamp; - console.log(chalk.gree(`Current datetime is ${currentTime} or ${moment.unix(currentTime).format("MM/DD/YYYY HH:mm:ss")}`)); + console.log(chalk.green(`Current datetime is ${currentTime} or ${moment.unix(currentTime).format("MM/DD/YYYY HH:mm:ss")}`)); } else { console.log(chalk.red(`It is not possible to go back in time. Please try again with a time in the future to travel to`)); } @@ -38,10 +67,16 @@ async function increaseTimeByDate(toTime) { } } -function increaseTimeByDuration(duration) { - let currentTime = moment().unix(); - let toTime = currentTime.add(duration, "seconds"); - return increaseTimeByDate(toTime); +async function increaseTimeByDuration(duration) { + if (await web3.eth.net.getId() === 15) { + if (duration > 0) { + await increaseTime(duration); + currentTime = (await web3.eth.getBlock('latest')).timestamp; + console.log(chalk.green(`Current datetime is ${currentTime} or ${moment.unix(currentTime).format("MM/DD/YYYY HH:mm:ss")}`)); + } else { + console.log(chalk.red(`It is not possible to go back in time. Please try again with a time in the future to travel to`)); + } + } } function increaseTimeToDate(date) { @@ -55,5 +90,3 @@ function increaseTimeToEpochDate(epochDate) { } module.exports = { increaseTimeByDuration, increaseTimeToDate, increaseTimeToEpochDate }; - - From 74f120632a9a17e73b337a3a320386ff95c98d61 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 10 Dec 2018 13:52:15 +0000 Subject: [PATCH 374/582] Add DateTimeLibrary --- .../libraries/BokkyPooBahsDateTimeLibrary.sol | 339 ++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 contracts/libraries/BokkyPooBahsDateTimeLibrary.sol diff --git a/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol b/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol new file mode 100644 index 000000000..29de4d7cd --- /dev/null +++ b/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol @@ -0,0 +1,339 @@ +pragma solidity ^0.4.24; + +// ---------------------------------------------------------------------------- +// BokkyPooBah's DateTime Library v1.00 +// +// A gas-efficient Solidity date and time library +// +// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary +// +// Tested date range 1970/01/01 to 2345/12/31 +// +// Conventions: +// Unit | Range | Notes +// :-------- |:-------------:|:----- +// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC +// year | 1970 ... 2345 | +// month | 1 ... 12 | +// day | 1 ... 31 | +// hour | 0 ... 23 | +// minute | 0 ... 59 | +// second | 0 ... 59 | +// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday +// +// +// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018. +// +// GNU Lesser General Public License 3.0 +// https://www.gnu.org/licenses/lgpl-3.0.en.html +// ---------------------------------------------------------------------------- + +library BokkyPooBahsDateTimeLibrary { + + uint constant SECONDS_PER_DAY = 24 * 60 * 60; + uint constant SECONDS_PER_HOUR = 60 * 60; + uint constant SECONDS_PER_MINUTE = 60; + int constant OFFSET19700101 = 2440588; + + uint constant DOW_MON = 1; + uint constant DOW_TUE = 2; + uint constant DOW_WED = 3; + uint constant DOW_THU = 4; + uint constant DOW_FRI = 5; + uint constant DOW_SAT = 6; + uint constant DOW_SUN = 7; + + // ------------------------------------------------------------------------ + // Calculate the number of days from 1970/01/01 to year/month/day using + // the date conversion algorithm from + // http://aa.usno.navy.mil/faq/docs/JD_Formula.php + // and subtracting the offset 2440588 so that 1970/01/01 is day 0 + // + // days = day + // - 32075 + // + 1461 * (year + 4800 + (month - 14) / 12) / 4 + // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12 + // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4 + // - offset + // ------------------------------------------------------------------------ + function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) { + require(year >= 1970); + int _year = int(year); + int _month = int(month); + int _day = int(day); + + int __days = _day + - 32075 + + 1461 * (_year + 4800 + (_month - 14) / 12) / 4 + + 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12 + - 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4 + - OFFSET19700101; + + _days = uint(__days); + } + + // ------------------------------------------------------------------------ + // Calculate year/month/day from the number of days since 1970/01/01 using + // the date conversion algorithm from + // http://aa.usno.navy.mil/faq/docs/JD_Formula.php + // and adding the offset 2440588 so that 1970/01/01 is day 0 + // + // int L = days + 68569 + offset + // int N = 4 * L / 146097 + // L = L - (146097 * N + 3) / 4 + // year = 4000 * (L + 1) / 1461001 + // L = L - 1461 * year / 4 + 31 + // month = 80 * L / 2447 + // dd = L - 2447 * month / 80 + // L = month / 11 + // month = month + 2 - 12 * L + // year = 100 * (N - 49) + year + L + // ------------------------------------------------------------------------ + function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) { + int __days = int(_days); + + int L = __days + 68569 + OFFSET19700101; + int N = 4 * L / 146097; + L = L - (146097 * N + 3) / 4; + int _year = 4000 * (L + 1) / 1461001; + L = L - 1461 * _year / 4 + 31; + int _month = 80 * L / 2447; + int _day = L - 2447 * _month / 80; + L = _month / 11; + _month = _month + 2 - 12 * L; + _year = 100 * (N - 49) + _year + L; + + year = uint(_year); + month = uint(_month); + day = uint(_day); + } + + function timestampFromDate(uint year, uint month, uint day) internal pure returns (uint timestamp) { + timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY; + } + function timestampFromDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (uint timestamp) { + timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second; + } + function timestampToDate(uint timestamp) internal pure returns (uint year, uint month, uint day) { + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + } + function timestampToDateTime(uint timestamp) internal pure returns (uint year, uint month, uint day, uint hour, uint minute, uint second) { + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + uint secs = timestamp % SECONDS_PER_DAY; + hour = secs / SECONDS_PER_HOUR; + secs = secs % SECONDS_PER_HOUR; + minute = secs / SECONDS_PER_MINUTE; + second = secs % SECONDS_PER_MINUTE; + } + + function isValidDate(uint year, uint month, uint day) internal pure returns (bool valid) { + if (year >= 1970 && month > 0 && month <= 12) { + uint daysInMonth = _getDaysInMonth(year, month); + if (day > 0 && day <= daysInMonth) { + valid = true; + } + } + } + function isValidDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (bool valid) { + if (isValidDate(year, month, day)) { + if (hour < 24 && minute < 60 && second < 60) { + valid = true; + } + } + } + function isLeapYear(uint timestamp) internal pure returns (bool leapYear) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + leapYear = _isLeapYear(year); + } + function _isLeapYear(uint year) internal pure returns (bool leapYear) { + leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); + } + function isWeekDay(uint timestamp) internal pure returns (bool weekDay) { + weekDay = getDayOfWeek(timestamp) <= DOW_FRI; + } + function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) { + weekEnd = getDayOfWeek(timestamp) >= DOW_SAT; + } + function getDaysInMonth(uint timestamp) internal pure returns (uint daysInMonth) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + daysInMonth = _getDaysInMonth(year, month); + } + function _getDaysInMonth(uint year, uint month) internal pure returns (uint daysInMonth) { + if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { + daysInMonth = 31; + } else if (month != 2) { + daysInMonth = 30; + } else { + daysInMonth = _isLeapYear(year) ? 29 : 28; + } + } + // 1 = Monday, 7 = Sunday + function getDayOfWeek(uint timestamp) internal pure returns (uint dayOfWeek) { + uint _days = timestamp / SECONDS_PER_DAY; + dayOfWeek = (_days + 3) % 7 + 1; + } + + function getYear(uint timestamp) internal pure returns (uint year) { + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + } + function getMonth(uint timestamp) internal pure returns (uint month) { + uint year; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + } + function getDay(uint timestamp) internal pure returns (uint day) { + uint year; + uint month; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + } + function getHour(uint timestamp) internal pure returns (uint hour) { + uint secs = timestamp % SECONDS_PER_DAY; + hour = secs / SECONDS_PER_HOUR; + } + function getMinute(uint timestamp) internal pure returns (uint minute) { + uint secs = timestamp % SECONDS_PER_HOUR; + minute = secs / SECONDS_PER_MINUTE; + } + function getSecond(uint timestamp) internal pure returns (uint second) { + second = timestamp % SECONDS_PER_MINUTE; + } + + function addYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + year += _years; + uint daysInMonth = _getDaysInMonth(year, month); + if (day > daysInMonth) { + day = daysInMonth; + } + newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; + require(newTimestamp >= timestamp); + } + function addMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + month += _months; + year += (month - 1) / 12; + month = (month - 1) % 12 + 1; + uint daysInMonth = _getDaysInMonth(year, month); + if (day > daysInMonth) { + day = daysInMonth; + } + newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; + require(newTimestamp >= timestamp); + } + function addDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp + _days * SECONDS_PER_DAY; + require(newTimestamp >= timestamp); + } + function addHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp + _hours * SECONDS_PER_HOUR; + require(newTimestamp >= timestamp); + } + function addMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE; + require(newTimestamp >= timestamp); + } + function addSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp + _seconds; + require(newTimestamp >= timestamp); + } + + function subYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + year -= _years; + uint daysInMonth = _getDaysInMonth(year, month); + if (day > daysInMonth) { + day = daysInMonth; + } + newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; + require(newTimestamp <= timestamp); + } + function subMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) { + uint year; + uint month; + uint day; + (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); + uint yearMonth = year * 12 + (month - 1) - _months; + year = yearMonth / 12; + month = yearMonth % 12 + 1; + uint daysInMonth = _getDaysInMonth(year, month); + if (day > daysInMonth) { + day = daysInMonth; + } + newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; + require(newTimestamp <= timestamp); + } + function subDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp - _days * SECONDS_PER_DAY; + require(newTimestamp <= timestamp); + } + function subHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp - _hours * SECONDS_PER_HOUR; + require(newTimestamp <= timestamp); + } + function subMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE; + require(newTimestamp <= timestamp); + } + function subSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) { + newTimestamp = timestamp - _seconds; + require(newTimestamp <= timestamp); + } + + function diffYears(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _years) { + require(fromTimestamp <= toTimestamp); + uint fromYear; + uint fromMonth; + uint fromDay; + uint toYear; + uint toMonth; + uint toDay; + (fromYear, fromMonth, fromDay) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); + (toYear, toMonth, toDay) = _daysToDate(toTimestamp / SECONDS_PER_DAY); + _years = toYear - fromYear; + } + function diffMonths(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _months) { + require(fromTimestamp <= toTimestamp); + uint fromYear; + uint fromMonth; + uint fromDay; + uint toYear; + uint toMonth; + uint toDay; + (fromYear, fromMonth, fromDay) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); + (toYear, toMonth, toDay) = _daysToDate(toTimestamp / SECONDS_PER_DAY); + _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth; + } + function diffDays(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _days) { + require(fromTimestamp <= toTimestamp); + _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY; + } + function diffHours(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _hours) { + require(fromTimestamp <= toTimestamp); + _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR; + } + function diffMinutes(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _minutes) { + require(fromTimestamp <= toTimestamp); + _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE; + } + function diffSeconds(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _seconds) { + require(fromTimestamp <= toTimestamp); + _seconds = toTimestamp - fromTimestamp; + } +} From 304555b27d6e9c24e7f2506c209f1b45cb3c2e67 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 10 Dec 2018 10:55:54 -0300 Subject: [PATCH 375/582] Error message --- CLI/commands/helpers/time.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CLI/commands/helpers/time.js b/CLI/commands/helpers/time.js index 720e25d41..294f54f67 100644 --- a/CLI/commands/helpers/time.js +++ b/CLI/commands/helpers/time.js @@ -76,6 +76,8 @@ async function increaseTimeByDuration(duration) { } else { console.log(chalk.red(`It is not possible to go back in time. Please try again with a time in the future to travel to`)); } + } else { + console.log(chalk.red(`Time traveling is only possible over develpment network`)); } } From 09be6ccb43292636370037aadbbf4d93ef469597 Mon Sep 17 00:00:00 2001 From: F O'Brien <42175565+F-OBrien@users.noreply.github.com> Date: Mon, 10 Dec 2018 20:33:07 +0530 Subject: [PATCH 376/582] Update CLI/commands/sto_manager.js Co-Authored-By: maxsam4 --- CLI/commands/sto_manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 796f7387f..c4559b048 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -323,7 +323,7 @@ async function addressesConfigUSDTieredSTO(usdTokenRaise) { let listOfAddress; if (usdTokenRaise) { - addresses.usdToken = readlineSync.question('Enter the address (or many addresses that you want separated by comma) of the USD Token or stable coin (' + usdToken.options.address + '): ', { + addresses.usdToken = readlineSync.question('Enter the address (or multiple addresses separated by commas) of the USD stable coin(s) (' + usdToken.options.address + '): ', { limit: function (input) { listOfAddress = input.split(','); return listOfAddress.every((addr) => { @@ -1045,4 +1045,4 @@ module.exports = { await initialize(_tokenSymbol); return addSTOModule(stoConfig) } -} \ No newline at end of file +} From 4a94e71b265edff915d26cef46bc800a703405be Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 20:36:19 +0530 Subject: [PATCH 377/582] Added native currency raised --- contracts/modules/STO/USDTieredSTO.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index d3be00047..590234a28 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -66,6 +66,9 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Amount of USD funds raised uint256 public fundsRaisedUSD; + // Amount of native currencies raised. 0x0 address is used for ETH. + mapping (address => uint256) public currencyRaised; + // Amount in USD invested by each address mapping (address => uint256) public investorInvestedUSD; @@ -447,6 +450,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Modify storage investorInvested[_beneficiary][uint8(FundRaiseType.ETH)] = investorInvested[_beneficiary][uint8(FundRaiseType.ETH)].add(spentValue); fundsRaised[uint8(FundRaiseType.ETH)] = fundsRaised[uint8(FundRaiseType.ETH)].add(spentValue); + currencyRaised[address(0)] = currencyRaised[address(0)].add(spentValue); // Forward ETH to issuer wallet wallet.transfer(spentValue); // Refund excess ETH to investor wallet @@ -486,6 +490,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // Modify storage investorInvested[_beneficiary][uint8(_fundRaiseType)] = investorInvested[_beneficiary][uint8(_fundRaiseType)].add(spentValue); fundsRaised[uint8(_fundRaiseType)] = fundsRaised[uint8(_fundRaiseType)].add(spentValue); + currencyRaised[address(_token)] = currencyRaised[address(_token)].add(spentValue); // Forward coins to issuer wallet require(_token.transferFrom(msg.sender, wallet, spentValue), "Transfer failed"); emit FundsReceived(msg.sender, _beneficiary, spentUSD, _fundRaiseType, _tokenAmount, spentValue, rate); From 0f47ceb7b998807a98b109c48fe6fe1b8facd1bd Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 10 Dec 2018 15:16:55 +0000 Subject: [PATCH 378/582] Skip DateTime library in code coverage --- .solcover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.solcover.js b/.solcover.js index dacedf1f1..dac86d6e3 100644 --- a/.solcover.js +++ b/.solcover.js @@ -4,6 +4,6 @@ module.exports = { copyPackages: ['openzeppelin-solidity'], testCommand: 'node ../node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js -and ! -name q_usd_tiered_sto_sim.js -and ! -name z_general_permission_manager_fuzzer.js` --network coverage', deepSkip: true, - skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'storage', 'modules/Experimental'], + skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'libraries/BokkyPooBahsDateTimeLibrary.sol', 'storage', 'modules/Experimental'], forceParse: ['mocks', 'oracles', 'modules/Experimental'] }; From c7c16ec31ef1e2d5b75c8b068e4b65e69d2004f7 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 10 Dec 2018 18:13:43 +0200 Subject: [PATCH 379/582] Applied review comments --- .../modules/Wallet/VestingEscrowWallet.sol | 34 ++++++------ .../Wallet/VestingEscrowWalletStorage.sol | 2 + test/z_vesting_escrow_wallet.js | 54 +++++++++++++------ 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index d7a425051..872946ccf 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -90,18 +90,24 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { function _depositTokens(uint256 _numberOfTokens) internal { require(_numberOfTokens > 0, "Should be > 0"); - ISecurityToken(securityToken).transferFrom(msg.sender, address(this), _numberOfTokens); + require( + ISecurityToken(securityToken).transferFrom(msg.sender, address(this), _numberOfTokens), + "Failed transferFrom due to insufficent Allowance provided" + ); unassignedTokens = unassignedTokens.add(_numberOfTokens); emit DepositTokens(_numberOfTokens, msg.sender); } /** * @notice Sends unassigned tokens to treasury + * @param _amount amount of tokens that should be send */ - function sendToTreasury() external withPerm(ADMIN) { + function sendToTreasury(uint256 _amount) external withPerm(ADMIN) { + require(_amount > 0, "Amount cannot be zero"); + require(_amount <= unassignedTokens, "Amount is greater than unassigned tokens"); uint256 amount = unassignedTokens; unassignedTokens = 0; - ISecurityToken(securityToken).transfer(treasuryWallet, amount); + require(ISecurityToken(securityToken).transfer(treasuryWallet, amount), "Transfer failed"); emit SendToTreasury(amount, msg.sender); } @@ -136,7 +142,7 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { require(!_isTemplateExists(_name), "Already exists"); _validateTemplate(_numberOfTokens, _duration, _frequency); templateNames.push(_name); - templates[_name] = Template(_numberOfTokens, _duration, _frequency); + templates[_name] = Template(_numberOfTokens, _duration, _frequency, templateNames.length - 1); emit AddTemplate(_name, _numberOfTokens, _duration, _frequency); } @@ -147,18 +153,16 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { function removeTemplate(bytes32 _name) external withPerm(ADMIN) { require(_isTemplateExists(_name), "Template not found"); require(templateToUsers[_name].length == 0, "Template is used"); - // delete template data - delete templates[_name]; - uint256 i; - for (i = 0; i < templateNames.length; i++) { - if (_name == templateNames[i]) { - break; - } - } - if (i != templateNames.length - 1) { - templateNames[i] = templateNames[templateNames.length - 1]; + uint256 index = templates[_name].index; + if (index != templateNames.length - 1) { + templateNames[index] = templateNames[templateNames.length - 1]; } templateNames.length--; + if (index != templateNames.length) { + templates[templateNames[index]].index = index; + } + // delete template data + delete templates[_name]; emit RemoveTemplate(_name); } @@ -538,7 +542,7 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { uint256 amount = _getAvailableTokens(_beneficiary, _index); if (amount > 0) { schedules[_beneficiary][_index].claimedTokens = schedules[_beneficiary][_index].claimedTokens.add(amount); - ISecurityToken(securityToken).transfer(_beneficiary, amount); + require(ISecurityToken(securityToken).transfer(_beneficiary, amount), "Transfer failed"); emit SendTokens(_beneficiary, amount); } } diff --git a/contracts/modules/Wallet/VestingEscrowWalletStorage.sol b/contracts/modules/Wallet/VestingEscrowWalletStorage.sol index bdf7d5df4..af40d32bf 100644 --- a/contracts/modules/Wallet/VestingEscrowWalletStorage.sol +++ b/contracts/modules/Wallet/VestingEscrowWalletStorage.sol @@ -21,6 +21,8 @@ contract VestingEscrowWalletStorage { uint256 duration; // Schedule frequency (It is a cliff time period) uint256 frequency; + // Index of the template in an array template names + uint256 index; } // Number of tokens that are hold by the `this` contract but are unassigned to any schedule diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 754bd65bd..d15acddd1 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -327,13 +327,26 @@ contract('VestingEscrowWallet', accounts => { it("Should not be able to withdraw tokens to a treasury -- fail because of permissions check", async () => { await catchRevert( - I_VestingEscrowWallet.sendToTreasury({from: account_beneficiary1}) + I_VestingEscrowWallet.sendToTreasury(10, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to withdraw tokens to a treasury -- fail because of zero amount", async () => { + await catchRevert( + I_VestingEscrowWallet.sendToTreasury(0, {from: wallet_admin}) + ); + }); + + it("Should not be able to withdraw tokens to a treasury -- fail because amount is greater than unassigned tokens", async () => { + let numberOfTokens = 25000 * 2; + await catchRevert( + I_VestingEscrowWallet.sendToTreasury(numberOfTokens, {from: wallet_admin}) ); }); it("Should withdraw tokens to a treasury", async () => { let numberOfTokens = 25000; - const tx = await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + const tx = await I_VestingEscrowWallet.sendToTreasury(numberOfTokens, {from: wallet_admin}); assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); @@ -388,7 +401,8 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); }); it("Should fail to modify vesting schedule -- fail because date in the past", async () => { @@ -422,7 +436,6 @@ contract('VestingEscrowWallet', accounts => { await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary3, {from: wallet_admin}); await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should withdraw available tokens 2 times by 3 schedules to the beneficiary address", async () => { @@ -489,7 +502,6 @@ contract('VestingEscrowWallet', accounts => { for (let i = 0; i < schedules.length; i++) { await I_VestingEscrowWallet.removeTemplate(schedules[i].templateName, {from: wallet_admin}); } - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); }); @@ -579,7 +591,8 @@ contract('VestingEscrowWallet', accounts => { await catchRevert( I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: account_beneficiary1}) ); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); }); it("Should add vesting schedule to the beneficiary address", async () => { @@ -626,7 +639,8 @@ contract('VestingEscrowWallet', accounts => { await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, templateName, {from: wallet_admin}); await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); }); it("Should fail to modify vesting schedule -- fail because schedule not found", async () => { @@ -658,8 +672,6 @@ contract('VestingEscrowWallet', accounts => { let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, "template-2-01"); checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); - - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); }); it("Should not be able to revoke schedule -- fail because of permissions check", async () => { @@ -671,7 +683,8 @@ contract('VestingEscrowWallet', accounts => { it("Should revoke vesting schedule from the beneficiary address", async () => { let templateName = "template-2-01"; const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, templateName, {from: wallet_admin}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary1); assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._templateName), templateName); @@ -732,7 +745,8 @@ contract('VestingEscrowWallet', accounts => { it("Should revoke 1 of 3 vesting schedule from the beneficiary address", async () => { let templateName = schedules[1].templateName; const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary2, templateName, {from: wallet_admin}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._templateName), templateName); @@ -743,7 +757,8 @@ contract('VestingEscrowWallet', accounts => { it("Should revoke 2 vesting schedules from the beneficiary address", async () => { const tx = await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary2, {from: wallet_admin}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); assert.equal(tx.logs[0].args._beneficiary, account_beneficiary2); @@ -811,7 +826,8 @@ contract('VestingEscrowWallet', accounts => { assert.equal(balance.toNumber(), totalNumberOfTokens - 100000 / 4); await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); }); }); @@ -937,7 +953,8 @@ contract('VestingEscrowWallet', accounts => { checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, templateName, {from: wallet_admin}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); }); it("Should not be able to add vesting schedule from template -- fail because template already added", async () => { @@ -984,7 +1001,8 @@ contract('VestingEscrowWallet', accounts => { await catchRevert( I_VestingEscrowWallet.addScheduleMulti(beneficiaries, templateNames, [20000, 30000, 10000], [4, 4], [1, 1, 1], startTimes, {from: wallet_admin}) ); - I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); }); it("Should add schedules for 3 beneficiaries", async () => { @@ -1081,7 +1099,8 @@ contract('VestingEscrowWallet', accounts => { await I_SecurityToken.transfer(token_owner, balance, {from: beneficiary}); await I_VestingEscrowWallet.revokeAllSchedules(beneficiary, {from: wallet_admin}); await I_VestingEscrowWallet.removeTemplate(templateNames[i], {from: wallet_admin}); - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); } }); @@ -1140,7 +1159,8 @@ contract('VestingEscrowWallet', accounts => { assert.equal(scheduleCount, 0); } - await I_VestingEscrowWallet.sendToTreasury({from: wallet_admin}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); }); }); From affcf54146858352cb7a696bf93fdd0462124e95 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 10 Dec 2018 22:03:19 +0530 Subject: [PATCH 380/582] remove the irrevalent if conditions --- contracts/modules/Wallet/VestingEscrowWallet.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 872946ccf..4e0f089b7 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -156,11 +156,9 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { uint256 index = templates[_name].index; if (index != templateNames.length - 1) { templateNames[index] = templateNames[templateNames.length - 1]; - } - templateNames.length--; - if (index != templateNames.length) { templates[templateNames[index]].index = index; } + templateNames.length--; // delete template data delete templates[_name]; emit RemoveTemplate(_name); From c85c52178aaadf91a0847d8dd4002a9858a50f40 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 22:38:09 +0530 Subject: [PATCH 381/582] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71457d9d9..d12951de2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ## CappedSTO 2.0.1 * `rate` is now accepted as multiplied by 10^18 to allow settting higher price than 1ETH/POLY per token. +* Indivisble tokens are now supported. When trying to buy partial tokens, allowed full units of tokens will be purchased and rest of the funds will be returned. ## USDTieredSTO 2.0.1 * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. From 1423a118ee4ddf82fa3ec10f99484fc2dd1e2957 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 22:39:27 +0530 Subject: [PATCH 382/582] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d12951de2..dd53ce781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ All notable changes to this project will be documented in this file. ## CappedSTO 2.0.1 * `rate` is now accepted as multiplied by 10^18 to allow settting higher price than 1ETH/POLY per token. -* Indivisble tokens are now supported. When trying to buy partial tokens, allowed full units of tokens will be purchased and rest of the funds will be returned. +* Indivisble tokens are now supported. When trying to buy partial tokens, allowed full units of tokens will be purchased and remaining funds will be returned. ## USDTieredSTO 2.0.1 * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. From a59e50e3f4a522d0c5e1091decad53c42ecfb0de Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 10 Dec 2018 23:09:10 +0530 Subject: [PATCH 383/582] improve the function definitions --- .../ManualApprovalTransferManager.sol | 223 ++++++++++++++---- 1 file changed, 183 insertions(+), 40 deletions(-) diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index bea99f672..48d87ab06 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -28,6 +28,7 @@ contract ManualApprovalTransferManager is ITransferManager { //Store mappings of address => address with ManualApprovals mapping (address => mapping (address => ManualApproval)) public manualApprovals; + mapping (address => mapping (address => uint256)) internal approvalsIndex; //An array to track all current active approvals ManualApproval[] public activeManualApprovals; @@ -40,10 +41,11 @@ contract ManualApprovalTransferManager is ITransferManager { address indexed _addedBy ); - event EditManualApproval( + event ModifyManualApproval( address indexed _from, address indexed _to, uint256 _expiryTime, + uint256 _allowance, address indexed _edittedBy ); @@ -71,7 +73,8 @@ contract ManualApprovalTransferManager is ITransferManager { return bytes4(0); } - /** @notice Used to verify the transfer transaction and allow a manually approved transqaction to bypass other restrictions + /** + * @notice Used to verify the transfer transaction and allow a manually approved transqaction to bypass other restrictions * @param _from Address of the sender * @param _to Address of the receiver * @param _amount The amount of tokens to transfer @@ -98,46 +101,149 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _to is the address to which transfers are approved * @param _allowance is the approved amount of tokens * @param _expiryTime is the time until which the transfer is allowed + * @param _description Description about the manual approval */ - function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime, bytes32 _description) public withPerm(TRANSFER_APPROVAL) { + function addManualApproval( + address _from, + address _to, + uint256 _allowance, + uint256 _expiryTime, + bytes32 _description + ) + external + withPerm(TRANSFER_APPROVAL) + { + _addManualApproval(_from, _to, _allowance, _expiryTime, _description); + } + + function _addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime, bytes32 _description) internal { require(_to != address(0), "Invalid to address"); require(_expiryTime > now, "Invalid expiry time"); - require(manualApprovals[_from][_to].allowance == 0, "Approval already exists"); + require(_allowance > 0, "Invalid allowance"); + require(manualApprovals[_from][_to].allowance == 0 || manualApprovals[_from][_to].expiryTime < now, "Approval already exists"); manualApprovals[_from][_to] = ManualApproval(_from, _to, _allowance, _expiryTime, _description); activeManualApprovals.push(ManualApproval(_from, _to, _allowance, _expiryTime, _description)); - + approvalsIndex[_from][_to] = activeManualApprovals.length - 1; emit AddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender); } - /** * @notice Adds mutiple manual approvals in batch * @param _from is the address array from which transfers are approved * @param _to is the address array to which transfers are approved - * @param _allowance is the array of approved amounts - * @param _expiryTime is the array of the times until which eath transfer is allowed - * @param _description is the description array for these manual approvals + * @param _allowances is the array of approved amounts + * @param _expiryTimes is the array of the times until which eath transfer is allowed + * @param _descriptions is the description array for these manual approvals */ - function addManualApprovalMulti(address[] _from, address[] _to, uint256[] _allowance, uint256[] _expiryTime, bytes32[] _description) public withPerm(TRANSFER_APPROVAL) { - require(_from.length == _to.length && _to.length == _allowance.length && _allowance.length == _expiryTime.length && _expiryTime.length == _description.length, "input array numbers not matching"); - for(uint8 i=0; i<_from.length; i++){ - addManualApproval(_from[i], _to[i], _allowance[i], _expiryTime[i], _description[i]); + function addManualApprovalMulti( + address[] _from, + address[] _to, + uint256[] _allowances, + uint256[] _expiryTimes, + bytes32[] _descriptions + ) + external + withPerm(TRANSFER_APPROVAL) + { + _checkInputLengthArray(_from, _to, _allowances, _expiryTimes, _descriptions); + for (uint256 i = 0; i < _from.length; i++){ + _addManualApproval(_from[i], _to[i], _allowances[i], _expiryTimes[i], _descriptions[i]); } } /** - * @notice Edit an existing manual approvals - * @param _from is the new address from which transfers are approved - * @param _to is the new address to which transfers are approved - * @param _expiryTime is the new time until which the transfer is allowed + * @notice Modify the existing manual approvals + * @param _from is the address from which transfers are approved + * @param _to is the address to which transfers are approved + * @param _expiryTime is the time until which the transfer is allowed + * @param _changedAllowance is the changed allowance + * @param _description Description about the manual approval + * @param _change uint values which tells whether the allowances will be increased (1) or decreased (0) + * or any value when there is no change in allowances */ - function updateManualApproval(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { + function modifyManualApproval( + address _from, + address _to, + uint256 _expiryTime, + uint256 _changedAllowance, + bytes32 _description, + uint8 _change + ) + external + withPerm(TRANSFER_APPROVAL) + { + _modifyManualApproval(_from, _to, _expiryTime, _changedAllowance, _description, _change); + } + + function _modifyManualApproval( + address _from, + address _to, + uint256 _expiryTime, + uint256 _changedAllowance, + bytes32 _description, + uint8 _change + ) + internal + { require(_to != address(0), "Invalid to address"); /*solium-disable-next-line security/no-block-members*/ require(_expiryTime > now, "Invalid expiry time"); require(manualApprovals[_from][_to].allowance != 0, "Approval does not exists"); - manualApprovals[_from][_to].expiryTime = _expiryTime; - emit EditManualApproval(_from, _to, _expiryTime, msg.sender); + uint256 currentAllowance = manualApprovals[_from][_to].allowance; + uint256 newAllowance; + if (_change == 1) { + // Allowance get increased + manualApprovals[_from][_to].allowance = ( + manualApprovals[_from][_to].allowance.add(_changedAllowance)); + newAllowance = currentAllowance.add(_changedAllowance); + } else if (_change == 0) { + // Allowance get decreased + if (_changedAllowance > currentAllowance) { + manualApprovals[_from][_to].allowance = 0; + } else { + manualApprovals[_from][_to].allowance = currentAllowance.sub(_changedAllowance); + } + newAllowance = currentAllowance.sub(_changedAllowance); + } else { + // No change in the Allowance + newAllowance = currentAllowance; + } + // Greedy storage technique + if (manualApprovals[_from][_to].expiryTime != _expiryTime) { + manualApprovals[_from][_to].expiryTime = _expiryTime; + } + if (manualApprovals[_from][_to].description != _description) { + manualApprovals[_from][_to].description = _description; + } + emit ModifyManualApproval(_from, _to, _expiryTime, newAllowance, msg.sender); + } + + /** + * @notice Adds mutiple manual approvals in batch + * @param _from is the address array from which transfers are approved + * @param _to is the address array to which transfers are approved + * @param _expiryTimes is the array of the times until which eath transfer is allowed + * @param _changedAllowances is the array of approved amounts + * @param _descriptions is the description array for these manual approvals + * @param _changes Array of uint values which tells whether the allowances will be increased (1) or decreased (0) + * or any value when there is no change in allowances + */ + function modifyManualApprovalMulti( + address[] _from, + address[] _to, + uint256[] _expiryTimes, + uint256[] _changedAllowances, + bytes32[] _descriptions, + uint8[] _changes + ) + public + withPerm(TRANSFER_APPROVAL) + { + _checkInputLengthArray(_from, _to, _changedAllowances, _expiryTimes, _descriptions); + require(_changes.length == _changedAllowances.length, "Input length array mismatch"); + for (uint256 i = 0; i < _from.length; i++) { + _modifyManualApproval(_from[i], _to[i], _expiryTimes[i], _changedAllowances[i], _descriptions[i], _changes[i]); + } } /** @@ -145,25 +251,22 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _from is the address from which transfers are approved * @param _to is the address to which transfers are approved */ - function revokeManualApproval(address _from, address _to) public withPerm(TRANSFER_APPROVAL) { - require(_to != address(0), "Invalid to address"); - delete manualApprovals[_from][_to]; + function revokeManualApproval(address _from, address _to) external withPerm(TRANSFER_APPROVAL) { + _revokeManualApproval(_from, _to); + } - //find the record in active approvals array & delete it - uint256 index; - for(uint256 i = 0; i < activeManualApprovals.length; i++){ - if (activeManualApprovals[i].from == _from && activeManualApprovals[i].to == _to){ - index = i; - } - } + function _revokeManualApproval(address _from, address _to) internal { + require(_to != address(0), "Invalid to address"); + require(manualApprovals[_from][_to].allowance != 0, "Approval not exist"); - for(uint256 j = index; j < activeManualApprovals.length-1; j++){ - activeManualApprovals[j] = activeManualApprovals[j+1]; + // find the record in active approvals array & delete it + uint256 index = approvalsIndex[_from][_to]; + if (index != activeManualApprovals.length -1) { + activeManualApprovals[index] = activeManualApprovals[activeManualApprovals.length -1]; + approvalsIndex[activeManualApprovals[index].from][activeManualApprovals[index].to] = index; } - - delete activeManualApprovals[activeManualApprovals.length-1]; + delete manualApprovals[_from][_to]; activeManualApprovals.length--; - emit RevokeManualApproval(_from, _to, msg.sender); } @@ -172,17 +275,57 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _from is the address array from which transfers are approved * @param _to is the address array to which transfers are approved */ - function revokeManualApprovalMulti(address[] _from, address[] _to) public withPerm(TRANSFER_APPROVAL) { - require(_from.length == _to.length, "input array numbers not matching"); - for(uint8 i=0; i<_from.length; i++){ - revokeManualApproval(_from[i], _to[i]); + function revokeManualApprovalMulti(address[] _from, address[] _to) external withPerm(TRANSFER_APPROVAL) { + require(_from.length == _to.length, "Input array length mismatch"); + for(uint256 i = 0; i < _from.length; i++){ + _revokeManualApproval(_from[i], _to[i]); + } + } + + function _checkInputLengthArray( + address[] _from, + address[] _to, + uint256[] _expiryTimes, + uint256[] _allowances, + bytes32[] _descriptions + ) + internal + pure + { + require(_from.length == _to.length && + _to.length == _allowances.length && + _allowances.length == _expiryTimes.length && + _expiryTimes.length == _descriptions.length, + "Input array length mismatch" + ); + } + + /** + * @notice Returns the all active approvals corresponds to an address + * @param _user Address of the holder corresponds to whom list of manual approvals + * need to return + * @return List of indexes + */ + function getActiveApprovalsToUser(address _user) external view returns(uint256[]) { + uint256 counter = 0; + for (uint256 i = 0; i < activeManualApprovals.length; i++) { + if (activeManualApprovals[i].from == _user || activeManualApprovals[i].to == _user) + counter ++; + } + uint256[] memory indexes = new uint256[](counter); + counter = 0; + for (i = 0; i < activeManualApprovals.length; i++) { + if (activeManualApprovals[i].from == _user || activeManualApprovals[i].to == _user) { + indexes[counter]; + counter ++; + } } } /** * @notice Returns the current number of active approvals */ - function getActiveApprovalsLength() public view returns(uint256) { + function getActiveApprovalsLength() external view returns(uint256) { return activeManualApprovals.length; } From 5d7263a9fc665d43dcfc599d31eeffc973b48af6 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 10 Dec 2018 23:20:31 +0530 Subject: [PATCH 384/582] add missing return statement --- .../modules/TransferManager/ManualApprovalTransferManager.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 48d87ab06..0e17fe6d0 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -320,6 +320,7 @@ contract ManualApprovalTransferManager is ITransferManager { counter ++; } } + return indexes; } /** From 46c9cddd561f1072abac4d409d5c5998becca2f3 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 10 Dec 2018 23:21:37 +0530 Subject: [PATCH 385/582] minor fix --- .../modules/TransferManager/ManualApprovalTransferManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 0e17fe6d0..2efcfc207 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -316,7 +316,7 @@ contract ManualApprovalTransferManager is ITransferManager { counter = 0; for (i = 0; i < activeManualApprovals.length; i++) { if (activeManualApprovals[i].from == _user || activeManualApprovals[i].to == _user) { - indexes[counter]; + indexes[counter] = i; counter ++; } } From ac7541f2c59ebec789d1f24a0898fcea04cab722 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 11 Dec 2018 09:24:15 +0530 Subject: [PATCH 386/582] Merge fix --- contracts/modules/STO/USDTieredSTO.sol | 82 ------------------- contracts/modules/STO/USDTieredSTOStorage.sol | 16 +++- 2 files changed, 13 insertions(+), 85 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index aedab75d1..c45bb4ac3 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -14,88 +14,6 @@ import "./USDTieredSTOStorage.sol"; */ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { using SafeMath for uint256; - - ///////////// - // Storage // - ///////////// - struct Tier { - // NB rates mentioned below are actually price and are used like price in the logic. - // How many token units a buyer gets per USD in this tier (multiplied by 10**18) - uint256 rate; - - // How many token units a buyer gets per USD in this tier (multiplied by 10**18) when investing in POLY up to tokensDiscountPoly - uint256 rateDiscountPoly; - - // How many tokens are available in this tier (relative to totalSupply) - uint256 tokenTotal; - - // How many token units are available in this tier (relative to totalSupply) at the ratePerTierDiscountPoly rate - uint256 tokensDiscountPoly; - - // How many tokens have been minted in this tier (relative to totalSupply) - uint256 mintedTotal; - - // How many tokens have been minted in this tier (relative to totalSupply) for each fund raise type - mapping (uint8 => uint256) minted; - - // How many tokens have been minted in this tier (relative to totalSupply) at discounted POLY rate - uint256 mintedDiscountPoly; - } - - string public POLY_ORACLE = "PolyUsdOracle"; - string public ETH_ORACLE = "EthUsdOracle"; - mapping (bytes32 => mapping (bytes32 => string)) oracleKeys; - - // Determine whether users can invest on behalf of a beneficiary - bool public allowBeneficialInvestments = false; - - // Whether or not the STO has been finalized - bool public isFinalized; - - // Address where ETH, POLY & Stable Coin funds are delivered - address public wallet; - - // Address of issuer reserve wallet for unsold tokens - address public reserveWallet; - - // List of stable coin addresses - address[] public usdTokens; - - // Current tier - uint256 public currentTier; - - // Amount of USD funds raised - uint256 public fundsRaisedUSD; - - // Amount of native currencies raised. 0x0 address is used for ETH. - mapping (address => uint256) public currencyRaised; - - // Amount in USD invested by each address - mapping (address => uint256) public investorInvestedUSD; - - // Amount in fund raise type invested by each investor - mapping (address => mapping (uint8 => uint256)) public investorInvested; - - // List of accredited investors - mapping (address => bool) public accredited; - - // List of active stable coin addresses - mapping (address => bool) public usdTokenEnabled; - - // Default limit in USD for non-accredited investors multiplied by 10**18 - uint256 public nonAccreditedLimitUSD; - - // Overrides for default limit in USD for non-accredited investors multiplied by 10**18 - mapping (address => uint256) public nonAccreditedLimitUSDOverride; - - // Minimum investable amount in USD - uint256 public minimumInvestmentUSD; - - // Final amount of tokens returned to issuer - uint256 public finalAmountReturned; - - // Array of Tiers - Tier[] public tiers; string public constant POLY_ORACLE = "PolyUsdOracle"; string public constant ETH_ORACLE = "EthUsdOracle"; diff --git a/contracts/modules/STO/USDTieredSTOStorage.sol b/contracts/modules/STO/USDTieredSTOStorage.sol index 031792f42..d9184021a 100644 --- a/contracts/modules/STO/USDTieredSTOStorage.sol +++ b/contracts/modules/STO/USDTieredSTOStorage.sol @@ -11,6 +11,7 @@ contract USDTieredSTOStorage { // Storage // ///////////// struct Tier { + // NB rates mentioned below are actually price and are used like price in the logic. // How many token units a buyer gets per USD in this tier (multiplied by 10**18) uint256 rate; @@ -33,28 +34,34 @@ contract USDTieredSTOStorage { uint256 mintedDiscountPoly; } + string public POLY_ORACLE = "PolyUsdOracle"; + string public ETH_ORACLE = "EthUsdOracle"; mapping (bytes32 => mapping (bytes32 => string)) oracleKeys; - IERC20 public usdToken; - // Determine whether users can invest on behalf of a beneficiary bool public allowBeneficialInvestments = false; // Whether or not the STO has been finalized bool public isFinalized; - // Address where ETH, POLY & DAI funds are delivered + // Address where ETH, POLY & Stable Coin funds are delivered address public wallet; // Address of issuer reserve wallet for unsold tokens address public reserveWallet; + // List of stable coin addresses + address[] public usdTokens; + // Current tier uint256 public currentTier; // Amount of USD funds raised uint256 public fundsRaisedUSD; + // Amount of native currencies raised. 0x0 address is used for ETH. + mapping (address => uint256) public currencyRaised; + // Amount in USD invested by each address mapping (address => uint256) public investorInvestedUSD; @@ -64,6 +71,9 @@ contract USDTieredSTOStorage { // List of accredited investors mapping (address => bool) public accredited; + // List of active stable coin addresses + mapping (address => bool) public usdTokenEnabled; + // Default limit in USD for non-accredited investors multiplied by 10**18 uint256 public nonAccreditedLimitUSD; From 3477f0f5fe537f12778442ea9a7ea5e91e55608d Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 11 Dec 2018 09:56:49 +0530 Subject: [PATCH 387/582] Minor fixes --- contracts/modules/STO/ISTO.sol | 17 +---------------- contracts/modules/STO/USDTieredSTO.sol | 2 +- test/p_usd_tiered_sto.js | 2 +- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/contracts/modules/STO/ISTO.sol b/contracts/modules/STO/ISTO.sol index 1672a8626..6fb216566 100644 --- a/contracts/modules/STO/ISTO.sol +++ b/contracts/modules/STO/ISTO.sol @@ -13,22 +13,7 @@ contract ISTO is ISTOStorage, Module, Pausable { using SafeMath for uint256; enum FundRaiseType { ETH, POLY, SC } - mapping (uint8 => bool) public fundRaiseTypes; - mapping (uint8 => uint256) public fundsRaised; - - // Start time of the STO - uint256 public startTime; - // End time of the STO - uint256 public endTime; - // Time STO was paused - uint256 public pausedTime; - // Number of individual investors - uint256 public investorCount; - // Address where ETH & POLY funds are delivered - address public wallet; - // Final amount of tokens sold - uint256 public totalTokensSold; - + // Event event SetFundRaiseTypes(FundRaiseType[] _fundRaiseTypes); diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index c45bb4ac3..0fa9bea63 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -14,7 +14,7 @@ import "./USDTieredSTOStorage.sol"; */ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { using SafeMath for uint256; - + string public constant POLY_ORACLE = "PolyUsdOracle"; string public constant ETH_ORACLE = "EthUsdOracle"; diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index c368432b7..6a857139c 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -325,7 +325,7 @@ contract("USDTieredSTO", accounts => { assert.equal(web3.utils.hexToString(tx.logs[2].args._name), "USDTieredSTO", "USDTieredSTOFactory module was not added"); I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); - assert.equal(await I_USDTieredSTO_Array[stoId].startTime.call(), _startTime[stoId], "Incorrect _startTime in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()).toNumber(), _startTime[stoId], "Incorrect _startTime in config"); assert.equal(await I_USDTieredSTO_Array[stoId].endTime.call(), _endTime[stoId], "Incorrect _endTime in config"); for (var i = 0; i < _ratePerTier[stoId].length; i++) { assert.equal( From 6e2768a45c3e444c8cdb8e7339023ec1cade0650 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 11 Dec 2018 10:00:45 +0530 Subject: [PATCH 388/582] Updated changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3879a73e9..b53323fb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,12 @@ All notable changes to this project will be documented in this file. [__2.1.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __13-09-18__ -## CappedSTO 2.0.1 +## CappedSTO 2.1.0 * `rate` is now accepted as multiplied by 10^18 to allow settting higher price than 1ETH/POLY per token. * Indivisble tokens are now supported. When trying to buy partial tokens, allowed full units of tokens will be purchased and remaining funds will be returned. -## USDTieredSTO 2.0.1 +## USDTieredSTO 2.1.0 +* Added `currencyRaised` function that returns native currency raised. It takes address of fund coin as parameter, use 0x0 for ETH. * Added support for multiple stable coins in USDTSTO. * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. * Added `getSTODetails` to USDTSTO. From 9410fbe1df45f15dbb81cc77564064fbe4fd381c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 11 Dec 2018 10:58:45 +0530 Subject: [PATCH 389/582] Changed currencyRaised to stableCoinsRaised --- CHANGELOG.md | 2 +- contracts/modules/STO/USDTieredSTO.sol | 4 ++-- contracts/modules/STO/USDTieredSTOStorage.sol | 6 ++---- test/p_usd_tiered_sto.js | 5 +++++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b53323fb7..27fc35c18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ All notable changes to this project will be documented in this file. * Indivisble tokens are now supported. When trying to buy partial tokens, allowed full units of tokens will be purchased and remaining funds will be returned. ## USDTieredSTO 2.1.0 -* Added `currencyRaised` function that returns native currency raised. It takes address of fund coin as parameter, use 0x0 for ETH. +* Added `stableCoinsRaised` function that returns amount of individual stable coin raised when address of that stable coin is passed. * Added support for multiple stable coins in USDTSTO. * Added `buyTokensView` and `getTokensMintedByTier` to USDTSTO. * Added `getSTODetails` to USDTSTO. diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 0fa9bea63..81386c1bd 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -373,7 +373,6 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { // Modify storage investorInvested[_beneficiary][uint8(FundRaiseType.ETH)] = investorInvested[_beneficiary][uint8(FundRaiseType.ETH)].add(spentValue); fundsRaised[uint8(FundRaiseType.ETH)] = fundsRaised[uint8(FundRaiseType.ETH)].add(spentValue); - currencyRaised[address(0)] = currencyRaised[address(0)].add(spentValue); // Forward ETH to issuer wallet wallet.transfer(spentValue); // Refund excess ETH to investor wallet @@ -413,7 +412,8 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { // Modify storage investorInvested[_beneficiary][uint8(_fundRaiseType)] = investorInvested[_beneficiary][uint8(_fundRaiseType)].add(spentValue); fundsRaised[uint8(_fundRaiseType)] = fundsRaised[uint8(_fundRaiseType)].add(spentValue); - currencyRaised[address(_token)] = currencyRaised[address(_token)].add(spentValue); + if(address(_token) != address(polyToken)) + stableCoinsRaised[address(_token)] = stableCoinsRaised[address(_token)].add(spentValue); // Forward coins to issuer wallet require(_token.transferFrom(msg.sender, wallet, spentValue), "Transfer failed"); emit FundsReceived(msg.sender, _beneficiary, spentUSD, _fundRaiseType, _tokenAmount, spentValue, rate); diff --git a/contracts/modules/STO/USDTieredSTOStorage.sol b/contracts/modules/STO/USDTieredSTOStorage.sol index d9184021a..5d9581408 100644 --- a/contracts/modules/STO/USDTieredSTOStorage.sol +++ b/contracts/modules/STO/USDTieredSTOStorage.sol @@ -34,8 +34,6 @@ contract USDTieredSTOStorage { uint256 mintedDiscountPoly; } - string public POLY_ORACLE = "PolyUsdOracle"; - string public ETH_ORACLE = "EthUsdOracle"; mapping (bytes32 => mapping (bytes32 => string)) oracleKeys; // Determine whether users can invest on behalf of a beneficiary @@ -59,8 +57,8 @@ contract USDTieredSTOStorage { // Amount of USD funds raised uint256 public fundsRaisedUSD; - // Amount of native currencies raised. 0x0 address is used for ETH. - mapping (address => uint256) public currencyRaised; + // Amount of stable coins raised + mapping (address => uint256) public stableCoinsRaised; // Amount in USD invested by each address mapping (address => uint256) public investorInvestedUSD; diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 6a857139c..5fad46f6f 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1829,6 +1829,11 @@ contract("USDTieredSTO", accounts => { init_WalletDAIBal.add(investment_DAI).toNumber(), "Wallet DAI Balance not changed as expected" ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].stableCoinsRaised.call(I_DaiToken.address)).toNumber(), + investment_DAI.toNumber(), + "DAI Raised not changed as expected" + ); }); it("should successfully buy using fallback at tier 0 for ACCREDITED1", async () => { From 0369cf3e105eb2ceb361a5f939607fef278c342b Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 11 Dec 2018 17:22:55 +0530 Subject: [PATCH 390/582] MATM contract and test fixes --- CHANGELOG.md | 4 + .../ManualApprovalTransferManager.sol | 113 +++-- test/j_manual_approval_transfer_manager.js | 436 ++++++++++++++---- test/z_general_permission_manager_fuzzer.js | 3 + 4 files changed, 431 insertions(+), 125 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71457d9d9..4dec19536 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,10 @@ All notable changes to this project will be documented in this file. * Removed `0x0` check for the `_from` address to `ManualApprovalTransferManager`. This allows for the Issuer/Transfer Agent to approve a one-off mint of tokens that otherwise would not be possible. * Changed the version of `ManualApprovalTransferManagerFactory` from `1.0.0` to `2.1.0`. * Deployed 2.0.1 `ManualApprovalTransferManagerFactory` to address 0x6af2afad53cb334e62b90ddbdcf3a086f654c298 +* Add `getActiveApprovalsToUser()` function to access all the active approvals for a user whether user is in the `from` or in `to`. +* Add `getApprovalDetails()` to get the details of the approval corresponds to `_from` and `_to` address. +* Add feature to modify the details of the active approval using `modifyApproval()` & `modifyApprovalMulti()`. +* Add `addManualApprovalMulti()` and `revokeManualApprovalMulti()` batch function for adding and revoking the manual approval respectively. ## Dividends * Changed the version of `ERC20DividendCheckpointFactory` & `EtherDividendCheckpointFactory` from `1.0.0` to `2.1.0`. diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 2efcfc207..6dcdabb75 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -26,18 +26,17 @@ contract ManualApprovalTransferManager is ITransferManager { bytes32 description; } - //Store mappings of address => address with ManualApprovals - mapping (address => mapping (address => ManualApproval)) public manualApprovals; - mapping (address => mapping (address => uint256)) internal approvalsIndex; - - //An array to track all current active approvals - ManualApproval[] public activeManualApprovals; + mapping (address => mapping (address => uint256)) public approvalIndex; + mapping (address => mapping (address => bool)) public hasApproval; + // An array to track all approvals + ManualApproval[] public approvals; event AddManualApproval( address indexed _from, address indexed _to, uint256 _allowance, uint256 _expiryTime, + bytes32 _description, address indexed _addedBy ); @@ -46,6 +45,7 @@ contract ManualApprovalTransferManager is ITransferManager { address indexed _to, uint256 _expiryTime, uint256 _allowance, + bytes32 _description, address indexed _edittedBy ); @@ -84,10 +84,12 @@ contract ManualApprovalTransferManager is ITransferManager { // function must only be called by the associated security token if _isTransfer == true require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); - if (!paused) { - if ((manualApprovals[_from][_to].expiryTime >= now) && (manualApprovals[_from][_to].allowance >= _amount)) { + if (!paused && hasApproval[_from][_to]) { + uint256 index = approvalIndex[_from][_to]; + ManualApproval storage approval = approvals[index]; + if ((approval.expiryTime >= now) && (approval.allowance >= _amount)) { if (_isTransfer) { - manualApprovals[_from][_to].allowance = manualApprovals[_from][_to].allowance.sub(_amount); + approval.allowance = approval.allowance.sub(_amount); } return Result.VALID; } @@ -120,11 +122,15 @@ contract ManualApprovalTransferManager is ITransferManager { require(_to != address(0), "Invalid to address"); require(_expiryTime > now, "Invalid expiry time"); require(_allowance > 0, "Invalid allowance"); - require(manualApprovals[_from][_to].allowance == 0 || manualApprovals[_from][_to].expiryTime < now, "Approval already exists"); - manualApprovals[_from][_to] = ManualApproval(_from, _to, _allowance, _expiryTime, _description); - activeManualApprovals.push(ManualApproval(_from, _to, _allowance, _expiryTime, _description)); - approvalsIndex[_from][_to] = activeManualApprovals.length - 1; - emit AddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender); + if (hasApproval[_from][_to]) { + uint256 index = approvalIndex[_from][_to]; + require(approvals[index].expiryTime < now || approvals[index].allowance == 0, "Approval already exists"); + _revokeManualApproval(_from, _to); + } + approvals.push(ManualApproval(_from, _to, _allowance, _expiryTime, _description)); + approvalIndex[_from][_to] = approvals.length - 1; + hasApproval[_from][_to] = true; + emit AddManualApproval(_from, _to, _allowance, _expiryTime, _description, msg.sender); } /** @@ -188,34 +194,37 @@ contract ManualApprovalTransferManager is ITransferManager { require(_to != address(0), "Invalid to address"); /*solium-disable-next-line security/no-block-members*/ require(_expiryTime > now, "Invalid expiry time"); - require(manualApprovals[_from][_to].allowance != 0, "Approval does not exists"); - uint256 currentAllowance = manualApprovals[_from][_to].allowance; + require(hasApproval[_from][_to], "Approval not present"); + uint256 index = approvalIndex[_from][_to]; + ManualApproval storage approval = approvals[index]; + require(approval.allowance != 0 && approval.expiryTime > now, "Not allowed"); + uint256 currentAllowance = approval.allowance; uint256 newAllowance; if (_change == 1) { // Allowance get increased - manualApprovals[_from][_to].allowance = ( - manualApprovals[_from][_to].allowance.add(_changedAllowance)); newAllowance = currentAllowance.add(_changedAllowance); + approval.allowance = newAllowance; } else if (_change == 0) { // Allowance get decreased if (_changedAllowance > currentAllowance) { - manualApprovals[_from][_to].allowance = 0; + newAllowance = 0; + approval.allowance = newAllowance; } else { - manualApprovals[_from][_to].allowance = currentAllowance.sub(_changedAllowance); + newAllowance = currentAllowance.sub(_changedAllowance); + approval.allowance = newAllowance; } - newAllowance = currentAllowance.sub(_changedAllowance); } else { // No change in the Allowance newAllowance = currentAllowance; } // Greedy storage technique - if (manualApprovals[_from][_to].expiryTime != _expiryTime) { - manualApprovals[_from][_to].expiryTime = _expiryTime; + if (approval.expiryTime != _expiryTime) { + approval.expiryTime = _expiryTime; } - if (manualApprovals[_from][_to].description != _description) { - manualApprovals[_from][_to].description = _description; + if (approval.description != _description) { + approval.description = _description; } - emit ModifyManualApproval(_from, _to, _expiryTime, newAllowance, msg.sender); + emit ModifyManualApproval(_from, _to, _expiryTime, newAllowance, _description, msg.sender); } /** @@ -256,17 +265,16 @@ contract ManualApprovalTransferManager is ITransferManager { } function _revokeManualApproval(address _from, address _to) internal { - require(_to != address(0), "Invalid to address"); - require(manualApprovals[_from][_to].allowance != 0, "Approval not exist"); + require(hasApproval[_from][_to], "Approval not exist"); // find the record in active approvals array & delete it - uint256 index = approvalsIndex[_from][_to]; - if (index != activeManualApprovals.length -1) { - activeManualApprovals[index] = activeManualApprovals[activeManualApprovals.length -1]; - approvalsIndex[activeManualApprovals[index].from][activeManualApprovals[index].to] = index; + uint256 index = approvalIndex[_from][_to]; + if (index != approvals.length -1) { + approvals[index] = approvals[approvals.length -1]; + approvalIndex[approvals[index].from][approvals[index].to] = index; } - delete manualApprovals[_from][_to]; - activeManualApprovals.length--; + hasApproval[_from][_to] = false; + approvals.length--; emit RevokeManualApproval(_from, _to, msg.sender); } @@ -308,14 +316,16 @@ contract ManualApprovalTransferManager is ITransferManager { */ function getActiveApprovalsToUser(address _user) external view returns(uint256[]) { uint256 counter = 0; - for (uint256 i = 0; i < activeManualApprovals.length; i++) { - if (activeManualApprovals[i].from == _user || activeManualApprovals[i].to == _user) + for (uint256 i = 0; i < approvals.length; i++) { + if ((approvals[i].from == _user || approvals[i].to == _user) + && approvals[i].expiryTime >= now) counter ++; } uint256[] memory indexes = new uint256[](counter); counter = 0; - for (i = 0; i < activeManualApprovals.length; i++) { - if (activeManualApprovals[i].from == _user || activeManualApprovals[i].to == _user) { + for (i = 0; i < approvals.length; i++) { + if ((approvals[i].from == _user || approvals[i].to == _user) + && approvals[i].expiryTime >= now) { indexes[counter] = i; counter ++; } @@ -323,11 +333,34 @@ contract ManualApprovalTransferManager is ITransferManager { return indexes; } + /** + * @notice Get the details of the approval corresponds to _from & _to addresses + * @param _from Address of the sender + * @param _to Address of the receiver + * @return uint256 expiryTime of the approval + * @return uint256 allowance provided to the approval + * @return uint256 Description provided to the approval + */ + function getApprovalDetails(address _from, address _to) external view returns(uint256, uint256, bytes32) { + if (hasApproval[_from][_to]) { + uint256 index = approvalIndex[_from][_to]; + if (index < approvals.length) { + ManualApproval storage approval = approvals[index]; + return( + approval.expiryTime, + approval.allowance, + approval.description + ); + } + } + return (uint256(0), uint256(0), bytes32(0)); + } + /** * @notice Returns the current number of active approvals */ - function getActiveApprovalsLength() external view returns(uint256) { - return activeManualApprovals.length; + function getTotalApprovalsLength() external view returns(uint256) { + return approvals.length; } /** diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 0b6a4752f..c801007b8 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -68,6 +68,8 @@ contract("ManualApprovalTransferManager", accounts => { const transferManagerKey = 2; const stoKey = 3; + let expiryTimeMA; + // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -170,7 +172,7 @@ contract("ManualApprovalTransferManager", accounts => { account_investor1, latestTime(), latestTime(), - latestTime() + duration.days(10), + latestTime() + duration.days(30), true, { from: account_issuer, @@ -188,9 +190,9 @@ contract("ManualApprovalTransferManager", accounts => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei("4", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor1, web3.utils.toWei("30", "ether"), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("30", "ether")); }); it("Should Buy some more tokens", async () => { @@ -200,7 +202,7 @@ contract("ManualApprovalTransferManager", accounts => { account_investor2, latestTime(), latestTime(), - latestTime() + duration.days(10), + latestTime() + duration.days(30), true, { from: account_issuer, @@ -215,9 +217,9 @@ contract("ManualApprovalTransferManager", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor2, web3.utils.toWei("10", "ether"), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("10", "ether")); }); it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { @@ -306,9 +308,9 @@ contract("ManualApprovalTransferManager", accounts => { await I_ManualApprovalTransferManager.pause({from: token_owner}); // Add the Investor in to the whitelist // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor3, web3.utils.toWei("10", "ether"), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("10", "ether")); // Unpause at the transferManager level await I_ManualApprovalTransferManager.unpause({from: token_owner}); }); @@ -318,7 +320,7 @@ contract("ManualApprovalTransferManager", accounts => { // Mint some tokens await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), { from: account_investor2 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("5", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("31", "ether")); }); it("Should fail to add a manual approval because invalid _to address", async () => { @@ -351,137 +353,401 @@ contract("ManualApprovalTransferManager", accounts => { await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - web3.utils.toWei("2", "ether"), + web3.utils.toWei("3", "ether"), latestTime() + duration.days(1), "DESCRIPTION", - { from: token_owner } + { + from: token_owner + } ); - - assert(await I_ManualApprovalTransferManager.getActiveApprovalsLength({ from: token_owner }), 1); + assert.equal((await I_ManualApprovalTransferManager.getTotalApprovalsLength.call()).toNumber(), 1); + let data = await I_ManualApprovalTransferManager.approvals.call(0); + assert.equal(data[0], account_investor1); + assert.equal(data[1], account_investor4); + assert.equal(data[2], web3.utils.toWei("3")); + assert.equal(web3.utils.toUtf8(data[4]), "DESCRIPTION"); }); - it("Should update the manual approval expiry time for 4th investor", async () => { - await I_ManualApprovalTransferManager.updateManualApproval( + it("Should try to add the same manual approval for the same `_from` & `_to` address", async() => { + await catchRevert( + I_ManualApprovalTransferManager.addManualApproval( + account_investor1, + account_investor4, + web3.utils.toWei("5", "ether"), + latestTime() + duration.days(1), + "DESCRIPTION", + { + from: token_owner + } + ) + ); + }) + + it("Check verifyTransfer without actually transferring", async () => { + let verified = await I_SecurityToken.verifyTransfer.call( account_investor1, account_investor4, - latestTime() + duration.days(2), - { from: token_owner } + web3.utils.toWei("2", "ether"), + "" ); - }); + console.log(JSON.stringify(verified)); + assert.equal(verified, true); - it("Add multiple manual approvals", async () => { - await I_ManualApprovalTransferManager.addManualApprovalMulti( - [account_investor2,account_investor3], - [account_investor3,account_investor4], - [web3.utils.toWei("2", "ether"), web3.utils.toWei("2", "ether")], - [latestTime() + duration.days(1),latestTime() + duration.days(1)], - ["DESCRIPTION", "DESCRIPTION"], - { from: token_owner } - ); + verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("4", "ether"), ""); + assert.equal(verified, false); - assert(await I_ManualApprovalTransferManager.getActiveApprovalsLength({ from: token_owner }), 3); + verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("1", "ether"), ""); + assert.equal(verified, true); }); - it("Revoke multiple manual approvals", async () => { - await I_ManualApprovalTransferManager.revokeManualApprovalMulti( - [account_investor2,account_investor3], - [account_investor3,account_investor4], - { from: token_owner } + it("Should fail to sell the tokens more than the allowance", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor4, web3.utils.toWei("4"), {from: account_investor1}) ); + }) - assert(await I_ManualApprovalTransferManager.getActiveApprovalsLength({ from: token_owner }), 1); + it("Approval fails with wrong from to address", async () => { + await catchRevert(I_SecurityToken.transfer(account_investor5, web3.utils.toWei("1", "ether"), { from: account_investor1 })); }); + it("Should sell the tokens to investor 4 (GTM will give INVALID as investor 4 not in the whitelist)", async() => { + let oldBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1"), {from: account_investor1}); + let newBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + assert.equal((newBal4.minus(oldBal4)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1); + }); + it("Should sell more tokens to investor 4 with in the same day(GTM will give INVALID as investor 4 not in the whitelist)", async() => { + let oldBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1"), {from: account_investor1}); + let newBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + assert.equal((newBal4.minus(oldBal4)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1); - it("Add a manual approval for a 5th investor from issuance", async () => { - await I_ManualApprovalTransferManager.addManualApproval( - "", - account_investor5, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), - "DESCRIPTION", - { from: token_owner } + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4)).length, 1) + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor1)).length, 1) + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4))[0], 0); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor1))[0], 0); + }); + + it("Should fail to transact after the approval get expired", async() => { + await increaseTime(duration.days(1)); + await catchRevert( + I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1"), {from: account_investor1}) ); }); - it("Should fail to add a manual approval because allowance is laready exists", async () => { + it("Should fail to modify the manual approval when the approval get expired", async() => { await catchRevert( - I_ManualApprovalTransferManager.addManualApproval( + I_ManualApprovalTransferManager.modifyManualApproval( account_investor1, account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(5), - "DESCRIPTION", - { from: token_owner } + latestTime() + duration.days(2), + web3.utils.toWei("5"), + "New Description", + 0, + { + from: token_owner + } ) ); }); - it("Should fail to revoke manual approval because invalid _to address", async () => { - await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, "", { from: token_owner })); - }); - - it("Should revoke manual approval", async () => { - let tx = await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { - from: token_owner - }); - assert.equal(tx.logs[0].args._from, account_investor1); - assert.equal(tx.logs[0].args._to, account_investor4); - assert.equal(tx.logs[0].args._addedBy, token_owner); + it("Should attach the manual approval for the investor4 again", async() => { + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4)).length, 0); await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, web3.utils.toWei("2", "ether"), latestTime() + duration.days(1), "DESCRIPTION", - { from: token_owner } + { + from: token_owner + } ); + assert.equal((await I_ManualApprovalTransferManager.getTotalApprovalsLength.call()).toNumber(), 1); + let data = await I_ManualApprovalTransferManager.approvals.call(0); + assert.equal(data[0], account_investor1); + assert.equal(data[1], account_investor4); + assert.equal(data[2], web3.utils.toWei("2")); + assert.equal(web3.utils.toUtf8(data[4]), "DESCRIPTION"); }); - it("Use 50% of manual approval for transfer", async () => { - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1", "ether"), { from: account_investor1 }); + it("Should modify the manual approval expiry time for 4th investor", async () => { + expiryTimeMA = latestTime() + duration.days(3); + let tx = await I_ManualApprovalTransferManager.modifyManualApproval( + account_investor1, + account_investor4, + expiryTimeMA, + web3.utils.toWei("5"), + "New Description", + 45, + { + from: token_owner + } + ); + + let data = await I_ManualApprovalTransferManager.approvals.call(0); + assert.equal(data[0], account_investor1); + assert.equal(data[1], account_investor4); + assert.equal(data[2], web3.utils.toWei("2")); + assert.equal(data[3].toNumber(), expiryTimeMA); + assert.equal(web3.utils.toUtf8(data[4]), "New Description"); + assert.equal(tx.logs[0].args._from, account_investor1); + assert.equal(tx.logs[0].args._to, account_investor4); + assert.equal((tx.logs[0].args._expiryTime).toNumber(), expiryTimeMA); + assert.equal((tx.logs[0].args._allowance).toNumber(), web3.utils.toWei("2")); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._description), "New Description"); + }); - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei("1", "ether")); + it("Should transact after two days", async() => { + await increaseTime(2); + let oldBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1"), {from: account_investor1}); + let newBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + assert.equal((newBal4.minus(oldBal4)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1); }); - it("Approval fails with wrong from to address", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor5, web3.utils.toWei("1", "ether"), { from: account_investor1 })); + it("Should modify the allowance of the manual approval (increase)", async() => { + await I_ManualApprovalTransferManager.modifyManualApproval( + account_investor1, + account_investor4, + expiryTimeMA, + web3.utils.toWei("4"), + "New Description", + 1, + { + from: token_owner + } + ); + + let data = await I_ManualApprovalTransferManager.approvals.call(0); + assert.equal(data[0], account_investor1); + assert.equal(data[1], account_investor4); + assert.equal(data[2].toNumber(), web3.utils.toWei("5")); + assert.equal(data[3].toNumber(), expiryTimeMA); + assert.equal(web3.utils.toUtf8(data[4]), "New Description"); }); - it("Use 100% of issuance approval", async () => { - await I_SecurityToken.mint(account_investor5, web3.utils.toWei("2", "ether"), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toNumber(), web3.utils.toWei("2", "ether")); + it("Should transact according to new allowance", async() => { + let oldBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei("3"), {from: account_investor1}); + let newBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + assert.equal((newBal4.minus(oldBal4)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 3); }); - it("Check verifyTransfer without actually transferring", async () => { - let verified = await I_SecurityToken.verifyTransfer.call( + it("Should decrease the allowance", async() => { + await I_ManualApprovalTransferManager.modifyManualApproval( account_investor1, account_investor4, - web3.utils.toWei("1", "ether"), - "" + expiryTimeMA, + web3.utils.toWei("1"), + "New Description", + 0, + { + from: token_owner + } ); - console.log(JSON.stringify(verified)); - assert.equal(verified, true); - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("2", "ether"), ""); - assert.equal(verified, false); + let data = await I_ManualApprovalTransferManager.approvals.call(0); + assert.equal(data[0], account_investor1); + assert.equal(data[1], account_investor4); + assert.equal(data[2].toNumber(), web3.utils.toWei("1")); + assert.equal(data[3].toNumber(), expiryTimeMA); + assert.equal(web3.utils.toUtf8(data[4]), "New Description"); + }); - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("1", "ether"), ""); - assert.equal(verified, true); + it("Should fail to transfer the tokens because allowance get changed", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor4, web3.utils.toWei("2"), {from: account_investor1}) + ); + }); + + it("Should successfully transfer the tokens within the allowance limit", async() => { + let oldBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + await I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1"), {from: account_investor1}); + let newBal4 = await I_SecurityToken.balanceOf.call(account_investor4); + assert.equal((newBal4.minus(oldBal4)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1); + }); + + it("Should fail to modify because allowance is zero", async() => { + await catchRevert( + I_ManualApprovalTransferManager.modifyManualApproval( + account_investor1, + account_investor4, + expiryTimeMA, + web3.utils.toWei("5"), + "New Description", + 0, + { + from: token_owner + } + ) + ); }); - it("Use remaining 50% of manual approval for transfer", async () => { - await I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1", "ether"), { from: account_investor1 }); + it("Should fail to revoke the manual Approval -- bad owner", async() => { + await catchRevert( + I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: account_investor5}) + ); + }) - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei("2", "ether")); + it("Should revoke the manual Approval b/w investor4 and 1", async() => { + await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: token_owner}); + assert.isFalse(await I_ManualApprovalTransferManager.hasApproval.call(account_investor1, account_investor4)); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor1)).length, 0); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4)).length, 0); }); - it("Check further transfers fail", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1", "ether"), { from: account_investor1 })); + it("Should fail to revoke the same manual approval again", async() => { + await catchRevert( + I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: token_owner}) + ); + }); - //Check that other transfers are still valid - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); + it("Should fail to add multiple manual approvals -- failed because of bad owner", async () => { + await catchRevert ( + I_ManualApprovalTransferManager.addManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + [web3.utils.toWei("2", "ether"), web3.utils.toWei("2", "ether")], + [latestTime() + duration.days(1),latestTime() + duration.days(1)], + ["DESCRIPTION_1", "DESCRIPTION_2"], + { + from: account_investor5 + } + ) + ) + }); + + it("Should fail to add multiple manual approvals -- failed because of length mismatch", async () => { + await catchRevert ( + I_ManualApprovalTransferManager.addManualApprovalMulti( + [account_investor2], + [account_investor3,account_investor4], + [web3.utils.toWei("2", "ether"), web3.utils.toWei("2", "ether")], + [latestTime() + duration.days(1),latestTime() + duration.days(1)], + ["DESCRIPTION_1", "DESCRIPTION_2"], + { + from: token_owner + } + ) + ) + }); + + it("Should fail to add multiple manual approvals -- failed because of length mismatch", async () => { + await catchRevert ( + I_ManualApprovalTransferManager.addManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + [web3.utils.toWei("2", "ether"), web3.utils.toWei("2", "ether")], + [latestTime() + duration.days(1)], + ["DESCRIPTION_1", "DESCRIPTION_2"], + { + from: token_owner + } + ) + ) + }); + + it("Should fail to add multiple manual approvals -- failed because of length mismatch", async () => { + await catchRevert ( + I_ManualApprovalTransferManager.addManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + [web3.utils.toWei("2", "ether")], + [latestTime() + duration.days(1),latestTime() + duration.days(1)], + ["DESCRIPTION_1", "DESCRIPTION_2"], + { + from: token_owner + } + ) + ) + }); + + it("Should fail to add multiple manual approvals -- failed because of length mismatch", async () => { + await catchRevert ( + I_ManualApprovalTransferManager.addManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + [web3.utils.toWei("2", "ether"), web3.utils.toWei("2", "ether")], + [latestTime() + duration.days(1),latestTime() + duration.days(1)], + ["DESCRIPTION_1"], + { + from: token_owner + } + ) + ) + }); + + it("Add multiple manual approvals", async () => { + let time = latestTime() + duration.days(1); + await I_ManualApprovalTransferManager.addManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + [web3.utils.toWei("2", "ether"), web3.utils.toWei("2", "ether")], + [time,latestTime() + duration.days(1)], + ["DESCRIPTION_1", "DESCRIPTION_2"], + { + from: token_owner + } + ); + + assert.equal(await I_ManualApprovalTransferManager.getTotalApprovalsLength.call(), 2); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor3)).length , 2); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor3))[0], 0); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor3))[1], 1); + let approvalDetail = await I_ManualApprovalTransferManager.getApprovalDetails.call(account_investor2, account_investor3); + assert.equal(approvalDetail[0].toNumber(), time); + assert.equal(approvalDetail[1].toNumber(), web3.utils.toWei("2", "ether")); + assert.equal(web3.utils.toUtf8(approvalDetail[2]), "DESCRIPTION_1"); + }); + + it("Should fail to revoke the multiple manual approvals -- because of bad owner", async() => { + await catchRevert( + I_ManualApprovalTransferManager.revokeManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + { + from: account_investor5 + } + ) + ); + }) + + it("Should fail to revoke the multiple manual approvals -- because of input length mismatch", async() => { + await catchRevert( + I_ManualApprovalTransferManager.revokeManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3], + { + from: token_owner + } + ) + ); + }) + + it("Revoke multiple manual approvals", async () => { + await I_ManualApprovalTransferManager.revokeManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + { + from: token_owner + } + ); + assert.equal(await I_ManualApprovalTransferManager.getTotalApprovalsLength.call(), 0); + }); + + it("Add a manual approval for a 5th investor from issuance", async () => { + await I_ManualApprovalTransferManager.addManualApproval( + "", + account_investor5, + web3.utils.toWei("2", "ether"), + latestTime() + duration.days(1), + "DESCRIPTION", + { + from: token_owner + } + ); }); it("Should successfully attach the CountTransferManager with the security token (count of 1)", async () => { diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index edebcce06..5fb405b0c 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -553,6 +553,7 @@ contract('GeneralPermissionManager', accounts => { account_investor4, web3.utils.toWei("2", "ether"), latestTime() + duration.days(1), + "ABC", { from: accounts[j] } ); @@ -574,6 +575,7 @@ contract('GeneralPermissionManager', accounts => { account_investor4, web3.utils.toWei("2", "ether"), latestTime() + duration.days(1), + "ABC", { from: accounts[j] } ) ); @@ -583,6 +585,7 @@ contract('GeneralPermissionManager', accounts => { account_investor4, web3.utils.toWei("2", "ether"), latestTime() + duration.days(1), + "ABC", { from: token_owner } ); From 552de1b3a1c25f50089d2eeb0a8d9a3fa3305a16 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 11 Dec 2018 19:14:13 +0530 Subject: [PATCH 391/582] minor fix --- .../ManualApprovalTransferManager.sol | 28 +++++++++---------- test/j_manual_approval_transfer_manager.js | 2 +- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 6dcdabb75..486c8b1ef 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -27,7 +27,6 @@ contract ManualApprovalTransferManager is ITransferManager { } mapping (address => mapping (address => uint256)) public approvalIndex; - mapping (address => mapping (address => bool)) public hasApproval; // An array to track all approvals ManualApproval[] public approvals; @@ -84,8 +83,8 @@ contract ManualApprovalTransferManager is ITransferManager { // function must only be called by the associated security token if _isTransfer == true require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); - if (!paused && hasApproval[_from][_to]) { - uint256 index = approvalIndex[_from][_to]; + if (!paused && approvalIndex[_from][_to] != 0) { + uint256 index = approvalIndex[_from][_to] - 1; ManualApproval storage approval = approvals[index]; if ((approval.expiryTime >= now) && (approval.allowance >= _amount)) { if (_isTransfer) { @@ -122,14 +121,13 @@ contract ManualApprovalTransferManager is ITransferManager { require(_to != address(0), "Invalid to address"); require(_expiryTime > now, "Invalid expiry time"); require(_allowance > 0, "Invalid allowance"); - if (hasApproval[_from][_to]) { - uint256 index = approvalIndex[_from][_to]; + if (approvalIndex[_from][_to] != 0) { + uint256 index = approvalIndex[_from][_to] - 1; require(approvals[index].expiryTime < now || approvals[index].allowance == 0, "Approval already exists"); _revokeManualApproval(_from, _to); } approvals.push(ManualApproval(_from, _to, _allowance, _expiryTime, _description)); - approvalIndex[_from][_to] = approvals.length - 1; - hasApproval[_from][_to] = true; + approvalIndex[_from][_to] = approvals.length; emit AddManualApproval(_from, _to, _allowance, _expiryTime, _description, msg.sender); } @@ -194,8 +192,8 @@ contract ManualApprovalTransferManager is ITransferManager { require(_to != address(0), "Invalid to address"); /*solium-disable-next-line security/no-block-members*/ require(_expiryTime > now, "Invalid expiry time"); - require(hasApproval[_from][_to], "Approval not present"); - uint256 index = approvalIndex[_from][_to]; + require(approvalIndex[_from][_to] != 0, "Approval not present"); + uint256 index = approvalIndex[_from][_to] - 1; ManualApproval storage approval = approvals[index]; require(approval.allowance != 0 && approval.expiryTime > now, "Not allowed"); uint256 currentAllowance = approval.allowance; @@ -265,15 +263,15 @@ contract ManualApprovalTransferManager is ITransferManager { } function _revokeManualApproval(address _from, address _to) internal { - require(hasApproval[_from][_to], "Approval not exist"); + require(approvalIndex[_from][_to] != 0, "Approval not exist"); // find the record in active approvals array & delete it - uint256 index = approvalIndex[_from][_to]; + uint256 index = approvalIndex[_from][_to] - 1; if (index != approvals.length -1) { approvals[index] = approvals[approvals.length -1]; - approvalIndex[approvals[index].from][approvals[index].to] = index; + approvalIndex[approvals[index].from][approvals[index].to] = index + 1; } - hasApproval[_from][_to] = false; + delete approvalIndex[_from][_to]; approvals.length--; emit RevokeManualApproval(_from, _to, msg.sender); } @@ -342,8 +340,8 @@ contract ManualApprovalTransferManager is ITransferManager { * @return uint256 Description provided to the approval */ function getApprovalDetails(address _from, address _to) external view returns(uint256, uint256, bytes32) { - if (hasApproval[_from][_to]) { - uint256 index = approvalIndex[_from][_to]; + if (approvalIndex[_from][_to] != 0) { + uint256 index = approvalIndex[_from][_to] - 1; if (index < approvals.length) { ManualApproval storage approval = approvals[index]; return( diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index c801007b8..d08389c20 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -366,6 +366,7 @@ contract("ManualApprovalTransferManager", accounts => { assert.equal(data[1], account_investor4); assert.equal(data[2], web3.utils.toWei("3")); assert.equal(web3.utils.toUtf8(data[4]), "DESCRIPTION"); + assert.equal((await I_ManualApprovalTransferManager.approvalIndex.call(account_investor1, account_investor4)).toNumber(), 1); }); it("Should try to add the same manual approval for the same `_from` & `_to` address", async() => { @@ -593,7 +594,6 @@ contract("ManualApprovalTransferManager", accounts => { it("Should revoke the manual Approval b/w investor4 and 1", async() => { await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: token_owner}); - assert.isFalse(await I_ManualApprovalTransferManager.hasApproval.call(account_investor1, account_investor4)); assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor1)).length, 0); assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4)).length, 0); }); From 41627660fcd4a5a477986700b52e652a3e83bce5 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 11 Dec 2018 15:18:30 -0300 Subject: [PATCH 392/582] CLI - LockupTM support --- CLI/commands/helpers/contract_abis.js | 5 + CLI/commands/transfer_manager.js | 608 ++++++++++++++---- .../Transfer/LockupTM/add_lockup_data.csv | 4 + .../LockupTM/add_lockup_investor_data.csv | 12 + .../Transfer/LockupTM/delete_lockup_data.csv | 2 + .../Transfer/LockupTM/modify_lockup_data.csv | 4 + .../LockupTM/remove_lockup_investor_data.csv | 12 + 7 files changed, 536 insertions(+), 111 deletions(-) create mode 100644 CLI/data/Transfer/LockupTM/add_lockup_data.csv create mode 100644 CLI/data/Transfer/LockupTM/add_lockup_investor_data.csv create mode 100644 CLI/data/Transfer/LockupTM/delete_lockup_data.csv create mode 100644 CLI/data/Transfer/LockupTM/modify_lockup_data.csv create mode 100644 CLI/data/Transfer/LockupTM/remove_lockup_investor_data.csv diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index 8a551b70b..934be67fd 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -10,6 +10,7 @@ let generalTransferManagerABI; let manualApprovalTransferManagerABI; let countTransferManagerABI; let percentageTransferManagerABI; +let lockUpTransferManagerABI; let generalPermissionManagerABI; let polyTokenABI; let cappedSTOFactoryABI; @@ -35,6 +36,7 @@ try { manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ManualApprovalTransferManager.json').toString()).abi; countTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/CountTransferManager.json').toString()).abi; percentageTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/PercentageTransferManager.json').toString()).abi; + lockUpTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/LockUpTransferManager.json').toString()).abi; generalPermissionManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralPermissionManager.json').toString()).abi; polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; @@ -88,6 +90,9 @@ module.exports = { percentageTransferManager: function () { return percentageTransferManagerABI; }, + lockUpTransferManager: function () { + return lockUpTransferManagerABI; + }, generalPermissionManager: function () { return generalPermissionManagerABI; }, diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 16af0e34e..8fe30206e 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -6,12 +6,17 @@ const contracts = require('./helpers/contract_addresses'); const abis = require('./helpers/contract_abis'); const gbl = require('./common/global'); const csvParse = require('./helpers/csv'); -const { table } = require('table') +const { table } = require('table'); /////////////////// // Constants const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelist_data.csv'; +const ADD_LOCKUP_DATA_CSV = './CLI/data/Transfer/LockupTM/add_lockup_data.csv'; +const MODIFY_LOCKUP_DATA_CSV = './CLI/data/Transfer/LockupTM/modify_lockup_data.csv'; +const DELETE_LOCKUP_DATA_CSV = './CLI/data/Transfer/LockupTM/delete_lockup_data.csv'; +const ADD_LOCKUP_INVESTOR_DATA_CSV = './CLI/data/Transfer/LockupTM/add_lockup_investor_data.csv'; +const REMOVE_LOCKUP_INVESTOR_DATA_CSV = './CLI/data/Transfer/LockupTM/remove_lockup_investor_data.csv'; // App flow let tokenSymbol; @@ -21,98 +26,96 @@ let moduleRegistry; let currentTransferManager; async function executeApp() { - let exit = false; - while (!exit) { - console.log('\n', chalk.blue('Transfer Manager - Main Menu', '\n')); - - let tmModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.TRANSFER); - let nonArchivedModules = tmModules.filter(m => !m.archived); - if (nonArchivedModules.length > 0) { - console.log(`Transfer Manager modules attached:`); - nonArchivedModules.map(m => console.log(`- ${m.name} at ${m.address}`)) - } else { - console.log(`There are no Transfer Manager modules attached`); - } + console.log('\n', chalk.blue('Transfer Manager - Main Menu', '\n')); - let options = ['Verify transfer', 'Transfer']; - let forcedTransferDisabled = await securityToken.methods.controllerDisabled().call(); - if (!forcedTransferDisabled) { - options.push('Forced transfers'); - } - if (nonArchivedModules.length > 0) { - options.push('Config existing modules'); - } - options.push('Add new Transfer Manager module'); - - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Exit' }); - let optionSelected = index != -1 ? options[index] : 'Exit'; - console.log('Selected:', optionSelected, '\n'); - switch (optionSelected) { - case 'Verify transfer': - let verifyTotalSupply = web3.utils.fromWei(await securityToken.methods.totalSupply().call()); - await logTotalInvestors(); - let verifyTransferFrom = readlineSync.question(`Enter the sender account (${Issuer.address}): `, { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - defaultInput: Issuer.address - }); - await logBalance(verifyTransferFrom, verifyTotalSupply); - let verifyTransferTo = readlineSync.question('Enter the receiver account: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - }); - await logBalance(verifyTransferTo, verifyTotalSupply); - let verifyTransferAmount = readlineSync.question('Enter amount of tokens to verify: '); - let isVerified = await securityToken.methods.verifyTransfer(verifyTransferFrom, verifyTransferTo, web3.utils.toWei(verifyTransferAmount), web3.utils.fromAscii("")).call(); - if (isVerified) { - console.log(chalk.green(`\n${verifyTransferAmount} ${tokenSymbol} can be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); - } else { - console.log(chalk.red(`\n${verifyTransferAmount} ${tokenSymbol} can't be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); - } - break; - case 'Transfer': - let totalSupply = web3.utils.fromWei(await securityToken.methods.totalSupply().call()); + let tmModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.TRANSFER); + let nonArchivedModules = tmModules.filter(m => !m.archived); + if (nonArchivedModules.length > 0) { + console.log(`Transfer Manager modules attached:`); + nonArchivedModules.map(m => console.log(`- ${m.name} at ${m.address}`)) + } else { + console.log(`There are no Transfer Manager modules attached`); + } + + let options = ['Verify transfer', 'Transfer']; + let forcedTransferDisabled = await securityToken.methods.controllerDisabled().call(); + if (!forcedTransferDisabled) { + options.push('Forced transfers'); + } + if (nonArchivedModules.length > 0) { + options.push('Config existing modules'); + } + options.push('Add new Transfer Manager module'); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'EXIT' }); + let optionSelected = index != -1 ? options[index] : 'EXIT'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Verify transfer': + let verifyTotalSupply = web3.utils.fromWei(await securityToken.methods.totalSupply().call()); + await logTotalInvestors(); + let verifyTransferFrom = readlineSync.question(`Enter the sender account (${Issuer.address}): `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: Issuer.address + }); + await logBalance(verifyTransferFrom, verifyTotalSupply); + let verifyTransferTo = readlineSync.question('Enter the receiver account: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + }); + await logBalance(verifyTransferTo, verifyTotalSupply); + let verifyTransferAmount = readlineSync.question('Enter amount of tokens to verify: '); + let isVerified = await securityToken.methods.verifyTransfer(verifyTransferFrom, verifyTransferTo, web3.utils.toWei(verifyTransferAmount), web3.utils.fromAscii("")).call(); + if (isVerified) { + console.log(chalk.green(`\n${verifyTransferAmount} ${tokenSymbol} can be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); + } else { + console.log(chalk.red(`\n${verifyTransferAmount} ${tokenSymbol} can't be transferred from ${verifyTransferFrom} to ${verifyTransferTo}!`)); + } + break; + case 'Transfer': + let totalSupply = web3.utils.fromWei(await securityToken.methods.totalSupply().call()); + await logTotalInvestors(); + await logBalance(Issuer.address, totalSupply); + let transferTo = readlineSync.question('Enter beneficiary of tranfer: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + await logBalance(transferTo, totalSupply); + let transferAmount = readlineSync.question('Enter amount of tokens to transfer: '); + let isTranferVerified = await securityToken.methods.verifyTransfer(Issuer.address, transferTo, web3.utils.toWei(transferAmount), web3.utils.fromAscii("")).call(); + if (isTranferVerified) { + let transferAction = securityToken.methods.transfer(transferTo, web3.utils.toWei(transferAmount)); + let receipt = await common.sendTransaction(transferAction); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); + console.log(chalk.green(`${event.from} transferred ${web3.utils.fromWei(event.value)} ${tokenSymbol} to ${event.to} successfully!`)); await logTotalInvestors(); await logBalance(Issuer.address, totalSupply); - let transferTo = readlineSync.question('Enter beneficiary of tranfer: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); await logBalance(transferTo, totalSupply); - let transferAmount = readlineSync.question('Enter amount of tokens to transfer: '); - let isTranferVerified = await securityToken.methods.verifyTransfer(Issuer.address, transferTo, web3.utils.toWei(transferAmount), web3.utils.fromAscii("")).call(); - if (isTranferVerified) { - let transferAction = securityToken.methods.transfer(transferTo, web3.utils.toWei(transferAmount)); - let receipt = await common.sendTransaction(transferAction); - let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); - console.log(chalk.green(`${event.from} transferred ${web3.utils.fromWei(event.value)} ${tokenSymbol} to ${event.to} successfully!`)); - await logTotalInvestors(); - await logBalance(Issuer.address, totalSupply); - await logBalance(transferTo, totalSupply); - } else { - console.log(chalk.red(`Transfer failed at verification. Please review the transfer restrictions.`)); - } - break; - case 'Forced transfers': - await forcedTransfers(); - break; - case 'Config existing modules': - await configExistingModules(nonArchivedModules); - break; - case 'Add new Transfer Manager module': - await addTransferManagerModule(); - break; - case 'Exit': - exit = true; - break - } + } else { + console.log(chalk.red(`Transfer failed at verification. Please review the transfer restrictions.`)); + } + break; + case 'Forced transfers': + await forcedTransfers(); + break; + case 'Config existing modules': + await configExistingModules(nonArchivedModules); + break; + case 'Add new Transfer Manager module': + await addTransferManagerModule(); + break; + case 'EXIT': + return; } + + await executeApp(); } async function forcedTransfers() { @@ -221,13 +224,10 @@ async function configExistingModules(tmModules) { *********************************` )); break; - case 'LookupVolumeRestrictionTM': - //await lookupVolumeRestrictionTM(); - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); + case 'LockUpTransferManager': + currentTransferManager = new web3.eth.Contract(abis.lockUpTransferManager(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await lockUpTransferManager(); break; } } @@ -303,13 +303,6 @@ async function addTransferManagerModule() { *********************************` )); break; - case 'LookupVolumeRestrictionTM': - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); - break; } let selectedTMFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.TRANSFER, options[index]); let addModuleAction = securityToken.methods.addModule(selectedTMFactoryAddress, bytes, 0, 0); @@ -320,7 +313,7 @@ async function addTransferManagerModule() { } async function generalTransferManager() { - console.log(chalk.blue(`General Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + console.log('\n', chalk.blue(`General Transfer Manager at ${currentTransferManager.options.address}`), '\n'); // Show current data let displayIssuanceAddress = await currentTransferManager.methods.issuanceAddress().call(); @@ -567,7 +560,7 @@ async function modifyWhitelistInBatch() { } async function manualApprovalTransferManager() { - console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address} `), '\n'); + console.log('\n', chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address} `), '\n'); let options = ['Check manual approval', 'Add manual approval', 'Revoke manual approval', 'Check manual blocking', 'Add manual blocking', 'Revoke manual blocking']; @@ -742,7 +735,7 @@ async function getManualBlocking(_from, _to) { } async function countTransferManager() { - console.log(chalk.blue(`Count Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + console.log('\n', chalk.blue(`Count Transfer Manager at ${currentTransferManager.options.address}`), '\n'); // Show current data let displayMaxHolderCount = await currentTransferManager.methods.maxHolderCount().call(); @@ -765,7 +758,7 @@ async function countTransferManager() { } async function percentageTransferManager() { - console.log(chalk.blue(`Percentage Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + console.log('\n', chalk.blue(`Percentage Transfer Manager at ${currentTransferManager.options.address}`), '\n'); // Show current data let displayMaxHolderPercentage = await currentTransferManager.methods.maxHolderPercentage().call(); @@ -865,7 +858,400 @@ async function percentageTransferManager() { console.log(chalk.green(`Transactions which are part of the primary issuance will NOT be ignored!`)); } break; + } +} + +async function lockUpTransferManager() { + console.log('\n', chalk.blue(`Lockup Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + + let currentLockups = await currentTransferManager.methods.getAllLockups().call(); + console.log(`- Lockups: ${currentLockups.length}`); + + let options = ['Add new lockup']; + if (currentLockups.length > 0) { + options.push('Manage existing lockups', 'Explore investor'); + } + options.push('Operate with multiple lockups'); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add new lockup': + let name = readlineSync.question(`Enter the name of the lockup type: `, { + limit: function (input) { + return input !== ""; + }, + limitMessage: `Invalid lockup name` + }); + let lockupAmount = readlineSync.questionInt(`Enter the amount of tokens that will be locked: `); + let minuteFromNow = Math.floor(Date.now() / 1000) + 60; + let startTime = readlineSync.questionInt(`Enter the start time (Unix Epoch time) of the lockup type (a minute from now = ${minuteFromNow}): `, { defaultInput: minuteFromNow }); + let lockUpPeriodSeconds = readlineSync.questionInt(`Enter the total period (seconds) of the lockup type (ten minutes = 600): `, { defaultInput: 600 }); + let releaseFrequencySeconds = readlineSync.questionInt(`Enter how often to release a tranche of tokens in seconds (one minute = 60): `, { defaultInput: 60 }); + if (readlineSync.keyInYNStrict(`Do you want to add an investor to this lockup type? `)) { + let investor = readlineSync.question(`Enter the address of the investor: `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: `Must be a valid address` + }); + let addNewLockUpToUserAction = currentTransferManager.methods.addNewLockUpToUser( + investor, + web3.utils.toWei(lockupAmount.toString()), + startTime, + lockUpPeriodSeconds, + releaseFrequencySeconds, + web3.utils.toHex(name) + ); + let addNewLockUpToUserReceipt = await common.sendTransaction(addNewLockUpToUserAction); + let addNewLockUpToUserEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addNewLockUpToUserReceipt.logs, 'AddNewLockUpType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(addNewLockUpToUserEvent.lockupName)} lockup type has been added successfully!`)); + let addLockUpToUserEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addNewLockUpToUserReceipt.logs, 'AddNewLockUpToUser'); + console.log(chalk.green(`${addLockUpToUserEvent.userAddress} has been added to ${web3.utils.hexToUtf8(addLockUpToUserEvent.lockupName)} successfully!`)); + } else { + let addLockupTypeAction = currentTransferManager.methods.addNewLockUpType(web3.utils.toWei(lockupAmount.toString()), startTime, lockUpPeriodSeconds, releaseFrequencySeconds, web3.utils.toHex(name)); + let addLockupTypeReceipt = await common.sendTransaction(addLockupTypeAction); + let addLockupTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addLockupTypeReceipt.logs, 'AddNewLockUpType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(addLockupTypeEvent.lockupName)} lockup type has been added successfully!`)); + } + break; + case 'Manage existing lockups': + let options = currentLockups.map(b => web3.utils.hexToUtf8(b)); + let index = readlineSync.keyInSelect(options, 'Which lockup type do you want to manage? ', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + if (index !== -1) { + await manageExistingLockups(currentLockups[index]); + } + break; + case 'Explore investor': + let investorToExplore = readlineSync.question('Enter the address you want to explore: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let lockupsToInvestor = await currentTransferManager.methods.getLockupsNamesToUser(investorToExplore).call(); + if (lockupsToInvestor.length > 0) { + let lockedTokenToInvestor = await currentTransferManager.methods.getLockedTokenToUser(investorToExplore).call(); + console.log(chalk.green(`The address ${investorToExplore} has ${web3.utils.fromWei(lockedTokenToInvestor)} ${tokenSymbol} locked across the following ${lockupsToInvestor.length} lockups: `)); + lockupsToInvestor.map(l => console.log(chalk.green(`- ${web3.utils.hexToUtf8(l)}`))); + } else { + console.log(chalk.yellow(`The address ${investorToExplore} has no lockups`)); + } + break; + case 'Operate with multiple lockups': + await operateWithMultipleLockups(currentLockups); + break; + case 'RETURN': + return; + } + + await lockUpTransferManager(); +} + +async function manageExistingLockups(lockupName) { + console.log('\n', chalk.blue(`Lockup ${web3.utils.hexToUtf8(lockupName)}`), '\n'); + + // Show current data + let currentLockup = await currentTransferManager.methods.lockups(lockupName).call(); + let investors = await currentTransferManager.methods.getListOfAddresses(lockupName).call(); + + console.log(`- Amount: ${web3.utils.fromWei(currentLockup.lockupAmount)} ${tokenSymbol}`) + console.log(`- Start time: ${moment.unix(currentLockup.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- Lockup period: ${currentLockup.lockUpPeriodSeconds} seconds`); + console.log(`- End time: ${moment.unix(currentLockup.startTime).add(parseInt(currentLockup.lockUpPeriodSeconds)).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- Release frequency: ${currentLockup.releaseFrequencySeconds} senconds`); + console.log(`- Investors: ${investors.length}`); + // ------------------ + + let options = [ + 'Modify properties', + 'Show investors', + 'Add this lockup to investors', + 'Remove this lockup from investors', + 'Delete this lockup type' + ]; + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Modify properties': + let lockupAmount = readlineSync.questionInt(`Enter the amount of tokens that will be locked: `); + let minuteFromNow = Math.floor(Date.now() / 1000) + 60; + let startTime = readlineSync.questionInt(`Enter the start time (Unix Epoch time) of the lockup type (a minute from now = ${minuteFromNow}): `, { defaultInput: minuteFromNow }); + let lockUpPeriodSeconds = readlineSync.questionInt(`Enter the total period (seconds) of the lockup type (ten minutes = 600): `, { defaultInput: 600 }); + let releaseFrequencySeconds = readlineSync.questionInt(`Enter how often to release a tranche of tokens in seconds (one minute = 60): `, { defaultInput: 60 }); + let modifyLockUpTypeAction = currentTransferManager.methods.modifyLockUpType(lockupAmount, startTime, lockUpPeriodSeconds, releaseFrequencySeconds, lockupName); + let modifyLockUpTypeReceipt = await common.sendTransaction(modifyLockUpTypeAction); + let modifyLockUpTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyLockUpTypeReceipt.logs, 'ModifyLockUpType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(modifyLockUpTypeEvent.lockupName)} lockup type has been modified successfully!`)); + break; + case 'Show investors': + if (investors.length > 0) { + console.log("************ List of investors ************"); + investors.map(i => console.log(i)); + } else { + console.log(chalk.yellow("There are no investors yet")); + } + break; + case 'Add this lockup to investors': + let investorsToAdd = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e.addr1, addr2, addr3): `, { + limit: function (input) { + return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); + }, + limitMessage: `All addresses must be valid` + }).split(","); + let addInvestorToLockupAction; + if (investorsToAdd.length === 1) { + addInvestorToLockupAction = currentTransferManager.methods.addLockUpByName(investorsToAdd[0], lockupName); + } else { + addInvestorToLockupAction = currentTransferManager.methods.addLockUpByNameMulti(investorsToAdd, investorsToAdd.map(i => lockupName)); + } + let addInvestorToLockupReceipt = await common.sendTransaction(addInvestorToLockupAction); + let addInvestorToLockupEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, addInvestorToLockupReceipt.logs, 'AddNewLockUpToUser'); + addInvestorToLockupEvents.map(e => console.log(chalk.green(`${e.userAddress} has been added to ${web3.utils.hexToUtf8(e.lockupName)} successfully!`))); + break; + case 'Remove this lockup from investors': + let investorsToRemove = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e.addr1, addr2, addr3): `, { + limit: function (input) { + return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); + }, + limitMessage: `All addresses must be valid` + }).split(","); + let removeLockupFromInvestorAction; + if (investorsToRemove.length === 1) { + removeLockupFromInvestorAction = currentTransferManager.methods.removeLockUpFromUser(investorsToRemove[0], lockupName); + } else { + removeLockupFromInvestorAction = currentTransferManager.methods.removeLockUpFromUserMulti(investorsToRemove, investorsToRemove.map(i => lockupName)); + } + let removeLockUpFromUserReceipt = await common.sendTransaction(removeLockupFromInvestorAction); + let removeLockUpFromUserEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, removeLockUpFromUserReceipt.logs, 'RemoveLockUpFromUser'); + removeLockUpFromUserEvents.map(e => console.log(chalk.green(`${e.userAddress} has been removed to ${web3.utils.hexToUtf8(e.lockupName)} successfully!`))); + break; + case 'Delete this lockup type': + let isEmpty = investors.length === 0; + if (!isEmpty) { + console.log(chalk.yellow(`This lockup have investors added to it. To delete it you must remove them first.`)); + if (readlineSync.keyInYNStrict(`Do you want to remove them? `)) { + let data = investors.map(i => [i, lockupName]) + let batches = common.splitIntoBatches(data, gbl.constants.DEFAULT_BATCH_SIZE); + let [investorArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to remove the following investors:\n\n`, investorArray[batch], '\n'); + let action = currentTransferManager.methods.removeLockUpFromUserMulti(investorArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Remove lockups from multiple investors transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } + isEmpty = true; + } + } + if (isEmpty) { + let removeLockupTypeAction = currentTransferManager.methods.removeLockupType(lockupName); + let removeLockupTypeReceipt = await common.sendTransaction(removeLockupTypeAction); + let removeLockupTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeLockupTypeReceipt.logs, 'RemoveLockUpType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(removeLockupTypeEvent.lockupName)} lockup type has been deleted successfully!`)); + } + return; + case 'RETURN': + return; + } + + await manageExistingLockups(lockupName); +} + +async function operateWithMultipleLockups(currentLockups) { + let options = ['Add multiple lockups']; + if (currentLockups.length > 0) { + options.push('Modify multiple lockups'); + } + options.push( + 'Delete multiple lockups', + 'Add lockups to multiple investors', + 'Remove lockups from multiple investors' + ); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add multiple lockups': + await addLockupsInBatch(); + break; + case 'Modify multiple lockups': + await modifyLockupsInBatch(); + break; + case 'Delete multiple lockups': + await deleteLockupsInBatch(); + break; + case 'Add lockups to multiple investors': + await addLockupsToInvestorsInBatch(); + break; + case 'Remove lockups from multiple investors': + await removeLockupsFromInvestorsInBatch(); + break; + } +} + +async function addLockupsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_LOCKUP_DATA_CSV}): `, { + defaultInput: ADD_LOCKUP_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => !isNaN(row[0]) && + moment.unix(row[1]).isValid() && + (!isNaN(row[2] && (parseFloat(row[2]) % 1 === 0))) && + (!isNaN(row[3] && (parseFloat(row[3]) % 1 === 0))) && + typeof row[4] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [amountArray, startTimeArray, lockUpPeriodArray, releaseFrequencyArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add the following lockups: \n\n`, lockupNameArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.addNewLockUpTypeMulti(amountArray[batch], startTimeArray[batch], lockUpPeriodArray[batch], releaseFrequencyArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add multiple lockups transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} +async function modifyLockupsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${MODIFY_LOCKUP_DATA_CSV}): `, { + defaultInput: MODIFY_LOCKUP_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => !isNaN(row[0]) && + moment.unix(row[1]).isValid() && + (!isNaN(row[2] && (parseFloat(row[2]) % 1 === 0))) && + (!isNaN(row[3] && (parseFloat(row[3]) % 1 === 0))) && + typeof row[4] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [amountArray, startTimeArray, lockUpPeriodArray, releaseFrequencyArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to modify the following lockups: \n\n`, lockupNameArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.modifyLockUpTypeMulti(amountArray[batch], startTimeArray[batch], lockUpPeriodArray[batch], releaseFrequencyArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Modify multiple lockups transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function deleteLockupsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${DELETE_LOCKUP_DATA_CSV}): `, { + defaultInput: DELETE_LOCKUP_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => typeof row[0] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to delete the following lockups: \n\n`, lockupNameArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.removeLockupTypeMulti(lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Delete multiple lockups transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function addLockupsToInvestorsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_LOCKUP_INVESTOR_DATA_CSV}): `, { + defaultInput: ADD_LOCKUP_INVESTOR_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + typeof row[1] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add lockups to the following investors: \n\n`, investorArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.addLockUpByNameMulti(investorArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add lockups to multiple investors transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function removeLockupsFromInvestorsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REMOVE_LOCKUP_INVESTOR_DATA_CSV}): `, { + defaultInput: REMOVE_LOCKUP_INVESTOR_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + typeof row[1] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to remove the following investors: \n\n`, investorArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.removeLockUpFromUserMulti(investorArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Remove lockups from multiple investors transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } } @@ -1159,13 +1545,13 @@ async function selectToken() { }); options.push('Enter token symbol manually'); - let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); - let selected = index != -1 ? options[index] : 'Exit'; + let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'EXIT' }); + let selected = index != -1 ? options[index] : 'EXIT'; switch (selected) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); break; - case 'Exit': + case 'EXIT': process.exit(); break; default: @@ -1178,13 +1564,13 @@ async function selectToken() { async function logTotalInvestors() { let investorsCount = await securityToken.methods.getInvestorCount().call(); - console.log(chalk.yellow(`Total investors at the moment: ${investorsCount}`)); + console.log(chalk.yellow(`Total investors at the moment: ${investorsCount} `)); } async function logBalance(from, totalSupply) { let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(from).call()); let percentage = totalSupply != '0' ? ` - ${parseFloat(fromBalance) / parseFloat(totalSupply) * 100}% of total supply` : ''; - console.log(chalk.yellow(`Balance of ${from}: ${fromBalance} ${tokenSymbol}${percentage}`)); + console.log(chalk.yellow(`Balance of ${from}: ${fromBalance} ${tokenSymbol} ${percentage} `)); } module.exports = { diff --git a/CLI/data/Transfer/LockupTM/add_lockup_data.csv b/CLI/data/Transfer/LockupTM/add_lockup_data.csv new file mode 100644 index 000000000..f3d27ab2d --- /dev/null +++ b/CLI/data/Transfer/LockupTM/add_lockup_data.csv @@ -0,0 +1,4 @@ +1000,1560178800,600,1,"TenMinutes" +1000,1560621600,3600,60,"OneHour" +2000,1567252800,7200,3600,"TwoHours" +3000,1567303200,14400,4800,"4Hours" diff --git a/CLI/data/Transfer/LockupTM/add_lockup_investor_data.csv b/CLI/data/Transfer/LockupTM/add_lockup_investor_data.csv new file mode 100644 index 000000000..68c08a7d7 --- /dev/null +++ b/CLI/data/Transfer/LockupTM/add_lockup_investor_data.csv @@ -0,0 +1,12 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,"TenMinutes" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,"TenMinutes" +0xac297053173b02b02a737d47f7b4a718e5b170ef,"TenMinutes" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"TenMinutes" +0x10223927009b8add0960359dd90d1449415b7ca9,"TenMinutes" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"OneHour" +0x10223927009b8add0960359dd90d1449415b7ca9,"OneHour" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,"OneHour" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,"OneHour" +0x10223927009b8add0960359dd90d1449415b7ca9,"OneHour" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,"OneHour" +0x56be93088141b16ebaa9416122fd1d928da25ecf,"OneHour" \ No newline at end of file diff --git a/CLI/data/Transfer/LockupTM/delete_lockup_data.csv b/CLI/data/Transfer/LockupTM/delete_lockup_data.csv new file mode 100644 index 000000000..0d9203ffe --- /dev/null +++ b/CLI/data/Transfer/LockupTM/delete_lockup_data.csv @@ -0,0 +1,2 @@ +"TwoHours" +"4Hours" \ No newline at end of file diff --git a/CLI/data/Transfer/LockupTM/modify_lockup_data.csv b/CLI/data/Transfer/LockupTM/modify_lockup_data.csv new file mode 100644 index 000000000..2b520c4ff --- /dev/null +++ b/CLI/data/Transfer/LockupTM/modify_lockup_data.csv @@ -0,0 +1,4 @@ +1000,1560178800,600,10,"TenMinutes" +1000,1560623200,3600,60,"OneHour" +2000,1567252800,7200,3600,"TwoHours" +6000,1567303200,14400,4800,"4Hours" diff --git a/CLI/data/Transfer/LockupTM/remove_lockup_investor_data.csv b/CLI/data/Transfer/LockupTM/remove_lockup_investor_data.csv new file mode 100644 index 000000000..68c08a7d7 --- /dev/null +++ b/CLI/data/Transfer/LockupTM/remove_lockup_investor_data.csv @@ -0,0 +1,12 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,"TenMinutes" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,"TenMinutes" +0xac297053173b02b02a737d47f7b4a718e5b170ef,"TenMinutes" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"TenMinutes" +0x10223927009b8add0960359dd90d1449415b7ca9,"TenMinutes" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"OneHour" +0x10223927009b8add0960359dd90d1449415b7ca9,"OneHour" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,"OneHour" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,"OneHour" +0x10223927009b8add0960359dd90d1449415b7ca9,"OneHour" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,"OneHour" +0x56be93088141b16ebaa9416122fd1d928da25ecf,"OneHour" \ No newline at end of file From 9b4e7b24e9d8358f0c11cf1ff5b14a43135b044f Mon Sep 17 00:00:00 2001 From: shuffledex Date: Tue, 11 Dec 2018 15:52:55 -0300 Subject: [PATCH 393/582] individual balance for every stable coin listed --- CLI/commands/investor_portal.js | 34 +++++++++++++----------- CLI/commands/sto_manager.js | 46 ++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index bbebc003c..fb4cc153d 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -9,7 +9,6 @@ var gbl = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); -const STO_KEY = 3; const ETH = 'ETH'; const POLY = 'POLY'; const STABLE = 'STABLE'; @@ -255,7 +254,7 @@ async function processAddress(array) { let list = []; for (const address of array) { let symbol = await checkSymbol(address); - list.push(symbol) + list.push({"symbol": symbol, "address": address}) } return list } @@ -290,7 +289,7 @@ async function showUserInfoForUSDTieredSTO() } let displayInvestorInvested = web3.utils.fromWei(await currentSTO.methods.investorInvested(User.address, gbl.constants.FUND_RAISE_TYPES[fundType]).call()); if ((fundType == STABLE) && (stableSymbols.length)) { - console.log(` - Invested in ${stableSymbols.toString()}:\t ${displayInvestorInvested} USD`); + console.log(` - Invested in stable coin(s): ${displayInvestorInvested} USD`); } else { console.log(` - Invested in ${fundType}:\t ${displayInvestorInvested} ${fundType}`); } @@ -298,7 +297,7 @@ async function showUserInfoForUSDTieredSTO() } let displayInvestorInvestedUSD = web3.utils.fromWei(await currentSTO.methods.investorInvestedUSD(User.address).call()); - console.log(` - Invested in USD: ${displayInvestorInvestedUSD} USD`); + console.log(` - Total invested in USD: ${displayInvestorInvestedUSD} USD`); await generalTransferManager.methods.whitelist(User.address).call({}, function (error, result) { displayCanBuy = result.canBuyFromSTO; @@ -371,7 +370,7 @@ async function showUSDTieredSTOInfo() { let mintedPerTier = mintedPerTierPerRaiseType[gbl.constants.FUND_RAISE_TYPES[type]]; if ((type == STABLE) && (stableSymbols.length)) { displayMintedPerTierPerType += ` - Sold for ${stableSymbols.toString()}:\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + Sold for stable coin(s): ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; } else { displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; @@ -396,8 +395,11 @@ async function showUSDTieredSTOInfo() { for (const type of raiseTypes) { let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); if ((type == STABLE) && (stableSymbols.length)) { - displayFundsRaisedPerType += ` - ${stableSymbols.toString()}:\t\t ${fundsRaised} USD`; + stableSymbols.forEach(async (stable) => { + let raised = await getStableCoinsRaised(currentSTO, stable.address); + displayFundsRaisedPerType += ` + ${stable.symbol}:\t\t\t ${web3.utils.fromWei(raised)} ${stable.symbol}`; + }) } else { displayFundsRaisedPerType += ` ${type}:\t\t\t ${fundsRaised} ${type}`; @@ -407,7 +409,7 @@ async function showUSDTieredSTOInfo() { let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(gbl.constants.FUND_RAISE_TYPES[type]).call()); if ((type == STABLE) && (stableSymbols.length)) { displayTokensSoldPerType += ` - Sold for ${stableSymbols.toString()}:\t ${tokensSoldPerType} ${displayTokenSymbol}`; + Sold for stable coin(s): ${tokensSoldPerType} ${displayTokenSymbol}`; } else { displayTokensSoldPerType += ` Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; @@ -418,7 +420,7 @@ async function showUSDTieredSTOInfo() { let displayRaiseType = raiseTypes.join(' - '); //If STO has stable coins, we list them one by one if (stableSymbols.length) { - displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.toString().replace(`,`,` - `)}` + displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.map((obj) => {return obj.symbol}).toString().replace(`,`,` - `)}` } let now = Math.floor(Date.now() / 1000); @@ -452,7 +454,7 @@ async function showUSDTieredSTOInfo() { - Investor count: ${displayInvestorCount} - Funds Raised` + displayFundsRaisedPerType + ` - USD: ${displayFundsRaisedUSD} USD + Total USD: ${displayFundsRaisedUSD} USD `); if (!displayCanBuy) { @@ -470,6 +472,10 @@ async function showUSDTieredSTOInfo() { } } +async function getStableCoinsRaised(currentSTO, address) { + return await currentSTO.methods.stableCoinsRaised(address).call() +} + // Allow investor to buy tokens. async function investCappedSTO(currency, amount) { if (typeof currency !== 'undefined' && !raiseTypes.inlcudes(currency)) { @@ -531,9 +537,7 @@ async function investUsdTieredSTO(currency, amount) { } else { for (const type of raiseTypes) { let displayPrice = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], web3.utils.toWei("1")).call()); - if ((type == STABLE) && (stableSymbols.length)) { - console.log(chalk.green(` Current ${stableSymbols.toString()} price:\t\t ${displayPrice} USD`)); - } else { + if (!((type == STABLE) && (stableSymbols.length))) { console.log(chalk.green(` Current ${type} price:\t\t ${displayPrice} USD`)); } } @@ -541,8 +545,8 @@ async function investUsdTieredSTO(currency, amount) { const stableIndex = raiseTypes.indexOf(STABLE); if (stableIndex > -1) { raiseTypes.splice(stableIndex, 1) - stableSymbols.forEach((symbol) => { - raiseTypes.push(symbol) + stableSymbols.forEach((stable) => { + raiseTypes.push(stable.symbol) }) } let index = readlineSync.keyInSelect(raiseTypes, 'Choose one of the allowed raise types: ', { cancel: false }); diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 9fec111df..fb8ccc32f 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -389,7 +389,7 @@ async function processAddress(array) { let list = []; for (const address of array) { let symbol = await checkSymbol(address); - list.push(symbol) + list.push({"symbol": symbol, "address": address}) } return list } @@ -628,7 +628,7 @@ async function usdTieredSTO_status(currentSTO) { let mintedPerTier = mintedPerTierPerRaiseType[gbl.constants.FUND_RAISE_TYPES[type]]; if ((type == STABLE) && (stableSymbols.length)) { displayMintedPerTierPerType += ` - Sold for ${stableSymbols.toString()}:\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + Sold for stable coin(s): ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; } else { displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; @@ -655,11 +655,14 @@ async function usdTieredSTO_status(currentSTO) { for (const type of raiseTypes) { let balance = await getBalance(displayWallet, gbl.constants.FUND_RAISE_TYPES[type]); let walletBalance = web3.utils.fromWei(balance); - let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); if ((type == STABLE) && (stableSymbols.length)) { - displayWalletBalancePerType += ` - Balance ${stableSymbols.toString()}:\t ${walletBalanceUSD} USD`; + stableSymbols.forEach(async (stable) => { + let raised = await checkStableBalance(displayWallet, stable.address); + displayWalletBalancePerType += ` + Balance ${stable.symbol}:\t\t ${web3.utils.fromWei(raised)} ${stable.symbol}`; + }) } else { + let walletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); displayWalletBalancePerType += ` Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; } @@ -668,8 +671,11 @@ async function usdTieredSTO_status(currentSTO) { let reserveWalletBalance = web3.utils.fromWei(balance); let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); if ((type == STABLE) && (stableSymbols.length)) { - displayReserveWalletBalancePerType += ` - Balance ${stableSymbols.toString()}:\t ${reserveWalletBalanceUSD} USD`; + stableSymbols.forEach(async (stable) => { + let raised = await checkStableBalance(displayReserveWallet, stable.address); + displayReserveWalletBalancePerType += ` + Balance ${stable.symbol}:\t\t ${web3.utils.fromWei(raised)} ${stable.symbol}`; + }) } else { displayReserveWalletBalancePerType += ` Balance ${type}:\t\t ${reserveWalletBalance} ${type} (${reserveWalletBalanceUSD} USD)`; @@ -677,8 +683,11 @@ async function usdTieredSTO_status(currentSTO) { let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); if ((type == STABLE) && (stableSymbols.length)) { - displayFundsRaisedPerType += ` - ${stableSymbols.toString()}:\t\t ${fundsRaised} USD`; + stableSymbols.forEach(async (stable) => { + let raised = await getStableCoinsRaised(currentSTO, stable.address); + displayFundsRaisedPerType += ` + ${stable.symbol}:\t\t\t ${web3.utils.fromWei(raised)} ${stable.symbol}`; + }) } else { displayFundsRaisedPerType += ` ${type}:\t\t\t ${fundsRaised} ${type}`; @@ -689,7 +698,7 @@ async function usdTieredSTO_status(currentSTO) { let tokensSoldPerType = web3.utils.fromWei(await currentSTO.methods.getTokensSoldFor(gbl.constants.FUND_RAISE_TYPES[type]).call()); if ((type == STABLE) && (stableSymbols.length)) { displayTokensSoldPerType += ` - Sold for ${stableSymbols.toString()}:\t ${tokensSoldPerType} ${displayTokenSymbol}`; + Sold for stable coin(s): ${tokensSoldPerType} ${displayTokenSymbol}`; } else { displayTokensSoldPerType += ` Sold for ${type}:\t\t ${tokensSoldPerType} ${displayTokenSymbol}`; @@ -700,7 +709,7 @@ async function usdTieredSTO_status(currentSTO) { let displayRaiseType = raiseTypes.join(' - '); //If STO has stable coins, we list them one by one if (stableSymbols.length) { - displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.toString().replace(`,`,` - `)}` + displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.map((obj) => {return obj.symbol}).toString().replace(`,`,` - `)}` } let now = Math.floor(Date.now() / 1000); @@ -741,12 +750,25 @@ async function usdTieredSTO_status(currentSTO) { - Investor count: ${displayInvestorCount} - Funds Raised` + displayFundsRaisedPerType + ` - USD: ${displayFundsRaisedUSD} USD + Total USD: ${displayFundsRaisedUSD} USD `); console.log(chalk.green(`\n${(web3.utils.fromWei(await getBalance(Issuer.address, gbl.constants.FUND_RAISE_TYPES.POLY)))} POLY balance remaining at issuer address ${Issuer.address}`)); } +async function checkStableBalance(walletAddress, stableAddress) { + let stableCoin = common.connect(abis.erc20(), stableAddress); + try { + return await stableCoin.methods.balanceOf(walletAddress).call(); + } catch (e) { + return "" + } +} + +async function getStableCoinsRaised(currentSTO, address) { + return await currentSTO.methods.stableCoinsRaised(address).call() +} + async function usdTieredSTO_configure(currentSTO) { console.log(chalk.blue('STO Configuration - USD Tiered STO')); From 3fd1e0727147ea001b445f0b4b8c256cb24a1df5 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Tue, 11 Dec 2018 22:22:56 -0300 Subject: [PATCH 394/582] CLI minor fixes --- CLI/commands/investor_portal.js | 19 +++++++++++++++---- CLI/commands/sto_manager.js | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index fb4cc153d..613414a71 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -549,11 +549,18 @@ async function investUsdTieredSTO(currency, amount) { raiseTypes.push(stable.symbol) }) } - let index = readlineSync.keyInSelect(raiseTypes, 'Choose one of the allowed raise types: ', { cancel: false }); - raiseType = raiseTypes[index]; + raiseType = raiseTypes[selectToken('Choose one of the allowed raise types: ')]; } else { - raiseType = raiseTypes[0]; - console.log(''); + if (raiseTypes[0] == STABLE) { + raiseTypes.splice(raiseTypes.indexOf(STABLE), 1) + stableSymbols.forEach((stable) => { + raiseTypes.push(stable.symbol) + }) + raiseType = raiseTypes[selectToken('Choose one of the allowed stable coin(s): ')]; + } else { + raiseType = raiseTypes[0]; + console.log(''); + } } } @@ -645,6 +652,10 @@ async function investUsdTieredSTO(currency, amount) { await showUserInfoForUSDTieredSTO(); } +function selectToken(msg) { + return readlineSync.keyInSelect(raiseTypes, msg, { cancel: false }); +} + async function polyBalance(_user) { let balance = await polyToken.methods.balanceOf(_user).call(); return web3.utils.fromWei(balance); diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index fb8ccc32f..9156b1fbd 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -348,7 +348,7 @@ async function addressesConfigUSDTieredSTO(usdTokenRaise) { addresses.usdToken = ['0x0000000000000000000000000000000000000000']; } - if (!await processArray(listOfAddress)) { + if ((usdTokenRaise) && (!await processArray(listOfAddress))) { console.log(chalk.yellow(`\nPlease, verify your stable coins addresses to continue with this process.\n`)) menu = true; } else { From 4ae3a219c4f5880308201637da9a170f07d39f66 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 12 Dec 2018 15:44:21 +0530 Subject: [PATCH 395/582] recommended fixes --- .../TransferManager/LockUpTransferManager.sol | 66 ++++++++----------- test/w_lockup_transfer_manager.js | 41 +++++------- 2 files changed, 46 insertions(+), 61 deletions(-) diff --git a/contracts/modules/TransferManager/LockUpTransferManager.sol b/contracts/modules/TransferManager/LockUpTransferManager.sol index 3d3450721..993bbd5bb 100644 --- a/contracts/modules/TransferManager/LockUpTransferManager.sol +++ b/contracts/modules/TransferManager/LockUpTransferManager.sol @@ -31,33 +31,33 @@ contract LockUpTransferManager is ITransferManager { bytes32[] lockupArray; - event AddNewLockUpToUser( - address indexed userAddress, - bytes32 indexed lockupName + event AddLockUpToUser( + address indexed _userAddress, + bytes32 indexed _lockupName ); event RemoveLockUpFromUser( - address indexed userAddress, - bytes32 indexed lockupName + address indexed _userAddress, + bytes32 indexed _lockupName ); event ModifyLockUpType( - uint256 lockupAmount, - uint256 startTime, - uint256 lockUpPeriodSeconds, - uint256 releaseFrequencySeconds, - bytes32 indexed lockupName + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 indexed _lockupName ); event AddNewLockUpType( - bytes32 indexed lockupName, - uint256 lockupAmount, - uint256 startTime, - uint256 lockUpPeriodSeconds, - uint256 releaseFrequencySeconds + bytes32 indexed _lockupName, + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds ); - event RemoveLockUpType(bytes32 indexed lockupName); + event RemoveLockUpType(bytes32 indexed _lockupName); /** * @notice Constructor @@ -344,37 +344,27 @@ contract LockUpTransferManager is ITransferManager { } } - /** - * @notice Get the length of the lockups array for a specific user address - * @param _userAddress Address of the user whose tokens should be locked up - */ - function getLockUpsLength(address _userAddress) public view returns (uint256) { - return userToLockups[_userAddress].length; - } - /** * @notice Get a specific element in a user's lockups array given the user's address and the element index - * @param _userAddress Address of the user whose tokens should be locked up * @param _lockupName The name of the lockup */ - function getLockUp(address _userAddress, bytes32 _lockupName) public view returns ( + function getLockUp(bytes32 _lockupName) external view returns ( uint256 lockupAmount, uint256 startTime, uint256 lockUpPeriodSeconds, uint256 releaseFrequencySeconds, uint256 unlockedAmount ) { - require( - userToLockups[_userAddress][userToLockupIndex[_userAddress][_lockupName]] == _lockupName, - "User not assosicated with given lockup" - ); - return ( - lockups[_lockupName].lockupAmount, - lockups[_lockupName].startTime, - lockups[_lockupName].lockUpPeriodSeconds, - lockups[_lockupName].releaseFrequencySeconds, - _getUnlockedAmountForLockup(_lockupName) - ); + if (lockups[_lockupName].lockupAmount != 0) { + return ( + lockups[_lockupName].lockupAmount, + lockups[_lockupName].startTime, + lockups[_lockupName].lockUpPeriodSeconds, + lockups[_lockupName].releaseFrequencySeconds, + _getUnlockedAmountForLockup(_lockupName) + ); + } + return (uint256(0), uint256(0), uint256(0), uint256(0), uint256(0)); } /** @@ -582,7 +572,7 @@ contract LockUpTransferManager is ITransferManager { lockupToUserIndex[_lockupName][_userAddress] = lockupToUsers[_lockupName].length; userToLockups[_userAddress].push(_lockupName); lockupToUsers[_lockupName].push(_userAddress); - emit AddNewLockUpToUser(_userAddress, _lockupName); + emit AddLockUpToUser(_userAddress, _lockupName); } function _addNewLockUpType( diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js index 59e1ed816..27924eb20 100644 --- a/test/w_lockup_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -446,7 +446,7 @@ contract('LockUpTransferManager', accounts => { from: token_owner } ); - assert.equal((tx.logs[0].args.lockupAmount).toNumber(), web3.utils.toWei('12', 'ether')); + assert.equal((tx.logs[0].args._lockupAmount).toNumber(), web3.utils.toWei('12', 'ether')); }); it("Should fail to add the creation of the lockup where lockupName is already exists", async() => { @@ -478,8 +478,8 @@ contract('LockUpTransferManager', accounts => { from: token_owner } ); - assert.equal(tx.logs[1].args.userAddress, account_investor1); - assert.equal((tx.logs[0].args.lockupAmount).toNumber(), web3.utils.toWei('0.5', 'ether')); + assert.equal(tx.logs[1].args._userAddress, account_investor1); + assert.equal((tx.logs[0].args._lockupAmount).toNumber(), web3.utils.toWei('0.5', 'ether')); }); it("Should allow the creation of a lockup where the lockup amount is prime no", async() => { @@ -495,8 +495,8 @@ contract('LockUpTransferManager', accounts => { from: token_owner } ); - assert.equal(tx.logs[1].args.userAddress, account_investor1); - assert.equal((tx.logs[0].args.lockupAmount).toNumber(), web3.utils.toWei('64951', 'ether')); + assert.equal(tx.logs[1].args._userAddress, account_investor1); + assert.equal((tx.logs[0].args._lockupAmount).toNumber(), web3.utils.toWei('64951', 'ether')); }); it("Should prevent the transfer of tokens in a lockup", async() => { @@ -517,7 +517,7 @@ contract('LockUpTransferManager', accounts => { } ); await increaseTime(2); - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); + let tx = await I_LockUpTransferManager.getLockUp.call("b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) @@ -527,7 +527,7 @@ contract('LockUpTransferManager', accounts => { it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { // wait 20 seconds await increaseTime(duration.seconds(20)); - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); + let tx = await I_LockUpTransferManager.getLockUp.call("b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }) @@ -535,13 +535,13 @@ contract('LockUpTransferManager', accounts => { }); it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); + let tx = await I_LockUpTransferManager.getLockUp.call("b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); }); it("Should again transfer of tokens in a lockup if a period has passed", async() => { - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); + let tx = await I_LockUpTransferManager.getLockUp.call("b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); }); @@ -550,7 +550,7 @@ contract('LockUpTransferManager', accounts => { // wait 20 more seconds + 1 to get rid of same block time await increaseTime(duration.seconds(21)); - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor2, "b_lockup"); + let tx = await I_LockUpTransferManager.getLockUp.call( "b_lockup"); console.log("Amount get unlocked:", (tx[4].toNumber())); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); }); @@ -682,8 +682,8 @@ contract('LockUpTransferManager', accounts => { ); await increaseTime(1); - let tx = await I_LockUpTransferManager.getLockUp.call(account_investor3, "c_lockup"); - let tx2 = await I_LockUpTransferManager.getLockUp.call(account_investor3, "d_lockup"); + let tx = await I_LockUpTransferManager.getLockUp.call("c_lockup"); + let tx2 = await I_LockUpTransferManager.getLockUp.call("d_lockup"); console.log("Total Amount get unlocked:", (tx[4].toNumber()) + (tx2[4].toNumber())); await catchRevert( I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor3 }) @@ -859,11 +859,7 @@ contract('LockUpTransferManager', accounts => { I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) ); - // check and get the lockup - let lockUpCount = await I_LockUpTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 1) - - let lockUp = await I_LockUpTransferManager.getLockUp(account_investor1, "f_lockup"); + let lockUp = await I_LockUpTransferManager.getLockUp("f_lockup"); console.log(lockUp); // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount assert.equal( @@ -902,7 +898,7 @@ contract('LockUpTransferManager', accounts => { it("Modify the lockup during the lockup periods", async() => { let balance = await I_SecurityToken.balanceOf(account_investor1) - let lockUp = await I_LockUpTransferManager.getLockUp(account_investor1, "f_lockup"); + let lockUp = await I_LockUpTransferManager.getLockUp("f_lockup"); console.log(lockUp[4].dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); // edit the lockup await I_LockUpTransferManager.modifyLockUpType( @@ -931,7 +927,7 @@ contract('LockUpTransferManager', accounts => { // removing the lockup type let tx = await I_LockUpTransferManager.removeLockupType("k_lockup", {from: token_owner}); - assert.equal(web3.utils.toUtf8(tx.logs[0].args.lockupName), "k_lockup"); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._lockupName), "k_lockup"); // attaching the lockup to a user @@ -944,10 +940,9 @@ contract('LockUpTransferManager', accounts => { ); }) - it("Should succesfully get the lockup - fail because no lockup exist for the user of this name", async() => { - await catchRevert( - I_LockUpTransferManager.getLockUp(account_investor1, 9) - ); + it("Should succesfully get the non existed lockup value, it will give everything 0", async() => { + let data = await I_LockUpTransferManager.getLockUp(9); + assert.equal(data[0], 0); }) it("Should get configuration function signature", async() => { From 216d3206bf8f16b134337679c948cc8f3d79084c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 12 Dec 2018 16:22:20 +0530 Subject: [PATCH 396/582] Added code comments --- .../TransferManager/VolumeRestrictionTM.sol | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index fff5f71f4..aa6d9d311 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -943,9 +943,21 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // the earlier value at that index if (counter >= _rollingPeriodInDays) { // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - sumOfLastPeriod = sumOfLastPeriod. - sub(bucket[_from][_bucketDetails.lastTradedDayTime. - sub((_bucketDetails.daysCovered.sub(counter.sub(_rollingPeriodInDays))).mul(1 days))]); + // The below line subtracts (the traded volume on days no longer covered by rolling period) from sumOfLastPeriod. + // Every loop execution subtracts one day's trade volume. + // Loop starts from the first day covered in sumOfLastPeriod upto the day that is covered by rolling period. + sumOfLastPeriod = + sumOfLastPeriod.sub( + bucket[_from][_bucketDetails.lastTradedDayTime.sub( + ( + _bucketDetails.daysCovered.sub( + counter.sub( + _rollingPeriodInDays + ) + ) + ).mul(1 days) + )] + ); } // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand // the alogrithm From a0700ea124d5f5325081c54d7c2513d4c7d3b9ac Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 12 Dec 2018 17:02:05 +0530 Subject: [PATCH 397/582] Removed uninitialized pointer --- .../TransferManager/VolumeRestrictionTM.sol | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index aa6d9d311..f619f2427 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -1002,11 +1002,29 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) internal { - BucketDetails storage details; - if (isDefault) - details = defaultUserToBucket[_from]; - else - details = userToBucket[_from]; + + if (isDefault){ + BucketDetails storage defaultUserToBucketDetails = defaultUserToBucket[_from]; + _updateStorageActual(_from, _amount, _lastTradedDayTime, _sumOfLastPeriod, _daysCovered, _dailyLastTradedDayTime, _endTime, defaultUserToBucketDetails); + } + else { + BucketDetails storage userToBucketDetails = userToBucket[_from]; + _updateStorageActual(_from, _amount, _lastTradedDayTime, _sumOfLastPeriod, _daysCovered, _dailyLastTradedDayTime, _endTime, userToBucketDetails); + } + } + + function _updateStorageActual( + address _from, + uint256 _amount, + uint256 _lastTradedDayTime, + uint256 _sumOfLastPeriod, + uint256 _daysCovered, + uint256 _dailyLastTradedDayTime, + uint256 _endTime, + BucketDetails storage details + ) + internal + { // Cheap storage technique if (details.lastTradedDayTime != _lastTradedDayTime) { // Assigning the latest transaction timestamp of the day From d1598e5cffa9d6d9af8267193f66a968889cbfd1 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 12 Dec 2018 08:38:58 -0300 Subject: [PATCH 398/582] CLI - Fixes for new contract changes --- CLI/commands/transfer_manager.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 8fe30206e..8202e9b2c 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -906,14 +906,14 @@ async function lockUpTransferManager() { ); let addNewLockUpToUserReceipt = await common.sendTransaction(addNewLockUpToUserAction); let addNewLockUpToUserEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addNewLockUpToUserReceipt.logs, 'AddNewLockUpType'); - console.log(chalk.green(`${web3.utils.hexToUtf8(addNewLockUpToUserEvent.lockupName)} lockup type has been added successfully!`)); - let addLockUpToUserEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addNewLockUpToUserReceipt.logs, 'AddNewLockUpToUser'); - console.log(chalk.green(`${addLockUpToUserEvent.userAddress} has been added to ${web3.utils.hexToUtf8(addLockUpToUserEvent.lockupName)} successfully!`)); + console.log(chalk.green(`${web3.utils.hexToUtf8(addNewLockUpToUserEvent._lockupName)} lockup type has been added successfully!`)); + let addLockUpToUserEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addNewLockUpToUserReceipt.logs, 'AddLockUpToUser'); + console.log(chalk.green(`${addLockUpToUserEvent._userAddress} has been added to ${web3.utils.hexToUtf8(addLockUpToUserEvent._lockupName)} successfully!`)); } else { let addLockupTypeAction = currentTransferManager.methods.addNewLockUpType(web3.utils.toWei(lockupAmount.toString()), startTime, lockUpPeriodSeconds, releaseFrequencySeconds, web3.utils.toHex(name)); let addLockupTypeReceipt = await common.sendTransaction(addLockupTypeAction); let addLockupTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addLockupTypeReceipt.logs, 'AddNewLockUpType'); - console.log(chalk.green(`${web3.utils.hexToUtf8(addLockupTypeEvent.lockupName)} lockup type has been added successfully!`)); + console.log(chalk.green(`${web3.utils.hexToUtf8(addLockupTypeEvent._lockupName)} lockup type has been added successfully!`)); } break; case 'Manage existing lockups': @@ -955,13 +955,15 @@ async function manageExistingLockups(lockupName) { console.log('\n', chalk.blue(`Lockup ${web3.utils.hexToUtf8(lockupName)}`), '\n'); // Show current data - let currentLockup = await currentTransferManager.methods.lockups(lockupName).call(); + let currentLockup = await currentTransferManager.methods.getLockUp(lockupName).call(); let investors = await currentTransferManager.methods.getListOfAddresses(lockupName).call(); - console.log(`- Amount: ${web3.utils.fromWei(currentLockup.lockupAmount)} ${tokenSymbol}`) + + console.log(`- Amount: ${web3.utils.fromWei(currentLockup.lockupAmount)} ${tokenSymbol}`); + console.log(`- Currently unlocked: ${web3.utils.fromWei(currentLockup.unlockedAmount)} ${tokenSymbol}`); console.log(`- Start time: ${moment.unix(currentLockup.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); console.log(`- Lockup period: ${currentLockup.lockUpPeriodSeconds} seconds`); - console.log(`- End time: ${moment.unix(currentLockup.startTime).add(parseInt(currentLockup.lockUpPeriodSeconds)).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- End time: ${moment.unix(currentLockup.endTime).add(parseInt(currentLockup.lockUpPeriodSeconds)).format('MMMM Do YYYY, HH:mm:ss')}`); console.log(`- Release frequency: ${currentLockup.releaseFrequencySeconds} senconds`); console.log(`- Investors: ${investors.length}`); // ------------------ @@ -987,7 +989,7 @@ async function manageExistingLockups(lockupName) { let modifyLockUpTypeAction = currentTransferManager.methods.modifyLockUpType(lockupAmount, startTime, lockUpPeriodSeconds, releaseFrequencySeconds, lockupName); let modifyLockUpTypeReceipt = await common.sendTransaction(modifyLockUpTypeAction); let modifyLockUpTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyLockUpTypeReceipt.logs, 'ModifyLockUpType'); - console.log(chalk.green(`${web3.utils.hexToUtf8(modifyLockUpTypeEvent.lockupName)} lockup type has been modified successfully!`)); + console.log(chalk.green(`${web3.utils.hexToUtf8(modifyLockUpTypeEvent._lockupName)} lockup type has been modified successfully!`)); break; case 'Show investors': if (investors.length > 0) { @@ -1011,8 +1013,8 @@ async function manageExistingLockups(lockupName) { addInvestorToLockupAction = currentTransferManager.methods.addLockUpByNameMulti(investorsToAdd, investorsToAdd.map(i => lockupName)); } let addInvestorToLockupReceipt = await common.sendTransaction(addInvestorToLockupAction); - let addInvestorToLockupEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, addInvestorToLockupReceipt.logs, 'AddNewLockUpToUser'); - addInvestorToLockupEvents.map(e => console.log(chalk.green(`${e.userAddress} has been added to ${web3.utils.hexToUtf8(e.lockupName)} successfully!`))); + let addInvestorToLockupEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, addInvestorToLockupReceipt.logs, 'AddLockUpToUser'); + addInvestorToLockupEvents.map(e => console.log(chalk.green(`${e._userAddress} has been added to ${web3.utils.hexToUtf8(e._lockupName)} successfully!`))); break; case 'Remove this lockup from investors': let investorsToRemove = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e.addr1, addr2, addr3): `, { @@ -1029,7 +1031,7 @@ async function manageExistingLockups(lockupName) { } let removeLockUpFromUserReceipt = await common.sendTransaction(removeLockupFromInvestorAction); let removeLockUpFromUserEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, removeLockUpFromUserReceipt.logs, 'RemoveLockUpFromUser'); - removeLockUpFromUserEvents.map(e => console.log(chalk.green(`${e.userAddress} has been removed to ${web3.utils.hexToUtf8(e.lockupName)} successfully!`))); + removeLockUpFromUserEvents.map(e => console.log(chalk.green(`${e._userAddress} has been removed to ${web3.utils.hexToUtf8(e._lockupName)} successfully!`))); break; case 'Delete this lockup type': let isEmpty = investors.length === 0; @@ -1053,7 +1055,7 @@ async function manageExistingLockups(lockupName) { let removeLockupTypeAction = currentTransferManager.methods.removeLockupType(lockupName); let removeLockupTypeReceipt = await common.sendTransaction(removeLockupTypeAction); let removeLockupTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeLockupTypeReceipt.logs, 'RemoveLockUpType'); - console.log(chalk.green(`${web3.utils.hexToUtf8(removeLockupTypeEvent.lockupName)} lockup type has been deleted successfully!`)); + console.log(chalk.green(`${web3.utils.hexToUtf8(removeLockupTypeEvent._lockupName)} lockup type has been deleted successfully!`)); } return; case 'RETURN': From 4054bcbec5cbade9af60a0eb8ea943f8fff9ef49 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 12 Dec 2018 08:53:43 -0300 Subject: [PATCH 399/582] Minor fix --- CLI/commands/sto_manager.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 9156b1fbd..c6757359c 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -316,7 +316,7 @@ async function addressesConfigUSDTieredSTO(usdTokenRaise) { defaultInput: Issuer.address }); if (addresses.wallet == "") addresses.wallet = Issuer.address; - + addresses.reserveWallet = readlineSync.question('Enter the address that will receive remaining tokens in the case the cap is not met (' + Issuer.address + '): ', { limit: function (input) { return web3.utils.isAddress(input); @@ -325,9 +325,9 @@ async function addressesConfigUSDTieredSTO(usdTokenRaise) { defaultInput: Issuer.address }); if (addresses.reserveWallet == "") addresses.reserveWallet = Issuer.address; - + let listOfAddress; - + if (usdTokenRaise) { addresses.usdToken = readlineSync.question('Enter the address (or multiple addresses separated by commas) of the USD stable coin(s) (' + usdToken.options.address + '): ', { limit: function (input) { @@ -344,17 +344,17 @@ async function addressesConfigUSDTieredSTO(usdTokenRaise) { addresses.usdToken = [usdToken.options.address]; } } else { - listOfAddress = ['0x0000000000000000000000000000000000000000'] - addresses.usdToken = ['0x0000000000000000000000000000000000000000']; + listOfAddress = [] + addresses.usdToken = []; } - + if ((usdTokenRaise) && (!await processArray(listOfAddress))) { console.log(chalk.yellow(`\nPlease, verify your stable coins addresses to continue with this process.\n`)) menu = true; } else { menu = false; } - + if (typeof addresses.usdToken === 'string') { addresses.usdToken = addresses.usdToken.split(",") } @@ -389,7 +389,7 @@ async function processAddress(array) { let list = []; for (const address of array) { let symbol = await checkSymbol(address); - list.push({"symbol": symbol, "address": address}) + list.push({ "symbol": symbol, "address": address }) } return list } @@ -666,7 +666,7 @@ async function usdTieredSTO_status(currentSTO) { displayWalletBalancePerType += ` Balance ${type}:\t\t ${walletBalance} ${type} (${walletBalanceUSD} USD)`; } - + balance = await getBalance(displayReserveWallet, gbl.constants.FUND_RAISE_TYPES[type]); let reserveWalletBalance = web3.utils.fromWei(balance); let reserveWalletBalanceUSD = web3.utils.fromWei(await currentSTO.methods.convertToUSD(gbl.constants.FUND_RAISE_TYPES[type], balance).call()); @@ -709,7 +709,7 @@ async function usdTieredSTO_status(currentSTO) { let displayRaiseType = raiseTypes.join(' - '); //If STO has stable coins, we list them one by one if (stableSymbols.length) { - displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.map((obj) => {return obj.symbol}).toString().replace(`,`,` - `)}` + displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.map((obj) => { return obj.symbol }).toString().replace(`,`, ` - `)}` } let now = Math.floor(Date.now() / 1000); @@ -759,9 +759,9 @@ async function usdTieredSTO_status(currentSTO) { async function checkStableBalance(walletAddress, stableAddress) { let stableCoin = common.connect(abis.erc20(), stableAddress); try { - return await stableCoin.methods.balanceOf(walletAddress).call(); + return await stableCoin.methods.balanceOf(walletAddress).call(); } catch (e) { - return "" + return "" } } From 34efb95ae345889edd69242a8ff0e90923fd94f5 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 12 Dec 2018 19:33:05 +0530 Subject: [PATCH 400/582] trying by adding some buffer in time travel --- test/y_volume_restriction_tm.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 260df3ef4..f84ef101c 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -1278,7 +1278,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should transfer the tokens freely after ending the default daily restriction", async() => { - await increaseTime(duration.days(3)); + await increaseTime(duration.days(3) + 10); //sell tokens upto the limit let tx = await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), {from: account_investor4}); assert.equal((tx.logs[0].args.value).toNumber(), web3.utils.toWei("5")); @@ -1313,6 +1313,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should transfer tokens on by investor 3 (comes under the Default restriction)", async() => { + await increaseTime(10); tempArray3.length = 0; let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); @@ -1336,7 +1337,6 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, 5); // Transfer tokens on another day - await increaseTime(duration.days(1)); //sell tokens upto the limit await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), {from: account_investor3}); @@ -1365,7 +1365,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should able to transfer tokens in the next rolling period", async() => { await increaseTime(duration.days(4.1)); - console.log(`Diff days: ${(latestTime() - ((await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3))[0]).toNumber()) / 86400}`) + console.log(`*** Diff days: ${(latestTime() - ((await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3))[0]).toNumber()) / 86400}`) for (let i = 0; i < 3; i++) { tempArray3.push(0); } From 4956441aa621e653b0f6ec53ca71f8f8661bccaa Mon Sep 17 00:00:00 2001 From: shuffledex Date: Wed, 12 Dec 2018 17:20:08 -0300 Subject: [PATCH 401/582] [WIP] CLI advances --- CLI/commands/transfer_manager.js | 171 +++++++++++++++++- .../Transfer/MATM/manualapproval_data.csv | 5 + .../MATM/revoke_manualapproval_data.csv | 2 + 3 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 CLI/data/Transfer/MATM/manualapproval_data.csv create mode 100644 CLI/data/Transfer/MATM/revoke_manualapproval_data.csv diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 0731503a5..ff3ec2b11 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -12,6 +12,8 @@ const { table } = require('table') // Constants const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelist_data.csv'; +const ADD_MANUAL_APPROVAL_DATA_CSV = './CLI/data/Transfer/MATM/manualapproval_data.csv'; +const REVOKE_MANUAL_APPROVAL_DATA_CSV = './CLI/data/Transfer/MATM/revoke_manualapproval_data.csv'; // App flow let tokenSymbol; @@ -571,8 +573,13 @@ async function manualApprovalTransferManager() { let options = [ 'Check manual approval', + 'List all active approvals', + 'List all active approvals corresponds to an address', 'Add manual approval', - 'Revoke manual approval' + 'Add manual approval in batches', + 'Revoke manual approval', + 'Revoke manual approval in batches', + 'Modify the existing manual approvals' ]; let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); @@ -598,12 +605,34 @@ async function manualApprovalTransferManager() { let manualApproval = await getManualApproval(from, to); if (manualApproval) { console.log(`Manual approval found!`); - console.log(`Allowance: ${web3.utils.fromWei(manualApproval.allowance)}`); - console.log(`Expiry time: ${moment.unix(manualApproval.expiryTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`Description: ${web3.utils.toAscii(manualApproval[2])}`); + console.log(`Allowance: ${web3.utils.fromWei(manualApproval[1])}`); + console.log(`Expiry time: ${moment.unix(manualApproval[0]).format('MMMM Do YYYY, HH:mm:ss')}`); } else { console.log(chalk.yellow(`There are no manual approvals from ${from} to ${to}.`)); } break; + case 'List all active approvals': + (await getApprovals()).forEach((a) => { + console.log(`From ${a.from} to ${a.to}\nAllowance: ${web3.utils.fromWei(a.allowance)}\nExpiry time: ${moment.unix(a.expiryTime).format('MMMM Do YYYY')}\nDescription: ${web3.utils.toAscii(a.description)}\n\n`); + }) + break; + case 'List all active approvals corresponds to an address': + let address = readlineSync.question('Enter the address: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let approvalsIndex = await getApprovalsToAnAddress(address); + if (!approvalsIndex.length) { + console.log(chalk.red(`\nThe address is not in the list\n`)) + } + approvalsIndex.forEach(async (i) => { + let a = await currentTransferManager.methods.approvals(i).call(); + console.log(`From ${a.from} to ${a.to}\nAllowance: ${web3.utils.fromWei(a.allowance)}\nExpiry time: ${moment.unix(a.expiryTime).format('MMMM Do YYYY')}\nDescription: ${web3.utils.toAscii(a.description)}\n\n`); + }) + break; case 'Add manual approval': from = readlineSync.question('Enter the address from which transfers will be approved: ', { limit: function (input) { @@ -617,18 +646,27 @@ async function manualApprovalTransferManager() { }, limitMessage: "Must be a valid address" }); + let description = readlineSync.question('Enter the description about the manual approval: ', { + limit: function (input) { + return input != "" && getBinarySize(input) < 33 + }, + limitMessage: "Description is required" + }); if (!await getManualApproval(from, to)) { let allowance = readlineSync.question('Enter the amount of tokens which will be approved: '); let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is allowed(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); - let addManualApprovalAction = currentTransferManager.methods.addManualApproval(from, to, web3.utils.toWei(allowance), expiryTime); + let addManualApprovalAction = currentTransferManager.methods.addManualApproval(from, to, web3.utils.toWei(allowance), expiryTime, web3.utils.fromAscii(description)); let addManualApprovalReceipt = await common.sendTransaction(addManualApprovalAction); let addManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualApprovalReceipt.logs, 'AddManualApproval'); console.log(chalk.green(`Manual approval has been added successfully!`)); } else { - console.log(chalk.red(`A manual approval already exists from ${from} to ${to}.Revoke it first if you want to add a new one.`)); + console.log(chalk.red(`A manual approval already exists from ${from} to ${to}. Revoke it first if you want to add a new one.`)); } break; + case 'Add manual approval in batches': + await addManualApproveInBatch(); + break; case 'Revoke manual approval': from = readlineSync.question('Enter the address from which transfers were approved: ', { limit: function (input) { @@ -651,20 +689,139 @@ async function manualApprovalTransferManager() { console.log(chalk.red(`Manual approval from ${from} to ${to} does not exist.`)); } break; + case 'Revoke manual approval in batches': + await revokeManualApproveInBatch(); + break; + case 'Modify the existing manual approvals': + let options = []; + (await getApprovals()).forEach((a) => { + options.push(`From ${a.from} to ${a.to} - Allowance: ${web3.utils.fromWei(a.allowance)} - Expiry time: ${moment.unix(a.expiryTime).format('MMMM Do YYYY')} - Description: ${web3.utils.toAscii(a.description)}\n\n`); + }) + let rowIndex = readlineSync.keyInSelect(options, 'Select a row to modify', { cancel: 'Return' }); + let optionSelected = options[rowIndex]; + console.log('Selected:', rowIndex != -1 ? optionSelected.description : 'Return', '\n'); + + let actualAllowance = optionSelected.allowance; + let actualExpiryTime = optionSelected.expiryTime; + let actualDescription = optionSelected.description; + + let newAllowance = readlineSync.question(`Enter the new amount of tokens which will be approved (${actualAllowance}): `, { + limit: function (input) { + if (input == "") { + return true + } + return parseFloat(input) > 0 + }, + limitMessage: "Amount must be bigger than 0" + }); + let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); + let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is allowed(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let description = readlineSync.question('Enter the description about the manual approval: ', { + limit: function (input) { + return input != "" && getBinarySize(input) < 33 + }, + limitMessage: "Description is required" + }); + break; + } +} + +async function getApprovals() { + let totalApprovals = await currentTransferManager.methods.getTotalApprovalsLength().call(); + let results = []; + for (let i = 0; i < totalApprovals; i++) { + results.push(await currentTransferManager.methods.approvals(i).call()); } + return results; +} + +async function getApprovalsToAnAddress(address) { + return await currentTransferManager.methods.getActiveApprovalsToUser(address).call(); } async function getManualApproval(_from, _to) { let result = null; - let manualApproval = await currentTransferManager.methods.manualApprovals(_from, _to).call(); - if (manualApproval.expiryTime !== "0") { + let manualApproval = await currentTransferManager.methods.getApprovalDetails(_from, _to).call(); + if (manualApproval[0] !== "0") { result = manualApproval; } return result; } +async function addManualApproveInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_MANUAL_APPROVAL_DATA_CSV}): `, { + defaultInput: ADD_MANUAL_APPROVAL_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => + web3.utils.isAddress(row[0]) && + web3.utils.isAddress(row[1]) && + parseFloat(row[2]) > 0 && + moment.unix(row[3]).isValid() && + typeof row[4] === 'string' && + getBinarySize(row[4]) < 33 + ); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [fromArray, toArray, allowanceArray, expiryArray, descriptionArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add manual approvals: \n\n`, descriptionArray[batch], '\n'); + descriptionArray[batch] = descriptionArray[batch].map(d => web3.utils.fromAscii(d)); + allowanceArray[batch] = allowanceArray[batch].map(a => web3.utils.toWei(new web3.utils.BN(a))); + let action = await currentTransferManager.methods.addManualApprovalMulti(fromArray[batch], toArray[batch], allowanceArray[batch], expiryArray[batch], descriptionArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add manual approval transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function revokeManualApproveInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REVOKE_MANUAL_APPROVAL_DATA_CSV}): `, { + defaultInput: REVOKE_MANUAL_APPROVAL_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => + web3.utils.isAddress(row[0]) && + web3.utils.isAddress(row[1]) + ); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [fromArray, toArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to revoke manual approvals`, '\n'); + let action = await currentTransferManager.methods.revokeManualApprovalMulti(fromArray[batch], toArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Revoke manual approval transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +function getBinarySize(string) { + return Buffer.byteLength(string, 'utf8'); +} + async function countTransferManager() { console.log(chalk.blue(`Count Transfer Manager at ${currentTransferManager.options.address}`), '\n'); diff --git a/CLI/data/Transfer/MATM/manualapproval_data.csv b/CLI/data/Transfer/MATM/manualapproval_data.csv new file mode 100644 index 000000000..48d5f2a54 --- /dev/null +++ b/CLI/data/Transfer/MATM/manualapproval_data.csv @@ -0,0 +1,5 @@ +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0x1DDF4FDBB8eaDB5dD6EeC6edB1A91a0926940a33,10,12/12/2019,Lorem ipsum dolor sit amet +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0xB849AC17d881183800300A31f022d3fe4B82D457,20,12/12/2019,Consectetur adipiscing elit +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0xD122e1951cfb337D5CC8bc5aDECC0eb66ffb4B80,25,12/12/2019,Pellentesque ultrices eros +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0x1D9127821A244b64852E8Da431bb389B81710985,20,12/12/2019,Non eleifend ante tincidunt eget +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0x42dc79375E511Fb7Ee17fF50417141bAE5E5698E,10,12/12/2019,Sed ante arcu \ No newline at end of file diff --git a/CLI/data/Transfer/MATM/revoke_manualapproval_data.csv b/CLI/data/Transfer/MATM/revoke_manualapproval_data.csv new file mode 100644 index 000000000..b398caf02 --- /dev/null +++ b/CLI/data/Transfer/MATM/revoke_manualapproval_data.csv @@ -0,0 +1,2 @@ +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0x1DDF4FDBB8eaDB5dD6EeC6edB1A91a0926940a33 +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0xB849AC17d881183800300A31f022d3fe4B82D457 \ No newline at end of file From bc0b62ebb7f0ede95ba20d1a8e6a2ac7203c66a6 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 13 Dec 2018 10:58:25 +0530 Subject: [PATCH 402/582] modify function changes --- .../TransferManager/VolumeRestrictionTM.sol | 62 ++++++++++++------- test/y_volume_restriction_tm.js | 40 ++++++------ 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index f619f2427..c452b4663 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -15,7 +15,16 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Emit when the token holder is added/removed from the exemption list event ChangedExemptWalletList(address indexed _wallet, bool _change); // Emit when the new individual restriction is added corresponds to new token holders - event AddNewIndividualRestriction( + event AddIndividualRestriction( + address indexed _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when the new daily (Individual) restriction is added + event AddIndividualDailyRestriction( address indexed _holder, uint256 _allowedTokens, uint256 _startTime, @@ -32,25 +41,25 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _endTime, uint256 _typeOfRestriction ); - // Emit when the new global restriction is added - event AddDefaultRestriction( + // Emit when individual daily restriction get modified + event ModifyIndividualDailyRestriction( + address indexed _holder, uint256 _allowedTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, uint256 _typeOfRestriction ); - // Emit when the new daily (Default) restriction is added - event AddDefaultDailyRestriction( + // Emit when the new global restriction is added + event AddDefaultRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, uint256 _typeOfRestriction ); - // Emit when the new daily (Individual) restriction is added - event AddIndividualDailyRestriction( - address _holder, + // Emit when the new daily (Default) restriction is added + event AddDefaultDailyRestriction( uint256 _allowedTokens, uint256 _startTime, uint256 _rollingPeriodInDays, @@ -74,9 +83,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _typeOfRestriction ); // Emit when the individual restriction gets removed - event IndividualRestrictionRemoved(address _holder); + event IndividualRestrictionRemoved(address indexed _holder); // Emit when individual daily restriction removed - event IndividualDailyRestrictionRemoved(address _holder); + event IndividualDailyRestrictionRemoved(address indexed _holder); // Emit when the default restriction gets removed event DefaultRestrictionRemoved(); // Emit when the daily default restriction gets removed @@ -196,7 +205,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _endTime, RestrictionType(_restrictionType) ); - emit AddNewIndividualRestriction( + emit AddIndividualRestriction( _holder, _allowedTokens, startTime, @@ -568,8 +577,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice Use to modify the existing individual daily restriction for a given token holder - * @dev It is possible to intialize the dailyLatestTradedTime by 0 for the given holder then - * changing of startTime will affect the 24 hrs span. i.e if in earlier restriction days start with + * @dev Changing of startTime will affect the 24 hrs span. i.e if in earlier restriction days start with * morning and end on midnight while after the change day may start with afternoon and end with other day afternoon * @param _holder Address of the token holder, whom restriction will be implied * @param _allowedTokens Amount of tokens allowed to be trade for a given address. @@ -611,8 +619,12 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { startTime = now; } _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); - // Initializing the value with 0 to allow the trade with new startTime of the restriction - userToBucket[_holder].dailyLastTradedDayTime = 0; + // If old startTime is already passed then new startTime should be greater than or equal to the + // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. + if (individualDailyRestriction[_holder].startTime <= now) + require(startTime >= individualDailyRestriction[_holder].startTime, "Invalid StartTime"); + else + require(startTime >= now); individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, startTime, @@ -620,7 +632,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _endTime, RestrictionType(_restrictionType) ); - emit ModifyDefaultDailyRestriction( + emit ModifyIndividualDailyRestriction( + _holder, _allowedTokens, startTime, 1, @@ -743,9 +756,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice Use to modify the daily default restriction for all token holder - * @dev If the start time is modified then it only affect the startTime of the restriction - * while it may carries the earlier dailyLatestStartDayTime value. Not possible to initialize the value - * of dailyLatestStartDayTime for every holder to 0. + * @dev Changing of startTime will affect the 24 hrs span. i.e if in earlier restriction days start with + * morning and end on midnight while after the change day may start with afternoon and end with other day afternoon. * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. @@ -763,8 +775,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 startTime = _startTime; if (_startTime == 0) { startTime = now; - } + } _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); + // If old startTime is already passed then new startTime should be greater than or equal to the + // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. + if (defaultDailyRestriction.startTime <= now) + require(startTime >= defaultDailyRestriction.startTime, "Invalid StartTime"); + else + require(startTime >= now); defaultDailyRestriction = VolumeRestriction( _allowedTokens, startTime, @@ -904,7 +922,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // the total amount get traded on a particular day (~ _fromTime) if ( now <= restriction.endTime && now >= restriction.startTime) { uint256 txSumOfDay = 0; - if (dailyLastTradedDayTime == 0) + if (dailyLastTradedDayTime == 0 || dailyLastTradedDayTime < restriction.startTime) // This if condition will be executed when the individual daily restriction executed first time dailyLastTradedDayTime = restriction.startTime.add(BokkyPooBahsDateTimeLibrary.diffDays(restriction.startTime, now).mul(1 days)); else if (now.sub(dailyLastTradedDayTime) >= 1 days) @@ -1133,7 +1151,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _user Address of the token holder * @param _at Timestamp */ - function getTotalTradeByuser(address _user, uint256 _at) external view returns(uint256) { + function getTotalTradedByUser(address _user, uint256 _at) external view returns(uint256) { return bucket[_user][_at]; } diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index f84ef101c..1075a64e4 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -82,9 +82,9 @@ contract('VolumeRestrictionTransferManager', accounts => { SumOfLastPeriod: ${data[1].dividedBy(new BigNumber(10).pow(18)).toNumber()} Days Covered: ${data[2].toNumber()} Latest timestamp daily: ${data[3].toNumber()} - Individual Total Trade on latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[0])) + Individual Total Trade on latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[0])) .dividedBy(new BigNumber(10).pow(18)).toNumber()} - Individual Total Trade on daily latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradeByuser.call(account, data[3])) + Individual Total Trade on daily latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[3])) .dividedBy(new BigNumber(10).pow(18)).toNumber()} `) } @@ -630,7 +630,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor1); assert.equal( - (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0])) + (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor1, data[0])) .dividedBy(new BigNumber(10).pow(18)).toNumber(), 0.3 ); @@ -751,7 +751,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(newData[3].toNumber(), data[3].toNumber()); assert.equal(data[3].toNumber(), startTime); - assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[3])) + assert.equal((await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[3])) .dividedBy(new BigNumber(10).pow(18)).toNumber(), 6); }); @@ -774,7 +774,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); assert.equal(data[3].toNumber(), startTime + duration.days(1)); - assert.equal((await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[3])) + assert.equal((await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[3])) .dividedBy(new BigNumber(10).pow(18)).toNumber(), 2); }); @@ -823,7 +823,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor1); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor1, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor1, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -881,7 +881,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -920,7 +920,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -970,7 +970,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1036,7 +1036,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1061,7 +1061,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1093,7 +1093,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1132,7 +1132,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1161,7 +1161,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1192,7 +1192,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1266,7 +1266,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor4, data[3].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor4, data[3].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1326,7 +1326,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1346,7 +1346,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1382,7 +1382,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes @@ -1439,7 +1439,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await print(data, account_investor3); // get the trade amount using the timestamp - let amt = (await I_VolumeRestrictionTM.getTotalTradeByuser.call(account_investor3, data[0].toNumber())) + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes From 6444f0d43178c52d3ea7488bc6fe29ccf77d6d32 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:13:02 +0530 Subject: [PATCH 403/582] WIP --- .circleci/config.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 26383b3bd..fe65e9fca 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - - run: yarn + - run: yarn install - run: sudo npm i truffle -g - run: node --version - run: truffle version @@ -23,7 +23,7 @@ jobs: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - - run: yarn + - run: yarn install - run: sudo npm i truffle -g - run: node --version - run: truffle version @@ -39,7 +39,7 @@ jobs: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - - run: yarn + - run: yarn install - run: sudo npm i truffle -g - run: node --version - run: truffle version @@ -55,7 +55,7 @@ jobs: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - - run: yarn + - run: yarn install - run: sudo npm i truffle -g - run: node --version - run: truffle version @@ -68,7 +68,5 @@ workflows: version: 2 build-test-coverage-docs: jobs: - - build - test - - coverage - - docs \ No newline at end of file + - coverage \ No newline at end of file From 7ed52080b5ec7224e15bc07d9dbdb2567ba2ce0e Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:30:49 +0530 Subject: [PATCH 404/582] CircleCI changes --- .circleci/config.yml | 17 +++++++++++++++-- scripts/coverage.sh | 2 +- scripts/test.sh | 25 ++++++++++--------------- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fe65e9fca..cff30c3ee 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -66,7 +66,20 @@ jobs: - node_modules workflows: version: 2 - build-test-coverage-docs: + commit: jobs: + - build - test - - coverage \ No newline at end of file + daily-coverage: + triggers: + - schedule: + cron: "0 0 * * *" + jobs: + - coverage + docs: + filters: + branches: + only: + - master + jobs: + - docs \ No newline at end of file diff --git a/scripts/coverage.sh b/scripts/coverage.sh index e42ed6a84..5d1e2a24e 100755 --- a/scripts/coverage.sh +++ b/scripts/coverage.sh @@ -2,4 +2,4 @@ rm -rf flat -TRAVIS_PULL_REQUEST=true scripts/test.sh \ No newline at end of file +COVERAGE=true scripts/test.sh \ No newline at end of file diff --git a/scripts/test.sh b/scripts/test.sh index 6dd3ce95a..fa569144f 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -19,11 +19,7 @@ cleanup() { fi } -if ! [ -z "${TRAVIS_PULL_REQUEST+x}" ] && [ "$TRAVIS_PULL_REQUEST" != false ]; then - testrpc_port=8545 -else - testrpc_port=8545 -fi +testrpc_port=8545 testrpc_running() { nc -z localhost "$testrpc_port" @@ -60,20 +56,19 @@ start_testrpc() { --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501209,1000000000000000000000000" ) - if ! [ -z "${TRAVIS_PULL_REQUEST+x}" ] && [ "$TRAVIS_PULL_REQUEST" != false ]; then + if [ "$COVERAGE" = true ]; then node_modules/.bin/testrpc-sc --gasLimit 0xfffffffffff --port "$testrpc_port" "${accounts[@]}" > /dev/null & else node_modules/.bin/ganache-cli --gasLimit 8000000 "${accounts[@]}" > /dev/null & fi - testrpc_pid=$! } if testrpc_running; then echo "Using existing testrpc instance" - # Do not start ethereum bridge unless it is a cron job from travis - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then + # Do not start ethereum bridge unless it is a cron job + if [ "$CIRCLE_CI_CRON" = true ]; then bridge_running if bridge_running; then echo "Using existing ethereum-bridge instance" @@ -85,23 +80,23 @@ if testrpc_running; then else echo "Starting our own testrpc instance" start_testrpc - # Do not start ethereum bridge unless it is a cron job from travis - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then + # Do not start ethereum bridge unless it is a cron job + if [ "$CIRCLE_CI_CRON" = true ]; then echo "Starting our own ethereum-bridge instance" sleep 10 start_bridge fi fi -if ! [ -z "${TRAVIS_PULL_REQUEST+x}" ] && [ "$TRAVIS_PULL_REQUEST" != false ]; then +if [ "$COVERAGE" = true ]; then curl -o node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js node_modules/.bin/solidity-coverage - if [ "$CONTINUOUS_INTEGRATION" = true ]; then + if [ "$CI" = true ]; then cat coverage/lcov.info | node_modules/.bin/coveralls fi else - # Do not run a_poly_oracle,js tests unless it is a cron job from travis - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then + # Do not run a_poly_oracle,js tests unless it is a cron job + if [ "$CIRCLE_CI_CRON" = true ]; then node_modules/.bin/truffle test `ls test/*.js` else node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js` From 6081cc8979ac19ae569bb5c6b40735f7357085ec Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:33:29 +0530 Subject: [PATCH 405/582] CircleCI changes --- .circleci/config.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index cff30c3ee..450b659a2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -74,6 +74,12 @@ workflows: triggers: - schedule: cron: "0 0 * * *" + filters: + branches: + only: + - master + - development-2.1.0 + - development-3.0.0 jobs: - coverage docs: From 67ceb1b6b580f6239ccf2b5d1aa01388e4aec703 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:36:04 +0530 Subject: [PATCH 406/582] CircleCI changes --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 450b659a2..d74a38924 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -83,9 +83,9 @@ workflows: jobs: - coverage docs: - filters: - branches: - only: - - master jobs: - - docs \ No newline at end of file + - docs: + filters: + branches: + only: + - master \ No newline at end of file From a4facea3d032c49016114884d821bb13cf11e064 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:47:32 +0530 Subject: [PATCH 407/582] Badge --- .circleci/config.yml | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d74a38924..421f32002 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -70,6 +70,7 @@ workflows: jobs: - build - test + - coverage daily-coverage: triggers: - schedule: diff --git a/README.md b/README.md index 8c5ae0a4e..c810f039a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/PolymathNetwork/polymath-core.svg?branch=master)](https://travis-ci.org/PolymathNetwork/polymath-core) +[![CircleCI](https://circleci.com/gh/maxsam4/polymath-core.svg?style=svg)](https://circleci.com/gh/maxsam4/polymath-core) [![Coverage Status](https://coveralls.io/repos/github/PolymathNetwork/polymath-core/badge.svg?branch=master)](https://coveralls.io/github/PolymathNetwork/polymath-core?branch=master) [![Gitter](https://img.shields.io/badge/chat-gitter-green.svg)](https://gitter.im/PolymathNetwork/Lobby) [![Telegram](https://img.shields.io/badge/50k+-telegram-blue.svg)](https://gitter.im/PolymathNetwork/Lobby) From adac3a5e8395501a3cc9c809b139f2c01eace109 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 14:18:02 +0530 Subject: [PATCH 408/582] Store test results --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 421f32002..105d4b9aa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -32,6 +32,8 @@ jobs: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules + - store_test_results: + path: test-results coverage: docker: - image: circleci/node:8 @@ -48,6 +50,9 @@ jobs: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules + - store_test_results: + path: test-results + docs: docker: - image: circleci/node:8 From 084d04743cc0893cc51749f0803560666dbd7c6f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 14:35:04 +0530 Subject: [PATCH 409/582] Removed coverage from commit workflow --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 105d4b9aa..de4dcba6b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -75,7 +75,6 @@ workflows: jobs: - build - test - - coverage daily-coverage: triggers: - schedule: From 62d4bb5e2430a8d0698389686eed24d2cc8da76e Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 12 Dec 2018 16:31:26 -0300 Subject: [PATCH 410/582] CLI - WIP VolumeRestrictionTM support --- CLI/commands/helpers/contract_abis.js | 5 + CLI/commands/transfer_manager.js | 339 +++++++++++++++++++++++++- 2 files changed, 338 insertions(+), 6 deletions(-) diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index 8a551b70b..86b42cea7 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -10,6 +10,7 @@ let generalTransferManagerABI; let manualApprovalTransferManagerABI; let countTransferManagerABI; let percentageTransferManagerABI; +let volumeRestrictionTMABI; let generalPermissionManagerABI; let polyTokenABI; let cappedSTOFactoryABI; @@ -35,6 +36,7 @@ try { manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ManualApprovalTransferManager.json').toString()).abi; countTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/CountTransferManager.json').toString()).abi; percentageTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/PercentageTransferManager.json').toString()).abi; + volumeRestrictionTMABI = JSON.parse(require('fs').readFileSync('./build/contracts/VolumeRestrictionTM.json').toString()).abi; generalPermissionManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralPermissionManager.json').toString()).abi; polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; @@ -88,6 +90,9 @@ module.exports = { percentageTransferManager: function () { return percentageTransferManagerABI; }, + volumeRestrictionTM: function () { + return volumeRestrictionTMABI; + }, generalPermissionManager: function () { return generalPermissionManagerABI; }, diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 16af0e34e..45a253025 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -13,6 +13,8 @@ const { table } = require('table') const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelist_data.csv'; +const RESTRICTION_TYPES = ['Fixed', 'Percentage']; + // App flow let tokenSymbol; let securityToken; @@ -211,6 +213,11 @@ async function configExistingModules(tmModules) { currentTransferManager.setProvider(web3.currentProvider); await percentageTransferManager(); break; + case 'VolumeRestrictionTM': + currentTransferManager = new web3.eth.Contract(abis.volumeRestrictionTM(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await volumeRestrictionTM(); + break; case 'SingleTradeVolumeRestrictionTM': //currentTransferManager = new web3.eth.Contract(abis.singleTradeVolumeRestrictionTM(), tmModules[index].address); //currentTransferManager.setProvider(web3.currentProvider); @@ -412,10 +419,10 @@ async function generalTransferManager() { limitMessage: "Must be a valid address" }); let now = Math.floor(Date.now() / 1000); - let fromTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens(now = ${now}): `, { defaultInput: now }); - let toTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others(now = ${now}): `, { defaultInput: now }); + let fromTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens (now = ${now}): `, { defaultInput: now }); + let toTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (now = ${now}): `, { defaultInput: now }); let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated(after that investor need to do re - KYC) (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated (after that investor need to do re - KYC) (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); @@ -617,7 +624,7 @@ async function manualApprovalTransferManager() { if (!await getManualApproval(from, to)) { let allowance = readlineSync.question('Enter the amount of tokens which will be approved: '); let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is allowed(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let expiryTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) until which the transfer is allowed (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); let addManualApprovalAction = currentTransferManager.methods.addManualApproval(from, to, web3.utils.toWei(allowance), expiryTime); let addManualApprovalReceipt = await common.sendTransaction(addManualApprovalAction); let addManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualApprovalReceipt.logs, 'AddManualApproval'); @@ -685,7 +692,7 @@ async function manualApprovalTransferManager() { }); if (!await getManualBlocking(from, to)) { let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is blocked(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let expiryTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) until which the transfer is blocked (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); let addManualBlockingAction = currentTransferManager.methods.addManualBlocking(from, to, expiryTime); let addManualBlockingReceipt = await common.sendTransaction(addManualBlockingAction); let addManualBlockingEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualBlockingReceipt.logs, 'AddManualBlocking'); @@ -869,6 +876,326 @@ async function percentageTransferManager() { } } +async function volumeRestrictionTM() { + console.log('\n', chalk.blue(`Volume Restriction Transfer Manager at ${currentTransferManager.options.address}`, '\n')); + + let defaultDailyRestriction = await currentTransferManager.methods.defaultDailyRestriction().call(); + let hasDefaultDailyRestriction = parseInt(defaultDailyRestriction.startTime) !== 0; + let defaultRestriction = await currentTransferManager.methods.defaultRestriction().call(); + let hasDefaultRestriction = parseInt(defaultRestriction.startTime) !== 0; + + console.log(`- Default daily restriction: ${hasDefaultDailyRestriction ? '' : 'None'}`); + if (hasDefaultDailyRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[defaultDailyRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${defaultDailyRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(defaultDailyRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(defaultDailyRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(defaultDailyRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${defaultDailyRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(defaultDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + } + console.log(`- Default restriction: ${hasDefaultRestriction ? '' : 'None'} `); + if (hasDefaultRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[defaultRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${defaultRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(defaultRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(defaultRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(defaultRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${defaultRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(defaultRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + } + + let options = [ + 'Change exempt wallet', + 'Change default restrictions', + 'Change individual restrictions', + 'Explore account', + 'Operate with multiple restrictions' + ]; + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Change exempt wallet': + await changeExemptWallet(); + break; + case 'Change default restrictions': + await changeDefaultRestrictions(hasDefaultDailyRestriction, hasDefaultRestriction); + break; + case 'Change individual restrictions': + await changeIndividualRestrictions(); + break; + case 'Explore account': + await exploreAccount(); + break; + case 'Operate with multiple restrictions': + await operateWithMultipleRestrictions(); + break; + case 'RETURN': + return; + } + + await volumeRestrictionTM(); +} + +async function changeExemptWallet() { + let options = [ + 'Add exempt wallet', + 'Remove exempt wallet' + ]; + + let change; + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add exempt wallet': + change = true; + break; + case 'Remove exempt wallet': + change = false; + break; + case 'RETURN': + return; + } + + let wallet = readlineSync.question('Enter the wallet to change: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let changeExemptWalletAction = currentTransferManager.methods.changeExemptWalletList(wallet, change); + let changeExemptWalletReceipt = await common.sendTransaction(changeExemptWalletAction); + let changeExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeExemptWalletReceipt.logs, 'ChangedExemptWalletList'); + console.log(chalk.green(`${changeExemptWalletEvent._wallet} has been ${changeExemptWalletEvent._change ? `added to` : `removed from`} exempt wallets successfully!`)); +} + +async function changeDefaultRestrictions(hasDefaultDailyRestriction, hasDefaultRestriction) { + let options = []; + if (!hasDefaultDailyRestriction) { + options.push('Add default daily restriction'); + } else { + options.push('Modify default daily restriction', 'Remove default daily restriction'); + } + + if (!hasDefaultRestriction) { + options.push('Add default restriction'); + } else { + options.push('Modify default restriction', 'Remove default restriction'); + } + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add default daily restriction': + let defaultDailyRestrictoToAdd = inputRestrictionData(true); + let addDefaultDailyRestrictionAction = currentTransferManager.methods.addDefaultDailyRestriction( + defaultDailyRestrictoToAdd.allowedTokens, + defaultDailyRestrictoToAdd.startTime, + defaultDailyRestrictoToAdd.endTime, + defaultDailyRestrictoToAdd.restrictionType + ); + let addDefaultDailyRestrictionReceipt = await common.sendTransaction(addDefaultDailyRestrictionAction); + let addDefaultDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addDefaultDailyRestrictionReceipt.logs, 'AddDefaultDailyRestriction'); + console.log(chalk.green(`Daily default restriction has been added successfully!`)); + break; + case 'Modify default daily restriction': + let defaultDailyRestrictoToModify = inputRestrictionData(true); + let modifyDefaultDailyRestrictionAction = currentTransferManager.methods.modifyDefaultDailyRestriction( + defaultDailyRestrictoToModify.allowedTokens, + defaultDailyRestrictoToModify.startTime, + defaultDailyRestrictoToModify.endTime, + defaultDailyRestrictoToModify.restrictionType + ); + let modifyDefaultDailyRestrictionReceipt = await common.sendTransaction(modifyDefaultDailyRestrictionAction); + let modifyDefaultDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyDefaultDailyRestrictionReceipt.logs, 'ModifyDefaultDailyRestriction'); + console.log(chalk.green(`Daily default restriction has been modified successfully!`)); + break; + case 'Remove default daily restriction': + let removeDefaultDailyRestrictionAction = currentTransferManager.methods.removeDefaultDailyRestriction(); + let removeDefaultDailyRestrictionReceipt = await common.sendTransaction(removeDefaultDailyRestrictionAction); + let removeDefaultDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeDefaultDailyRestrictionReceipt.logs, 'DefaultDailyRestrictionRemoved'); + console.log(chalk.green(`Daily default restriction has been removed successfully!`)); + break; + case 'Add default restriction': + let defaultRestrictoToAdd = inputRestrictionData(false); + let addDefaultRestrictionAction = currentTransferManager.methods.addDefaultRestriction( + defaultRestrictoToAdd.allowedTokens, + defaultRestrictoToAdd.startTime, + defaultRestrictoToAdd.rollingPeriodInDays, + defaultRestrictoToAdd.endTime, + defaultRestrictoToAdd.restrictionType + ); + let addDefaultRestrictionReceipt = await common.sendTransaction(addDefaultRestrictionAction); + let addDefaultRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addDefaultRestrictionReceipt.logs, 'AddDefaultRestriction'); + console.log(chalk.green(`Default restriction has been added successfully!`)); + break; + case 'Modify default restriction': + let defaultRestrictoToModify = inputRestrictionData(false); + let modifyDefaultRestrictionAction = currentTransferManager.methods.modifyDefaultRestriction( + defaultRestrictoToModify.allowedTokens, + defaultRestrictoToModify.startTime, + defaultRestrictoToModify.rollingPeriodInDays, + defaultRestrictoToModify.endTime, + defaultRestrictoToModify.restrictionType + ); + let modifyDefaultRestrictionReceipt = await common.sendTransaction(modifyDefaultRestrictionAction); + let modifyDefaultRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyDefaultRestrictionReceipt.logs, 'ModifyDefaultRestriction'); + console.log(chalk.green(`Default restriction has been modified successfully!`)); + break; + case 'Remove default restriction': + let removeDefaultRestrictionAction = currentTransferManager.methods.removeDefaultRestriction(); + let removeDefaultRestrictionReceipt = await common.sendTransaction(removeDefaultRestrictionAction); + let removeDefaultRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeDefaultRestrictionReceipt.logs, 'DefaultRestrictionRemoved'); + console.log(chalk.green(`Default restriction has been removed successfully!`)); + break; + } +} + +async function changeIndividualRestrictions() { + let holder = readlineSync.question('Enter the address of the token holder, whom restriction will be implied: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + + let currentDailyRestriction = await currentTransferManager.methods.individualDailyRestriction(holder).call(); + let hasDailyRestriction = parseInt(currentDailyRestriction.startTime) !== 0; + let currentRestriction = await currentTransferManager.methods.individualRestriction(holder).call(); + let hasRestriction = parseInt(currentRestriction.startTime) !== 0; + + console.log(`*** Current restrictions for ${holder} ***`, '\n'); + + console.log(`- Daily restriction: ${hasDailyRestriction ? '' : 'None'}`); + if (hasDailyRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[currentDailyRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${currentDailyRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(currentDailyRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(currentDailyRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(currentDailyRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${currentDailyRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(currentDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + } + console.log(`- Default daily restriction: ${hasRestriction ? '' : 'None'} `); + if (hasRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[currentRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${currentRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(currentRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(currentRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(currentRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${currentRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(currentRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + } + + let options = []; + if (!hasDailyRestriction) { + options.push('Add individual daily restriction'); + } else { + options.push('Modify individual daily restriction', 'Remove individual daily restriction'); + } + + if (!hasRestriction) { + options.push('Add individual restriction'); + } else { + options.push('Modify individual restriction', 'Remove individual restriction'); + } + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add individual daily restriction': + let dailyRestrictoToAdd = inputRestrictionData(true); + let addDailyRestrictionAction = currentTransferManager.methods.addIndividualDailyRestriction( + holder, + dailyRestrictoToAdd.allowedTokens, + dailyRestrictoToAdd.startTime, + dailyRestrictoToAdd.endTime, + dailyRestrictoToAdd.restrictionType + ); + let addDailyRestrictionReceipt = await common.sendTransaction(addDailyRestrictionAction); + let addDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addDailyRestrictionReceipt.logs, 'AddIndividualDailyRestriction'); + console.log(chalk.green(`Daily restriction for ${addDailyRestrictionEvent._holder} has been added successfully!`)); + break; + case 'Modify individual daily restriction': + let dailyRestrictoToModify = inputRestrictionData(true); + let modifyDailyRestrictionAction = currentTransferManager.methods.modifyIndividualDailyRestriction( + holder, + dailyRestrictoToModify.allowedTokens, + dailyRestrictoToModify.startTime, + dailyRestrictoToModify.endTime, + dailyRestrictoToModify.restrictionType + ); + let modifyDailyRestrictionReceipt = await common.sendTransaction(modifyDailyRestrictionAction); + let modifyDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyDailyRestrictionReceipt.logs, 'ModifyIndividualDailyRestriction'); + console.log(chalk.green(`Daily restriction for ${modifyDailyRestrictionEvent._holder} has been modified successfully!`)); + break; + case 'Remove individual daily restriction': + let removeDailyRestrictionAction = currentTransferManager.methods.removeIndividualDailyRestriction(holder); + let removeDailyRestrictionReceipt = await common.sendTransaction(removeDailyRestrictionAction); + let removeDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeDailyRestrictionReceipt.logs, 'IndividualDailyRestrictionRemoved'); + console.log(chalk.green(`Daily restriction for ${removeDailyRestrictionEvent._holder} has been removed successfully!`)); + break; + case 'Add individual restriction': + let restrictoToAdd = inputRestrictionData(false); + let addRestrictionAction = currentTransferManager.methods.addIndividualRestriction( + holder, + restrictoToAdd.allowedTokens, + restrictoToAdd.startTime, + restrictoToAdd.rollingPeriodInDays, + restrictoToAdd.endTime, + restrictoToAdd.restrictionType + ); + let addRestrictionReceipt = await common.sendTransaction(addRestrictionAction); + let addRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addRestrictionReceipt.logs, 'AddIndividualRestriction'); + console.log(chalk.green(`Restriction for ${addRestrictionEvent._holder} has been added successfully!`)); + break; + case 'Modify individual restriction': + let restrictoToModify = inputRestrictionData(false); + let modifyRestrictionAction = currentTransferManager.methods.modifyIndividualRestriction( + holder, + restrictoToModify.allowedTokens, + restrictoToModify.startTime, + restrictoToModify.rollingPeriodInDays, + restrictoToModify.endTime, + restrictoToModify.restrictionType + ); + let modifyRestrictionReceipt = await common.sendTransaction(modifyRestrictionAction); + let modifyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyRestrictionReceipt.logs, 'ModifyIndividualRestriction'); + console.log(chalk.green(`Restriction for ${modifyRestrictionEvent._holder} has been modified successfully!`)); + break; + case 'Remove individual restriction': + let removeRestrictionAction = currentTransferManager.methods.removeIndividualRestriction(holder); + let removeRestrictionReceipt = await common.sendTransaction(removeRestrictionAction); + let removeRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeRestrictionReceipt.logs, 'IndividualRestrictionRemoved'); + console.log(chalk.green(`Restriction for ${removeRestrictionEvent._holder} has been removed successfully!`)); + break; + case 'RETURN': + return; + } +} + +function inputRestrictionData(isDaily) { + let restriction = {}; + restriction.restrictionType = readlineSync.keyInSelect(RESTRICTION_TYPES, 'How do you want to set the allowance? ', { cancel: false }); + if (restriction.restrictionType == RESTRICTION_TYPES.indexOf('Fixed')) { + restriction.allowedTokens = web3.utils.toWei(readlineSync.questionInt(`Enter the maximum amount of tokens allowed to be traded every ${isDaily ? 'day' : 'rolling period'}: `).toString()); + } else { + restriction.allowedTokens = toWeiPercentage(readlineSync.questionInt(`Enter the maximum percentage of total supply allowed to be traded every ${isDaily ? 'day' : 'rolling period'}: `).toString()); + } + if (isDaily) { + restriction.rollingPeriodInDays = 1; + } else { + restriction.rollingPeriodInDays = readlineSync.questionInt(`Enter the rolling period in days (10 days): `, { defaultInput: 10 }); + } + restriction.startTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) at which restriction get into effect (now = 0): `, { defaultInput: 0 }); + let oneMonthFromNow = Math.floor(Date.now() / 1000) + gbl.constants.DURATION.days(30); + restriction.endTime = readlineSync.question(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (1 week from now = ${oneMonthFromNow}): `, { + limit: function (input) { + return input > restriction.startTime + gbl.constants.DURATION.days(restriction.rollingPeriodInDays); + }, + limitMessage: 'Must be greater than startTime + rolling period', + defaultInput: oneMonthFromNow + }); + return restriction; +} + async function singleTradeVolumeRestrictionTM() { console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address} `)); console.log(); @@ -1178,7 +1505,7 @@ async function selectToken() { async function logTotalInvestors() { let investorsCount = await securityToken.methods.getInvestorCount().call(); - console.log(chalk.yellow(`Total investors at the moment: ${investorsCount}`)); + console.log(chalk.yellow(`Total investors at the moment: ${investorsCount} `)); } async function logBalance(from, totalSupply) { From 70f6cac5b6a9076982db461479779326f0c57367 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 12 Dec 2018 16:33:48 -0300 Subject: [PATCH 411/582] CLI - Removed STVR TM from CLI --- CLI/commands/transfer_manager.js | 248 ------------------------------- 1 file changed, 248 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 45a253025..4df500208 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -218,24 +218,6 @@ async function configExistingModules(tmModules) { currentTransferManager.setProvider(web3.currentProvider); await volumeRestrictionTM(); break; - case 'SingleTradeVolumeRestrictionTM': - //currentTransferManager = new web3.eth.Contract(abis.singleTradeVolumeRestrictionTM(), tmModules[index].address); - //currentTransferManager.setProvider(web3.currentProvider); - //await singleTradeVolumeRestrictionTM(); - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); - break; - case 'LookupVolumeRestrictionTM': - //await lookupVolumeRestrictionTM(); - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); - break; } } @@ -267,56 +249,6 @@ async function addTransferManagerModule() { let configurePercentageTM = abis.percentageTransferManager().find(o => o.name === 'configure' && o.type === 'function'); bytes = web3.eth.abi.encodeFunctionCall(configurePercentageTM, [maxHolderPercentage, allowPercentagePrimaryIssuance]); break; - case 'SingleTradeVolumeRestrictionTM': - /* - let isTransferLimitInPercentage = !!readlineSync.keyInSelect(['In tokens', 'In percentage'], 'How do you want to set the transfer limit? ', {cancel: false}); - let globalTransferLimitInPercentageOrToken; - if (isTransferLimitInPercentage) { - globalTransferLimitInPercentageOrToken = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { - limit: function(input) { - return (parseInt(input) > 0 && parseInt(input) <= 100); - }, - limitMessage: "Must be greater than 0 and less than 100" - })); - } else { - globalTransferLimitInPercentageOrToken = web3.utils.toWei(readlineSync.question('Enter the amount of tokens for default limit: ', { - limit: function(input) { - return parseInt(input) > 0; - }, - limitMessage: "Must be greater than 0" - })); - } - let allowPrimaryIssuance = readlineSync.keyInYNStrict(`Do you want to allow all primary issuance transfers? `); - bytes = web3.eth.abi.encodeFunctionCall( { - name: 'configure', - type: 'function', - inputs: [ - { - type: 'bool', - name: '_isTransferLimitInPercentage' - },{ - type: 'uint256', - name: '_globalTransferLimitInPercentageOrToken' - },{ - type: 'bool', - name: '_isTransferLimitInPercentage' - } - ] - }, [isTransferLimitInPercentage, globalTransferLimitInPercentageOrToken, allowPrimaryIssuance]); - */ - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); - break; - case 'LookupVolumeRestrictionTM': - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); - break; } let selectedTMFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.TRANSFER, options[index]); let addModuleAction = securityToken.methods.addModule(selectedTMFactoryAddress, bytes, 0, 0); @@ -1196,186 +1128,6 @@ function inputRestrictionData(isDaily) { return restriction; } -async function singleTradeVolumeRestrictionTM() { - console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address} `)); - console.log(); - - // Show current data - let displayIsInPercentage = await currentTransferManager.methods.isTransferLimitInPercentage().call(); - let displayGlobalTransferLimit; - if (displayIsInPercentage) { - displayGlobalTransferLimit = fromWeiPercentage(await currentTransferManager.methods.globalTransferLimitInPercentage().call()); - } else { - displayGlobalTransferLimit = web3.utils.fromWei(await currentTransferManager.methods.globalTransferLimitInTokens().call()); - } - let displayAllowPrimaryIssuance = await currentTransferManager.methods.allowPrimaryIssuance().call(); - - console.log(`- Limit type: ${displayIsInPercentage ? `Percentage` : `Tokens`} `); - console.log(`- Default transfer limit: ${displayGlobalTransferLimit} ${displayIsInPercentage ? `%` : `${tokenSymbol}`} `); - console.log(`- Allow primary issuance: ${displayAllowPrimaryIssuance ? `YES` : `NO`} `); - // ------------------ - - let options = []; - if (displayAllowPrimaryIssuance) { - options.push('Disallow primary issuance'); - } else { - options.push('Allow primary issuance'); - } - options.push('Add exempted wallet', 'Remove exempted wallet'); - if (displayIsInPercentage) { - options.push('Change transfer limit to tokens', 'Change default percentage limit', - 'Set percentage transfer limit per account', 'Remove percentage transfer limit per account'); - } else { - options.push('Change transfer limit to percentage', 'Change default tokens limit', - 'Set tokens transfer limit per account', 'Remove tokens transfer limit per account'); - } - - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); - switch (optionSelected) { - case 'Allow primary issuance': - case 'Disallow primary issuance': - let disallowPrimaryIssuanceAction = currentTransferManager.methods.setAllowPrimaryIssuance(!displayAllowPrimaryIssuance); - await common.sendTransaction(disallowPrimaryIssuanceAction); - break; - case 'Add exempted wallet': - let walletToExempt = readlineSync.question('Enter the wallet to exempt: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let addExemptWalletAction = currentTransferManager.methods.addExemptWallet(walletToExempt); - let addExemptWalletReceipt = await common.sendTransaction(addExemptWalletAction); - let addExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addExemptWalletReceipt.logs, 'ExemptWalletAdded'); - console.log(chalk.green(`${addExemptWalletEvent._wallet} has been exempted sucessfully!`)); - break; - case 'Remove exempted wallet': - let exemptedWallet = readlineSync.question('Enter the wallet to remove from exempt: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let removeExemptWalletAction = currentTransferManager.methods.removeExemptWallet(exemptedWallet); - let removeExemptWalletReceipt = await common.sendTransaction(removeExemptWalletAction); - let removeExemptWalletEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeExemptWalletReceipt.logs, 'ExemptWalletRemoved'); - console.log(chalk.green(`${removeExemptWalletEvent._wallet} has been removed from exempt wallets sucessfully!`)); - break; - case 'Change transfer limit to tokens': - let newDefaultLimitInTokens = web3.utils.toWei(readlineSync.question('Enter the amount of tokens for default limit: ', { - limit: function (input) { - return parseInt(input) > 0; - }, - limitMessage: "Must be greater than zero" - })); - let changeTransferLimitToTokensAction = currentTransferManager.methods.changeTransferLimitToTokens(newDefaultLimitInTokens); - let changeTransferLimitToTokensReceipt = await common.sendTransaction(changeTransferLimitToTokensAction); - let changeTransferLimitToTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); - console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); - console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeTransferLimitToTokensEvent._amount)} ${tokenSymbol} `)); - break; - case 'Change transfer limit to percentage': - let newDefaultLimitInPercentage = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { - limit: function (input) { - return (parseInt(input) > 0 && parseInt(input) <= 100); - }, - limitMessage: "Must be greater than 0 and less than 100" - })); - let changeTransferLimitToPercentageAction = currentTransferManager.methods.changeTransferLimitToPercentage(newDefaultLimitInPercentage); - let changeTransferLimitToPercentageReceipt = await common.sendTransaction(changeTransferLimitToPercentageAction); - let changeTransferLimitToPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeTransferLimitToPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); - console.log(chalk.green(`Transfer limit has been set to tokens sucessfully!`)); - console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeTransferLimitToPercentageEvent._percentage)} % `)); - break; - case 'Change default percentage limit': - let defaultLimitInPercentage = toWeiPercentage(readlineSync.question('Enter the percentage for default limit: ', { - limit: function (input) { - return (parseInt(input) > 0 && parseInt(input) <= 100); - }, - limitMessage: "Must be greater than 0 and less than 100" - })); - let changeGlobalLimitInPercentageAction = currentTransferManager.methods.changeGlobalLimitInPercentage(defaultLimitInPercentage); - let changeGlobalLimitInPercentageReceipt = await common.sendTransaction(changeGlobalLimitInPercentageAction); - let changeGlobalLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInPercentageReceipt.logs, 'GlobalTransferLimitInPercentageSet'); - console.log(chalk.green(`The default transfer limit is ${fromWeiPercentage(changeGlobalLimitInPercentageEvent._percentage)} % `)); - break; - case 'Change default tokens limit': - let defaultLimitInTokens = web3.utils.toWei(readlineSync.question('Enter the amount of tokens for default limit: ', { - limit: function (input) { - return parseInt(input) > 0; - }, - limitMessage: "Must be greater than zero" - })); - let changeGlobalLimitInTokensAction = currentTransferManager.methods.changeGlobalLimitInTokens(defaultLimitInTokens); - let changeGlobalLimitInTokensReceipt = await common.sendTransaction(changeGlobalLimitInTokensAction); - let changeGlobalLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeGlobalLimitInTokensReceipt.logs, 'GlobalTransferLimitInTokensSet'); - console.log(chalk.green(`The default transfer limit is ${web3.utils.fromWei(changeGlobalLimitInTokensEvent._amount)} ${tokenSymbol} `)); - break; - case 'Set percentage transfer limit per account': - let percentageAccount = readlineSync.question('Enter the wallet: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let accountLimitInPercentage = toWeiPercentage(readlineSync.question(`Enter the transfer limit for ${percentageAccount} in percentage: `, { - limit: function (input) { - return (parseInt(input) > 0 && parseInt(input) <= 100); - }, - limitMessage: "Must be greater than 0 and less than 100" - })); - let setTransferLimitInPercentageAction = currentTransferManager.methods.setTransferLimitInPercentage(percentageAccount, accountLimitInPercentage); - let setTransferLimitInPercentageReceipt = await common.sendTransaction(setTransferLimitInPercentageAction); - let setTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageSet'); - console.log(chalk.green(`The transfer limit for ${setTransferLimitInPercentageEvent._wallet} is ${fromWeiPercentage(setTransferLimitInPercentageEvent._percentage)} % `)); - break; - case 'Set tokens transfer limit per account': - let tokensAccount = readlineSync.question('Enter the wallet: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let accountLimitInTokens = web3.utils.toWei(readlineSync.question(`Enter the transfer limit for ${tokensAccount} in amount of tokens: `, { - limit: function (input) { - return parseInt(input) > 0; - }, - limitMessage: "Must be greater than zero" - })); - let setTransferLimitInTokensAction = currentTransferManager.methods.setTransferLimitInTokens(tokensAccount, accountLimitInTokens); - let setTransferLimitInTokensReceipt = await common.sendTransaction(setTransferLimitInTokensAction); - let setTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, setTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensSet'); - console.log(chalk.green(`The transfer limit for ${setTransferLimitInTokensEvent._wallet} is ${web3.utils.fromWei(setTransferLimitInTokensEvent._amount)} ${tokenSymbol} `)); - break; - case 'Remove percentage transfer limit per account': - let percentageAccountToRemove = readlineSync.question('Enter the wallet to remove: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let removeTransferLimitInPercentageAction = currentTransferManager.methods.removeTransferLimitInPercentage(percentageAccountToRemove); - let removeTransferLimitInPercentageReceipt = await common.sendTransaction(removeTransferLimitInPercentageAction); - let removeTransferLimitInPercentageEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeTransferLimitInPercentageReceipt.logs, 'TransferLimitInPercentageRemoved'); - console.log(chalk.green(`The transfer limit for ${removeTransferLimitInPercentageEvent._wallet} is the default limit`)); - break; - case 'Remove tokens transfer limit per account': - let tokensAccountToRemove = readlineSync.question('Enter the wallet to remove: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let removeTransferLimitInTokensAction = currentTransferManager.methods.removeTransferLimitInTokens(tokensAccountToRemove); - let removeTransferLimitInTokensReceipt = await common.sendTransaction(removeTransferLimitInTokensAction); - let removeTransferLimitInTokensEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeTransferLimitInTokensReceipt.logs, 'TransferLimitInTokensRemoved'); - console.log(chalk.green(`The transfer limit for ${removeTransferLimitInTokensEvent._wallet} is the default limit`)); - break; - } -} - /* // Copied from tests function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, pk) { From e543061f78e79f3b9d92f2b3317023725d1cfe11 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:07:52 +0530 Subject: [PATCH 412/582] Added test reporter --- .circleci/config.yml | 8 +++----- .gitignore | 3 ++- package.json | 1 + scripts/test.sh | 6 ++++++ truffle-ci.js | 33 +++++++++++++++++++++++++++++++++ yarn.lock | 39 +++++++++++++++++++++++++++++++++++++-- 6 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 truffle-ci.js diff --git a/.circleci/config.yml b/.circleci/config.yml index de4dcba6b..47f5344f1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -50,9 +50,6 @@ jobs: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules - - store_test_results: - path: test-results - docs: docker: - image: circleci/node:8 @@ -73,9 +70,9 @@ workflows: version: 2 commit: jobs: - - build - test - daily-coverage: + - coverage + daily-builds: triggers: - schedule: cron: "0 0 * * *" @@ -86,6 +83,7 @@ workflows: - development-2.1.0 - development-3.0.0 jobs: + - test - coverage docs: jobs: diff --git a/.gitignore b/.gitignore index 395634f11..f1aed51ad 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ bridge.log allFiredEvents extract/ extract.py -extract.zip \ No newline at end of file +extract.zip +/test-results \ No newline at end of file diff --git a/package.json b/package.json index 58104d99b..8f514a762 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "ethereum-bridge": "^0.6.1", "ethereumjs-abi": "^0.6.5", "ganache-cli": "^6.1.8", + "mocha-junit-reporter": "^1.18.0", "prettier": "^1.14.3", "sol-merger": "^0.1.2", "solidity-coverage": "^0.5.11", diff --git a/scripts/test.sh b/scripts/test.sh index fa569144f..12a3704c5 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -95,6 +95,12 @@ if [ "$COVERAGE" = true ]; then cat coverage/lcov.info | node_modules/.bin/coveralls fi else + if [ "$CI" = true ]; then + mkdir test-results + mkdir test-results/mocha + rm truffle-config.js + mv truffle-ci.js truffle-config.js + fi # Do not run a_poly_oracle,js tests unless it is a cron job if [ "$CIRCLE_CI_CRON" = true ]; then node_modules/.bin/truffle test `ls test/*.js` diff --git a/truffle-ci.js b/truffle-ci.js new file mode 100644 index 000000000..f427eb332 --- /dev/null +++ b/truffle-ci.js @@ -0,0 +1,33 @@ +require('babel-register'); +require('babel-polyfill'); + +module.exports = { + networks: { + development: { + host: 'localhost', + port: 8545, + network_id: '*', // Match any network id + gas: 7900000, + }, + coverage: { + host: "localhost", + network_id: "*", + port: 8545, // <-- If you change this, also set the port option in .solcover.js. + gas: 0xfffffffffff, // <-- Use this high gas value + gasPrice: 0x01 // <-- Use this low gas price + } + }, + solc: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + mocha: { + enableTimeouts: false, + reporter: "mocha-junit-reporter", + reporterOptions: { + mochaFile: './test-results/mocha/results.xml' + } + } +}; diff --git a/yarn.lock b/yarn.lock index 31973936e..914397852 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1331,6 +1331,11 @@ chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" +charenc@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= + checkpoint-store@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" @@ -1656,6 +1661,11 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" +crypt@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= + crypto-browserify@3.12.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -3444,7 +3454,7 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" -is-buffer@^1.1.5: +is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -4100,6 +4110,15 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +md5@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" + integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk= + dependencies: + charenc "~0.0.1" + crypt "~0.0.1" + is-buffer "~1.1.1" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -4299,12 +4318,23 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" +mocha-junit-reporter@^1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.18.0.tgz#9209a3fba30025ae3ae5e6bfe7f9c5bc3c2e8ee2" + integrity sha512-y3XuqKa2+HRYtg0wYyhW/XsLm2Ps+pqf9HaTAt7+MVUAKFJaNAHOrNseTZo9KCxjfIbxUWwckP5qCDDPUmjSWA== + dependencies: + debug "^2.2.0" + md5 "^2.1.0" + mkdirp "~0.5.1" + strip-ansi "^4.0.0" + xml "^1.0.0" + mocha@^4.0.1, mocha@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" @@ -7047,6 +7077,11 @@ xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: parse-headers "^2.0.0" xtend "^4.0.0" +xml@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" + integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= + xmlhttprequest@*, xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" From 602b67e27d0cfe67d2e60494b6ffd1f5037372ed Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:19:47 +0530 Subject: [PATCH 413/582] Addded artifact collection --- .circleci/config.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 47f5344f1..c17f9010e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,6 +34,8 @@ jobs: - node_modules - store_test_results: path: test-results + - store_artifacts: + path: ./test-results/mocha/results.xml coverage: docker: - image: circleci/node:8 @@ -50,6 +52,8 @@ jobs: key: dependency-cache-{{ checksum "package.json" }} paths: - node_modules + - store_artifacts: + path: ./coverage/lcov.info docs: docker: - image: circleci/node:8 From 8793f08132b85f90fbf79987120cd1feac646409 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:34:11 +0530 Subject: [PATCH 414/582] Added parallelism --- .circleci/config.yml | 1 + scripts/test.sh | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c17f9010e..1dff7a561 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,6 +19,7 @@ jobs: test: docker: - image: circleci/node:8 + parallelism: 2 steps: - checkout - restore_cache: diff --git a/scripts/test.sh b/scripts/test.sh index 12a3704c5..b0b99dd34 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -100,10 +100,11 @@ else mkdir test-results/mocha rm truffle-config.js mv truffle-ci.js truffle-config.js - fi - # Do not run a_poly_oracle,js tests unless it is a cron job - if [ "$CIRCLE_CI_CRON" = true ]; then - node_modules/.bin/truffle test `ls test/*.js` + if [ "$CIRCLE_CI_CRON" = true ]; then + node_modules/.bin/truffle test `ls test/*.js | circleci tests split --split-by=timings` + else + node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js | circleci tests split --split-by=timings` + fi else node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js` fi From 1c04aae38b1ee3932931cf526f32296b30e75a17 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:44:34 +0530 Subject: [PATCH 415/582] Comment --- scripts/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/test.sh b/scripts/test.sh index b0b99dd34..2f4e5b057 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -100,6 +100,7 @@ else mkdir test-results/mocha rm truffle-config.js mv truffle-ci.js truffle-config.js + # only run poly oracle and upgrade tests if cron job by CI if [ "$CIRCLE_CI_CRON" = true ]; then node_modules/.bin/truffle test `ls test/*.js | circleci tests split --split-by=timings` else From 5c8017867f1af6f3d2eb2db3195d9be01a69769f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:46:08 +0530 Subject: [PATCH 416/582] Bumped parallelism to 3 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1dff7a561..e55982c40 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,7 +19,7 @@ jobs: test: docker: - image: circleci/node:8 - parallelism: 2 + parallelism: 3 steps: - checkout - restore_cache: From 526608d4b9e9dd01272d9337dd29d3124184ea15 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:51:23 +0530 Subject: [PATCH 417/582] Coverage requires approval --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e55982c40..78530ce94 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -76,7 +76,8 @@ workflows: commit: jobs: - test - - coverage + - coverage: + type: approval daily-builds: triggers: - schedule: From 6329cc1b3b39035d69cb28346a71d1aa884551a9 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 18:06:20 +0530 Subject: [PATCH 418/582] Bumped parallelism to 4 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 78530ce94..d73bda085 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,7 +19,7 @@ jobs: test: docker: - image: circleci/node:8 - parallelism: 3 + parallelism: 4 steps: - checkout - restore_cache: From 01dfda9a45fa159ee1af9cdb51e78f09bf975f24 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 18:12:49 +0530 Subject: [PATCH 419/582] Removed manual approval --- .circleci/config.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d73bda085..e55982c40 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,7 +19,7 @@ jobs: test: docker: - image: circleci/node:8 - parallelism: 4 + parallelism: 3 steps: - checkout - restore_cache: @@ -76,8 +76,7 @@ workflows: commit: jobs: - test - - coverage: - type: approval + - coverage daily-builds: triggers: - schedule: From 1e81411eeff4709cb4a92aa613f7fec21b605fc8 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 20:09:16 +0530 Subject: [PATCH 420/582] Combine travis and CircleCI --- .circleci/config.yml | 9 ++++----- .travis.yml | 15 +-------------- README.md | 2 +- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e55982c40..986c13c2d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,7 +19,7 @@ jobs: test: docker: - image: circleci/node:8 - parallelism: 3 + parallelism: 2 steps: - checkout - restore_cache: @@ -75,7 +75,6 @@ workflows: version: 2 commit: jobs: - - test - coverage daily-builds: triggers: @@ -85,10 +84,10 @@ workflows: branches: only: - master - - development-2.1.0 - - development-3.0.0 + - dev-2.1.0 + - dev-2.2.0 + - dev-3.0.0 jobs: - - test - coverage docs: jobs: diff --git a/.travis.yml b/.travis.yml index 2265b2d88..b676c5840 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,24 +4,11 @@ node_js: cache: directories: - node_modules -matrix: - fast_finish: true - allow_failures: - - env: 'TASK=docs' jobs: include: - - stage: Tests and Coverage - after_install: wget -O node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js + - stage: test before_script: truffle version script: npm run test - - stage: Docs - env: 'TASK=docs' - before_install: - - echo -ne '\n' | sudo apt-add-repository -y ppa:hvr/z3 - - sudo apt-get -y update - - sudo apt-get -y install libz3-dev - before_script: wget -O node_modules/solidity-docgen/lib/index.js https://raw.githubusercontent.com/maxsam4/solidity-docgen/buffer-size/lib/index.js - script: npm run docs notifications: slack: secure: W4FZSabLrzF74f317hutolEHnlq2GBlQxU6b85L5XymrjgLEhlgE16c5Qz7Emoyt6le6PXL+sfG2ujJc3XYys/6hppgrHSAasuJnKCdQNpmMZ9BNyMs6WGkmB3enIf3K/FLXb26AQdwpQdIXuOeJUTf879u+YoiZV0eZH8d3+fsIOyovq9N6X5pKOpDM9iT8gGB4t7fie7xf51s+iUaHxyO9G7jDginZ4rBXHcU7mxCub9z+Z1H8+kCTnPWaF+KKVEXx4Z0nI3+urboD7E4OIP02LwrThQls2CppA3X0EoesTcdvj/HLErY/JvsXIFiFEEHZzB1Wi+k2TiOeLcYwEuHIVij+HPxxlJNX/j8uy01Uk8s4rd+0EhvfdKHJqUKqxH4YN2npcKfHEss7bU3y7dUinXQfYShW5ZewHdvc7pnnxBTfhvmdi64HdNrXAPq+s1rhciH7MmnU+tsm4lhrpr+FBuHzUMA9fOCr7b0SQytZEgWpiUls88gdbh3yG8TjyZxmZJGx09cwEP0q7VoH0UwFh7mIu5XmYdd5tWUhavTiO7YV8cUPn7MvwMsTltB3YBpF/fB26L7ka8zBhCsjm9prW6SVYU/dyO3m91VeZtO/zJFHRDA6Q58JGVW2rgzO39z193qC1EGRXqTie96VwAAtNg8+hRb+bI/CWDVzSPc= \ No newline at end of file diff --git a/README.md b/README.md index c810f039a..8c5ae0a4e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![CircleCI](https://circleci.com/gh/maxsam4/polymath-core.svg?style=svg)](https://circleci.com/gh/maxsam4/polymath-core) +[![Build Status](https://travis-ci.org/PolymathNetwork/polymath-core.svg?branch=master)](https://travis-ci.org/PolymathNetwork/polymath-core) [![Coverage Status](https://coveralls.io/repos/github/PolymathNetwork/polymath-core/badge.svg?branch=master)](https://coveralls.io/github/PolymathNetwork/polymath-core?branch=master) [![Gitter](https://img.shields.io/badge/chat-gitter-green.svg)](https://gitter.im/PolymathNetwork/Lobby) [![Telegram](https://img.shields.io/badge/50k+-telegram-blue.svg)](https://gitter.im/PolymathNetwork/Lobby) From a89562c4823de31a38c709d7cb95436059ee73ce Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 20:55:37 +0530 Subject: [PATCH 421/582] env var changes --- scripts/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test.sh b/scripts/test.sh index 2f4e5b057..f23df2845 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -91,11 +91,11 @@ fi if [ "$COVERAGE" = true ]; then curl -o node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js node_modules/.bin/solidity-coverage - if [ "$CI" = true ]; then + if [ "$CIRCLECI" = true ]; then cat coverage/lcov.info | node_modules/.bin/coveralls fi else - if [ "$CI" = true ]; then + if [ "$CIRCLECI" = true ]; then mkdir test-results mkdir test-results/mocha rm truffle-config.js From 742cdad7ed98525402b04c1899d91405d968d67a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 21:01:27 +0530 Subject: [PATCH 422/582] comment --- scripts/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test.sh b/scripts/test.sh index f23df2845..9f595d0ba 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -95,7 +95,7 @@ if [ "$COVERAGE" = true ]; then cat coverage/lcov.info | node_modules/.bin/coveralls fi else - if [ "$CIRCLECI" = true ]; then + if [ "$CIRCLECI" = true ]; then # using mocha junit reporter for parallelism in CircleCI mkdir test-results mkdir test-results/mocha rm truffle-config.js From 5e2ec74d6c457661805f94dccfd2987754aad363 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Thu, 13 Dec 2018 14:07:01 -0300 Subject: [PATCH 423/582] Improve MATM to allow allowances and expiryTimes to be changed for existing approvals --- CLI/commands/transfer_manager.js | 51 +++++++++++++++++++------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index ff3ec2b11..97f3372a6 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -695,33 +695,42 @@ async function manualApprovalTransferManager() { case 'Modify the existing manual approvals': let options = []; (await getApprovals()).forEach((a) => { - options.push(`From ${a.from} to ${a.to} - Allowance: ${web3.utils.fromWei(a.allowance)} - Expiry time: ${moment.unix(a.expiryTime).format('MMMM Do YYYY')} - Description: ${web3.utils.toAscii(a.description)}\n\n`); + options.push(`${a.from},${a.to},${web3.utils.fromWei(a.allowance)},${a.expiryTime},${web3.utils.toAscii(a.description)}`); }) let rowIndex = readlineSync.keyInSelect(options, 'Select a row to modify', { cancel: 'Return' }); - let optionSelected = options[rowIndex]; - console.log('Selected:', rowIndex != -1 ? optionSelected.description : 'Return', '\n'); - - let actualAllowance = optionSelected.allowance; - let actualExpiryTime = optionSelected.expiryTime; - let actualDescription = optionSelected.description; - - let newAllowance = readlineSync.question(`Enter the new amount of tokens which will be approved (${actualAllowance}): `, { - limit: function (input) { - if (input == "") { - return true - } - return parseFloat(input) > 0 - }, - limitMessage: "Amount must be bigger than 0" - }); - let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is allowed(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); - let description = readlineSync.question('Enter the description about the manual approval: ', { + if (rowIndex == -1) { + return + } + let optionSelected = options[rowIndex].split(","); + let actualExpiryTime = optionSelected[3]; + let actualDescription = optionSelected[4]; + + let changeAllowance = readlineSync.question(`Enter (1) to increased, (0) to decreased or leave empty to no change in allowances: `, { defaultInput: 2 }); + let newAllowance; + if (parseInt(changeAllowance) != 2) { + let minWord = parseInt(changeAllowance) == 1 ? "incresed" : "decreased"; + newAllowance = readlineSync.question(`Enter the amount of tokens to ${minWord}: `, { + limit: function (input) { + return parseFloat(input) > 0 + }, + limitMessage: "Amount must be bigger than 0" + }); + } else { + newAllowance = "0"; + } + let newExpiryTime = readlineSync.questionInt(`Enter the new time(Unix Epoch time) until which the transfer is allowed (${actualExpiryTime}): `, { defaultInput: actualExpiryTime }); + let newDescription = readlineSync.question(`Enter the new description about the manual approval (${actualDescription}): `, { limit: function (input) { return input != "" && getBinarySize(input) < 33 }, - limitMessage: "Description is required" + limitMessage: "Description is required", + defaultInput: actualDescription }); + + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(optionSelected[0], optionSelected[1], parseInt(newExpiryTime), web3.utils.toWei(newAllowance), web3.utils.fromAscii(newDescription), parseInt(changeAllowance)); + let modifyManualApprovalReceipt = await common.sendTransaction(modifyManualApprovalAction); + console.log(chalk.green(`The row has been modify successfully!`)); + break; } } From c8832cb40720ee30718e0238c45ea539b39e362b Mon Sep 17 00:00:00 2001 From: shuffledex Date: Thu, 13 Dec 2018 19:50:33 -0300 Subject: [PATCH 424/582] Refactoring and improvements --- CLI/commands/transfer_manager.js | 457 +++++++++++------- .../MATM/modify_manualapproval_data.csv | 5 + 2 files changed, 284 insertions(+), 178 deletions(-) create mode 100644 CLI/data/Transfer/MATM/modify_manualapproval_data.csv diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 97f3372a6..d2e1a9f83 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -13,7 +13,21 @@ const { table } = require('table') const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelist_data.csv'; const ADD_MANUAL_APPROVAL_DATA_CSV = './CLI/data/Transfer/MATM/manualapproval_data.csv'; +const MODIFY_MANUAL_APPROVAL_DATA_CSV = './CLI/data/Transfer/MATM/modify_manualapproval_data.csv'; const REVOKE_MANUAL_APPROVAL_DATA_CSV = './CLI/data/Transfer/MATM/revoke_manualapproval_data.csv'; +const ZERO = '0x0000000000000000000000000000000000000000'; +const MATM_ADD = 'Add new manual approval'; +const MATM_MANAGE = 'Manage existing approvals'; +const MATM_EXPLORE = 'Explore account'; +const MATM_OPERATE = 'Operate with multiple approvals'; +const MATM_MANAGE_INCRESE = 'Increase allowance'; +const MATM_MANAGE_DECREASE = 'Decrease allowance'; +const MATM_MANAGE_TIME = 'Modify expiry time'; +const MATM_MANAGE_REVOKE = 'Revoke this approval'; +const MATM_OPERATE_ADD = 'Add multiple approvals in batch'; +const MATM_OPERATE_MODIFY = 'Modify multiple approvals in batch'; +const MATM_OPERATE_REVOKE = 'Revoke multiple approvals in batch'; + // App flow let tokenSymbol; @@ -571,170 +585,235 @@ async function modifyWhitelistInBatch() { async function manualApprovalTransferManager() { console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address} `), '\n'); - let options = [ - 'Check manual approval', - 'List all active approvals', - 'List all active approvals corresponds to an address', - 'Add manual approval', - 'Add manual approval in batches', - 'Revoke manual approval', - 'Revoke manual approval in batches', - 'Modify the existing manual approvals' + let matmOptions = [ + MATM_ADD, + MATM_MANAGE, + MATM_EXPLORE, + MATM_OPERATE ]; - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = options[index]; + let index = readlineSync.keyInSelect(matmOptions, 'What do you want to do?', { + cancel: 'Return' + }); + let optionSelected = matmOptions[index]; console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); - let from; - let to; + switch (optionSelected) { - case 'Check manual approval': - from = readlineSync.question('Enter the address from which transfers would be approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers would be approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - console.log(); - let manualApproval = await getManualApproval(from, to); - if (manualApproval) { - console.log(`Manual approval found!`); - console.log(`Description: ${web3.utils.toAscii(manualApproval[2])}`); - console.log(`Allowance: ${web3.utils.fromWei(manualApproval[1])}`); - console.log(`Expiry time: ${moment.unix(manualApproval[0]).format('MMMM Do YYYY, HH:mm:ss')}`); - } else { - console.log(chalk.yellow(`There are no manual approvals from ${from} to ${to}.`)); - } + case MATM_ADD: + await matmAdd(); break; - case 'List all active approvals': - (await getApprovals()).forEach((a) => { - console.log(`From ${a.from} to ${a.to}\nAllowance: ${web3.utils.fromWei(a.allowance)}\nExpiry time: ${moment.unix(a.expiryTime).format('MMMM Do YYYY')}\nDescription: ${web3.utils.toAscii(a.description)}\n\n`); - }) + case MATM_MANAGE: + await matmManage(); break; - case 'List all active approvals corresponds to an address': - let address = readlineSync.question('Enter the address: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let approvalsIndex = await getApprovalsToAnAddress(address); - if (!approvalsIndex.length) { - console.log(chalk.red(`\nThe address is not in the list\n`)) - } - approvalsIndex.forEach(async (i) => { - let a = await currentTransferManager.methods.approvals(i).call(); - console.log(`From ${a.from} to ${a.to}\nAllowance: ${web3.utils.fromWei(a.allowance)}\nExpiry time: ${moment.unix(a.expiryTime).format('MMMM Do YYYY')}\nDescription: ${web3.utils.toAscii(a.description)}\n\n`); - }) + case MATM_EXPLORE: + await matmExplore(); break; - case 'Add manual approval': - from = readlineSync.question('Enter the address from which transfers will be approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers will be approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - let description = readlineSync.question('Enter the description about the manual approval: ', { - limit: function (input) { - return input != "" && getBinarySize(input) < 33 - }, - limitMessage: "Description is required" - }); - if (!await getManualApproval(from, to)) { - let allowance = readlineSync.question('Enter the amount of tokens which will be approved: '); - let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is allowed(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); - let addManualApprovalAction = currentTransferManager.methods.addManualApproval(from, to, web3.utils.toWei(allowance), expiryTime, web3.utils.fromAscii(description)); - let addManualApprovalReceipt = await common.sendTransaction(addManualApprovalAction); - let addManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualApprovalReceipt.logs, 'AddManualApproval'); - console.log(chalk.green(`Manual approval has been added successfully!`)); - } else { - console.log(chalk.red(`A manual approval already exists from ${from} to ${to}. Revoke it first if you want to add a new one.`)); - } + case MATM_OPERATE: + await matmOperate(); break; - case 'Add manual approval in batches': + } +} + +async function matmAdd() { + let from = readlineSync.question('Enter the address from which transfers will be approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let to = readlineSync.question('Enter the address to which transfers will be approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let description = readlineSync.question('Enter the description about the manual approval: ', { + limit: function (input) { + return input != "" && getBinarySize(input) < 33 + }, + limitMessage: "Description is required" + }); + if (!await getManualApproval(from, to)) { + let allowance = readlineSync.question('Enter the amount of tokens which will be approved: '); + let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); + let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is allowed(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let addManualApprovalAction = currentTransferManager.methods.addManualApproval(from, to, web3.utils.toWei(allowance), expiryTime, web3.utils.fromAscii(description)); + let addManualApprovalReceipt = await common.sendTransaction(addManualApprovalAction); + let addManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualApprovalReceipt.logs, 'AddManualApproval'); + console.log(chalk.green(`Manual approval has been added successfully!`)); + } else { + console.log(chalk.red(`A manual approval already exists from ${from} to ${to}. Revoke it first if you want to add a new one.`)); + } +} + +async function matmManage() { + + let manageOptions = [ + MATM_MANAGE_INCRESE, + MATM_MANAGE_DECREASE, + MATM_MANAGE_TIME, + MATM_MANAGE_REVOKE + ]; + + let getApprovals = await getApprovalsArray(); + + let options = [] + getApprovals.forEach((item) => { + options.push(`From ${item.from} to ${item.to}`) + }) + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { + cancel: 'Return' + }); + let optionSelected = options[index]; + console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + + let index2 = readlineSync.keyInSelect(manageOptions, 'What do you want to do?', { + cancel: 'Return' + }); + let optionSelected2 = manageOptions[index2]; + console.log('Selected:', index2 != -1 ? optionSelected2 : 'Return', '\n'); + + const addrs = optionSelected.replace("From ", "").replace(" to ", ",").split(','); + + switch (optionSelected2) { + case MATM_MANAGE_INCRESE: + await matmManageIncrese(addrs[0], addrs[1]); + break; + case MATM_MANAGE_DECREASE: + await matmManageDecrease(addrs[0], addrs[1]); + break; + case MATM_MANAGE_TIME: + await matmManageTime(addrs[0], addrs[1]); + break; + case MATM_MANAGE_REVOKE: + await matmManageRevoke(addrs[0], addrs[1]); + break; + } +} + +async function matmExplore() { + let getApprovals = await getApprovalsArray(); + getApprovals.forEach((item) => { + printMatmRow(item.from, item.to, item.allowance, item.expiryTime, item.description); + }) +} + +async function matmOperate() { + let operateOptions = [ + MATM_OPERATE_ADD, + MATM_OPERATE_MODIFY, + MATM_OPERATE_REVOKE + ]; + + let index = readlineSync.keyInSelect(operateOptions, 'What do you want to do?', { + cancel: 'Return' + }); + let optionSelected = operateOptions[index]; + console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + + switch (optionSelected) { + case MATM_OPERATE_ADD: await addManualApproveInBatch(); break; - case 'Revoke manual approval': - from = readlineSync.question('Enter the address from which transfers were approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers were approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - if (await getManualApproval(from, to)) { - let revokeManualApprovalAction = currentTransferManager.methods.revokeManualApproval(from, to); - let revokeManualApprovalReceipt = await common.sendTransaction(revokeManualApprovalAction); - let revokeManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, revokeManualApprovalReceipt.logs, 'RevokeManualApproval'); - console.log(chalk.green(`Manual approval has been revoked successfully!`)); - } else { - console.log(chalk.red(`Manual approval from ${from} to ${to} does not exist.`)); - } + case MATM_OPERATE_MODIFY: + await modifyManualApproveInBatch(); break; - case 'Revoke manual approval in batches': + case MATM_OPERATE_REVOKE: await revokeManualApproveInBatch(); break; - case 'Modify the existing manual approvals': - let options = []; - (await getApprovals()).forEach((a) => { - options.push(`${a.from},${a.to},${web3.utils.fromWei(a.allowance)},${a.expiryTime},${web3.utils.toAscii(a.description)}`); - }) - let rowIndex = readlineSync.keyInSelect(options, 'Select a row to modify', { cancel: 'Return' }); - if (rowIndex == -1) { - return - } - let optionSelected = options[rowIndex].split(","); - let actualExpiryTime = optionSelected[3]; - let actualDescription = optionSelected[4]; - - let changeAllowance = readlineSync.question(`Enter (1) to increased, (0) to decreased or leave empty to no change in allowances: `, { defaultInput: 2 }); - let newAllowance; - if (parseInt(changeAllowance) != 2) { - let minWord = parseInt(changeAllowance) == 1 ? "incresed" : "decreased"; - newAllowance = readlineSync.question(`Enter the amount of tokens to ${minWord}: `, { - limit: function (input) { - return parseFloat(input) > 0 - }, - limitMessage: "Amount must be bigger than 0" - }); - } else { - newAllowance = "0"; - } - let newExpiryTime = readlineSync.questionInt(`Enter the new time(Unix Epoch time) until which the transfer is allowed (${actualExpiryTime}): `, { defaultInput: actualExpiryTime }); - let newDescription = readlineSync.question(`Enter the new description about the manual approval (${actualDescription}): `, { - limit: function (input) { - return input != "" && getBinarySize(input) < 33 - }, - limitMessage: "Description is required", - defaultInput: actualDescription - }); + } +} - let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(optionSelected[0], optionSelected[1], parseInt(newExpiryTime), web3.utils.toWei(newAllowance), web3.utils.fromAscii(newDescription), parseInt(changeAllowance)); - let modifyManualApprovalReceipt = await common.sendTransaction(modifyManualApprovalAction); - console.log(chalk.green(`The row has been modify successfully!`)); +async function getApprovalDetail(from, to) { + let detail = await currentTransferManager.methods.getApprovalDetails(from, to).call(); + return { + "expiryTime": detail[0], + "allowance": detail[1], + "description": detail[2] + } +} - break; +async function matmManageIncrese(from, to) { + let detail = await getApprovalDetail(from, to) + let allowance = readlineSync.question(`Enter a value to increased allowance: `, { + limit: function (input) { + return parseFloat(input) > 0 + }, + limitMessage: "Amount must be bigger than 0" + }); + + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(from, to, parseInt(detail.expiryTime), web3.utils.toWei(allowance), detail.description, 1); + await common.sendTransaction(modifyManualApprovalAction); + console.log(chalk.green(`The row has been modify successfully!`)); +} + +async function matmManageDecrease(from, to) { + let detail = await getApprovalDetail(from, to); + let allowance = readlineSync.question(`Enter a value to decrease allowance: `, { + limit: function (input) { + return parseFloat(input) > 0 + }, + limitMessage: "Amount must be bigger than 0" + }); + + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(from, to, parseInt(detail.expiryTime), web3.utils.toWei(allowance), detail.description, 0); + await common.sendTransaction(modifyManualApprovalAction); + console.log(chalk.green(`The row has been modify successfully!`)); +} + +async function matmManageTime(from, to) { + let detail = await getApprovalDetail(from, to); + let expiryTime = readlineSync.questionInt(`Enter the new time(Unix Epoch time) until which the transfer is allowed: `, { + limit: function (input) { + return parseFloat(input) > 0 + }, + limitMessage: "Enter Unix Epoch time" + }); + + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(from, to, parseInt(expiryTime), detail.allowance, detail.description, 2); + await common.sendTransaction(modifyManualApprovalAction); + console.log(chalk.green(`The row has been modify successfully!`)); +} + +async function matmManageRevoke(from, to) { + let modifyManualApprovalAction = currentTransferManager.methods.revokeManualApproval(from, to); + await common.sendTransaction(modifyManualApprovalAction); + console.log(chalk.green(`The row has been revoke successfully!`)); +} + +async function getApprovalsArray() { + let address = readlineSync.question('Enter an address to filter or leave empty to get all the rows: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: ZERO + }); + if (address == ZERO) { + return await getApprovals(); + } else { + let approvalsIndex = await getApprovalsToAnAddress(address); + if (!approvalsIndex.length) { + console.log(chalk.red(`\nThe address is not listed\n`)) + } + return await processApprovalsArray(approvalsIndex) } } +async function processApprovalsArray(array) { + let result = [] + for (const item in array) { + let ap = await currentTransferManager.methods.approvals(item).call(); + result.push(ap) + }; + return result +} + +function printMatmRow(from, to, allowance, time, description) { + console.log(`\nFrom ${from} to ${to}\nAllowance: ${web3.utils.fromWei(allowance)}\nExpiry time: ${moment.unix(time).format('MMMM Do YYYY')}\nDescription: ${web3.utils.toAscii(description)}\n\n`); +} + async function getApprovals() { let totalApprovals = await currentTransferManager.methods.getTotalApprovalsLength().call(); let results = []; @@ -752,16 +831,15 @@ async function getManualApproval(_from, _to) { let result = null; let manualApproval = await currentTransferManager.methods.getApprovalDetails(_from, _to).call(); - if (manualApproval[0] !== "0") { + if ((manualApproval[0] >= new Date()) && (manualApproval[1] != 0)) { result = manualApproval; } - return result; } -async function addManualApproveInBatch() { - let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_MANUAL_APPROVAL_DATA_CSV}): `, { - defaultInput: ADD_MANUAL_APPROVAL_DATA_CSV +async function matmGenericCsv(path, f) { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${path}): `, { + defaultInput: path }); let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { limit: function (input) { @@ -771,19 +849,27 @@ async function addManualApproveInBatch() { defaultInput: gbl.constants.DEFAULT_BATCH_SIZE }); let parsedData = csvParse(csvFilePath); - let validData = parsedData.filter(row => - web3.utils.isAddress(row[0]) && + let validData = parsedData.filter(row => f(row)); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + return common.splitIntoBatches(validData, batchSize); +} + +async function addManualApproveInBatch() { + + var f = (row) => { + return (web3.utils.isAddress(row[0]) && web3.utils.isAddress(row[1]) && parseFloat(row[2]) > 0 && moment.unix(row[3]).isValid() && typeof row[4] === 'string' && - getBinarySize(row[4]) < 33 - ); - let invalidRows = parsedData.filter(row => !validData.includes(row)); - if (invalidRows.length > 0) { - console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + getBinarySize(row[4]) < 33) } - let batches = common.splitIntoBatches(validData, batchSize); + + let batches = await matmGenericCsv(ADD_MANUAL_APPROVAL_DATA_CSV, f) + let [fromArray, toArray, allowanceArray, expiryArray, descriptionArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { console.log(`Batch ${batch + 1} - Attempting to add manual approvals: \n\n`, descriptionArray[batch], '\n'); @@ -797,26 +883,14 @@ async function addManualApproveInBatch() { } async function revokeManualApproveInBatch() { - let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REVOKE_MANUAL_APPROVAL_DATA_CSV}): `, { - defaultInput: REVOKE_MANUAL_APPROVAL_DATA_CSV - }); - let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { - limit: function (input) { - return parseInt(input) > 0; - }, - limitMessage: 'Must be greater than 0', - defaultInput: gbl.constants.DEFAULT_BATCH_SIZE - }); - let parsedData = csvParse(csvFilePath); - let validData = parsedData.filter(row => - web3.utils.isAddress(row[0]) && - web3.utils.isAddress(row[1]) - ); - let invalidRows = parsedData.filter(row => !validData.includes(row)); - if (invalidRows.length > 0) { - console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + + var f = (row) => { + return (web3.utils.isAddress(row[0]) && + web3.utils.isAddress(row[1])) } - let batches = common.splitIntoBatches(validData, batchSize); + + let batches = await matmGenericCsv(REVOKE_MANUAL_APPROVAL_DATA_CSV, f) + let [fromArray, toArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { console.log(`Batch ${batch + 1} - Attempting to revoke manual approvals`, '\n'); @@ -827,6 +901,33 @@ async function revokeManualApproveInBatch() { } } +async function modifyManualApproveInBatch() { + + var f = (row) => { + return (web3.utils.isAddress(row[0]) && + web3.utils.isAddress(row[1]) && + moment.unix(row[3]).isValid() && + parseFloat(row[2]) > 0 && + typeof row[4] === 'string' && + getBinarySize(row[4]) < 33 && + parseInt(row[5])) + } + + let batches = await matmGenericCsv(MODIFY_MANUAL_APPROVAL_DATA_CSV, f) + + let [fromArray, toArray, expiryArray, allowanceArray, descriptionArray, changesArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to modify manual approvals: \n\n`, descriptionArray[batch], '\n'); + descriptionArray[batch] = descriptionArray[batch].map(d => web3.utils.fromAscii(d)); + allowanceArray[batch] = allowanceArray[batch].map(a => web3.utils.toWei(new web3.utils.BN(a))); + changesArray[batch] = changesArray[batch].map(c => parseInt(c)); + let action = await currentTransferManager.methods.modifyManualApprovalMulti(fromArray[batch], toArray[batch], expiryArray[batch], allowanceArray[batch], descriptionArray[batch], changesArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Modify manual approval transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + function getBinarySize(string) { return Buffer.byteLength(string, 'utf8'); } diff --git a/CLI/data/Transfer/MATM/modify_manualapproval_data.csv b/CLI/data/Transfer/MATM/modify_manualapproval_data.csv new file mode 100644 index 000000000..7e695f3b2 --- /dev/null +++ b/CLI/data/Transfer/MATM/modify_manualapproval_data.csv @@ -0,0 +1,5 @@ +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0x1DDF4FDBB8eaDB5dD6EeC6edB1A91a0926940a33,12/12/2019,1,Lorem ipsum dolor sit amet,0 +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0xB849AC17d881183800300A31f022d3fe4B82D457,12/12/2019,2,Consectetur adipiscing elit,0 +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0xD122e1951cfb337D5CC8bc5aDECC0eb66ffb4B80,12/12/2019,3,Pellentesque ultrices eros,1 +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0x1D9127821A244b64852E8Da431bb389B81710985,12/12/2019,4,Non eleifend ante tincidunt eget,2 +0x127b4F58A825Dfc6d4058AcdB7bB397d1F0411b5,0x42dc79375E511Fb7Ee17fF50417141bAE5E5698E,12/12/2019,5,Sed ante arcu,1 \ No newline at end of file From 125c1b858e33a59544babcede966cfbcc307ed9f Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 13 Dec 2018 20:13:32 -0300 Subject: [PATCH 425/582] CLI - Operations in batch for VRTM --- CLI/commands/transfer_manager.js | 239 ++++++++++++++++++ .../VRTM/add_daily_restriction_data.csv | 8 + .../Transfer/VRTM/add_restriction_data.csv | 8 + .../VRTM/modify_daily_restriction_data.csv | 5 + .../Transfer/VRTM/modify_restriction_data.csv | 5 + .../VRTM/remove_daily_restriction_data.csv | 6 + .../Transfer/VRTM/remove_restriction_data.csv | 2 + 7 files changed, 273 insertions(+) create mode 100644 CLI/data/Transfer/VRTM/add_daily_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/add_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/modify_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/remove_daily_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/remove_restriction_data.csv diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 4df500208..9d6641519 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -12,6 +12,12 @@ const { table } = require('table') // Constants const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelist_data.csv'; +const ADD_DAILY_RESTRICTIONS_DATA_CSV = './CLI/data/Transfer/VRTM/add_daily_restriction_data.csv'; +const MODIFY_DAILY_RESTRICTIONS_DATA_CSV = './CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv'; +const REMOVE_DAILY_RESTRICTIONS_DATA_CSV = './CLI/data/Transfer/VRTM/remove_daily_restriction_data.csv'; +const ADD_RESTRICTIONS_DATA_CSV = './CLI/data/Transfer/VRTM/add_restriction_data.csv'; +const MODIFY_RESTRICTIONS_DATA_CSV = './CLI/data/Transfer/VRTM/modify_restriction_data.csv'; +const REMOVE_RESTRICTIONS_DATA_CSV = './CLI/data/Transfer/VRTM/remove_restriction_data.csv'; const RESTRICTION_TYPES = ['Fixed', 'Percentage']; @@ -1103,6 +1109,239 @@ async function changeIndividualRestrictions() { } } +async function operateWithMultipleRestrictions() { + let options = [ + 'Add multiple individual daily restrictions', + 'Modify multiple individual daily restrictions', + 'Remove multiple individual daily restrictions', + 'Add multiple individual restrictions', + 'Modify multiple individual restrictions', + 'Remove multiple individual restrictions' + ]; + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add multiple individual daily restrictions': + await addDailyRestrictionsInBatch(); + break; + case 'Modify multiple individual daily restrictions': + await modifyDailyRestrictionsInBatch(); + break; + case 'Remove multiple individual daily restrictions': + await removeDailyRestrictionsInBatch(); + break; + case 'Add multiple individual restrictions': + await addRestrictionsInBatch(); + break; + case 'Modify multiple individual restrictions': + await modifyRestrictionsInBatch(); + break; + case 'Remove multiple individual restrictions': + await removeRestrictionsInBatch(); + break; + } +} + +async function addDailyRestrictionsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_DAILY_RESTRICTIONS_DATA_CSV}): `, { + defaultInput: ADD_DAILY_RESTRICTIONS_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + !isNaN(row[1]) && + moment.unix(row[2]).isValid() && + moment.unix(row[3]).isValid() && + typeof row[4] === 'string' && RESTRICTION_TYPES.includes(row[4])); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [holderArray, allowanceArray, startTimeArray, endTimeArray, restrictionTypeArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add daily restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); + allowanceArray[batch] = allowanceArray[batch].map(n => web3.utils.toWei(n.toString())); + restrictionTypeArray[batch] = restrictionTypeArray[batch].map(n => RESTRICTION_TYPES.indexOf(n)); + let action = currentTransferManager.methods.addIndividualDailyRestrictionMulti(holderArray[batch], allowanceArray[batch], startTimeArray[batch], endTimeArray[batch], restrictionTypeArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add multiple daily restrictions transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function modifyDailyRestrictionsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${MODIFY_DAILY_RESTRICTIONS_DATA_CSV}): `, { + defaultInput: MODIFY_DAILY_RESTRICTIONS_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + !isNaN(row[1]) && + moment.unix(row[2]).isValid() && + moment.unix(row[3]).isValid() && + typeof row[4] === 'string' && RESTRICTION_TYPES.includes(row[4])); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [holderArray, allowanceArray, startTimeArray, endTimeArray, restrictionTypeArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to modify daily restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); + allowanceArray[batch] = allowanceArray[batch].map(n => web3.utils.toWei(n.toString())); + restrictionTypeArray[batch] = restrictionTypeArray[batch].map(n => RESTRICTION_TYPES.indexOf(n)); + let action = currentTransferManager.methods.modifyIndividualDailyRestrictionMulti(holderArray[batch], allowanceArray[batch], startTimeArray[batch], endTimeArray[batch], restrictionTypeArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Modify multiple daily restrictions transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function removeDailyRestrictionsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REMOVE_DAILY_RESTRICTIONS_DATA_CSV}): `, { + defaultInput: REMOVE_DAILY_RESTRICTIONS_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => web3.utils.isAddress(row[0])); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [holderArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to remove daily restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); + let action = currentTransferManager.methods.removeIndividualDailyRestrictionMulti(holderArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Remove multiple daily restrictions transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function addRestrictionsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_RESTRICTIONS_DATA_CSV}): `, { + defaultInput: ADD_RESTRICTIONS_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + !isNaN(row[1]) && + moment.unix(row[2]).isValid() && + (!isNaN(row[3]) && (parseFloat(row[3]) % 1 === 0)) && + moment.unix(row[4]).isValid() && + typeof row[5] === 'string' && RESTRICTION_TYPES.includes(row[5])); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [holderArray, allowanceArray, startTimeArray, rollingPeriodArray, endTimeArray, restrictionTypeArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); + allowanceArray[batch] = allowanceArray[batch].map(n => web3.utils.toWei(n.toString())); + restrictionTypeArray[batch] = restrictionTypeArray[batch].map(n => RESTRICTION_TYPES.indexOf(n)); + let action = currentTransferManager.methods.addIndividualRestrictionMulti(holderArray[batch], allowanceArray[batch], startTimeArray[batch], rollingPeriodArray[batch], endTimeArray[batch], restrictionTypeArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add multiple restrictions transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function modifyRestrictionsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${MODIFY_RESTRICTIONS_DATA_CSV}): `, { + defaultInput: MODIFY_RESTRICTIONS_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + !isNaN(row[1]) && + moment.unix(row[2]).isValid() && + (!isNaN(row[3]) && (parseFloat(row[3]) % 1 === 0)) && + moment.unix(row[4]).isValid() && + typeof row[5] === 'string' && RESTRICTION_TYPES.includes(row[5])); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [holderArray, allowanceArray, startTimeArray, rollingPeriodArray, endTimeArray, restrictionTypeArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to modify restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); + allowanceArray[batch] = allowanceArray[batch].map(n => web3.utils.toWei(n.toString())); + restrictionTypeArray[batch] = restrictionTypeArray[batch].map(n => RESTRICTION_TYPES.indexOf(n)); + let action = currentTransferManager.methods.modifyIndividualRestrictionMulti(holderArray[batch], allowanceArray[batch], startTimeArray[batch], rollingPeriodArray[batch], endTimeArray[batch], restrictionTypeArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Modify multiple restrictions transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function removeRestrictionsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REMOVE_RESTRICTIONS_DATA_CSV}): `, { + defaultInput: REMOVE_RESTRICTIONS_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => web3.utils.isAddress(row[0])); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [holderArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to remove restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); + let action = currentTransferManager.methods.removeIndividualRestrictionMulti(holderArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Remove multiple restrictions transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + function inputRestrictionData(isDaily) { let restriction = {}; restriction.restrictionType = readlineSync.keyInSelect(RESTRICTION_TYPES, 'How do you want to set the allowance? ', { cancel: false }); diff --git a/CLI/data/Transfer/VRTM/add_daily_restriction_data.csv b/CLI/data/Transfer/VRTM/add_daily_restriction_data.csv new file mode 100644 index 000000000..782c1107d --- /dev/null +++ b/CLI/data/Transfer/VRTM/add_daily_restriction_data.csv @@ -0,0 +1,8 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,1000,1/8/2019,10/10/2019,"Fixed" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,1/8/2019,10/10/2019,"Fixed" +0xac297053173b02b02a737d47f7b4a718e5b170ef,500,1/8/2019,10/10/2019,"Fixed" +0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,1/8/2019,10/10/2019,"Percentage" +0x10223927009b8add0960359dd90d1449415b7ca9,0.25,1/8/2019,10/10/2019,"Percentage" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,0.1,1/8/2019,10/10/2019,"Percentage" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,1234,1/8/2019,10/10/2019,"Fixed" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,5678,1/8/2019,10/10/2019,"Fixed" \ No newline at end of file diff --git a/CLI/data/Transfer/VRTM/add_restriction_data.csv b/CLI/data/Transfer/VRTM/add_restriction_data.csv new file mode 100644 index 000000000..072151a64 --- /dev/null +++ b/CLI/data/Transfer/VRTM/add_restriction_data.csv @@ -0,0 +1,8 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,1000,1/8/2019,90,10/10/2019,"Fixed" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,1/8/2019,30,10/10/2019,"Fixed" +0xac297053173b02b02a737d47f7b4a718e5b170ef,500,1/8/2019,15,10/10/2019,"Fixed" +0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,1/8/2019,90,10/10/2019,"Percentage" +0x10223927009b8add0960359dd90d1449415b7ca9,0.25,1/8/2019,30,10/10/2019,"Percentage" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,0.1,1/8/2019,15,10/10/2019,"Percentage" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,1234,1/8/2019,10,10/10/2019,"Fixed" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,5678,1/8/2019,2,10/10/2019,"Fixed" \ No newline at end of file diff --git a/CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv b/CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv new file mode 100644 index 000000000..194e9b1d5 --- /dev/null +++ b/CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv @@ -0,0 +1,5 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,2000,1/8/2019,10/10/2019,"Fixed" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,2/8/2019,10/10/2019,"Fixed" +0xac297053173b02b02a737d47f7b4a718e5b170ef,500,1/8/2019,10/10/2019,"Fixed" +0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,1/8/2019,20/10/2019,"Percentage" +0x10223927009b8add0960359dd90d1449415b7ca9,25,1/8/2019,10/10/2019,"Fixed" diff --git a/CLI/data/Transfer/VRTM/modify_restriction_data.csv b/CLI/data/Transfer/VRTM/modify_restriction_data.csv new file mode 100644 index 000000000..588e39211 --- /dev/null +++ b/CLI/data/Transfer/VRTM/modify_restriction_data.csv @@ -0,0 +1,5 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,2000,1/8/2019,90,10/10/2019,"Fixed" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,2/8/2019,30,10/10/2019,"Fixed" +0xac297053173b02b02a737d47f7b4a718e5b170ef,500,1/8/2019,20,10/10/2019,"Fixed" +0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,1/8/2019,90,20/10/2019,"Percentage" +0x10223927009b8add0960359dd90d1449415b7ca9,25,1/8/2019,30,10/10/2019,"Fixed" \ No newline at end of file diff --git a/CLI/data/Transfer/VRTM/remove_daily_restriction_data.csv b/CLI/data/Transfer/VRTM/remove_daily_restriction_data.csv new file mode 100644 index 000000000..a7fef30c4 --- /dev/null +++ b/CLI/data/Transfer/VRTM/remove_daily_restriction_data.csv @@ -0,0 +1,6 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1 +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1 +0xac297053173b02b02a737d47f7b4a718e5b170ef +0x49fc0b78238dab644698a90fa351b4c749e123d2 +0x10223927009b8add0960359dd90d1449415b7ca9 +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399 diff --git a/CLI/data/Transfer/VRTM/remove_restriction_data.csv b/CLI/data/Transfer/VRTM/remove_restriction_data.csv new file mode 100644 index 000000000..d927ee57b --- /dev/null +++ b/CLI/data/Transfer/VRTM/remove_restriction_data.csv @@ -0,0 +1,2 @@ +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98 +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3 From 4c92fce8e32b37dca9b7cad9a006269ed1eafbe0 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 14 Dec 2018 10:24:58 +0700 Subject: [PATCH 426/582] fuzz test for adding and removing modules --- .../z_fuzz_test_adding_removing_modules_ST.js | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index b3975cfce..149d4b5d3 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -117,8 +117,15 @@ contract('GeneralPermissionManager', accounts => { // permission manager fuzz test // let modules = ['CountTransferManager', 'SingleTradeVolumeRestrictionManager', 'ManualApprovalTransferManager', 'I_VolumeRestrictionTransferManager', 'PercentageTransferManager']; - let modules = ['I_CountTransferManagerFactory']; - let totalModules = modules.length; + var factoriesAndModules = [ + { factory: 'I_CountTransferManagerFactory', module: 'CountTransferManager'}, + //{ factory: 'I_SingleTradeVolumeRestrictionManagerFactory', module: 'SingleTradeVolumeRestrictionManager'}, + { factory: 'I_ManualApprovalTransferManagerFactory', module: 'ManualApprovalTransferManager'}, + { factory: 'I_VolumeRestrictionTransferManagerFactory', module: 'VolumeRestrictionTransferManager'}, + //{ factory: 'I_PercentageTransferManagerFactory', module: 'PercentageTransferManager'}, + ]; + + let totalModules = factoriesAndModules.length; before(async () => { @@ -270,22 +277,21 @@ contract('GeneralPermissionManager', accounts => { console.log("1.2"); // choose a random module - let randomModuleFactory = modules[Math.floor(Math.random() * Math.floor(totalModules))]; - console.log("choosen module "+ randomModuleFactory.address); - + let random = factoriesAndModules[Math.floor(Math.random() * Math.floor(totalModules))]; + let randomFactory = eval(random.factory); + let randomModule = eval(random.module); + console.log("choosen factory "+ random.factory); + console.log("choosen module "+ random.module); + // attach it to the ST - let tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - console.log("1.3"); - let randomModule = CountTransferManager.at(tx.logs[2].args._module); - console.log("1.4"); - console.log("successfully attached module " + randomModule); - console.log("1.5"); - console.log(randomModule.address); - - + let tx = await I_SecurityToken.addModule(randomFactory.address, bytesSTO, 0, 0, { from: token_owner }); + let randomModuleInstance = randomModule.at(tx.logs[2].args._module); + console.log("successfully attached module " + randomModuleInstance.address); + // remove it from the ST - tx = await I_SecurityToken.removeModule(randomModule.address, { from: token_owner }); - console.log("successfully removed module " + randomModule); + tx = await I_SecurityToken.archiveModule(randomModuleInstance.address, { from: token_owner }); + tx = await I_SecurityToken.removeModule(randomModuleInstance.address, { from: token_owner }); + console.log("successfully removed module " + randomModuleInstance.address); } }) From bea3115254fd10e2cc35a13c275993f6d9bdeb07 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 14 Dec 2018 12:36:50 +0700 Subject: [PATCH 427/582] finished module fuzz test --- .../z_fuzz_test_adding_removing_modules_ST.js | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index 149d4b5d3..e81df39aa 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -108,24 +108,20 @@ contract('GeneralPermissionManager', accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); - // CountTransferManager details - const holderCount = 2; // Maximum number of token holders - let bytesSTO = encodeModuleCall(["uint256"], [holderCount]); - let _details = "details holding for test"; let testRepeat = 20; - // permission manager fuzz test - // let modules = ['CountTransferManager', 'SingleTradeVolumeRestrictionManager', 'ManualApprovalTransferManager', 'I_VolumeRestrictionTransferManager', 'PercentageTransferManager']; + // define factories and modules for fuzz test var factoriesAndModules = [ { factory: 'I_CountTransferManagerFactory', module: 'CountTransferManager'}, - //{ factory: 'I_SingleTradeVolumeRestrictionManagerFactory', module: 'SingleTradeVolumeRestrictionManager'}, + { factory: 'I_SingleTradeVolumeRestrictionManagerFactory', module: 'SingleTradeVolumeRestrictionManager'}, { factory: 'I_ManualApprovalTransferManagerFactory', module: 'ManualApprovalTransferManager'}, { factory: 'I_VolumeRestrictionTransferManagerFactory', module: 'VolumeRestrictionTransferManager'}, - //{ factory: 'I_PercentageTransferManagerFactory', module: 'PercentageTransferManager'}, + { factory: 'I_PercentageTransferManagerFactory', module: 'PercentageTransferManager'}, ]; let totalModules = factoriesAndModules.length; + let bytesSTO; before(async () => { @@ -270,26 +266,53 @@ contract('GeneralPermissionManager', accounts => { it("should pass test for randomly adding and removing modules ", async () => { console.log("1"); - // fuzz test loop over total times of testRepeat, inside each loop, we use a variable j to randomly choose an account out of the 10 default accounts + // fuzz test loop over total times of testRepeat for (var i = 0; i < testRepeat; i++) { - var j = Math.floor(Math.random() * 10); - console.log("1.2"); - // choose a random module + + // choose a random module with in the totalMoudules available let random = factoriesAndModules[Math.floor(Math.random() * Math.floor(totalModules))]; let randomFactory = eval(random.factory); let randomModule = eval(random.module); console.log("choosen factory "+ random.factory); console.log("choosen module "+ random.module); + + //calculate the data needed for different modules + if (random.module == 'CountTransferManager' || random.module == 'ManualApprovalTransferManager' || random.module == 'VolumeRestrictionTransferManager' ){ + const holderCount = 2; // Maximum number of token holders + bytesSTO = encodeModuleCall(["uint256"], [holderCount]); + } else if(random.module == 'SingleTradeVolumeRestrictionManager'){ + bytesSTO = encodeModuleCall(STVRParameters, [false, (7 * Math.pow(10, 16)).toString(), false]) + } else if (random.module == 'PercentageTransferManager'){ + console.log("PTM 01"); + const holderPercentage = 70 * 10**16; + bytesSTO = web3.eth.abi.encodeFunctionCall({ + name: 'configure', + type: 'function', + inputs: [{ + type: 'uint256', + name: '_maxHolderPercentage' + },{ + type: 'bool', + name: '_allowPrimaryIssuance' + } + ] + }, [holderPercentage, false]); + console.log("encoded."); + } else { + console.log("no data defined for choosen module "+random.module); + } // attach it to the ST let tx = await I_SecurityToken.addModule(randomFactory.address, bytesSTO, 0, 0, { from: token_owner }); + console.log("1.3"); let randomModuleInstance = randomModule.at(tx.logs[2].args._module); console.log("successfully attached module " + randomModuleInstance.address); // remove it from the ST tx = await I_SecurityToken.archiveModule(randomModuleInstance.address, { from: token_owner }); + console.log("1.4"); tx = await I_SecurityToken.removeModule(randomModuleInstance.address, { from: token_owner }); console.log("successfully removed module " + randomModuleInstance.address); From 06ce33215c3e592f4ee5761048002241750d274f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 14 Dec 2018 15:49:42 +0530 Subject: [PATCH 428/582] Fix rounding off errors (#467) * Fixed rounding off errors * Increased tolerance * Reduced tolerance to zero * Comment updated * Tolerance set to 2 --- contracts/modules/STO/USDTieredSTO.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 825df2122..1d7278796 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -455,7 +455,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { fundsRaisedUSD = fundsRaisedUSD.add(spentUSD); } - spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, originalUSD), _investmentValue); + spentValue = DecimalMath.div(spentUSD, _rate); } /** @@ -494,7 +494,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { } } - spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, originalUSD), _investmentValue); + spentValue = DecimalMath.div(spentUSD, rate); } function _buyTokensChecks( From 002951baf6871a5d35060620d3cd02b86ebccd41 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 14 Dec 2018 10:26:47 -0300 Subject: [PATCH 429/582] Minor CLI changes --- CLI/commands/transfer_manager.js | 237 +++++++++--------- ...l_data.csv => add_manualapproval_data.csv} | 0 2 files changed, 119 insertions(+), 118 deletions(-) rename CLI/data/Transfer/MATM/{manualapproval_data.csv => add_manualapproval_data.csv} (100%) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index d2e1a9f83..89cee08c0 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -12,21 +12,21 @@ const { table } = require('table') // Constants const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelist_data.csv'; -const ADD_MANUAL_APPROVAL_DATA_CSV = './CLI/data/Transfer/MATM/manualapproval_data.csv'; +const ADD_MANUAL_APPROVAL_DATA_CSV = './CLI/data/Transfer/MATM/add_manualapproval_data.csv'; const MODIFY_MANUAL_APPROVAL_DATA_CSV = './CLI/data/Transfer/MATM/modify_manualapproval_data.csv'; const REVOKE_MANUAL_APPROVAL_DATA_CSV = './CLI/data/Transfer/MATM/revoke_manualapproval_data.csv'; -const ZERO = '0x0000000000000000000000000000000000000000'; -const MATM_ADD = 'Add new manual approval'; -const MATM_MANAGE = 'Manage existing approvals'; -const MATM_EXPLORE = 'Explore account'; -const MATM_OPERATE = 'Operate with multiple approvals'; -const MATM_MANAGE_INCRESE = 'Increase allowance'; -const MATM_MANAGE_DECREASE = 'Decrease allowance'; -const MATM_MANAGE_TIME = 'Modify expiry time'; -const MATM_MANAGE_REVOKE = 'Revoke this approval'; -const MATM_OPERATE_ADD = 'Add multiple approvals in batch'; -const MATM_OPERATE_MODIFY = 'Modify multiple approvals in batch'; -const MATM_OPERATE_REVOKE = 'Revoke multiple approvals in batch'; + +const MATM_MENU_ADD = 'Add new manual approval'; +const MATM_MENU_MANAGE = 'Manage existing approvals'; +const MATM_MENU_EXPLORE = 'Explore account'; +const MATM_MENU_OPERATE = 'Operate with multiple approvals'; +const MATM_MENU_MANAGE_INCRESE = 'Increase allowance'; +const MATM_MENU_MANAGE_DECREASE = 'Decrease allowance'; +const MATM_MENU_MANAGE_TIME = 'Modify expiry time'; +const MATM_MENU_MANAGE_REVOKE = 'Revoke this approval'; +const MATM_MENU_OPERATE_ADD = 'Add multiple approvals in batch'; +const MATM_MENU_OPERATE_MODIFY = 'Modify multiple approvals in batch'; +const MATM_MENU_OPERATE_REVOKE = 'Revoke multiple approvals in batch'; // App flow @@ -585,11 +585,14 @@ async function modifyWhitelistInBatch() { async function manualApprovalTransferManager() { console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address} `), '\n'); + let totalApprovals = await currentTransferManager.methods.getTotalApprovalsLength().call(); + console.log(`- Current active approvals: ${totalApprovals}`); + let matmOptions = [ - MATM_ADD, - MATM_MANAGE, - MATM_EXPLORE, - MATM_OPERATE + MATM_MENU_ADD, + MATM_MENU_MANAGE, + MATM_MENU_EXPLORE, + MATM_MENU_OPERATE ]; let index = readlineSync.keyInSelect(matmOptions, 'What do you want to do?', { @@ -599,16 +602,16 @@ async function manualApprovalTransferManager() { console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); switch (optionSelected) { - case MATM_ADD: + case MATM_MENU_ADD: await matmAdd(); break; - case MATM_MANAGE: + case MATM_MENU_MANAGE: await matmManage(); break; - case MATM_EXPLORE: + case MATM_MENU_EXPLORE: await matmExplore(); break; - case MATM_OPERATE: + case MATM_MENU_OPERATE: await matmOperate(); break; } @@ -627,68 +630,78 @@ async function matmAdd() { }, limitMessage: "Must be a valid address" }); - let description = readlineSync.question('Enter the description about the manual approval: ', { - limit: function (input) { - return input != "" && getBinarySize(input) < 33 - }, - limitMessage: "Description is required" - }); if (!await getManualApproval(from, to)) { + let description = readlineSync.question('Enter the description for the manual approval: ', { + limit: function (input) { + return input != "" && getBinarySize(input) < 33 + }, + limitMessage: "Description is required" + }); let allowance = readlineSync.question('Enter the amount of tokens which will be approved: '); let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time(Unix Epoch time) until which the transfer is allowed(1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let expiryTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) until which the transfer is allowed (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); let addManualApprovalAction = currentTransferManager.methods.addManualApproval(from, to, web3.utils.toWei(allowance), expiryTime, web3.utils.fromAscii(description)); let addManualApprovalReceipt = await common.sendTransaction(addManualApprovalAction); let addManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualApprovalReceipt.logs, 'AddManualApproval'); console.log(chalk.green(`Manual approval has been added successfully!`)); } else { - console.log(chalk.red(`A manual approval already exists from ${from} to ${to}. Revoke it first if you want to add a new one.`)); + console.log(chalk.red(`A manual approval already exists from ${from} to ${to}. Revoke it first if you want to add a new one or modify the existing one.`)); } } async function matmManage() { let manageOptions = [ - MATM_MANAGE_INCRESE, - MATM_MANAGE_DECREASE, - MATM_MANAGE_TIME, - MATM_MANAGE_REVOKE + MATM_MENU_MANAGE_INCRESE, + MATM_MENU_MANAGE_DECREASE, + MATM_MENU_MANAGE_TIME, + MATM_MENU_MANAGE_REVOKE ]; let getApprovals = await getApprovalsArray(); - let options = [] - getApprovals.forEach((item) => { - options.push(`From ${item.from} to ${item.to}`) - }) + if (getApprovals.length > 0) { + let options = [] + getApprovals.forEach((item) => { + options.push(`From ${item.from} to ${item.to}`) + }) - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { - cancel: 'Return' - }); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); - - let index2 = readlineSync.keyInSelect(manageOptions, 'What do you want to do?', { - cancel: 'Return' - }); - let optionSelected2 = manageOptions[index2]; - console.log('Selected:', index2 != -1 ? optionSelected2 : 'Return', '\n'); + let index = readlineSync.keyInSelect(options, 'Select an existing approval: ', { + cancel: 'RETURN' + }); + let optionSelected = index != -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); - const addrs = optionSelected.replace("From ", "").replace(" to ", ",").split(','); + if (optionSelected !== 'RETURN') { + let selectedApproval = getApprovals[index]; - switch (optionSelected2) { - case MATM_MANAGE_INCRESE: - await matmManageIncrese(addrs[0], addrs[1]); - break; - case MATM_MANAGE_DECREASE: - await matmManageDecrease(addrs[0], addrs[1]); - break; - case MATM_MANAGE_TIME: - await matmManageTime(addrs[0], addrs[1]); - break; - case MATM_MANAGE_REVOKE: - await matmManageRevoke(addrs[0], addrs[1]); - break; + let index2 = readlineSync.keyInSelect(manageOptions, 'What do you want to do?', { + cancel: 'RETURN' + }); + let optionSelected2 = index2 != -1 ? manageOptions[index2] : 'RETURN'; + console.log('Selected:', optionSelected2, '\n'); + + if (optionSelected2 !== 'RETURN') { + + + switch (optionSelected2) { + case MATM_MENU_MANAGE_INCRESE: + await matmManageIncrese(selectedApproval); + break; + case MATM_MENU_MANAGE_DECREASE: + await matmManageDecrease(selectedApproval); + break; + case MATM_MENU_MANAGE_TIME: + await matmManageTime(selectedApproval); + break; + case MATM_MENU_MANAGE_REVOKE: + await matmManageRevoke(selectedApproval); + break; + } + } + } + } else { + console.log(chalk.yellow(`There are no existing approvals to show`)); } } @@ -701,96 +714,84 @@ async function matmExplore() { async function matmOperate() { let operateOptions = [ - MATM_OPERATE_ADD, - MATM_OPERATE_MODIFY, - MATM_OPERATE_REVOKE + MATM_MENU_OPERATE_ADD, + MATM_MENU_OPERATE_MODIFY, + MATM_MENU_OPERATE_REVOKE ]; let index = readlineSync.keyInSelect(operateOptions, 'What do you want to do?', { - cancel: 'Return' + cancel: 'RETURN' }); - let optionSelected = operateOptions[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + let optionSelected = index != -1 ? operateOptions[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { - case MATM_OPERATE_ADD: + case MATM_MENU_OPERATE_ADD: await addManualApproveInBatch(); break; - case MATM_OPERATE_MODIFY: + case MATM_MENU_OPERATE_MODIFY: await modifyManualApproveInBatch(); break; - case MATM_OPERATE_REVOKE: + case MATM_MENU_OPERATE_REVOKE: await revokeManualApproveInBatch(); break; } } -async function getApprovalDetail(from, to) { - let detail = await currentTransferManager.methods.getApprovalDetails(from, to).call(); - return { - "expiryTime": detail[0], - "allowance": detail[1], - "description": detail[2] - } -} - -async function matmManageIncrese(from, to) { - let detail = await getApprovalDetail(from, to) - let allowance = readlineSync.question(`Enter a value to increased allowance: `, { +async function matmManageIncrese(selectedApproval) { + let allowance = readlineSync.question(`Enter a value to increase allowance (current allowance = ${web3.utils.fromWei(selectedApproval.allowance)}): `, { limit: function (input) { return parseFloat(input) > 0 }, limitMessage: "Amount must be bigger than 0" }); - let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(from, to, parseInt(detail.expiryTime), web3.utils.toWei(allowance), detail.description, 1); + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(selectedApproval.expiryTime), web3.utils.toWei(allowance), selectedApproval.description, 1); await common.sendTransaction(modifyManualApprovalAction); - console.log(chalk.green(`The row has been modify successfully!`)); + console.log(chalk.green(`The approval allowance has been increased successfully!`)); } -async function matmManageDecrease(from, to) { - let detail = await getApprovalDetail(from, to); - let allowance = readlineSync.question(`Enter a value to decrease allowance: `, { +async function matmManageDecrease(selectedApproval) { + let allowance = readlineSync.question(`Enter a value to decrease allowance (current allowance = ${web3.utils.fromWei(selectedApproval.allowance)}): `, { limit: function (input) { return parseFloat(input) > 0 }, limitMessage: "Amount must be bigger than 0" }); - let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(from, to, parseInt(detail.expiryTime), web3.utils.toWei(allowance), detail.description, 0); + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(selectedApproval.expiryTime), web3.utils.toWei(allowance), selectedApproval.description, 0); await common.sendTransaction(modifyManualApprovalAction); - console.log(chalk.green(`The row has been modify successfully!`)); + console.log(chalk.green(`The approval allowance has been decreased successfully!`)); } -async function matmManageTime(from, to) { - let detail = await getApprovalDetail(from, to); - let expiryTime = readlineSync.questionInt(`Enter the new time(Unix Epoch time) until which the transfer is allowed: `, { +async function matmManageTime(selectedApproval) { + let expiryTime = readlineSync.questionInt(`Enter the new expiry time (Unix Epoch time) until which the transfer is allowed (current expiry time = ${selectedApproval.expiryTime}): `, { limit: function (input) { return parseFloat(input) > 0 }, limitMessage: "Enter Unix Epoch time" }); - let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(from, to, parseInt(expiryTime), detail.allowance, detail.description, 2); + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(expiryTime), selectedApproval.allowance, selectedApproval.description, 2); await common.sendTransaction(modifyManualApprovalAction); - console.log(chalk.green(`The row has been modify successfully!`)); + console.log(chalk.green(`The approval expiry time has been modified successfully!`)); } -async function matmManageRevoke(from, to) { - let modifyManualApprovalAction = currentTransferManager.methods.revokeManualApproval(from, to); +async function matmManageRevoke(selectedApproval) { + let modifyManualApprovalAction = currentTransferManager.methods.revokeManualApproval(selectedApproval.from, selectedApproval.to); await common.sendTransaction(modifyManualApprovalAction); - console.log(chalk.green(`The row has been revoke successfully!`)); + console.log(chalk.green(`The approval has been revoked successfully!`)); } async function getApprovalsArray() { - let address = readlineSync.question('Enter an address to filter or leave empty to get all the rows: ', { + let address = readlineSync.question('Enter an address to filter or leave empty to get all the approvals: ', { limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address", - defaultInput: ZERO + defaultInput: gbl.constants.ADDRESS_ZERO }); - if (address == ZERO) { + if (address == gbl.constants.ADDRESS_ZERO) { return await getApprovals(); } else { let approvalsIndex = await getApprovalsToAnAddress(address); @@ -811,13 +812,13 @@ async function processApprovalsArray(array) { } function printMatmRow(from, to, allowance, time, description) { - console.log(`\nFrom ${from} to ${to}\nAllowance: ${web3.utils.fromWei(allowance)}\nExpiry time: ${moment.unix(time).format('MMMM Do YYYY')}\nDescription: ${web3.utils.toAscii(description)}\n\n`); + console.log(`\nDescription: ${web3.utils.toAscii(description)}\nFrom ${from} to ${to}\nAllowance: ${web3.utils.fromWei(allowance)}\nExpiry time: ${moment.unix(time).format('MMMM Do YYYY HH:mm')}\n`); } async function getApprovals() { let totalApprovals = await currentTransferManager.methods.getTotalApprovalsLength().call(); let results = []; - for (let i = 0; i < totalApprovals; i++) { + for (let i = 0; i < totalApprovals; i++) { results.push(await currentTransferManager.methods.approvals(i).call()); } return results; @@ -861,11 +862,11 @@ async function addManualApproveInBatch() { var f = (row) => { return (web3.utils.isAddress(row[0]) && - web3.utils.isAddress(row[1]) && - parseFloat(row[2]) > 0 && - moment.unix(row[3]).isValid() && - typeof row[4] === 'string' && - getBinarySize(row[4]) < 33) + web3.utils.isAddress(row[1]) && + parseFloat(row[2]) > 0 && + moment.unix(row[3]).isValid() && + typeof row[4] === 'string' && + getBinarySize(row[4]) < 33) } let batches = await matmGenericCsv(ADD_MANUAL_APPROVAL_DATA_CSV, f) @@ -877,7 +878,7 @@ async function addManualApproveInBatch() { allowanceArray[batch] = allowanceArray[batch].map(a => web3.utils.toWei(new web3.utils.BN(a))); let action = await currentTransferManager.methods.addManualApprovalMulti(fromArray[batch], toArray[batch], allowanceArray[batch], expiryArray[batch], descriptionArray[batch]); let receipt = await common.sendTransaction(action); - console.log(chalk.green('Add manual approval transaction was successful.')); + console.log(chalk.green('Add multiple manual approvals transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } } @@ -886,7 +887,7 @@ async function revokeManualApproveInBatch() { var f = (row) => { return (web3.utils.isAddress(row[0]) && - web3.utils.isAddress(row[1])) + web3.utils.isAddress(row[1])) } let batches = await matmGenericCsv(REVOKE_MANUAL_APPROVAL_DATA_CSV, f) @@ -896,7 +897,7 @@ async function revokeManualApproveInBatch() { console.log(`Batch ${batch + 1} - Attempting to revoke manual approvals`, '\n'); let action = await currentTransferManager.methods.revokeManualApprovalMulti(fromArray[batch], toArray[batch]); let receipt = await common.sendTransaction(action); - console.log(chalk.green('Revoke manual approval transaction was successful.')); + console.log(chalk.green('Revoke multip;e manual approvals transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } } @@ -905,12 +906,12 @@ async function modifyManualApproveInBatch() { var f = (row) => { return (web3.utils.isAddress(row[0]) && - web3.utils.isAddress(row[1]) && - moment.unix(row[3]).isValid() && - parseFloat(row[2]) > 0 && - typeof row[4] === 'string' && - getBinarySize(row[4]) < 33 && - parseInt(row[5])) + web3.utils.isAddress(row[1]) && + moment.unix(row[3]).isValid() && + parseFloat(row[2]) > 0 && + typeof row[4] === 'string' && + getBinarySize(row[4]) < 33 && + parseInt(row[5])) } let batches = await matmGenericCsv(MODIFY_MANUAL_APPROVAL_DATA_CSV, f) @@ -923,7 +924,7 @@ async function modifyManualApproveInBatch() { changesArray[batch] = changesArray[batch].map(c => parseInt(c)); let action = await currentTransferManager.methods.modifyManualApprovalMulti(fromArray[batch], toArray[batch], expiryArray[batch], allowanceArray[batch], descriptionArray[batch], changesArray[batch]); let receipt = await common.sendTransaction(action); - console.log(chalk.green('Modify manual approval transaction was successful.')); + console.log(chalk.green('Modify multiple manual approvals transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } } diff --git a/CLI/data/Transfer/MATM/manualapproval_data.csv b/CLI/data/Transfer/MATM/add_manualapproval_data.csv similarity index 100% rename from CLI/data/Transfer/MATM/manualapproval_data.csv rename to CLI/data/Transfer/MATM/add_manualapproval_data.csv From a10e0c03a2bea96436d093510ab607c64cdde8f7 Mon Sep 17 00:00:00 2001 From: shuffledex Date: Fri, 14 Dec 2018 11:49:12 -0300 Subject: [PATCH 430/582] fix modify batch --- CLI/commands/transfer_manager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index d2e1a9f83..62a446192 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -906,11 +906,11 @@ async function modifyManualApproveInBatch() { var f = (row) => { return (web3.utils.isAddress(row[0]) && web3.utils.isAddress(row[1]) && - moment.unix(row[3]).isValid() && - parseFloat(row[2]) > 0 && + moment.unix(row[2]).isValid() && + parseFloat(row[3]) > 0 && typeof row[4] === 'string' && getBinarySize(row[4]) < 33 && - parseInt(row[5])) + typeof parseInt(row[5])) === 'number' } let batches = await matmGenericCsv(MODIFY_MANUAL_APPROVAL_DATA_CSV, f) From 4c40494cbd74a44ed4ac0c0ca3ac86f1c92f7342 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 14 Dec 2018 20:20:34 +0530 Subject: [PATCH 431/582] Increased no o/p timeout --- .circleci/config.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 986c13c2d..a39d287a0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,7 +48,9 @@ jobs: - run: sudo npm i truffle -g - run: node --version - run: truffle version - - run: npm run coverage + - run: + command: npm run coverage + no_output_timeout: 1h - save_cache: key: dependency-cache-{{ checksum "package.json" }} paths: @@ -95,4 +97,4 @@ workflows: filters: branches: only: - - master \ No newline at end of file + - master From 4d481872ff2864284f54a27a17ca1090228ae48c Mon Sep 17 00:00:00 2001 From: shuffledex Date: Fri, 14 Dec 2018 11:59:11 -0300 Subject: [PATCH 432/582] Improve menu string --- CLI/commands/transfer_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 2751412ea..86ca2771f 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -663,7 +663,7 @@ async function matmManage() { if (getApprovals.length > 0) { let options = [] getApprovals.forEach((item) => { - options.push(`From ${item.from} to ${item.to}`) + options.push(`${web3.utils.toAscii(item.description)}\nFrom: ${item.from}\nTo: ${item.to}\nAmount: ${web3.utils.fromWei(item.allowance)}\nExpiry date: ${moment.unix(item.expiryTime).format('MM/DD/YYYY HH:mm')}\n`) }) let index = readlineSync.keyInSelect(options, 'Select an existing approval: ', { From 115f3b1c3ef6cc3fd4ed224e45970bac43d7fb05 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 14 Dec 2018 20:45:19 +0530 Subject: [PATCH 433/582] Triggering CircleCI --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f1aed51ad..dac654947 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,4 @@ allFiredEvents extract/ extract.py extract.zip -/test-results \ No newline at end of file +/test-results From b53d90441a1b66337f1ac4b4164886d248c9963b Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 14 Dec 2018 12:28:27 -0300 Subject: [PATCH 434/582] CLI minor changes --- CLI/commands/transfer_manager.js | 70 ++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 86ca2771f..583b596c7 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -22,7 +22,7 @@ const MATM_MENU_EXPLORE = 'Explore account'; const MATM_MENU_OPERATE = 'Operate with multiple approvals'; const MATM_MENU_MANAGE_INCRESE = 'Increase allowance'; const MATM_MENU_MANAGE_DECREASE = 'Decrease allowance'; -const MATM_MENU_MANAGE_TIME = 'Modify expiry time'; +const MATM_MENU_MANAGE_TIME = 'Modify expiry time and/or description'; const MATM_MENU_MANAGE_REVOKE = 'Revoke this approval'; const MATM_MENU_OPERATE_ADD = 'Add multiple approvals in batch'; const MATM_MENU_OPERATE_MODIFY = 'Modify multiple approvals in batch'; @@ -596,10 +596,10 @@ async function manualApprovalTransferManager() { ]; let index = readlineSync.keyInSelect(matmOptions, 'What do you want to do?', { - cancel: 'Return' + cancel: 'RETURN' }); - let optionSelected = matmOptions[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); + let optionSelected = index != -1 ? matmOptions[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case MATM_MENU_ADD: @@ -614,7 +614,11 @@ async function manualApprovalTransferManager() { case MATM_MENU_OPERATE: await matmOperate(); break; + case 'RETURN': + return; } + + await manualApprovalTransferManager(); } async function matmAdd() { @@ -663,7 +667,7 @@ async function matmManage() { if (getApprovals.length > 0) { let options = [] getApprovals.forEach((item) => { - options.push(`${web3.utils.toAscii(item.description)}\nFrom: ${item.from}\nTo: ${item.to}\nAmount: ${web3.utils.fromWei(item.allowance)}\nExpiry date: ${moment.unix(item.expiryTime).format('MM/DD/YYYY HH:mm')}\n`) + options.push(`${web3.utils.toAscii(item.description)}\n From: ${item.from}\n To: ${item.to}\n Amount: ${web3.utils.fromWei(item.allowance)} ${tokenSymbol}\n Expiry date: ${moment.unix(item.expiryTime).format('MM/DD/YYYY HH:mm')}\n`) }) let index = readlineSync.keyInSelect(options, 'Select an existing approval: ', { @@ -682,8 +686,6 @@ async function matmManage() { console.log('Selected:', optionSelected2, '\n'); if (optionSelected2 !== 'RETURN') { - - switch (optionSelected2) { case MATM_MENU_MANAGE_INCRESE: await matmManageIncrese(selectedApproval); @@ -692,7 +694,7 @@ async function matmManage() { await matmManageDecrease(selectedApproval); break; case MATM_MENU_MANAGE_TIME: - await matmManageTime(selectedApproval); + await matmManageTimeOrDescription(selectedApproval); break; case MATM_MENU_MANAGE_REVOKE: await matmManageRevoke(selectedApproval); @@ -746,6 +748,12 @@ async function matmManageIncrese(selectedApproval) { limitMessage: "Amount must be bigger than 0" }); + if (readlineSync.keyInYNStrict(`Do you want to modify expiry time or description?`)) { + let { expiryTime, description } = readExpiryTimeAndDescription(selectedApproval); + selectedApproval.expiryTime = expiryTime; + selectedApproval.description = web3.utils.fromAscii(description); + } + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(selectedApproval.expiryTime), web3.utils.toWei(allowance), selectedApproval.description, 1); await common.sendTransaction(modifyManualApprovalAction); console.log(chalk.green(`The approval allowance has been increased successfully!`)); @@ -759,24 +767,42 @@ async function matmManageDecrease(selectedApproval) { limitMessage: "Amount must be bigger than 0" }); + if (readlineSync.keyInYNStrict(`Do you want to modify expiry time or description?`)) { + let { expiryTime, description } = readExpiryTimeAndDescription(selectedApproval); + selectedApproval.expiryTime = expiryTime; + selectedApproval.description = web3.utils.fromAscii(description); + } + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(selectedApproval.expiryTime), web3.utils.toWei(allowance), selectedApproval.description, 0); await common.sendTransaction(modifyManualApprovalAction); console.log(chalk.green(`The approval allowance has been decreased successfully!`)); } -async function matmManageTime(selectedApproval) { - let expiryTime = readlineSync.questionInt(`Enter the new expiry time (Unix Epoch time) until which the transfer is allowed (current expiry time = ${selectedApproval.expiryTime}): `, { - limit: function (input) { - return parseFloat(input) > 0 - }, - limitMessage: "Enter Unix Epoch time" - }); +async function matmManageTimeOrDescription(selectedApproval) { + let { expiryTime, description } = readExpiryTimeAndDescription(selectedApproval); - let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(expiryTime), selectedApproval.allowance, selectedApproval.description, 2); + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(expiryTime), selectedApproval.allowance, web3.utils.fromAscii(description), 2); await common.sendTransaction(modifyManualApprovalAction); console.log(chalk.green(`The approval expiry time has been modified successfully!`)); } +function readExpiryTimeAndDescription(selectedApproval) { + let expiryTime = readlineSync.questionInt(`Enter the new expiry time (Unix Epoch time) until which the transfer is allowed or leave empty to keep the current (${selectedApproval.expiryTime}): `, { + limit: function (input) { + return parseFloat(input) > 0; + }, + limitMessage: "Enter Unix Epoch time", + defaultInput: selectedApproval.expiryTime + }); + let description = readlineSync.question(`Enter the new description for the manual approval or leave empty to keep the current (${web3.utils.toAscii(selectedApproval.description)}): `, { + limit: function (input) { + return input != "" && getBinarySize(input) < 33; + }, + limitMessage: "Description is required" + }); + return { expiryTime, description }; +} + async function matmManageRevoke(selectedApproval) { let modifyManualApprovalAction = currentTransferManager.methods.revokeManualApproval(selectedApproval.from, selectedApproval.to); await common.sendTransaction(modifyManualApprovalAction); @@ -906,12 +932,12 @@ async function modifyManualApproveInBatch() { var f = (row) => { return (web3.utils.isAddress(row[0]) && - web3.utils.isAddress(row[1]) && - moment.unix(row[2]).isValid() && - parseFloat(row[3]) > 0 && - typeof row[4] === 'string' && - getBinarySize(row[4]) < 33 && - typeof parseInt(row[5])) === 'number' + web3.utils.isAddress(row[1]) && + moment.unix(row[2]).isValid() && + parseFloat(row[3]) > 0 && + typeof row[4] === 'string' && + getBinarySize(row[4]) < 33 && + typeof parseInt(row[5])) === 'number' } let batches = await matmGenericCsv(MODIFY_MANUAL_APPROVAL_DATA_CSV, f) From cbd2f5724d5d4460a787f86745b0be455aae1fcf Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Fri, 14 Dec 2018 18:49:03 +0000 Subject: [PATCH 435/582] Add ability to see excluded addresses --- .../modules/Checkpoint/DividendCheckpoint.sol | 9 ++++++ .../Checkpoint/DividendCheckpointStorage.sol | 1 + .../Checkpoint/ERC20DividendCheckpoint.sol | 1 + .../Checkpoint/EtherDividendCheckpoint.sol | 3 +- test/e_erc20_dividends.js | 28 ++++++++++++++++++- 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 3a345af25..9d7858ceb 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -226,6 +226,15 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { */ function withdrawWithholding(uint256 _dividendIndex) external; + /** + * @notice Retrieves list of excluded addresses for a dividend + * @param _dividendIndex Dividend to withdraw from + */ + function getExcluded(uint256 _dividendIndex) external view returns (address[]) { + require(_dividendIndex < dividends.length, "Invalid dividend"); + return dividends[_dividendIndex].excluded; + } + /** * @notice Return the permissions flag that are associated with this module * @return bytes32 array diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol index 4cf1f2838..f56a35bc9 100644 --- a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -25,6 +25,7 @@ contract DividendCheckpointStorage { uint256 dividendWithheldReclaimed; mapping (address => bool) claimed; // List of addresses which have claimed dividend mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends + address[] excluded; bytes32 name; // Name/title - used for identification } diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index b779088f7..54d130940 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -192,6 +192,7 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec false, 0, 0, + _excluded, _name ) ); diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index f5a916818..d58886549 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -8,7 +8,7 @@ import "../../interfaces/IOwnable.sol"; */ contract EtherDividendCheckpoint is DividendCheckpoint { using SafeMath for uint256; - + event EtherDividendDeposited( address indexed _depositor, uint256 _checkpointId, @@ -147,6 +147,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { false, 0, 0, + _excluded, _name ) ); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 1b2bd7482..1dcbb396e 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -412,7 +412,10 @@ contract("ERC20DividendCheckpoint", accounts => { dividendName, { from: token_owner } ); + console.log("Gas used w/ no exclusions: " + tx.receipt.gasUsed); + let excluded = await I_ERC20DividendCheckpoint.getExcluded.call(tx.logs[0].args._dividendIndex); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 1"); + assert.equal(excluded.length, 0, "Dividend has no exclusions"); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails past expiry", async () => { @@ -493,6 +496,17 @@ contract("ERC20DividendCheckpoint", accounts => { await catchRevert(I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { from: token_owner })); }); + it("Set EXCLUDED_ADDRESS_LIMIT number of addresses to excluded", async () => { + let limit = await I_ERC20DividendCheckpoint.EXCLUDED_ADDRESS_LIMIT(); + limit = limit.toNumber(); + let addresses = []; + addresses.push(account_temp); + while (--limit) addresses.push(limit); + await I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { from: token_owner }); + let excluded = await I_ERC20DividendCheckpoint.getDefaultExcluded(); + assert.equal(excluded[0], account_temp); + }); + it("Create another new dividend", async () => { let maturity = latestTime(); let expiry = latestTime() + duration.days(10); @@ -506,7 +520,10 @@ contract("ERC20DividendCheckpoint", accounts => { dividendName, { from: token_owner } ); + console.log("Gas used w/ 50 exclusions - default: " + tx.receipt.gasUsed); + let excluded = await I_ERC20DividendCheckpoint.getExcluded.call(tx.logs[0].args._dividendIndex); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 2"); + assert.equal(excluded.length, 50, "Dividend "); }); it("should investor 3 claims dividend - fail bad index", async () => { @@ -1062,7 +1079,13 @@ contract("ERC20DividendCheckpoint", accounts => { it("should allow manager with permission to create dividend with exclusion", async () => { let maturity = latestTime() + duration.days(1); let expiry = latestTime() + duration.days(10); - let exclusions = [1]; + + let limit = await I_ERC20DividendCheckpoint.EXCLUDED_ADDRESS_LIMIT(); + limit = limit.toNumber(); + let exclusions = []; + exclusions.push(account_temp); + while (--limit) exclusions.push(limit); + let tx = await I_ERC20DividendCheckpoint.createDividendWithExclusions( maturity, expiry, @@ -1073,6 +1096,9 @@ contract("ERC20DividendCheckpoint", accounts => { { from: account_manager } ); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 9); + console.log("Gas used w/ 50 exclusions - non-default: " + tx.receipt.gasUsed); + let excluded = await I_ERC20DividendCheckpoint.getExcluded.call(tx.logs[0].args._dividendIndex); + assert.equal(excluded.length, 50, "Dividend exclusions should match"); }); it("should allow manager with permission to create dividend with checkpoint and exclusion", async () => { From c0f5594630f74dbb292d63f1d925df8d750d4fff Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 16 Dec 2018 20:23:46 +0000 Subject: [PATCH 436/582] Updates --- .../modules/Checkpoint/DividendCheckpoint.sol | 18 ++++++++++++--- .../Checkpoint/DividendCheckpointStorage.sol | 1 - .../Checkpoint/ERC20DividendCheckpoint.sol | 1 - .../Checkpoint/EtherDividendCheckpoint.sol | 1 - test/e_erc20_dividends.js | 22 ++++++++++--------- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 9d7858ceb..708b2351c 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -227,12 +227,24 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { function withdrawWithholding(uint256 _dividendIndex) external; /** - * @notice Retrieves list of excluded addresses for a dividend + * @notice Retrieves list of investors, their claim status and whether they are excluded * @param _dividendIndex Dividend to withdraw from + * @return address[] list of investors + * @return bool[] whether investor has claimed + * @return bool[] whether investor is excluded */ - function getExcluded(uint256 _dividendIndex) external view returns (address[]) { + function getDividendInfo(uint256 _dividendIndex) external view returns (address[], bool[], bool[]) { require(_dividendIndex < dividends.length, "Invalid dividend"); - return dividends[_dividendIndex].excluded; + //Get list of Investors + uint256 checkpointId = dividends[_dividendIndex].checkpointId; + address[] memory investors = ISecurityToken(securityToken).getInvestorsAt(checkpointId); + bool[] memory resultClaimed = new bool[](investors.length); + bool[] memory resultExcluded = new bool[](investors.length); + for (uint256 i; i < investors.length; i++) { + resultClaimed[i] = dividends[_dividendIndex].claimed[investors[i]]; + resultExcluded[i] = dividends[_dividendIndex].dividendExcluded[investors[i]]; + } + return (investors, resultClaimed, resultExcluded); } /** diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol index f56a35bc9..4cf1f2838 100644 --- a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -25,7 +25,6 @@ contract DividendCheckpointStorage { uint256 dividendWithheldReclaimed; mapping (address => bool) claimed; // List of addresses which have claimed dividend mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends - address[] excluded; bytes32 name; // Name/title - used for identification } diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 54d130940..b779088f7 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -192,7 +192,6 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec false, 0, 0, - _excluded, _name ) ); diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index d58886549..e1cb3174c 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -147,7 +147,6 @@ contract EtherDividendCheckpoint is DividendCheckpoint { false, 0, 0, - _excluded, _name ) ); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 1dcbb396e..416078971 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -413,9 +413,8 @@ contract("ERC20DividendCheckpoint", accounts => { { from: token_owner } ); console.log("Gas used w/ no exclusions: " + tx.receipt.gasUsed); - let excluded = await I_ERC20DividendCheckpoint.getExcluded.call(tx.logs[0].args._dividendIndex); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 1"); - assert.equal(excluded.length, 0, "Dividend has no exclusions"); + console.log(await I_ERC20DividendCheckpoint.getDividendInfo.call(tx.logs[0].args._dividendIndex)); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails past expiry", async () => { @@ -500,11 +499,9 @@ contract("ERC20DividendCheckpoint", accounts => { let limit = await I_ERC20DividendCheckpoint.EXCLUDED_ADDRESS_LIMIT(); limit = limit.toNumber(); let addresses = []; - addresses.push(account_temp); while (--limit) addresses.push(limit); await I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { from: token_owner }); let excluded = await I_ERC20DividendCheckpoint.getDefaultExcluded(); - assert.equal(excluded[0], account_temp); }); it("Create another new dividend", async () => { @@ -520,10 +517,9 @@ contract("ERC20DividendCheckpoint", accounts => { dividendName, { from: token_owner } ); - console.log("Gas used w/ 50 exclusions - default: " + tx.receipt.gasUsed); - let excluded = await I_ERC20DividendCheckpoint.getExcluded.call(tx.logs[0].args._dividendIndex); + console.log("Gas used w/ max exclusions - default: " + tx.receipt.gasUsed); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 2"); - assert.equal(excluded.length, 50, "Dividend "); + console.log(await I_ERC20DividendCheckpoint.getDividendInfo.call(tx.logs[0].args._dividendIndex)); }); it("should investor 3 claims dividend - fail bad index", async () => { @@ -539,9 +535,14 @@ contract("ERC20DividendCheckpoint", accounts => { let investor1BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); let investor2BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); let investor3BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); + console.log(await I_ERC20DividendCheckpoint.dividends(2)); assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei("7", "ether")); + let info = await I_ERC20DividendCheckpoint.getDividendInfo.call(2); + console.log(info); + // assert.equal(info[0][2], account_temp, "account_temp is excluded"); + // assert.equal(info[2][2], true, "account_temp is excluded"); }); it("should investor 3 claims dividend - fails already claimed", async () => { @@ -1096,9 +1097,10 @@ contract("ERC20DividendCheckpoint", accounts => { { from: account_manager } ); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 9); - console.log("Gas used w/ 50 exclusions - non-default: " + tx.receipt.gasUsed); - let excluded = await I_ERC20DividendCheckpoint.getExcluded.call(tx.logs[0].args._dividendIndex); - assert.equal(excluded.length, 50, "Dividend exclusions should match"); + console.log("Gas used w/ max exclusions - non-default: " + tx.receipt.gasUsed); + let info = await I_ERC20DividendCheckpoint.getDividendInfo.call(tx.logs[0].args._dividendIndex); + assert.equal(info[0][2], account_temp, "account_temp is excluded"); + assert.equal(info[2][2], true, "account_temp is excluded"); }); it("should allow manager with permission to create dividend with checkpoint and exclusion", async () => { From 5574125aa37735e2e6cf49b23f8ce89e392aafe6 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 16 Dec 2018 20:57:32 +0000 Subject: [PATCH 437/582] Fixes --- .../modules/Checkpoint/DividendCheckpoint.sol | 20 ++++++++++++++++++ test/e_erc20_dividends.js | 21 ++++++------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 708b2351c..497f6a5bc 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -247,6 +247,26 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { return (investors, resultClaimed, resultExcluded); } + /** + * @notice Checks whether an address is excluded from claiming a dividend + * @param _dividendIndex Dividend to withdraw from + * @return bool whether the address is excluded + */ + function isExcluded(address _investor, uint256 _dividendIndex) external view returns (bool) { + require(_dividendIndex < dividends.length, "Invalid dividend"); + return dividends[_dividendIndex].dividendExcluded[_investor]; + } + + /** + * @notice Checks whether an address has claimed a dividend + * @param _dividendIndex Dividend to withdraw from + * @return bool whether the address has claimed + */ + function isClaimed(address _investor, uint256 _dividendIndex) external view returns (bool) { + require(_dividendIndex < dividends.length, "Invalid dividend"); + return dividends[_dividendIndex].claimed[_investor]; + } + /** * @notice Return the permissions flag that are associated with this module * @return bytes32 array diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 416078971..b0256eec0 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -414,7 +414,6 @@ contract("ERC20DividendCheckpoint", accounts => { ); console.log("Gas used w/ no exclusions: " + tx.receipt.gasUsed); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 2, "Dividend should be created at checkpoint 1"); - console.log(await I_ERC20DividendCheckpoint.getDividendInfo.call(tx.logs[0].args._dividendIndex)); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails past expiry", async () => { @@ -492,18 +491,10 @@ contract("ERC20DividendCheckpoint", accounts => { let addresses = []; addresses.push(account_temp); while (limit--) addresses.push(limit); + console.log(addresses.length); await catchRevert(I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { from: token_owner })); }); - it("Set EXCLUDED_ADDRESS_LIMIT number of addresses to excluded", async () => { - let limit = await I_ERC20DividendCheckpoint.EXCLUDED_ADDRESS_LIMIT(); - limit = limit.toNumber(); - let addresses = []; - while (--limit) addresses.push(limit); - await I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { from: token_owner }); - let excluded = await I_ERC20DividendCheckpoint.getDefaultExcluded(); - }); - it("Create another new dividend", async () => { let maturity = latestTime(); let expiry = latestTime() + duration.days(10); @@ -519,7 +510,7 @@ contract("ERC20DividendCheckpoint", accounts => { ); console.log("Gas used w/ max exclusions - default: " + tx.receipt.gasUsed); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 3, "Dividend should be created at checkpoint 2"); - console.log(await I_ERC20DividendCheckpoint.getDividendInfo.call(tx.logs[0].args._dividendIndex)); + assert.equal((await I_ERC20DividendCheckpoint.isExcluded.call(account_temp, tx.logs[0].args._dividendIndex)), true, "account_temp is excluded"); }); it("should investor 3 claims dividend - fail bad index", async () => { @@ -535,14 +526,14 @@ contract("ERC20DividendCheckpoint", accounts => { let investor1BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); let investor2BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); let investor3BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); - console.log(await I_ERC20DividendCheckpoint.dividends(2)); assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei("7", "ether")); let info = await I_ERC20DividendCheckpoint.getDividendInfo.call(2); - console.log(info); - // assert.equal(info[0][2], account_temp, "account_temp is excluded"); - // assert.equal(info[2][2], true, "account_temp is excluded"); + assert.equal(info[0][1], account_temp, "account_temp is excluded"); + assert.equal(info[2][1], true, "account_temp is excluded"); + assert.equal(info[0][2], account_investor3, "account_investor3 is claimed"); + assert.equal(info[1][2], true, "account_temp is claimed"); }); it("should investor 3 claims dividend - fails already claimed", async () => { From b01b826c06675f73278761d07cb788da5fdd9105 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 16 Dec 2018 21:13:22 +0000 Subject: [PATCH 438/582] Bump excluded limit to 150 --- contracts/modules/Checkpoint/DividendCheckpointStorage.sol | 2 +- test/e_erc20_dividends.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol index 4cf1f2838..fd95e7e00 100644 --- a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -6,7 +6,7 @@ pragma solidity ^0.4.24; */ contract DividendCheckpointStorage { - uint256 public EXCLUDED_ADDRESS_LIMIT = 50; + uint256 public EXCLUDED_ADDRESS_LIMIT = 150; bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; bytes32 public constant MANAGE = "MANAGE"; bytes32 public constant CHECKPOINT = "CHECKPOINT"; diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index b0256eec0..e77ff69e6 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -1077,7 +1077,7 @@ contract("ERC20DividendCheckpoint", accounts => { let exclusions = []; exclusions.push(account_temp); while (--limit) exclusions.push(limit); - + console.log(exclusions.length); let tx = await I_ERC20DividendCheckpoint.createDividendWithExclusions( maturity, expiry, From fe306e0a5189010e56fd1449aa69ac983becdcd4 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 17 Dec 2018 15:26:21 +0530 Subject: [PATCH 439/582] remove SRVTM --- .../SingleTradeVolumeRestrictionTM.sol | 331 ------------------ .../SingleTradeVolumeRestrictionTMFactory.sol | 79 ----- .../z_fuzz_test_adding_removing_modules_ST.js | 13 - test/z_general_permission_manager_fuzzer.js | 5 - 4 files changed, 428 deletions(-) delete mode 100644 contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol delete mode 100644 contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol deleted file mode 100644 index b92272167..000000000 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol +++ /dev/null @@ -1,331 +0,0 @@ -pragma solidity ^0.4.24; - -import "./../../TransferManager/ITransferManager.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -/** - * @title Transfer Manager for limiting volume of tokens in a single trade - */ - -contract SingleTradeVolumeRestrictionTM is ITransferManager { - using SafeMath for uint256; - - bytes32 constant public ADMIN = "ADMIN"; - - bool public isTransferLimitInPercentage; - - uint256 public globalTransferLimitInTokens; - - // should be multipled by 10^16. if the transfer percentage is 20%, then globalTransferLimitInPercentage should be 20*10^16 - uint256 public globalTransferLimitInPercentage; - - // Ignore transactions which are part of the primary issuance - bool public allowPrimaryIssuance = true; - - //mapping to store the wallets that are exempted from the volume restriction - mapping(address => bool) public exemptWallets; - - //addresses on this list have special transfer restrictions apart from global - mapping(address => uint) public specialTransferLimitsInTokens; - - mapping(address => uint) public specialTransferLimitsInPercentages; - - event ExemptWalletAdded(address _wallet); - event ExemptWalletRemoved(address _wallet); - event TransferLimitInTokensSet(address _wallet, uint256 _amount); - event TransferLimitInPercentageSet(address _wallet, uint _percentage); - event TransferLimitInPercentageRemoved(address _wallet); - event TransferLimitInTokensRemoved(address _wallet); - event GlobalTransferLimitInTokensSet(uint256 _amount, uint256 _oldAmount); - event GlobalTransferLimitInPercentageSet(uint256 _percentage, uint256 _oldPercentage); - event TransferLimitChangedToTokens(); - event TransferLimitChangedtoPercentage(); - event SetAllowPrimaryIssuance(bool _allowPrimaryIssuance, uint256 _timestamp); - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor(address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) - { - - } - - /** @notice Used to verify the transfer transaction and prevent an account from sending more tokens than allowed in a single transfer - * @param _from Address of the sender - * @param _amount The amount of tokens to transfer - */ - function verifyTransfer( - address _from, - address /* _to */, - uint256 _amount, - bytes /* _data */, - bool /* _isTransfer */ - ) - public - returns(Result) - { - bool validTransfer; - - if (exemptWallets[_from] || paused) return Result.NA; - - if (_from == address(0) && allowPrimaryIssuance) { - return Result.NA; - } - - if (isTransferLimitInPercentage) { - if(specialTransferLimitsInPercentages[_from] > 0) { - validTransfer = (_amount.mul(10**18).div(ISecurityToken(securityToken).totalSupply())) <= specialTransferLimitsInPercentages[_from]; - } else { - validTransfer = (_amount.mul(10**18).div(ISecurityToken(securityToken).totalSupply())) <= globalTransferLimitInPercentage; - } - } else { - if (specialTransferLimitsInTokens[_from] > 0) { - validTransfer = _amount <= specialTransferLimitsInTokens[_from]; - } else { - validTransfer = _amount <= globalTransferLimitInTokens; - } - } - if (validTransfer) return Result.NA; - return Result.INVALID; - } - - /** - * @notice Used to intialize the variables of the contract - * @param _isTransferLimitInPercentage true if the transfer limit is in percentage else false - * @param _globalTransferLimitInPercentageOrToken transfer limit per single transaction. - */ - function configure( - bool _isTransferLimitInPercentage, - uint256 _globalTransferLimitInPercentageOrToken, - bool _allowPrimaryIssuance - ) public onlyFactory { - isTransferLimitInPercentage = _isTransferLimitInPercentage; - if (isTransferLimitInPercentage) { - changeGlobalLimitInPercentage(_globalTransferLimitInPercentageOrToken); - } else { - changeGlobalLimitInTokens(_globalTransferLimitInPercentageOrToken); - } - allowPrimaryIssuance = _allowPrimaryIssuance; - } - - /** - * @notice Sets whether or not to consider primary issuance transfers - * @param _allowPrimaryIssuance whether to allow all primary issuance transfers - */ - function setAllowPrimaryIssuance(bool _allowPrimaryIssuance) public withPerm(ADMIN) { - require(_allowPrimaryIssuance != allowPrimaryIssuance, "Must change setting"); - allowPrimaryIssuance = _allowPrimaryIssuance; - /*solium-disable-next-line security/no-block-members*/ - emit SetAllowPrimaryIssuance(_allowPrimaryIssuance, now); - } - - /** - * @notice Changes the manager to use transfer limit as Percentages - * @param _newGlobalTransferLimitInPercentage uint256 new global Transfer Limit In Percentage. - * @dev specialTransferLimits set for wallets have to re-configured - */ - function changeTransferLimitToPercentage(uint256 _newGlobalTransferLimitInPercentage) public withPerm(ADMIN) { - require(!isTransferLimitInPercentage, "Transfer limit already in percentage"); - isTransferLimitInPercentage = true; - changeGlobalLimitInPercentage(_newGlobalTransferLimitInPercentage); - emit TransferLimitChangedtoPercentage(); - } - - /** - * @notice Changes the manager to use transfer limit as tokens - * @param _newGlobalTransferLimit uint256 new global Transfer Limit in tokens. - * @dev specialTransferLimits set for wallets have to re-configured - */ - function changeTransferLimitToTokens(uint _newGlobalTransferLimit) public withPerm(ADMIN) { - require(isTransferLimitInPercentage, "Transfer limit already in tokens"); - isTransferLimitInPercentage = false; - changeGlobalLimitInTokens(_newGlobalTransferLimit); - emit TransferLimitChangedToTokens(); - } - /** - * @notice Changes the global transfer limit - * @param _newGlobalTransferLimitInTokens new transfer limit in tokens - * @dev This function can be used only when The manager is configured to use limits in tokens - */ - function changeGlobalLimitInTokens(uint256 _newGlobalTransferLimitInTokens) public withPerm(ADMIN) { - require(!isTransferLimitInPercentage, "Transfer limit not set in tokens"); - require(_newGlobalTransferLimitInTokens > 0, "Transfer limit has to greater than zero"); - emit GlobalTransferLimitInTokensSet(_newGlobalTransferLimitInTokens, globalTransferLimitInTokens); - globalTransferLimitInTokens = _newGlobalTransferLimitInTokens; - - } - - /** - * @notice Changes the global transfer limit - * @param _newGlobalTransferLimitInPercentage new transfer limit in percentage. - * Multiply the percentage by 10^16. Eg 22% will be 22*10^16 - * @dev This function can be used only when The manager is configured to use limits in percentage - */ - function changeGlobalLimitInPercentage(uint256 _newGlobalTransferLimitInPercentage) public withPerm(ADMIN) { - require(isTransferLimitInPercentage, "Transfer limit not set in Percentage"); - require(_newGlobalTransferLimitInPercentage > 0 && _newGlobalTransferLimitInPercentage <= 100 * 10 ** 16, "Limit not within [0,100]"); - emit GlobalTransferLimitInPercentageSet(_newGlobalTransferLimitInPercentage, globalTransferLimitInPercentage); - globalTransferLimitInPercentage = _newGlobalTransferLimitInPercentage; - - } - - /** - * @notice Adds an exempt wallet - * @param _wallet exempt wallet address - */ - function addExemptWallet(address _wallet) public withPerm(ADMIN) { - require(_wallet != address(0), "Wallet address cannot be a zero address"); - exemptWallets[_wallet] = true; - emit ExemptWalletAdded(_wallet); - } - - /** - * @notice Removes an exempt wallet - * @param _wallet exempt wallet address - */ - function removeExemptWallet(address _wallet) public withPerm(ADMIN) { - require(_wallet != address(0), "Wallet address cannot be a zero address"); - exemptWallets[_wallet] = false; - emit ExemptWalletRemoved(_wallet); - } - - /** - * @notice Adds an array of exempt wallet - * @param _wallets array of exempt wallet addresses - */ - function addExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - for (uint256 i = 0; i < _wallets.length; i++) { - addExemptWallet(_wallets[i]); - } - } - - /** - * @notice Removes an array of exempt wallet - * @param _wallets array of exempt wallet addresses - */ - function removeExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - for (uint256 i = 0; i < _wallets.length; i++) { - removeExemptWallet(_wallets[i]); - } - } - - /** - * @notice Sets transfer limit per wallet - * @param _wallet wallet address - * @param _transferLimit transfer limit for the wallet in tokens - * @dev the manager has to be configured to use limits in tokens - */ - function setTransferLimitInTokens(address _wallet, uint _transferLimit) public withPerm(ADMIN) { - require(_transferLimit > 0, "Transfer limit has to be greater than 0"); - require(!isTransferLimitInPercentage, "Transfer limit not in token amount"); - specialTransferLimitsInTokens[_wallet] = _transferLimit; - emit TransferLimitInTokensSet(_wallet, _transferLimit); - } - - /** - * @notice Sets transfer limit for a wallet - * @param _wallet wallet address - * @param _transferLimitInPercentage transfer limit for the wallet in percentage. - * Multiply the percentage by 10^16. Eg 22% will be 22*10^16 - * @dev The manager has to be configured to use percentages - */ - function setTransferLimitInPercentage(address _wallet, uint _transferLimitInPercentage) public withPerm(ADMIN) { - require(isTransferLimitInPercentage, "Transfer limit not in percentage"); - require(_transferLimitInPercentage > 0 && _transferLimitInPercentage <= 100 * 10 ** 16, "Transfer limit not in required range"); - specialTransferLimitsInPercentages[_wallet] = _transferLimitInPercentage; - emit TransferLimitInPercentageSet(_wallet, _transferLimitInPercentage); - } - - - /** - * @notice Removes transfer limit set in percentage for a wallet - * @param _wallet wallet address - */ - function removeTransferLimitInPercentage(address _wallet) public withPerm(ADMIN) { - require(specialTransferLimitsInPercentages[_wallet] > 0, "Wallet Address does not have a transfer limit"); - specialTransferLimitsInPercentages[_wallet] = 0; - emit TransferLimitInPercentageRemoved(_wallet); - } - - /** - * @notice Removes transfer limit set in tokens for a wallet - * @param _wallet wallet address - */ - function removeTransferLimitInTokens(address _wallet) public withPerm(ADMIN) { - require(specialTransferLimitsInTokens[_wallet] > 0, "Wallet Address does not have a transfer limit"); - specialTransferLimitsInTokens[_wallet] = 0; - emit TransferLimitInTokensRemoved(_wallet); - } - - /** - * @notice Sets transfer limits for an array of wallet - * @param _wallets array of wallet addresses - * @param _transferLimits array of transfer limits for each wallet in tokens - * @dev The manager has to be configured to use tokens as limit - */ - function setTransferLimitInTokensMulti(address[] _wallets, uint[] _transferLimits) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - require(_wallets.length == _transferLimits.length, "Wallets don't match to transfer limits"); - for (uint256 i = 0; i < _wallets.length; i++ ) { - setTransferLimitInTokens(_wallets[i], _transferLimits[i]); - } - } - - /** - * @notice Sets transfer limits for an array of wallet - * @param _wallets array of wallet addresses - * @param _transferLimitsInPercentage array of transfer limits for each wallet in percentages - * The percentage has to be multipled by 10 ** 16. Eg: 20% would be 20 * 10 ** 16 - * @dev The manager has to be configured to use percentage as limit - */ - function setTransferLimitInPercentageMulti(address[] _wallets, uint[] _transferLimitsInPercentage) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - require(_wallets.length == _transferLimitsInPercentage.length, "Wallets don't match to percentage limits"); - for (uint256 i = 0; i < _wallets.length; i++) { - setTransferLimitInPercentage(_wallets[i], _transferLimitsInPercentage[i]); - } - } - - /** - * @notice Removes transfer limits set in tokens for an array of wallet - * @param _wallets array of wallet addresses - */ - function removeTransferLimitInTokensMulti(address[] _wallets) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - for (uint i = 0; i < _wallets.length; i++) { - removeTransferLimitInTokens(_wallets[i]); - } - } - - /** - * @notice Removes transfer limits set in percentage for an array of wallet - * @param _wallets array of wallet addresses - */ - function removeTransferLimitInPercentageMulti(address[] _wallets) public withPerm(ADMIN) { - require(_wallets.length > 0, "Wallets cannot be empty"); - for (uint i = 0; i < _wallets.length; i++) { - removeTransferLimitInPercentage(_wallets[i]); - } - } - - /** - * @notice This function returns the signature of configure function - */ - function getInitFunction() public pure returns (bytes4) { - return bytes4(keccak256("configure(bool,uint256,bool)")); - } - - /** - * @notice Returns the permissions flag that are associated with SingleTradeVolumeRestrictionManager - */ - function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](1); - allPermissions[0] = ADMIN; - return allPermissions; - } -} diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol deleted file mode 100644 index e6d8ed2be..000000000 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol +++ /dev/null @@ -1,79 +0,0 @@ -pragma solidity ^0.4.24; - -import "./../../ModuleFactory.sol"; -import "./SingleTradeVolumeRestrictionTM.sol"; -import "../../../libraries/Util.sol"; - -/** - * @title Factory for deploying SingleTradeVolumeRestrictionManager - */ -contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { - - - /** - * @notice Constructor - * @param _polyAddress Address of the polytoken - * @param _setupCost Setup cost of the module - * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module - */ - constructor(address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { - version = "1.0.0"; - name = "SingleTradeVolumeRestrictionTM"; - title = "Single Trade Volume Restriction Manager"; - description = "Imposes volume restriction on a single trade"; - compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - } - - /** - * @notice Used to launch the Module with the help of factory - * @return address Contract address of the Module - */ - function deploy(bytes _data) external returns(address) { - if (setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - SingleTradeVolumeRestrictionTM singleTradeVolumeRestrictionManager = new SingleTradeVolumeRestrictionTM(msg.sender, address(polyToken)); - - require(Util.getSig(_data) == singleTradeVolumeRestrictionManager.getInitFunction(), "Provided data is not valid"); - /*solium-disable-next-line security/no-low-level-calls*/ - require(address(singleTradeVolumeRestrictionManager).call(_data), "Unsuccessful call"); - /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(singleTradeVolumeRestrictionManager), getName(), address(this), msg.sender, setupCost, now); - return address(singleTradeVolumeRestrictionManager); - } - - /** - * @notice Get the types of the Module factory - * @return uint8[] - */ - function getTypes() external view returns(uint8[]) { - uint8[] memory res = new uint8[](1); - res[0] = 2; - return res; - } - - /** - * @notice Get the Instructions that help to use the module - * @return string - */ - function getInstructions() external view returns(string) { - /*solium-disable-next-line max-len*/ - return "Allows an issuer to impose volume restriction on a single trade. Init function takes two parameters. First parameter is a bool indicating if restriction is in percentage. The second parameter is the value in percentage or amount of tokens"; - } - - /** - * @notice Get the tags related to the module factory - * @return bytes32[] - */ - function getTags() external view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](3); - availableTags[0] = "Single Trade"; - availableTags[1] = "Transfer"; - availableTags[2] = "Volume"; - return availableTags; - } - -} diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index e81df39aa..32d28c6ab 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -9,7 +9,6 @@ import { setUpPolymathNetwork, deployCountTMAndVerifyed, deployLockupVolumeRTMAndVerified, deployPercentageTMAndVerified, - deploySingleTradeVolumeRMAndVerified, deployManualApprovalTMAndVerifyed } from "./helpers/createInstances"; import { encodeModuleCall } from "./helpers/encodeCall"; @@ -20,7 +19,6 @@ const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager') // modules for test const CountTransferManager = artifacts.require("./CountTransferManager"); -const SingleTradeVolumeRestrictionManager = artifacts.require('./SingleTradeVolumeRestrictionTM'); const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); @@ -76,12 +74,6 @@ contract('GeneralPermissionManager', accounts => { let I_CountTransferManagerFactory; let I_CountTransferManager; - let I_SingleTradeVolumeRestrictionManagerFactory; - let I_SingleTradeVolumeRestrictionManager; - - let P_SingleTradeVolumeRestrictionManagerFactory; - let P_SingleTradeVolumeRestrictionManager; - let I_ManualApprovalTransferManagerFactory; let I_ManualApprovalTransferManager; @@ -114,7 +106,6 @@ contract('GeneralPermissionManager', accounts => { // define factories and modules for fuzz test var factoriesAndModules = [ { factory: 'I_CountTransferManagerFactory', module: 'CountTransferManager'}, - { factory: 'I_SingleTradeVolumeRestrictionManagerFactory', module: 'SingleTradeVolumeRestrictionManager'}, { factory: 'I_ManualApprovalTransferManagerFactory', module: 'ManualApprovalTransferManager'}, { factory: 'I_VolumeRestrictionTransferManagerFactory', module: 'VolumeRestrictionTransferManager'}, { factory: 'I_PercentageTransferManagerFactory', module: 'PercentageTransferManager'}, @@ -166,8 +157,6 @@ contract('GeneralPermissionManager', accounts => { // Deploy Modules [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); @@ -282,8 +271,6 @@ contract('GeneralPermissionManager', accounts => { if (random.module == 'CountTransferManager' || random.module == 'ManualApprovalTransferManager' || random.module == 'VolumeRestrictionTransferManager' ){ const holderCount = 2; // Maximum number of token holders bytesSTO = encodeModuleCall(["uint256"], [holderCount]); - } else if(random.module == 'SingleTradeVolumeRestrictionManager'){ - bytesSTO = encodeModuleCall(STVRParameters, [false, (7 * Math.pow(10, 16)).toString(), false]) } else if (random.module == 'PercentageTransferManager'){ console.log("PTM 01"); const holderPercentage = 70 * 10**16; diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index 4206991ee..24a9ce5ad 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -70,11 +70,6 @@ contract('GeneralPermissionManager', accounts => { let I_PolymathRegistry; let I_CountTransferManagerFactory; let I_CountTransferManager; - let I_SingleTradeVolumeRestrictionManagerFactory; - let I_SingleTradeVolumeRestrictionManager; - let I_SingleTradeVolumeRestrictionPercentageManager; - let P_SingleTradeVolumeRestrictionManager; - let P_SingleTradeVolumeRestrictionManagerFactory; let I_ManualApprovalTransferManagerFactory; let I_ManualApprovalTransferManager; From d5058bf4cd1c132ef03b2a6ab14c3a34256ed079 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 17 Dec 2018 13:45:16 +0000 Subject: [PATCH 440/582] Use investor list from checkpoint --- contracts/modules/Checkpoint/DividendCheckpoint.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 497f6a5bc..daa5f1e50 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -142,7 +142,8 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { validDividendIndex(_dividendIndex) { Dividend storage dividend = dividends[_dividendIndex]; - address[] memory investors = ISecurityToken(securityToken).getInvestors(); + uint256 checkpointId = dividend.checkpointId; + address[] memory investors = ISecurityToken(securityToken).getInvestorsAt(checkpointId); uint256 numberInvestors = Math.min256(investors.length, _start.add(_iterations)); for (uint256 i = _start; i < numberInvestors; i++) { address payee = investors[i]; From 549f83e7f5a8b956202bd8ecbc108eaa135545f8 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 17 Dec 2018 14:25:12 -0300 Subject: [PATCH 441/582] CLI - Script to generate tokens, whitelist investors and mint to them --- CLI/commands/ST20Generator.js | 4 +- CLI/commands/TickerRollForward.js | 18 ++-- CLI/commands/common/global.js | 4 +- CLI/commands/dividends_manager.js | 108 ++++++++++----------- CLI/commands/helpers/contract_abis.js | 50 +++++----- CLI/commands/helpers/contract_addresses.js | 18 ++-- CLI/commands/sto_manager.js | 6 +- CLI/commands/strMigrator.js | 6 +- CLI/commands/token_manager.js | 4 +- CLI/commands/transfer_manager.js | 48 ++++++--- CLI/data/Transfer/GTM/whitelist_data.csv | 2 +- CLI/package.json | 2 +- CLI/polymath-cli.js | 9 +- CLI/scripts/stable_coin.sh | 18 ++++ 14 files changed, 171 insertions(+), 126 deletions(-) create mode 100755 CLI/scripts/stable_coin.sh diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 689b2b27f..0863c727e 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -32,7 +32,9 @@ async function executeApp(_ticker, _transferOwnership, _name, _details, _divisib await step_transfer_ticker_ownership(_transferOwnership); await step_token_deploy(_name, _details, _divisible); } - await tokenManager.executeApp(tokenSymbol); + if (typeof _divisible === 'undefined') { + await tokenManager.executeApp(tokenSymbol); + } } catch (err) { console.log(err); return; diff --git a/CLI/commands/TickerRollForward.js b/CLI/commands/TickerRollForward.js index 69d36575d..266749da1 100644 --- a/CLI/commands/TickerRollForward.js +++ b/CLI/commands/TickerRollForward.js @@ -20,9 +20,9 @@ let securityTokenRegistry; let securityTokenRegistryAddress; function Ticker(_owner, _symbol, _name) { - this.owner = _owner; - this.symbol = _symbol; - this.name = _name; + this.owner = _owner; + this.symbol = _symbol; + this.name = _name; } function FailedRegistration(_ticker, _error) { @@ -58,11 +58,11 @@ async function startScript() { } async function readFile() { - var stream = fs.createReadStream("./CLI/data/ticker_data.csv"); + var stream = fs.createReadStream(`${__dirname}/../data/ticker_data.csv`); var csvStream = csv() .on("data", function (data) { - ticker_data.push(new Ticker(data[0],data[1],data[2],data[3])); + ticker_data.push(new Ticker(data[0], data[1], data[2], data[3])); }) .on("end", async function () { await registerTickers(); @@ -73,12 +73,12 @@ async function readFile() { async function registerTickers() { // Poly approval for registration fees let polyBalance = BigNumber(await polyToken.methods.balanceOf(Issuer.address).call()); - let fee = web3.utils.fromWei(await securityTokenRegistry.methods.getTickerRegistrationFee().call()); + let fee = web3.utils.fromWei(await securityTokenRegistry.methods.getTickerRegistrationFee().call()); let totalFee = BigNumber(ticker_data.length).mul(fee); if (totalFee.gt(polyBalance)) { console.log(chalk.red(`\n*******************************************************************************`)); - console.log(chalk.red(`Not enough POLY to pay registration fee. Require ${totalFee.div(10**18).toNumber()} POLY but have ${polyBalance.div(10**18).toNumber()} POLY.`)); + console.log(chalk.red(`Not enough POLY to pay registration fee. Require ${totalFee.div(10 ** 18).toNumber()} POLY but have ${polyBalance.div(10 ** 18).toNumber()} POLY.`)); console.log(chalk.red(`*******************************************************************************\n`)); process.exit(0); } else { @@ -100,7 +100,7 @@ async function registerTickers() { } // validate ticker - await securityTokenRegistry.methods.getTickerDetails(ticker_data[i].symbol).call({}, function(error, result){ + await securityTokenRegistry.methods.getTickerDetails(ticker_data[i].symbol).call({}, function (error, result) { if (result[1] != 0) { failed_tickers.push(` ${i} is already registered`); valid = false; @@ -131,7 +131,7 @@ async function logResults() { Successful registrations: ${registered_tickers.length} Failed registrations: ${failed_tickers.length} Total gas consumed: ${totalGas} - Total gas cost: ${defaultGasPrice.mul(totalGas).div(10**18)} ETH + Total gas cost: ${defaultGasPrice.mul(totalGas).div(10 ** 18)} ETH List of failed registrations: ${failed_tickers} diff --git a/CLI/commands/common/global.js b/CLI/commands/common/global.js index 51972ea92..4b8fc5a3a 100644 --- a/CLI/commands/common/global.js +++ b/CLI/commands/common/global.js @@ -44,9 +44,9 @@ module.exports = { console.log("Invalid remote node") process.exit(0) } - await httpProvider(remoteNetwork, './privKey'); + await httpProvider(remoteNetwork, `${__dirname}/../../../privKey`); } else { - await httpProvider("http://localhost:8545", './privKeyLocal'); + await httpProvider("http://localhost:8545", `${__dirname}/../../../privKeyLocal`); } defaultGasPrice = getGasPrice(await web3.eth.net.getId()); } diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 0f423bf5d..19ef24910 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -32,7 +32,7 @@ async function executeApp(type) { } }; -async function setup(){ +async function setup() { try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -45,13 +45,13 @@ async function setup(){ polyToken.setProvider(web3.currentProvider); } catch (err) { console.log(err) - console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); + console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); process.exit(0); } } -async function start_explorer(){ - console.log('\n\x1b[34m%s\x1b[0m',"Dividends Manager - Main Menu"); +async function start_explorer() { + console.log('\n\x1b[34m%s\x1b[0m', "Dividends Manager - Main Menu"); if (!tokenSymbol) tokenSymbol = readlineSync.question('Enter the token symbol: '); @@ -62,7 +62,7 @@ async function start_explorer(){ console.log(chalk.red(`Token symbol provided is not a registered Security Token.`)); } else { let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI,result); + securityToken = new web3.eth.Contract(securityTokenABI, result); // Get the GTM result = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); @@ -76,7 +76,7 @@ async function start_explorer(){ let typeOptions = ['POLY', 'ETH']; if (!typeOptions.includes(dividendsType)) { - let index = readlineSync.keyInSelect(typeOptions, 'What type of dividends do you want work with?', {cancel: false}); + let index = readlineSync.keyInSelect(typeOptions, 'What type of dividends do you want work with?', { cancel: false }); dividendsType = typeOptions[index]; console.log(`Selected: ${dividendsType}`) } @@ -101,50 +101,50 @@ async function start_explorer(){ console.log('Selected:', selected, '\n'); switch (selected) { case 'Mint tokens': - let _to = readlineSync.question('Enter beneficiary of minting: '); - let _amount = readlineSync.question('Enter amount of tokens to mint: '); - await mintTokens(_to,_amount); - break; + let _to = readlineSync.question('Enter beneficiary of minting: '); + let _amount = readlineSync.question('Enter amount of tokens to mint: '); + await mintTokens(_to, _amount); + break; case 'Transfer tokens': - let _to2 = readlineSync.question('Enter beneficiary of tranfer: '); - let _amount2 = readlineSync.question('Enter amount of tokens to transfer: '); - await transferTokens(_to2,_amount2); - break; + let _to2 = readlineSync.question('Enter beneficiary of tranfer: '); + let _amount2 = readlineSync.question('Enter amount of tokens to transfer: '); + await transferTokens(_to2, _amount2); + break; case 'Create checkpoint': let createCheckpointAction = securityToken.methods.createCheckpoint(); await common.sendTransaction(createCheckpointAction); - break; + break; case 'Set default exclusions for dividends': await setDefaultExclusions(); - break; + break; case 'Tax holding settings': await taxHoldingMenu(); - break; + break; case 'Create dividends': let divName = readlineSync.question(`Enter a name or title to indetify this dividend: `); let dividend = readlineSync.question(`How much ${dividendsType} would you like to distribute to token holders?: `); await checkBalance(dividend); let checkpointId = currentCheckpoint == 0 ? 0 : await selectCheckpoint(true); // If there are no checkpoints, it must create a new one await createDividends(divName, dividend, checkpointId); - break; + break; case 'Explore account at checkpoint': - let _address = readlineSync.question('Enter address to explore: '); + let _address = readlineSync.question('Enter address to explore: '); let _checkpoint = await selectCheckpoint(false); await exploreAddress(_address, _checkpoint); - break; + break; case 'Explore total supply at checkpoint': let _checkpoint2 = await selectCheckpoint(false); await exploreTotalSupply(_checkpoint2); - break; + break; case 'Push dividends to accounts': - let _dividend = await selectDividend({valid: true, expired: false, reclaimed: false, withRemaining: true}); + let _dividend = await selectDividend({ valid: true, expired: false, reclaimed: false, withRemaining: true }); if (_dividend !== null) { let _addresses = readlineSync.question('Enter addresses to push dividends to (ex- add1,add2,add3,...): '); await pushDividends(_dividend, _addresses); } - break; + break; case `Explore ${dividendsType} balance`: - let _address3 = readlineSync.question('Enter address to explore: '); + let _address3 = readlineSync.question('Enter address to explore: '); let _dividend3 = await selectDividend(); if (_dividend3 !== null) { let dividendAmounts = await currentDividendsModule.methods.calculateDividend(_dividend3.index, _address3).call(); @@ -157,9 +157,9 @@ async function start_explorer(){ Tax withheld: ${web3.utils.fromWei(dividendTax)} ${dividendsType} `); } - break; + break; case 'Reclaim expired dividends': - let _dividend4 = await selectDividend({expired: true, reclaimed: false}); + let _dividend4 = await selectDividend({ expired: true, reclaimed: false }); if (_dividend4 !== null) { await reclaimedDividend(_dividend4); } @@ -174,14 +174,14 @@ async function start_explorer(){ await start_explorer(); } -async function mintTokens(address, amount){ +async function mintTokens(address, amount) { if (await securityToken.methods.mintingFrozen().call()) { console.log(chalk.red("Minting is not possible - Minting has been permanently frozen by issuer")); } else { await whitelistAddress(address); try { - let mintAction = securityToken.methods.mint(address,web3.utils.toWei(amount)); + let mintAction = securityToken.methods.mint(address, web3.utils.toWei(amount)); let receipt = await common.sendTransaction(mintAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` @@ -195,12 +195,12 @@ async function mintTokens(address, amount){ } } -async function transferTokens(address, amount){ +async function transferTokens(address, amount) { await whitelistAddress(address); - try{ - let transferAction = securityToken.methods.transfer(address,web3.utils.toWei(amount)); - let receipt = await common.sendTransaction(transferAction, {factor: 1.5}); + try { + let transferAction = securityToken.methods.transfer(address, web3.utils.toWei(amount)); + let receipt = await common.sendTransaction(transferAction, { factor: 1.5 }); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(` Account ${event.from} @@ -213,17 +213,17 @@ async function transferTokens(address, amount){ } } -async function exploreAddress(address, checkpoint){ +async function exploreAddress(address, checkpoint) { let balance = await securityToken.methods.balanceOf(address).call(); balance = web3.utils.fromWei(balance); console.log(`Balance of ${address} is: ${balance} (Using balanceOf)`); - let balanceAt = await securityToken.methods.balanceOfAt(address,checkpoint).call(); + let balanceAt = await securityToken.methods.balanceOfAt(address, checkpoint).call(); balanceAt = web3.utils.fromWei(balanceAt); console.log(`Balance of ${address} is: ${balanceAt} (Using balanceOfAt - checkpoint ${checkpoint})`); } -async function exploreTotalSupply(checkpoint){ +async function exploreTotalSupply(checkpoint) { let totalSupply = await securityToken.methods.totalSupply().call(); totalSupply = web3.utils.fromWei(totalSupply); console.log(`TotalSupply is: ${totalSupply} (Using totalSupply)`); @@ -246,7 +246,7 @@ async function setDefaultExclusions() { let receipt = await common.sendTransaction(setDefaultExclusionsActions); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'SetDefaultExcludedAddresses'); console.log(chalk.green(`Exclusions were successfully set.`)); - showExcluded(event._excluded); + showExcluded(event._excluded); } } @@ -254,30 +254,30 @@ async function taxHoldingMenu() { await addDividendsModule(); let options = ['Set a % to withhold from dividends sent to an address', 'Withdraw withholding for dividend', 'Return to main menu']; - let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: false}); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: false }); let selected = options[index]; console.log("Selected:", selected); switch (selected) { case 'Set a % to withhold from dividends sent to an address': let address = readlineSync.question('Enter the address of the investor: ', { - limit: function(input) { + limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address", }); let percentage = readlineSync.question('Enter the percentage of dividends to withhold (number between 0-100): ', { - limit: function(input) { + limit: function (input) { return (parseInt(input) >= 0 && parseInt(input) <= 100); }, limitMessage: "Must be a value between 0 and 100", }); let percentageWei = web3.utils.toWei((percentage / 100).toString()); let setWithHoldingFixedAction = currentDividendsModule.methods.setWithholdingFixed([address], percentageWei); - let receipt = await common.sendTransaction(setWithHoldingFixedAction); + let receipt = await common.sendTransaction(setWithHoldingFixedAction); console.log(chalk.green(`Successfully set tax withholding of ${percentage}% for ${address}.`)); break; case 'Withdraw withholding for dividend': - let _dividend = await selectDividend({withRemainingWithheld: true}); + let _dividend = await selectDividend({ withRemainingWithheld: true }); if (_dividend !== null) { let withdrawWithholdingAction = currentDividendsModule.methods.withdrawWithholding(_dividend.index); let receipt = await common.sendTransaction(withdrawWithholdingAction); @@ -299,11 +299,11 @@ async function taxHoldingMenu() { async function createDividends(name, dividend, checkpointId) { await addDividendsModule(); - let time = Math.floor(Date.now()/1000); - let maturityTime = readlineSync.questionInt('Enter the dividend maturity time from which dividend can be paid (Unix Epoch time)\n(Now = ' + time + ' ): ', {defaultInput: time}); + let time = Math.floor(Date.now() / 1000); + let maturityTime = readlineSync.questionInt('Enter the dividend maturity time from which dividend can be paid (Unix Epoch time)\n(Now = ' + time + ' ): ', { defaultInput: time }); let defaultTime = time + gbl.constants.DURATION.minutes(10); - let expiryTime = readlineSync.questionInt('Enter the dividend expiry time (Unix Epoch time)\n(10 minutes from now = ' + defaultTime + ' ): ', {defaultInput: defaultTime}); - + let expiryTime = readlineSync.questionInt('Enter the dividend expiry time (Unix Epoch time)\n(10 minutes from now = ' + defaultTime + ' ): ', { defaultInput: defaultTime }); + let useDefaultExcluded = readlineSync.keyInYNStrict(`Do you want to use the default excluded addresses for this dividend? If not, data from 'dividendsExclusions_data.csv' will be used instead.`); let createDividendAction; @@ -344,7 +344,7 @@ async function createDividends(name, dividend, checkpointId) { createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, excluded, web3.utils.toHex(name)); } } - let receipt = await common.sendTransaction(createDividendAction, {value: web3.utils.toWei(dividend)}); + let receipt = await common.sendTransaction(createDividendAction, { value: web3.utils.toWei(dividend) }); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'EtherDividendDeposited'); console.log(` Dividend ${event._dividendIndex} deposited` @@ -352,7 +352,7 @@ async function createDividends(name, dividend, checkpointId) { } } -async function pushDividends(dividend, account){ +async function pushDividends(dividend, account) { let accs = account.split(','); let pushDividendPaymentToAddressesAction = currentDividendsModule.methods.pushDividendPaymentToAddresses(dividend.index, accs); let receipt = await common.sendTransaction(pushDividendPaymentToAddressesAction); @@ -474,19 +474,19 @@ async function addDividendsModule() { async function selectCheckpoint(includeCreate) { let options = []; let fix = 1; //Checkpoint 0 is not included, so I need to add 1 to fit indexes for checkpoints and options - let checkpoints = (await getCheckpoints()).map(function(c) { return c.timestamp }); + let checkpoints = (await getCheckpoints()).map(function (c) { return c.timestamp }); if (includeCreate) { options.push('Create new checkpoint'); fix = 0; //If this option is added, fix isn't needed. } options = options.concat(checkpoints); - return readlineSync.keyInSelect(options, 'Select a checkpoint:', {cancel: false}) + fix; + return readlineSync.keyInSelect(options, 'Select a checkpoint:', { cancel: false }) + fix; } async function getCheckpoints() { let result = []; - + let checkPointsTimestamps = await securityToken.methods.getCheckpointTimes().call(); for (let index = 0; index < checkPointsTimestamps.length; index++) { let checkpoint = {}; @@ -502,7 +502,7 @@ async function selectDividend(filter) { let result = null; let dividends = await getDividends(); - let now = Math.floor(Date.now()/1000); + let now = Math.floor(Date.now() / 1000); if (typeof filter !== 'undefined') { if (typeof filter.valid !== 'undefined') { dividends = dividends.filter(d => filter.valid == (now > d.maturity)); @@ -522,7 +522,7 @@ async function selectDividend(filter) { } if (dividends.length > 0) { - let options = dividends.map(function(d) { + let options = dividends.map(function (d) { return `${web3.utils.toAscii(d.name)} Created: ${moment.unix(d.created).format('MMMM Do YYYY, HH:mm:ss')} Maturity: ${moment.unix(d.maturity).format('MMMM Do YYYY, HH:mm:ss')} @@ -564,7 +564,7 @@ async function getDividends() { } function getExcludedFromDataFile() { - let excludedFromFile = require('fs').readFileSync('./CLI/data/dividendsExclusions_data.csv').toString().split("\n"); + let excludedFromFile = require('fs').readFileSync(`${__dirname}/../data/dividendsExclusions_data.csv`).toString().split("\n"); let excluded = excludedFromFile.filter(function (address) { return web3.utils.isAddress(address); }); @@ -582,7 +582,7 @@ function showExcluded(excluded) { } module.exports = { - executeApp: async function(type) { + executeApp: async function (type) { return executeApp(type); } } diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index b169c9896..329a789ff 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -21,33 +21,33 @@ let ownableABI; let iSTOABI; let iTransferManagerABI; let moduleFactoryABI; -let erc20; +let erc20ABI; try { - polymathRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolymathRegistry.json').toString()).abi; - securityTokenRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/SecurityTokenRegistry.json').toString()).abi; - featureRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/FeatureRegistry.json').toString()).abi; - moduleRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleRegistry.json').toString()).abi; - securityTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/SecurityToken.json').toString()).abi; - stoInterfaceABI = JSON.parse(require('fs').readFileSync('./build/contracts/ISTO.json').toString()).abi; - cappedSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTO.json').toString()).abi; - usdTieredSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTO.json').toString()).abi; - generalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralTransferManager.json').toString()).abi; - manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ManualApprovalTransferManager.json').toString()).abi; - countTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/CountTransferManager.json').toString()).abi; - percentageTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/PercentageTransferManager.json').toString()).abi; - generalPermissionManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralPermissionManager.json').toString()).abi; - polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; - cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; - usdTieredSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTOFactory.json').toString()).abi; - erc20DividendCheckpointABI = JSON.parse(require('fs').readFileSync('./build/contracts/ERC20DividendCheckpoint.json').toString()).abi; - etherDividendCheckpointABI = JSON.parse(require('fs').readFileSync('./build/contracts/EtherDividendCheckpoint.json').toString()).abi; - moduleInterfaceABI = JSON.parse(require('fs').readFileSync('./build/contracts/IModule.json').toString()).abi; - ownableABI = JSON.parse(require('fs').readFileSync('./build/contracts/Ownable.json').toString()).abi; - iSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/ISTO.json').toString()).abi - iTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ITransferManager.json').toString()).abi - moduleFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleFactory.json').toString()).abi; - erc20ABI = JSON.parse(require('fs').readFileSync('./build/contracts/DetailedERC20.json').toString()).abi; + polymathRegistryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PolymathRegistry.json`).toString()).abi; + securityTokenRegistryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/SecurityTokenRegistry.json`).toString()).abi; + featureRegistryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/FeatureRegistry.json`).toString()).abi; + moduleRegistryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ModuleRegistry.json`).toString()).abi; + securityTokenABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/SecurityToken.json`).toString()).abi; + stoInterfaceABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ISTO.json`).toString()).abi; + cappedSTOABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/CappedSTO.json`).toString()).abi; + usdTieredSTOABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/USDTieredSTO.json`).toString()).abi; + generalTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/GeneralTransferManager.json`).toString()).abi; + manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ManualApprovalTransferManager.json`).toString()).abi; + countTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/CountTransferManager.json`).toString()).abi; + percentageTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PercentageTransferManager.json`).toString()).abi; + generalPermissionManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/GeneralPermissionManager.json`).toString()).abi; + polyTokenABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PolyTokenFaucet.json`).toString()).abi; + cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/CappedSTOFactory.json`).toString()).abi; + usdTieredSTOFactoryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/USDTieredSTOFactory.json`).toString()).abi; + erc20DividendCheckpointABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ERC20DividendCheckpoint.json`).toString()).abi; + etherDividendCheckpointABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/EtherDividendCheckpoint.json`).toString()).abi; + moduleInterfaceABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/IModule.json`).toString()).abi; + ownableABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/Ownable.json`).toString()).abi; + iSTOABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ISTO.json`).toString()).abi + iTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ITransferManager.json`).toString()).abi + moduleFactoryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ModuleFactory.json`).toString()).abi; + erc20ABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/DetailedERC20.json`).toString()).abi; } catch (err) { console.log('\x1b[31m%s\x1b[0m', "Couldn't find contracts' artifacts. Make sure you ran truffle compile first"); throw err; diff --git a/CLI/commands/helpers/contract_addresses.js b/CLI/commands/helpers/contract_addresses.js index 59a2f39c4..79f5cba10 100644 --- a/CLI/commands/helpers/contract_addresses.js +++ b/CLI/commands/helpers/contract_addresses.js @@ -13,7 +13,7 @@ function getPolymathRegistryAddress(networkId) { result = ""; break; case 15: // GANACHE - result = JSON.parse(require('fs').readFileSync('./build/contracts/PolymathRegistry.json').toString()).networks[networkId].address; + result = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PolymathRegistry.json`).toString()).networks[networkId].address; break; case 42: // KOVAN result = "0x5b215a7d39ee305ad28da29bf2f0425c6c2a00b3"; @@ -52,35 +52,35 @@ module.exports = { let networkId = await web3.eth.net.getId(); return getPolymathRegistryAddress(networkId); }, - securityTokenRegistry: async function() { + securityTokenRegistry: async function () { let polymathRegistry = await getPolymathRegistry(); return await polymathRegistry.methods.getAddress("SecurityTokenRegistry").call(); }, - moduleRegistry: async function() { + moduleRegistry: async function () { let polymathRegistry = await getPolymathRegistry(); return await polymathRegistry.methods.getAddress("ModuleRegistry").call(); }, - featureRegistry: async function() { + featureRegistry: async function () { let polymathRegistry = await getPolymathRegistry(); return await polymathRegistry.methods.getAddress("FeatureRegistry").call(); }, - polyToken: async function() { + polyToken: async function () { let polymathRegistry = await getPolymathRegistry(); return await polymathRegistry.methods.getAddress("PolyToken").call(); }, - usdToken: async function() { + usdToken: async function () { let networkId = await web3.eth.net.getId(); if (networkId == 1) return "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359"; else if (networkId == 42) return "0xc4375b7de8af5a38a93548eb8453a498222c4ff2"; else - return JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).networks[networkId].address; + return JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PolyTokenFaucet.json`).toString()).networks[networkId].address; }, - getModuleFactoryAddressByName: async function(stAddress, moduleType, moduleName) { + getModuleFactoryAddressByName: async function (stAddress, moduleType, moduleName) { let moduleRegistry = await getModuleRegistry(); let availableModules = await moduleRegistry.methods.getModulesByTypeAndToken(moduleType, stAddress).call(); - + let result = null; let counter = 0; let moduleFactoryABI = abis.moduleFactory(); diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index c6757359c..35df918e4 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -9,8 +9,8 @@ const STABLE = 'STABLE'; /////////////////// // Constants -const ACCREDIT_DATA_CSV = './CLI/data/STO/USDTieredSTO/accredited_data.csv'; -const NON_ACCREDIT_LIMIT_DATA_CSV = './CLI/data/STO/USDTieredSTO/nonAccreditedLimits_data.csv' +const ACCREDIT_DATA_CSV = `${__dirname}/../data/STO/USDTieredSTO/accredited_data.csv`; +const NON_ACCREDIT_LIMIT_DATA_CSV = `${__dirname}/../data/STO/USDTieredSTO/nonAccreditedLimits_data.csv`; /////////////////// // Crowdsale params @@ -974,7 +974,7 @@ async function getAllModulesByType(type) { let nameTemp = web3.utils.hexToUtf8(details[0]); let pausedTemp = null; if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER) { - let abiTemp = JSON.parse(require('fs').readFileSync(`./build/contracts/${nameTemp}.json`).toString()).abi; + let abiTemp = JSON.parse(require('fs').readFileSync(`${__dirname}/../../build/contracts/${nameTemp}.json`).toString()).abi; let contractTemp = new web3.eth.Contract(abiTemp, details[1]); pausedTemp = await contractTemp.methods.paused().call(); } diff --git a/CLI/commands/strMigrator.js b/CLI/commands/strMigrator.js index 4a8dabfe0..f27d0bfbd 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -216,7 +216,7 @@ async function step_get_deployed_tokens(securityTokenRegistry, singleTicker) { let event = common.getEventFromLogs(securityTokenRegistry._jsonInterface, [log], 'LogNewSecurityToken'); if (typeof singleTicker === 'undefined' || event._ticker == singleTicker) { let tokenAddress = event._securityTokenAddress; - let securityTokenABI = JSON.parse(require('fs').readFileSync('./CLI/data/SecurityToken1-4-0.json').toString()).abi; + let securityTokenABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../data/SecurityToken1-4-0.json`).toString()).abi; console.log(`Creating SecurityToken contract instance of address: ${tokenAddress}...`); let token = new web3.eth.Contract(securityTokenABI, tokenAddress); token.setProvider(web3.currentProvider); @@ -230,7 +230,7 @@ async function step_get_deployed_tokens(securityTokenRegistry, singleTicker) { let gmtAddress = (await token.methods.getModule(2, 0).call())[1]; - let gtmABI = JSON.parse(require('fs').readFileSync('./CLI/data/GeneralTransferManager1-4-0.json').toString()).abi; + let gtmABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../data/GeneralTransferManager1-4-0.json`).toString()).abi; let gmt = new web3.eth.Contract(gtmABI, gmtAddress); //let gtmEvents = await gmt.getPastEvents('LogModifyWhitelist', { fromBlock: event.blockNumber}); let gtmLogs = await getLogsFromEtherscan(gmt.options.address, 0, 'latest', 'LogModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)'); @@ -284,7 +284,7 @@ async function step_launch_STs(tokens, securityTokenRegistry, tokenAddress) { let failed = []; let totalGas = new web3.utils.BN(0); let polymathRegistryAddress = await contracts.polymathRegistry(); - let STFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/STFactory.json').toString()).abi; + let STFactoryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../build/contracts/STFactory.json`).toString()).abi; let STFactoryAddress = await securityTokenRegistry.methods.getSTFactoryAddress().call(); let STFactory = new web3.eth.Contract(STFactoryABI, STFactoryAddress); for (const t of tokens) { diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index b74505257..54a5d215b 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -8,7 +8,7 @@ const gbl = require('./common/global'); const csvParse = require('./helpers/csv'); // Constants -const MULTIMINT_DATA_CSV = './CLI/data/ST/multi_mint_data.csv'; +const MULTIMINT_DATA_CSV = `${__dirname}/../data/ST/multi_mint_data.csv`; // Load contract artifacts const contracts = require('./helpers/contract_addresses'); @@ -617,7 +617,7 @@ async function getAllModules() { let nameTemp = web3.utils.hexToUtf8(details[0]); let pausedTemp = null; if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER) { - let abiTemp = JSON.parse(require('fs').readFileSync(`./build/contracts/${nameTemp}.json`).toString()).abi; + let abiTemp = JSON.parse(require('fs').readFileSync(`${__dirname}/../../build/contracts/${nameTemp}.json`).toString()).abi; let contractTemp = new web3.eth.Contract(abiTemp, details[1]); pausedTemp = await contractTemp.methods.paused().call(); } diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 16af0e34e..3bb7f42d7 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -10,8 +10,8 @@ const { table } = require('table') /////////////////// // Constants -const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; -const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelist_data.csv'; +const WHITELIST_DATA_CSV = `${__dirname}/../data/Transfer/GTM/whitelist_data.csv`; +const PERCENTAGE_WHITELIST_DATA_CSV = `${__dirname}/../data/Transfer/PercentageTM/whitelist_data.csv`; // App flow let tokenSymbol; @@ -532,17 +532,27 @@ function showWhitelistTable(investorsArray, fromTimeArray, toTimeArray, expiryTi console.log(table(dataTable)); } -async function modifyWhitelistInBatch() { - let csvFilePath = readlineSync.question(`Enter the path for csv data file (${WHITELIST_DATA_CSV}): `, { - defaultInput: WHITELIST_DATA_CSV - }); - let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { - limit: function (input) { - return parseInt(input) > 0; - }, - limitMessage: 'Must be greater than 0', - defaultInput: gbl.constants.DEFAULT_BATCH_SIZE - }); +async function modifyWhitelistInBatch(_csvFilePath, _batchSize) { + let csvFilePath; + if (typeof _csvFilePath === 'undefined') { + csvFilePath = readlineSync.question(`Enter the path for csv data file (${WHITELIST_DATA_CSV}): `, { + defaultInput: WHITELIST_DATA_CSV + }); + } else { + csvFilePath = _csvFilePath; + } + let batchSize; + if (typeof _batchSize === 'undefined') { + batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + } else { + batchSize = _batchSize; + } let parsedData = csvParse(csvFilePath); let validData = parsedData.filter(row => web3.utils.isAddress(row[0]) && @@ -1092,7 +1102,7 @@ async function getAllModulesByType(type) { let nameTemp = web3.utils.hexToUtf8(details[0]); let pausedTemp = null; if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER) { - let abiTemp = JSON.parse(require('fs').readFileSync(`./build/contracts/${nameTemp}.json`).toString()).abi; + let abiTemp = JSON.parse(require('fs').readFileSync(`${__dirname}/../../build/contracts/${nameTemp}.json`).toString()).abi; let contractTemp = new web3.eth.Contract(abiTemp, details[1]); pausedTemp = await contractTemp.methods.paused().call(); } @@ -1194,6 +1204,14 @@ module.exports = { }, addTransferManagerModule: async function (_tokenSymbol) { await initialize(_tokenSymbol); - return addTransferManagerModule() + return addTransferManagerModule(); + }, + modifyWhitelistInBatch: async function (_tokenSymbol, _csvFilePath, _batchSize) { + await initialize(_tokenSymbol); + let gmtModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + let generalTransferManagerAddress = gmtModules[0]; + currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), generalTransferManagerAddress); + currentTransferManager.setProvider(web3.currentProvider); + return modifyWhitelistInBatch(_csvFilePath, _batchSize); } } \ No newline at end of file diff --git a/CLI/data/Transfer/GTM/whitelist_data.csv b/CLI/data/Transfer/GTM/whitelist_data.csv index 3276dec64..236cac436 100644 --- a/CLI/data/Transfer/GTM/whitelist_data.csv +++ b/CLI/data/Transfer/GTM/whitelist_data.csv @@ -7,4 +7,4 @@ 0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,5/5/2018,1/8/2018,10/10/2019,false 0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,5/5/2018,1/8/2018,10/10/2019,false 0x56be93088141b16ebaa9416122fd1d928da25ecf,5/5/2018,1/8/2018,10/10/2019,false -0xbb276b6f68f0a41d54b7e0a608fe8eb1ebdee7b0,5/5/2018,1/8/2018,10/10/2019,true +0xbb276b6f68f0a41d54b7e0a608fe8eb1ebdee7b0,5/5/2018,1/8/2018,10/10/2019,true \ No newline at end of file diff --git a/CLI/package.json b/CLI/package.json index 4dfcbf3a4..cc2773b74 100644 --- a/CLI/package.json +++ b/CLI/package.json @@ -4,7 +4,7 @@ "description": "CLI for Polymath-core", "main": "polymath-cli.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "stable_coin": "scripts/stable_coin.sh" }, "author": "Polymath Inc", "license": "MIT", diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index d2b4c68fa..94df66e0a 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -120,10 +120,17 @@ program .command('transfer_manager') .alias('tm') .option('-t, --securityToken ', 'Selects a ST to manage transfer modules') + .option('-w, --whitelist ', 'Whitelists addresses according to a csv file') + .option('-b, --batchSize ', 'Max number of records per transaction') .description('Runs transfer_manager') .action(async function (cmd) { await gbl.initialize(program.remoteNode); - await transfer_manager.executeApp(cmd.securityToken); + if (cmd.whitelist) { + let batchSize = cmd.batchSize ? cmd.batchSize : gbl.constants.DEFAULT_BATCH_SIZE; + await transfer_manager.modifyWhitelistInBatch(cmd.securityToken, cmd.whitelist, batchSize); + } else { + await transfer_manager.executeApp(cmd.securityToken); + } }); program diff --git a/CLI/scripts/stable_coin.sh b/CLI/scripts/stable_coin.sh new file mode 100755 index 000000000..98415d7cc --- /dev/null +++ b/CLI/scripts/stable_coin.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Exit script as soon as a command fails. +set -o errexit + +# Token symbol read from args. +TOKEN_SYMBOL=$1 + +# Paths +CWD="$(pwd)" +WHITELIST='/data/Transfer/GTM/whitelist_data.csv' +MULTIMINT='/data/ST/multi_mint_data.csv' + +# Scripts + +node polymath-cli st -t $TOKEN_SYMBOL -o false -n $TOKEN_SYMBOL -d '' -D true +node polymath-cli tm -t $TOKEN_SYMBOL -w $CWD$WHITELIST +node polymath-cli stm -t $TOKEN_SYMBOL -m $CWD$MULTIMINT From 67d3429a388902d840f5fe4b4f7684d16fad8e89 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 17 Dec 2018 16:32:46 -0300 Subject: [PATCH 442/582] CLI - Explore account --- CLI/commands/transfer_manager.js | 78 +++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 9d6641519..3d6dd8906 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1002,7 +1002,7 @@ async function changeIndividualRestrictions() { let currentRestriction = await currentTransferManager.methods.individualRestriction(holder).call(); let hasRestriction = parseInt(currentRestriction.startTime) !== 0; - console.log(`*** Current restrictions for ${holder} ***`, '\n'); + console.log(`*** Current individual restrictions for ${holder} ***`, '\n'); console.log(`- Daily restriction: ${hasDailyRestriction ? '' : 'None'}`); if (hasDailyRestriction) { @@ -1012,7 +1012,7 @@ async function changeIndividualRestrictions() { console.log(` Rolling period: ${currentDailyRestriction.rollingPeriodInDays} days`); console.log(` End time: ${moment.unix(currentDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - console.log(`- Default daily restriction: ${hasRestriction ? '' : 'None'} `); + console.log(`- Other restriction: ${hasRestriction ? '' : 'None'} `); if (hasRestriction) { console.log(` Type: ${RESTRICTION_TYPES[currentRestriction.typeOfRestriction]}`); console.log(` Allowed tokens: ${currentRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(currentRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(currentRestriction.allowedTokens)}%`}`); @@ -1109,6 +1109,80 @@ async function changeIndividualRestrictions() { } } +async function exploreAccount() { + let account = readlineSync.question('Enter the account to explore: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + + let appliyngdDailyRestriction = null; + let applyingOtherRestriction = null; + let hasIndividualRestrictions = false; + let isExempted = await currentTransferManager.methods.exemptList(account).call(); + if (!isExempted) { + let indiviaulDailyRestriction = await currentTransferManager.methods.individualDailyRestriction(account).call(); + if (parseInt(indiviaulDailyRestriction.endTime) !== 0) { + appliyngdDailyRestriction = indiviaulDailyRestriction; + } + let otherRestriction = await currentTransferManager.methods.individualRestriction(account).call(); + if (parseInt(otherRestriction.endTime) !== 0) { + applyingOtherRestriction = otherRestriction; + } + + hasIndividualRestrictions = applyingOtherRestriction || appliyngdDailyRestriction; + + if (!hasIndividualRestrictions) { + let defaultDailyRestriction = await currentTransferManager.methods.defaultDailyRestriction(account).call(); + if (parseInt(defaultDailyRestriction.endTime) !== 0) { + appliyngdDailyRestriction = defaultDailyRestriction; + } + let defaultOtherRestriction = await currentTransferManager.methods.defaultRestriction().call(); + if (parseInt(defaultOtherRestriction.endTime) === 0) { + applyingOtherRestriction = defaultOtherRestriction; + } + } + } + + console.log(`*** Applying restrictions for ${account} ***`, '\n'); + + console.log(`- Daily restriction: ${appliyngdDailyRestriction ? (!hasIndividualRestrictions ? 'default' : '') : 'None'}`); + if (appliyngdDailyRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[appliyngdDailyRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${appliyngdDailyRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(appliyngdDailyRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(appliyngdDailyRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(appliyngdDailyRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${appliyngdDailyRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(appliyngdDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + } + console.log(`- Other restriction: ${applyingOtherRestriction ? (!hasIndividualRestrictions ? 'default' : '') : 'None'} `); + if (applyingOtherRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[applyingOtherRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${applyingOtherRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(applyingOtherRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(applyingOtherRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(applyingOtherRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${applyingOtherRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(applyingOtherRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + } + + if (applyingOtherRestriction || appliyngdDailyRestriction) { + let bucketDetails; + if (hasIndividualRestrictions) { + bucketDetails = await currentTransferManager.methods.getIndividualBucketDetailsToUser(account).call(); + } else { + bucketDetails = await currentTransferManager.methods.getDefaultBucketDetailsToUser(account).call(); + } + let now = Math.floor(Date.now() / 1000) - gbl.constants.DURATION.days(1); + let tradedByUserLastDay = await currentTransferManager.methods.getTotalTradedByUser(account, now).call(); + console.log(); + console.log(`Last trade: ${bucketDetails[0]}`); + console.log(`Last daily trade: ${bucketDetails[3]}`); + console.log(`Days since rolling period started: ${bucketDetails[2]}`); + console.log(`Transacted amount since rolling period started: ${web3.utils.fromWei(bucketDetails[1])}`); + console.log(`Transacted amount within last 24 hours: ${web3.utils.fromWei(tradedByUserLastDay)}`); + console.log(); + } +} + async function operateWithMultipleRestrictions() { let options = [ 'Add multiple individual daily restrictions', From 64a72de57558f57b423d7b6b51eb1119d23d9513 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 18 Dec 2018 10:21:15 +0530 Subject: [PATCH 443/582] Update PolyTokenFaucet.sol --- contracts/mocks/PolyTokenFaucet.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/mocks/PolyTokenFaucet.sol b/contracts/mocks/PolyTokenFaucet.sol index 76f1a5596..f06716c42 100644 --- a/contracts/mocks/PolyTokenFaucet.sol +++ b/contracts/mocks/PolyTokenFaucet.sol @@ -18,8 +18,8 @@ contract PolyTokenFaucet { mapping(address => uint256) balances; mapping(address => mapping(address => uint256)) allowed; - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); constructor() public { decimals = 18; From af0ab90a294bc4cc1da6f9b4594e0fb558f4f260 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 18 Dec 2018 17:37:18 +0200 Subject: [PATCH 444/582] Improved the natspec comments --- .../modules/Wallet/VestingEscrowWallet.sol | 135 +++++++++--------- 1 file changed, 68 insertions(+), 67 deletions(-) diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Wallet/VestingEscrowWallet.sol index 4e0f089b7..17f6dbb08 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Wallet/VestingEscrowWallet.sol @@ -63,7 +63,7 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Use to intialize the treasury wallet address + * @notice Used to initialize the treasury wallet address * @param _treasuryWallet Address of the treasury wallet */ function configure(address _treasuryWallet) public onlyFactory { @@ -72,7 +72,7 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Use to change the treasury wallet address + * @notice Used to change the treasury wallet address * @param _newTreasuryWallet Address of the treasury wallet */ function changeTreasuryWallet(address _newTreasuryWallet) public onlyOwner { @@ -82,7 +82,8 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Used to deposit tokens from treasury + * @notice Used to deposit tokens from treasury wallet to the vesting escrow wallet + * @param _numberOfTokens Number of tokens that should be deposited */ function depositTokens(uint256 _numberOfTokens) external withPerm(ADMIN) { _depositTokens(_numberOfTokens); @@ -99,8 +100,8 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Sends unassigned tokens to treasury - * @param _amount amount of tokens that should be send + * @notice Sends unassigned tokens to the treasury wallet + * @param _amount Amount of tokens that should be send to the treasury wallet */ function sendToTreasury(uint256 _amount) external withPerm(ADMIN) { require(_amount > 0, "Amount cannot be zero"); @@ -112,8 +113,8 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Pushes available tokens to beneficiary - * @param _beneficiary beneficiary's address + * @notice Pushes available tokens to the beneficiary's address + * @param _beneficiary Address of the beneficiary who will receive tokens */ function pushAvailableTokens(address _beneficiary) public withPerm(ADMIN) { _sendTokens(_beneficiary); @@ -127,11 +128,11 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Add template - * @param _name name of template - * @param _numberOfTokens number of tokens - * @param _duration vesting duration - * @param _frequency vesting frequency + * @notice Adds template that can be used for creating schedule + * @param _name Name of the template will be created + * @param _numberOfTokens Number of tokens that should be assigned to schedule + * @param _duration Duration of the vesting schedule + * @param _frequency Frequency of the vesting schedule */ function addTemplate(bytes32 _name, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) external withPerm(ADMIN) { _addTemplate(_name, _numberOfTokens, _duration, _frequency); @@ -147,8 +148,8 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Removes template - * @param _name name of template + * @notice Removes template with a given name + * @param _name Name of the template that will be removed */ function removeTemplate(bytes32 _name) external withPerm(ADMIN) { require(_isTemplateExists(_name), "Template not found"); @@ -165,29 +166,29 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Returns count of templates - * @return count of templates + * @notice Returns count of the templates those can be used for creating schedule + * @return Count of the templates */ function getTemplateCount() external view returns(uint256) { return templateNames.length; } /** - * @notice get the list of template names - * @return bytes32 Array of template names + * @notice Gets the list of the template names those can be used for creating schedule + * @return bytes32 Array of all template names were created */ function getAllTemplateNames() external view returns(bytes32[]) { return templateNames; } /** - * @notice Adds vesting schedules for each of beneficiary - * @param _beneficiary beneficiary's addresses - * @param _templateName name of the template that will be created - * @param _numberOfTokens number of tokens - * @param _duration vesting duration - * @param _frequency vesting frequency - * @param _startTime vesting start time + * @notice Adds vesting schedules for each of the beneficiary's address + * @param _beneficiary Address of the beneficiary for whom it is scheduled + * @param _templateName Name of the template that will be created + * @param _numberOfTokens Total number of tokens for created schedule + * @param _duration Duration of the created vesting schedule + * @param _frequency Frequency of the created vesting schedule + * @param _startTime Start time of the created vesting schedule */ function addSchedule( address _beneficiary, @@ -218,10 +219,10 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Adds vesting schedules from template for each of beneficiary - * @param _beneficiary beneficiary's addresses - * @param _templateName name of the template - * @param _startTime vesting start time + * @notice Adds vesting schedules from template for the beneficiary + * @param _beneficiary Address of the beneficiary for whom it is scheduled + * @param _templateName Name of the exists template + * @param _startTime Start time of the created vesting schedule */ function addScheduleFromTemplate(address _beneficiary, bytes32 _templateName, uint256 _startTime) external withPerm(ADMIN) { _addScheduleFromTemplate(_beneficiary, _templateName, _startTime); @@ -255,10 +256,10 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Modifies vesting schedules for each of beneficiary - * @param _beneficiary beneficiary's addresses - * @param _templateName name of the template - * @param _startTime vesting start time + * @notice Modifies vesting schedules for each of the beneficiary + * @param _beneficiary Address of the beneficiary for whom it is modified + * @param _templateName Name of the template was used for schedule creation + * @param _startTime Start time of the created vesting schedule */ function modifySchedule(address _beneficiary, bytes32 _templateName, uint256 _startTime) public withPerm(ADMIN) { _modifySchedule(_beneficiary, _templateName, _startTime); @@ -276,9 +277,9 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Revokes beneficiary's schedule - * @param _beneficiary beneficiary's address - * @param _templateName name of the template + * @notice Revokes vesting schedule with given template name for given beneficiary + * @param _beneficiary Address of the beneficiary for whom it is revoked + * @param _templateName Name of the template was used for schedule creation */ function revokeSchedule(address _beneficiary, bytes32 _templateName) external withPerm(ADMIN) { _checkSchedule(_beneficiary, _templateName); @@ -315,8 +316,8 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Revokes all beneficiary's schedules - * @param _beneficiary beneficiary's address + * @notice Revokes all vesting schedules for given beneficiary's address + * @param _beneficiary Address of the beneficiary for whom all schedules will be revoked */ function revokeAllSchedules(address _beneficiary) public withPerm(ADMIN) { _revokeAllSchedules(_beneficiary); @@ -339,9 +340,9 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Returns beneficiary's schedule - * @param _beneficiary beneficiary's address - * @param _templateName name of the template + * @notice Returns beneficiary's schedule created using template name + * @param _beneficiary Address of the beneficiary who will receive tokens + * @param _templateName Name of the template was used for schedule creation * @return beneficiary's schedule data (numberOfTokens, duration, frequency, startTime, claimedTokens, State) */ function getSchedule(address _beneficiary, bytes32 _templateName) external view returns(uint256, uint256, uint256, uint256, uint256, State) { @@ -372,9 +373,9 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Returns list of template names - * @param _beneficiary beneficiary's address - * @return list of template names + * @notice Returns list of the template names for given beneficiary's address + * @param _beneficiary Address of the beneficiary + * @return List of the template names that were used for schedule creation */ function getTemplateNames(address _beneficiary) external view returns(bytes32[]) { require(_beneficiary != address(0), "Invalid address"); @@ -382,9 +383,9 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Returns count of beneficiary's schedules - * @param _beneficiary beneficiary's address - * @return count of beneficiary's schedules + * @notice Returns count of the schedules were created for given beneficiary + * @param _beneficiary Address of the beneficiary + * @return Count of beneficiary's schedules */ function getScheduleCount(address _beneficiary) external view returns(uint256) { require(_beneficiary != address(0), "Invalid address"); @@ -415,9 +416,9 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Used to bulk send available tokens for each of beneficiaries - * @param _fromIndex start index of array of beneficiary's addresses - * @param _toIndex end index of array of beneficiary's addresses + * @notice Used to bulk send available tokens for each of the beneficiaries + * @param _fromIndex Start index of array of beneficiary's addresses + * @param _toIndex End index of array of beneficiary's addresses */ function pushAvailableTokensMulti(uint256 _fromIndex, uint256 _toIndex) external withPerm(ADMIN) { require(_toIndex <= beneficiaries.length - 1, "Array out of bound"); @@ -428,13 +429,13 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Used to bulk add vesting schedules for each of beneficiaries - * @param _beneficiaries array of beneficiary's addresses - * @param _templateNames array of the template names - * @param _numberOfTokens array of number of tokens - * @param _durations array of vesting duration - * @param _frequencies array of vesting frequency - * @param _startTimes array of vesting start time + * @notice Used to bulk add vesting schedules for each of beneficiary + * @param _beneficiaries Array of the beneficiary's addresses + * @param _templateNames Array of the template names + * @param _numberOfTokens Array of number of tokens should be assigned to schedules + * @param _durations Array of the vesting duration + * @param _frequencies Array of the vesting frequency + * @param _startTimes Array of the vesting start time */ function addScheduleMulti( address[] _beneficiaries, @@ -461,10 +462,10 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Used to bulk add vesting schedules from template for each of beneficiaries - * @param _beneficiaries array of beneficiary's addresses - * @param _templateNames array of the template names - * @param _startTimes array of vesting start time + * @notice Used to bulk add vesting schedules from template for each of the beneficiary + * @param _beneficiaries Array of beneficiary's addresses + * @param _templateNames Array of the template names were used for schedule creation + * @param _startTimes Array of the vesting start time */ function addScheduleFromTemplateMulti(address[] _beneficiaries, bytes32[] _templateNames, uint256[] _startTimes) external withPerm(ADMIN) { require(_beneficiaries.length == _templateNames.length && _beneficiaries.length == _startTimes.length, "Arrays sizes mismatch"); @@ -474,8 +475,8 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Used to bulk revoke vesting schedules for each of beneficiaries - * @param _beneficiaries array of beneficiary's addresses + * @notice Used to bulk revoke vesting schedules for each of the beneficiaries + * @param _beneficiaries Array of the beneficiary's addresses */ function revokeSchedulesMulti(address[] _beneficiaries) external withPerm(ADMIN) { for (uint256 i = 0; i < _beneficiaries.length; i++) { @@ -484,10 +485,10 @@ contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { } /** - * @notice Used to bulk modify vesting schedules for each of beneficiaries - * @param _beneficiaries array of beneficiary's addresses - * @param _templateNames array of the template names - * @param _startTimes array of vesting start time + * @notice Used to bulk modify vesting schedules for each of the beneficiaries + * @param _beneficiaries Array of the beneficiary's addresses + * @param _templateNames Array of the template names + * @param _startTimes Array of the vesting start time */ function modifyScheduleMulti( address[] _beneficiaries, From 9088434c1f3f340caf1ead09646dd7e5821563d5 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 19 Dec 2018 10:14:14 +0200 Subject: [PATCH 445/582] added VestingEscrowWalletLogic to output --- migrations/2_deploy_contracts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index eefc66d28..4beb28252 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -357,6 +357,7 @@ module.exports = function (deployer, network, accounts) { EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} VestingEscrowWalletFactory: ${VestingEscrowWalletFactory.address} + VestingEscrowWalletLogic: ${VestingEscrowWalletLogic.address} --------------------------------------------------------------------------------- `); console.log('\n'); From 65b2b49fd9bf8a48526b82efb3b8e78abf51ed5a Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 19 Dec 2018 22:32:22 +0000 Subject: [PATCH 446/582] Track withheld at dividend granularity --- .../modules/Checkpoint/DividendCheckpoint.sol | 41 ++++++++++++++++++- .../Checkpoint/DividendCheckpointStorage.sol | 8 ++-- .../Checkpoint/ERC20DividendCheckpoint.sol | 10 +++-- .../Checkpoint/EtherDividendCheckpoint.sol | 10 +++-- test/e_erc20_dividends.js | 30 +++++++++++--- 5 files changed, 79 insertions(+), 20 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index daa5f1e50..6f1887693 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -227,25 +227,62 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { */ function withdrawWithholding(uint256 _dividendIndex) external; + /** + * @notice Get static dividend data + * @return uint256[] timestamp of dividends creation + * @return uint256[] timestamp of dividends maturity + * @return uint256[] timestamp of dividends expiry + * @return uint256[] amount of dividends + * @return uint256[] claimed amount of dividends + * @return bytes32[] name of dividends + */ + function getDividendsData() external view returns ( + uint256[] memory createds, + uint256[] memory maturitys, + uint256[] memory expirys, + uint256[] memory amounts, + uint256[] memory claimedAmounts, + bytes32[] memory names) + { + createds = new uint256[](dividends.length); + maturitys = new uint256[](dividends.length); + expirys = new uint256[](dividends.length); + amounts = new uint256[](dividends.length); + claimedAmounts = new uint256[](dividends.length); + names = new bytes32[](dividends.length); + for (uint256 i = 0; i < dividends.length; i++) { + createds[i] = dividends[i].created; + maturitys[i] = dividends[i].maturity; + expirys[i] = dividends[i].expiry; + amounts[i] = dividends[i].amount; + claimedAmounts[i] = dividends[i].claimedAmount; + names[i] = dividends[i].name; + } + return (createds, maturitys, expirys, amounts, claimedAmounts, names); + } + /** * @notice Retrieves list of investors, their claim status and whether they are excluded * @param _dividendIndex Dividend to withdraw from * @return address[] list of investors * @return bool[] whether investor has claimed * @return bool[] whether investor is excluded + * @return uint256[] amount of withheld tax */ - function getDividendInfo(uint256 _dividendIndex) external view returns (address[], bool[], bool[]) { + function getDividendProgress(uint256 _dividendIndex) external view returns (address[], bool[], bool[], uint256[]) { require(_dividendIndex < dividends.length, "Invalid dividend"); //Get list of Investors uint256 checkpointId = dividends[_dividendIndex].checkpointId; address[] memory investors = ISecurityToken(securityToken).getInvestorsAt(checkpointId); bool[] memory resultClaimed = new bool[](investors.length); bool[] memory resultExcluded = new bool[](investors.length); + uint256[] memory resultWithheld = new uint256[](investors.length); for (uint256 i; i < investors.length; i++) { resultClaimed[i] = dividends[_dividendIndex].claimed[investors[i]]; resultExcluded[i] = dividends[_dividendIndex].dividendExcluded[investors[i]]; + resultWithheld[i] = dividends[_dividendIndex].withheld[investors[i]]; } - return (investors, resultClaimed, resultExcluded); + return (investors, resultClaimed, resultExcluded, resultWithheld); } /** diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol index fd95e7e00..85e7e789a 100644 --- a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -21,10 +21,11 @@ contract DividendCheckpointStorage { uint256 claimedAmount; // Amount of dividend claimed so far uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this) bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend - uint256 dividendWithheld; - uint256 dividendWithheldReclaimed; + uint256 totalWithheld; + uint256 totalWithheldWithdrawn; mapping (address => bool) claimed; // List of addresses which have claimed dividend mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends + mapping (address => uint256) withheld; // Amount of tax withheld from claim bytes32 name; // Name/title - used for identification } @@ -37,7 +38,4 @@ contract DividendCheckpointStorage { // Mapping from address to withholding tax as a percentage * 10**16 mapping (address => uint256) public withholdingTax; - // Total amount of ETH withheld per investor - mapping (address => uint256) public investorWithheld; - } diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index b779088f7..174498537 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -241,8 +241,10 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec uint256 claimAfterWithheld = claim.sub(withheld); if (claimAfterWithheld > 0) { require(IERC20(dividendTokens[_dividendIndex]).transfer(_payee, claimAfterWithheld), "transfer failed"); - _dividend.dividendWithheld = _dividend.dividendWithheld.add(withheld); - investorWithheld[_payee] = investorWithheld[_payee].add(withheld); + if (withheld > 0) { + _dividend.totalWithheld = _dividend.totalWithheld.add(withheld); + _dividend.withheld[_payee] = withheld; + } emit ERC20DividendClaimed(_payee, _dividendIndex, dividendTokens[_dividendIndex], claim, withheld); } } @@ -271,8 +273,8 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec function withdrawWithholding(uint256 _dividendIndex) external withPerm(MANAGE) { require(_dividendIndex < dividends.length, "Invalid dividend"); Dividend storage dividend = dividends[_dividendIndex]; - uint256 remainingWithheld = dividend.dividendWithheld.sub(dividend.dividendWithheldReclaimed); - dividend.dividendWithheldReclaimed = dividend.dividendWithheld; + uint256 remainingWithheld = dividend.totalWithheld.sub(dividend.totalWithheldWithdrawn); + dividend.totalWithheldWithdrawn = dividend.totalWithheld; address owner = IOwnable(securityToken).owner(); require(IERC20(dividendTokens[_dividendIndex]).transfer(owner, remainingWithheld), "transfer failed"); emit ERC20DividendWithholdingWithdrawn(owner, _dividendIndex, dividendTokens[_dividendIndex], remainingWithheld); diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index e1cb3174c..3397f208b 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -176,8 +176,10 @@ contract EtherDividendCheckpoint is DividendCheckpoint { /*solium-disable-next-line security/no-send*/ if (_payee.send(claimAfterWithheld)) { _dividend.claimedAmount = _dividend.claimedAmount.add(claim); - _dividend.dividendWithheld = _dividend.dividendWithheld.add(withheld); - investorWithheld[_payee] = investorWithheld[_payee].add(withheld); + if (withheld > 0) { + _dividend.totalWithheld = _dividend.totalWithheld.add(withheld); + _dividend.withheld[_payee] = withheld; + } emit EtherDividendClaimed(_payee, _dividendIndex, claim, withheld); } else { _dividend.claimed[_payee] = false; @@ -210,8 +212,8 @@ contract EtherDividendCheckpoint is DividendCheckpoint { function withdrawWithholding(uint256 _dividendIndex) external withPerm(MANAGE) { require(_dividendIndex < dividends.length, "Incorrect dividend index"); Dividend storage dividend = dividends[_dividendIndex]; - uint256 remainingWithheld = dividend.dividendWithheld.sub(dividend.dividendWithheldReclaimed); - dividend.dividendWithheldReclaimed = dividend.dividendWithheld; + uint256 remainingWithheld = dividend.totalWithheld.sub(dividend.totalWithheldWithdrawn); + dividend.totalWithheldWithdrawn = dividend.totalWithheld; address owner = IOwnable(securityToken).owner(); owner.transfer(remainingWithheld); emit EtherDividendWithholdingWithdrawn(owner, _dividendIndex, remainingWithheld); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index e77ff69e6..192e13598 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -330,6 +330,12 @@ contract("ERC20DividendCheckpoint", accounts => { ); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 1, "Dividend should be created at checkpoint 1"); assert.equal(tx.logs[0].args._name.toString(), dividendName, "Dividend name incorrect in event"); + let data = await I_ERC20DividendCheckpoint.getDividendsData(); + assert.equal(data[1][0].toNumber(), maturity, "maturity match"); + assert.equal(data[2][0].toNumber(), expiry, "expiry match"); + assert.equal(data[3][0].toNumber(), web3.utils.toWei("1.5", "ether"), "amount match"); + assert.equal(data[4][0].toNumber(), 0, "claimed match"); + assert.equal(data[5][0], dividendName, "dividendName match"); }); it("Investor 1 transfers his token balance to investor 2", async () => { @@ -529,11 +535,16 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), web3.utils.toWei("7", "ether")); - let info = await I_ERC20DividendCheckpoint.getDividendInfo.call(2); - assert.equal(info[0][1], account_temp, "account_temp is excluded"); + let info = await I_ERC20DividendCheckpoint.getDividendProgress.call(2); + console.log(info); + assert.equal(info[0][1], account_temp, "account_temp"); + assert.equal(info[1][1], false, "account_temp is not claimed"); assert.equal(info[2][1], true, "account_temp is excluded"); - assert.equal(info[0][2], account_investor3, "account_investor3 is claimed"); - assert.equal(info[1][2], true, "account_temp is claimed"); + assert.equal(info[3][1], 0, "account_temp is not withheld"); + assert.equal(info[0][2], account_investor3, "account_investor3"); + assert.equal(info[1][2], true, "account_investor3 is claimed"); + assert.equal(info[2][2], false, "account_investor3 is claimed"); + assert.equal(info[3][2], 0, "account_investor3 is not withheld"); }); it("should investor 3 claims dividend - fails already claimed", async () => { @@ -832,6 +843,15 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Issuer reclaims withholding tax", async () => { + let info = await I_ERC20DividendCheckpoint.getDividendProgress.call(3); + assert.equal(info[0][0], account_investor1, "account match"); + assert.equal(info[0][1], account_investor2, "account match"); + assert.equal(info[0][2], account_temp, "account match"); + assert.equal(info[0][3], account_investor3, "account match"); + assert.equal(info[3][0].toNumber(), 0, "withheld match"); + assert.equal(info[3][1].toNumber(), web3.utils.toWei("0.2", "ether"), "withheld match"); + assert.equal(info[3][2].toNumber(), web3.utils.toWei("0.2", "ether"), "withheld match"); + assert.equal(info[3][3].toNumber(), 0, "withheld match"); let issuerBalance = new BigNumber(await I_PolyToken.balanceOf(token_owner)); await I_ERC20DividendCheckpoint.withdrawWithholding(3, { from: token_owner, gasPrice: 0 }); let issuerBalanceAfter = new BigNumber(await I_PolyToken.balanceOf(token_owner)); @@ -1089,7 +1109,7 @@ contract("ERC20DividendCheckpoint", accounts => { ); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 9); console.log("Gas used w/ max exclusions - non-default: " + tx.receipt.gasUsed); - let info = await I_ERC20DividendCheckpoint.getDividendInfo.call(tx.logs[0].args._dividendIndex); + let info = await I_ERC20DividendCheckpoint.getDividendProgress.call(tx.logs[0].args._dividendIndex); assert.equal(info[0][2], account_temp, "account_temp is excluded"); assert.equal(info[2][2], true, "account_temp is excluded"); }); From 33860722276507c2e29097d1433771396ff8f269 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 20 Dec 2018 15:22:13 +0700 Subject: [PATCH 447/582] wip - issue with test not finishing --- ...zer_volumn_restriction_transfer_manager.js | 309 ++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 test/z_fuzzer_volumn_restriction_transfer_manager.js diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js new file mode 100644 index 000000000..9152a73c3 --- /dev/null +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -0,0 +1,309 @@ +import latestTime from './helpers/latestTime'; +import {signData} from './helpers/signData'; +import { pk } from './helpers/testprivateKey'; +import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { catchRevert } from "./helpers/exceptions"; +import { setUpPolymathNetwork, deployVRTMAndVerifyed } from "./helpers/createInstances"; + +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager.sol'); +const VolumeRestrictionTM = artifacts.require('./VolumeRestrictionTM.sol'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('VolumeRestrictionTransferManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let token_owner_pk; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + let account_delegate; + let account_delegate2; + let account_delegate3; + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_VolumeRestrictionTMFactory; + let P_VolumeRestrictionTMFactory; + let I_SecurityTokenRegistryProxy; + let P_VolumeRestrictionTM; + let I_GeneralTransferManagerFactory; + let I_VolumeRestrictionTM; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_DummySTOFactory; + let I_STFactory; + let I_SecurityToken; + let I_MRProxied; + let I_STRProxied; + let I_PolyToken; + let I_PolymathRegistry; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + const delegateDetails = "Hello I am legit delegate"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + let tempAmount = new BigNumber(0); + let tempArray = new Array(); + let tempArray3 = new Array(); + let tempArrayGlobal = new Array(); + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + async function print(data, account) { + console.log(` + Latest timestamp: ${data[0].toNumber()} + SumOfLastPeriod: ${data[1].dividedBy(new BigNumber(10).pow(18)).toNumber()} + Days Covered: ${data[2].toNumber()} + Latest timestamp daily: ${data[3].toNumber()} + Individual Total Trade on latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[0])) + .dividedBy(new BigNumber(10).pow(18)).toNumber()} + Individual Total Trade on daily latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[3])) + .dividedBy(new BigNumber(10).pow(18)).toNumber()} + `) + } + + async function calculateSum(rollingPeriod, tempArray) { + let sum = 0; + let start = 0; + if (tempArray.length >= rollingPeriod) + start = tempArray.length - rollingPeriod; + for (let i = start; i < tempArray.length; i++) { + sum += tempArray[i]; + } + return sum; + } + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + token_owner_pk = pk.account_1; + + account_investor1 = accounts[8]; + account_investor2 = accounts[9]; + account_investor3 = accounts[4]; + account_investor4 = accounts[3]; + account_delegate = accounts[7]; + account_delegate2 = accounts[6]; + account_delegate3 = accounts[5]; + + // Step 1: Deploy the genral PM ecosystem + let instances = await setUpPolymathNetwork(account_polymath, token_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; + + // STEP 5: Deploy the VolumeRestrictionTMFactory + [I_VolumeRestrictionTMFactory] = await deployVRTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 6: Deploy the VolumeRestrictionTMFactory + [P_VolumeRestrictionTMFactory] = await deployVRTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${I_PolymathRegistry.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistryProxy ${I_ModuleRegistryProxy.address} + ModuleRegistry: ${I_ModuleRegistry.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + STFactory: ${I_STFactory.address} + GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + VolumeRestrictionTMFactory: ${I_VolumeRestrictionTMFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async () => { + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from: token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, true, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal(web3.utils.toAscii(log.args._name).replace(/\u0000/g, ""), "GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + }); + + describe("Attach the VRTMaaaaa", async() => { + it("Deploy the VRTM and attach with the ST", async()=> { + let tx = await I_SecurityToken.addModule(I_VolumeRestrictionTMFactory.address, 0, 0, 0, {from: token_owner }); + assert.equal(tx.logs[2].args._moduleFactory, I_VolumeRestrictionTMFactory.address); + assert.equal( + web3.utils.toUtf8(tx.logs[2].args._name), + "VolumeRestrictionTM", + "VolumeRestrictionTMFactory doesn not added"); + I_VolumeRestrictionTM = VolumeRestrictionTM.at(tx.logs[2].args._module); + }); + + it("Transfer some tokens to different account", async() => { + // Add tokens in to the whitelist + await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor1, account_investor2, account_investor3], + [latestTime(), latestTime(), latestTime()], + [latestTime(), latestTime(), latestTime()], + [latestTime() + duration.days(60), latestTime() + duration.days(60), latestTime() + duration.days(60)], + [true, true, true], + { + from: token_owner + } + ); + + // Mint some tokens and transferred to whitelisted addresses + await I_SecurityToken.mint(account_investor1, web3.utils.toWei("40", "ether"), {from: token_owner}); + await I_SecurityToken.mint(account_investor2, web3.utils.toWei("30", "ether"), {from: token_owner}); + await I_SecurityToken.mint(account_investor3, web3.utils.toWei("30", "ether"), {from: token_owner}); + + }); + + }); + + describe("Fuzz test - multiple transaction within 1 day with Individual and daily Restrictions", async() => { + + let snapId = await takeSnapshot(); + + var testRepeat = 2; + var sumOfLastPeriod = 0; + var txAmount = []; + var txDates = []; + + for (var i = 0; i < testRepeat; i++) { + + var individualRestrictTotalAmount = 3; + var dailyRestrictionAmount = 6; + var rollingPeriod = 2; + var transferAmount = Math.floor(Math.random() * 10); + var timePassed = Math.floor(Math.random() * 10); + console.log("individualRestrictTotalAmount : " + individualRestrictTotalAmount + "transferAmount : " + transferAmount + "timePassed : " + timePassed); + + // 1 - add individual restriction with a random number + it("Should add individual restriction succesfully", async() => { + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei(individualRestrictTotalAmount.toString()), + latestTime() + duration.seconds(2), + rollingPeriod, + latestTime() + duration.days(3), + 0, + { + from: token_owner + } + ); + }); + + it("Should add daily restriction succesfully", async() => { + + let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor1, + web3.utils.toWei(dailyRestrictionAmount.toString()), + latestTime() + duration.seconds(1), + latestTime() + duration.days(4), + 0, + { + from: token_owner + } + ); + + }); + + it("transaction tests", async() => { + + var txNumber = 2; // define fuzz test amount for tx within 24 hrs + + for (var j=0; j individualRestrictTotalAmount || accumulatedTxValue > dailyRestrictionAmount){ + + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) + ); + + console.log("tx failed as expected due to over limit"); + + } else if (accumulatedTxValue < individualRestrictTotalAmount && accumulatedTxValue < dailyRestrictionAmount ){ + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); + + sumOfLastPeriod = sumOfLastPeriod + transactionAmount; + + console.log("tx succeeded"); + } + + await increaseTime(duration.seconds(20/txNumber*3600)); + + } + + }); + + await revertToSnapshot(snapId); + } + + }); + +}); \ No newline at end of file From 20abb7d04bb0fffb5d6e44194eb9a7fcf5681515 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 20 Dec 2018 14:56:11 +0200 Subject: [PATCH 448/582] removed redundant dependencies --- package.json | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index b7c961872..99127d0c6 100644 --- a/package.json +++ b/package.json @@ -65,21 +65,14 @@ "chalk": "^2.4.1", "coveralls": "^3.0.1", "csv-parse": "^4.0.1", - "ethereumjs-testrpc": "^6.0.3", "ethers": "^4.0.7", "fs": "0.0.2", "openzeppelin-solidity": "1.10.0", "prompt": "^1.0.0", - "readline-sync": "^1.4.9", - "request": "^2.88.0", - "request-promise": "^4.2.2", - "solc": "^0.4.24", - "truffle-contract": "^3.0.4", "truffle-hdwallet-provider-privkey": "0.2.0", "web3": "1.0.0-beta.34" }, "devDependencies": { - "@soldoc/soldoc": "^0.4.3", "eslint": "^5.8.0", "eslint-config-standard": "^12.0.0", "eslint-plugin-import": "^2.10.0", @@ -91,6 +84,8 @@ "ganache-cli": "^6.1.8", "mocha-junit-reporter": "^1.18.0", "prettier": "^1.14.3", + "request": "^2.88.0", + "request-promise": "^4.2.2", "sol-merger": "^0.1.2", "solidity-coverage": "^0.5.11", "solidity-docgen": "^0.1.0", From 5c7c2a7ce1f68fb9c18d6f26c88e9e6077526077 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 20 Dec 2018 15:25:38 +0200 Subject: [PATCH 449/582] increased versions --- package.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 99127d0c6..fdf975a9d 100644 --- a/package.json +++ b/package.json @@ -63,19 +63,19 @@ "babel-register": "6.26.0", "bignumber.js": "5.0.0", "chalk": "^2.4.1", - "coveralls": "^3.0.1", - "csv-parse": "^4.0.1", - "ethers": "^4.0.7", + "coveralls": "^3.0.2", + "csv-parse": "^4.2.0", + "ethers": "^4.0.20", "fs": "0.0.2", "openzeppelin-solidity": "1.10.0", "prompt": "^1.0.0", - "truffle-hdwallet-provider-privkey": "0.2.0", + "truffle-hdwallet-provider-privkey": "0.3.0", "web3": "1.0.0-beta.34" }, "devDependencies": { - "eslint": "^5.8.0", + "eslint": "^5.10.0", "eslint-config-standard": "^12.0.0", - "eslint-plugin-import": "^2.10.0", + "eslint-plugin-import": "^2.14.0", "eslint-plugin-node": "^8.0.0", "eslint-plugin-promise": "^4.0.1", "eslint-plugin-standard": "^4.0.0", @@ -83,13 +83,13 @@ "ethereumjs-abi": "^0.6.5", "ganache-cli": "^6.1.8", "mocha-junit-reporter": "^1.18.0", - "prettier": "^1.14.3", + "prettier": "^1.15.3", "request": "^2.88.0", "request-promise": "^4.2.2", - "sol-merger": "^0.1.2", + "sol-merger": "^0.1.3", "solidity-coverage": "^0.5.11", "solidity-docgen": "^0.1.0", - "solium": "^1.1.6", + "solium": "^1.1.8", "truffle": "4.1.14", "truffle-wallet-provider": "0.0.5" }, From 43cc95a7065b2512fe4d0b3afbfeca4c6f34e191 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 20 Dec 2018 22:14:24 +0700 Subject: [PATCH 450/582] WIP-multiple transaction within 1 day with Individual and daily Restrictions --- ...zer_volumn_restriction_transfer_manager.js | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index 9152a73c3..b606ad1bf 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -219,26 +219,25 @@ contract('VolumeRestrictionTransferManager', accounts => { }); - describe("Fuzz test - multiple transaction within 1 day with Individual and daily Restrictions", async() => { - - let snapId = await takeSnapshot(); - - var testRepeat = 2; - var sumOfLastPeriod = 0; - var txAmount = []; - var txDates = []; - - for (var i = 0; i < testRepeat; i++) { - - var individualRestrictTotalAmount = 3; - var dailyRestrictionAmount = 6; - var rollingPeriod = 2; - var transferAmount = Math.floor(Math.random() * 10); - var timePassed = Math.floor(Math.random() * 10); - console.log("individualRestrictTotalAmount : " + individualRestrictTotalAmount + "transferAmount : " + transferAmount + "timePassed : " + timePassed); + describe("Fuzz test", async() => { + + it("Should work with multiple transaction within 1 day with Individual and daily Restrictions", async() => { + // let snapId = await takeSnapshot(); - // 1 - add individual restriction with a random number - it("Should add individual restriction succesfully", async() => { + var testRepeat = 2; + + for (var i = 0; i < testRepeat; i++) { + + console.log("fuzzer number " + i); + + var individualRestrictTotalAmount = 7; + var dailyRestrictionAmount = 6; + var rollingPeriod = 2; + var sumOfLastPeriod = 0; + + + // 1 - add individual restriction with a random number + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei(individualRestrictTotalAmount.toString()), @@ -250,11 +249,9 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ); - }); - it("Should add daily restriction succesfully", async() => { - - let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + + tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor1, web3.utils.toWei(dailyRestrictionAmount.toString()), latestTime() + duration.seconds(1), @@ -264,46 +261,49 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ); - - }); - - it("transaction tests", async() => { + - var txNumber = 2; // define fuzz test amount for tx within 24 hrs + var txNumber = 3; // define fuzz test amount for tx within 24 hrs for (var j=0; j individualRestrictTotalAmount || accumulatedTxValue > dailyRestrictionAmount){ + console.log("tx should fail"); + await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) ); console.log("tx failed as expected due to over limit"); - } else if (accumulatedTxValue < individualRestrictTotalAmount && accumulatedTxValue < dailyRestrictionAmount ){ + } else if (accumulatedTxValue <= individualRestrictTotalAmount && accumulatedTxValue <= dailyRestrictionAmount ){ + console.log("tx should succeed"); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); sumOfLastPeriod = sumOfLastPeriod + transactionAmount; console.log("tx succeeded"); } - - await increaseTime(duration.seconds(20/txNumber*3600)); - + console.log("2"); } - - }); - - await revertToSnapshot(snapId); - } - + } + // await revertToSnapshot(snapId); + }); }); }); \ No newline at end of file From 28449383fd49f46514b6c898d5b0202d21cdba69 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Thu, 20 Dec 2018 18:28:46 +0200 Subject: [PATCH 451/582] updated yarn.lock --- yarn.lock | 2470 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 1412 insertions(+), 1058 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6357fb487..d18ea0c04 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,78 +18,47 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@soldoc/markdown@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@soldoc/markdown/-/markdown-0.1.0.tgz#9f85be75049af9721b5129f133d52dafbf5f671e" - -"@soldoc/soldoc@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@soldoc/soldoc/-/soldoc-0.4.3.tgz#24ffee9264228e1c3edd61fd3162d63587954933" - dependencies: - "@soldoc/markdown" "^0.1.0" - chalk "^2.3.1" - deep-assign "^2.0.0" - fs-extra "^5.0.0" - shelljs "^0.8.1" - solc "^0.4.19" - valid-url "^1.0.9" - yargs "^11.0.0" - "@types/node@^10.3.2": - version "10.12.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.2.tgz#d77f9faa027cadad9c912cd47f4f8b07b0fb0864" - integrity sha512-53ElVDSnZeFUUFIYzI8WLQ25IhWzb6vbddNp8UHlXQyU0ET2RhV5zg0NfubzU7iNMh5bBXb0htCzfvrSVNgzaQ== + version "10.12.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" + integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= abstract-leveldown@~2.6.0: version "2.6.3" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== dependencies: xtend "~4.0.0" abstract-leveldown@~2.7.1: version "2.7.2" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== dependencies: xtend "~4.0.0" accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" + integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= dependencies: mime-types "~2.1.18" negotiator "0.6.1" -acorn-dynamic-import@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" - dependencies: - acorn "^4.0.3" - -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - dependencies: - acorn "^3.0.4" - -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - -acorn@^4.0.3: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - -acorn@^5.0.0: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" +acorn-jsx@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" + integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== acorn@^6.0.2: version "6.0.4" @@ -99,48 +68,37 @@ acorn@^6.0.2: aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= aes-js@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072" + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== -ajv-keywords@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - -ajv-keywords@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" - -ajv@^5.1.1, ajv@^5.2.2, ajv@^5.3.0: +ajv@^5.2.2: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ajv@^6.1.0: - version "6.5.4" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59" +ajv@^6.5.3, ajv@^6.5.5, ajv@^6.6.1: + version "6.6.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" + integrity sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - ambi@^2.2.0: version "2.5.0" resolved "https://registry.yarnpkg.com/ambi/-/ambi-2.5.0.tgz#7c8e372be48891157e7cea01cb6f9143d1f74220" + integrity sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA= dependencies: editions "^1.1.1" typechecker "^4.3.0" @@ -148,54 +106,62 @@ ambi@^2.2.0: amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= ansi-escapes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" + integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" + integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= -ansi-styles@^3.2.1: +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== dependencies: micromatch "^2.1.5" normalize-path "^2.0.0" -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -203,71 +169,51 @@ are-we-there-yet@~1.1.2: argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -arguments-extended@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/arguments-extended/-/arguments-extended-0.0.3.tgz#6107e4917d0eb6f0a4dd66320fc15afc72ef4946" - dependencies: - extended "~0.0.3" - is-extended "~0.0.8" - arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= dependencies: arr-flatten "^1.0.1" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - -array-extended@~0.0.3, array-extended@~0.0.4, array-extended@~0.0.5: - version "0.0.11" - resolved "https://registry.yarnpkg.com/array-extended/-/array-extended-0.0.11.tgz#d7144ae748de93ca726f121009dbff1626d164bd" - dependencies: - arguments-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -276,34 +222,38 @@ asn1.js@^4.0.0: asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -assert@^1.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - dependencies: - util "0.10.3" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-eventemitter@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== dependencies: async "^2.4.0" -async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c: +"async-eventemitter@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c": version "0.2.3" resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c" dependencies: @@ -312,44 +262,54 @@ async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== async@1.x, async@^1.4.2, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.4.1, async@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== dependencies: lodash "^4.17.10" async@~0.9.0: version "0.9.2" - resolved "http://registry.npmjs.org/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= async@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" + integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -358,6 +318,7 @@ babel-code-frame@^6.26.0: babel-core@^6.0.14, babel-core@^6.26.0: version "6.26.3" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== dependencies: babel-code-frame "^6.26.0" babel-generator "^6.26.0" @@ -382,6 +343,7 @@ babel-core@^6.0.14, babel-core@^6.26.0: babel-generator@^6.26.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" @@ -395,6 +357,7 @@ babel-generator@^6.26.0: babel-helper-bindify-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" + integrity sha1-FMGeXxQte0fxmlJDHlKxzLxAozA= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -403,6 +366,7 @@ babel-helper-bindify-decorators@^6.24.1: babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= dependencies: babel-helper-explode-assignable-expression "^6.24.1" babel-runtime "^6.22.0" @@ -411,6 +375,7 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -420,6 +385,7 @@ babel-helper-call-delegate@^6.24.1: babel-helper-define-map@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.26.0" @@ -429,6 +395,7 @@ babel-helper-define-map@^6.24.1: babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -437,6 +404,7 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-helper-explode-class@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" + integrity sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes= dependencies: babel-helper-bindify-decorators "^6.24.1" babel-runtime "^6.22.0" @@ -446,6 +414,7 @@ babel-helper-explode-class@^6.24.1: babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= dependencies: babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" @@ -456,6 +425,7 @@ babel-helper-function-name@^6.24.1: babel-helper-get-function-arity@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -463,6 +433,7 @@ babel-helper-get-function-arity@^6.24.1: babel-helper-hoist-variables@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -470,6 +441,7 @@ babel-helper-hoist-variables@^6.24.1: babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -477,6 +449,7 @@ babel-helper-optimise-call-expression@^6.24.1: babel-helper-regex@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= dependencies: babel-runtime "^6.26.0" babel-types "^6.26.0" @@ -485,6 +458,7 @@ babel-helper-regex@^6.24.1: babel-helper-remap-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -495,6 +469,7 @@ babel-helper-remap-async-to-generator@^6.24.1: babel-helper-replace-supers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= dependencies: babel-helper-optimise-call-expression "^6.24.1" babel-messages "^6.23.0" @@ -506,6 +481,7 @@ babel-helper-replace-supers@^6.24.1: babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -513,50 +489,61 @@ babel-helpers@^6.24.1: babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= dependencies: babel-runtime "^6.22.0" babel-plugin-check-es2015-constants@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= dependencies: babel-runtime "^6.22.0" babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= babel-plugin-syntax-async-generators@^6.5.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" + integrity sha1-a8lj67FuzLrmuStZbrfzXDQqi5o= babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= babel-plugin-syntax-decorators@^6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" + integrity sha1-MSVjtNvePMgGzuPkFszurd0RrAs= babel-plugin-syntax-dynamic-import@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= babel-plugin-transform-async-generator-functions@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" + integrity sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-generators "^6.5.0" @@ -565,6 +552,7 @@ babel-plugin-transform-async-generator-functions@^6.24.1: babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-functions "^6.8.0" @@ -573,6 +561,7 @@ babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async- babel-plugin-transform-class-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= dependencies: babel-helper-function-name "^6.24.1" babel-plugin-syntax-class-properties "^6.8.0" @@ -582,6 +571,7 @@ babel-plugin-transform-class-properties@^6.24.1: babel-plugin-transform-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" + integrity sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0= dependencies: babel-helper-explode-class "^6.24.1" babel-plugin-syntax-decorators "^6.13.0" @@ -592,18 +582,21 @@ babel-plugin-transform-decorators@^6.24.1: babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= dependencies: babel-runtime "^6.26.0" babel-template "^6.26.0" @@ -614,6 +607,7 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= dependencies: babel-helper-define-map "^6.24.1" babel-helper-function-name "^6.24.1" @@ -628,6 +622,7 @@ babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-cla babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -635,12 +630,14 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transfor babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -648,12 +645,14 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2 babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -662,12 +661,14 @@ babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= dependencies: babel-plugin-transform-es2015-modules-commonjs "^6.24.1" babel-runtime "^6.22.0" @@ -676,6 +677,7 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.26.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== dependencies: babel-plugin-transform-strict-mode "^6.24.1" babel-runtime "^6.26.0" @@ -685,6 +687,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -693,6 +696,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= dependencies: babel-plugin-transform-es2015-modules-amd "^6.24.1" babel-runtime "^6.22.0" @@ -701,6 +705,7 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= dependencies: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" @@ -708,6 +713,7 @@ babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= dependencies: babel-helper-call-delegate "^6.24.1" babel-helper-get-function-arity "^6.24.1" @@ -719,6 +725,7 @@ babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015- babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -726,12 +733,14 @@ babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transfo babel-plugin-transform-es2015-spread@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -740,18 +749,21 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -760,6 +772,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= dependencies: babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" babel-plugin-syntax-exponentiation-operator "^6.8.0" @@ -768,6 +781,7 @@ babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-e babel-plugin-transform-object-rest-spread@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" + integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" @@ -775,12 +789,14 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= dependencies: regenerator-transform "^0.10.0" babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -788,6 +804,7 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-polyfill@6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" + integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= dependencies: babel-runtime "^6.26.0" core-js "^2.5.0" @@ -796,6 +813,7 @@ babel-polyfill@6.26.0: babel-preset-env@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -831,6 +849,7 @@ babel-preset-env@^1.7.0: babel-preset-es2015@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" + integrity sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk= dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-transform-es2015-arrow-functions "^6.22.0" @@ -860,6 +879,7 @@ babel-preset-es2015@6.24.1: babel-preset-stage-2@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" + integrity sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE= dependencies: babel-plugin-syntax-dynamic-import "^6.18.0" babel-plugin-transform-class-properties "^6.24.1" @@ -869,6 +889,7 @@ babel-preset-stage-2@6.24.1: babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" + integrity sha1-g2raCp56f6N8sTj7kyb4eTSkg5U= dependencies: babel-plugin-syntax-trailing-function-commas "^6.22.0" babel-plugin-transform-async-generator-functions "^6.24.1" @@ -879,6 +900,7 @@ babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: babel-register@6.26.0, babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= dependencies: babel-core "^6.26.0" babel-runtime "^6.26.0" @@ -891,6 +913,7 @@ babel-register@6.26.0, babel-register@^6.26.0: babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" @@ -898,6 +921,7 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= dependencies: babel-runtime "^6.26.0" babel-traverse "^6.26.0" @@ -908,6 +932,7 @@ babel-template@^6.24.1, babel-template@^6.26.0: babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= dependencies: babel-code-frame "^6.26.0" babel-messages "^6.23.0" @@ -922,6 +947,7 @@ babel-traverse@^6.24.1, babel-traverse@^6.26.0: babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= dependencies: babel-runtime "^6.26.0" esutils "^2.0.2" @@ -931,6 +957,7 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: babelify@^7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" + integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= dependencies: babel-core "^6.0.14" object-assign "^4.0.0" @@ -938,28 +965,34 @@ babelify@^7.3.0: babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base-x@^3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" + version "3.0.5" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.5.tgz#d3ada59afed05b921ab581ec3112e6444ba0795a" + integrity sha512-C3picSgzPSLE+jW3tcBzJoGwitOtazb5B+5YmAxZm2ybmTi9LNgAtDO/jjVEBZwHoXmDBZ9m/IELj3elJVRBcA== dependencies: safe-buffer "^5.0.1" base64-js@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" + integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg= base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -972,13 +1005,10 @@ base@^0.11.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - bignumber.js@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" @@ -987,23 +1017,21 @@ bignumber.js@5.0.0: bignumber.js@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" + integrity sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA== -bignumber.js@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" - -bignumber.js@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-6.0.0.tgz#bbfa047644609a5af093e9cbd83b0461fa3f6002" - -"bignumber.js@git+https://github.com/debris/bignumber.js#master": - version "2.0.7" - resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9" +bignumber.js@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" + integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== "bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": version "2.0.7" resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" +"bignumber.js@git+https://github.com/debris/bignumber.js.git#master": + version "2.0.7" + resolved "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9" + "bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git": version "2.0.7" resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" @@ -1011,20 +1039,24 @@ bignumber.js@^6.0.0: binary-extensions@^1.0.0: version "1.12.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" + integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== bindings@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" + version "1.3.1" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.1.tgz#21fc7c6d67c18516ec5aaa2815b145ff77b26ea5" + integrity sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew== bip66@^1.1.3: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" + integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= dependencies: safe-buffer "^5.0.1" bitcore-lib@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.15.0.tgz#f924be13869f2aab7e04aeec5642ad3359b6cec2" + integrity sha512-AeXLWhiivF6CDFzrABZHT4jJrflyylDWTi32o30rF92HW9msfuKpjzrHtFKYGa9w0kNVv5HABQjCB3OEav4PhQ== dependencies: bn.js "=4.11.8" bs58 "=4.0.1" @@ -1033,16 +1065,30 @@ bitcore-lib@^0.15.0: inherits "=2.0.1" lodash "=4.17.4" +bitcore-lib@^0.16.0: + version "0.16.0" + resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.16.0.tgz#a2c3ec1108cdb90386f728282ab833e0c77c9533" + integrity sha512-CEtcrPAH2gwgaMN+OPMJc18TBEak1+TtzMyafrqrIbK9PIa3kat195qBJhC0liJSHRiRr6IE2eLcXeIFFs+U8w== + dependencies: + bn.js "=4.11.8" + bs58 "=4.0.1" + buffer-compare "=1.1.1" + elliptic "=6.4.0" + inherits "=2.0.1" + lodash "=4.17.11" + bitcore-mnemonic@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-1.5.0.tgz#c7e785beb6bf0616ed4992785dc3658670425a39" + version "1.7.0" + resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-1.7.0.tgz#253295a773135e1a0b455871de614996afc8f5e1" + integrity sha512-1JV1okgz9Vv+Y4fG2m3ToR+BGdKA6tSoqjepIxA95BZjW6YaeopVW4iOe/dY9dnkZH4+LA2AJ4YbDE6H3ih3Yw== dependencies: - bitcore-lib "^0.15.0" - unorm "^1.3.3" + bitcore-lib "^0.16.0" + unorm "^1.4.1" bl@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== dependencies: readable-stream "^2.3.5" safe-buffer "^5.1.1" @@ -1050,32 +1096,39 @@ bl@^1.0.0: block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= dependencies: inherits "~2.0.0" bluebird@^2.9.34: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" + integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= -bluebird@^3.4.6, bluebird@^3.5.0: - version "3.5.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" +bluebird@^3.4.6, bluebird@^3.5.0, bluebird@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" + integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= -bn.js@=4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: +bn.js@4.11.8, bn.js@=4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== bn.js@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625" + integrity sha1-EhYrwq5x/EClYmwzQ486h1zTdiU= body-parser@1.18.3, body-parser@^1.16.0: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" + integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= dependencies: bytes "3.0.0" content-type "~1.0.4" @@ -1089,8 +1142,9 @@ body-parser@1.18.3, body-parser@^1.16.0: type-is "~1.6.16" borc@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/borc/-/borc-2.0.3.tgz#08845ea73a6d3211120928ee3929f8dc2de9f52e" + version "2.0.4" + resolved "https://registry.yarnpkg.com/borc/-/borc-2.0.4.tgz#52926dc561137188c6ca9fe01c9542576529a689" + integrity sha512-SCVjto/dbKfduyl+LDQ1Km28ly2aTIXtJbrYZWHFQAxkHph96I/zXTrTQXWuJobG8lQZjIA/dw9z7hmJHJhjMg== dependencies: bignumber.js "^7.2.1" commander "^2.15.0" @@ -1100,6 +1154,7 @@ borc@^2.0.2: brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1107,14 +1162,16 @@ brace-expansion@^1.1.7: braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= dependencies: expand-range "^1.8.1" preserve "^0.2.0" repeat-element "^1.1.2" -braces@^2.3.0, braces@^2.3.1: +braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -1130,18 +1187,22 @@ braces@^2.3.0, braces@^2.3.1: brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1153,6 +1214,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: browserify-cipher@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -1161,6 +1223,7 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -1170,19 +1233,23 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= dependencies: bn.js "^4.1.0" randombytes "^2.0.1" -browserify-sha3@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" +browserify-sha3@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.4.tgz#086c47b8c82316c9d47022c26185954576dd8e26" + integrity sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY= dependencies: - js-sha3 "^0.3.1" + js-sha3 "^0.6.1" + safe-buffer "^5.1.1" browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= dependencies: bn.js "^4.1.1" browserify-rsa "^4.0.0" @@ -1192,15 +1259,10 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - dependencies: - pako "~1.0.5" - browserslist@^3.2.6: version "3.2.8" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== dependencies: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" @@ -1208,16 +1270,19 @@ browserslist@^3.2.6: bs58@=4.0.1, bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= dependencies: base-x "^3.0.2" bs58@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" + integrity sha1-VZCNWPGYKrogCPob7Y+RmYopv40= bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== dependencies: bs58 "^4.0.0" create-hash "^1.1.0" @@ -1226,14 +1291,17 @@ bs58check@^2.1.2: bson@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.0.tgz#bee57d1fb6a87713471af4e32bcae36de814b5b0" + integrity sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA== buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== buffer-alloc@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== dependencies: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" @@ -1241,38 +1309,46 @@ buffer-alloc@^1.2.0: buffer-compare@=1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.1.1.tgz#5be7be853af89198d1f4ddc090d1d66a48aef596" + integrity sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY= buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-to-arraybuffer@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^3.0.1: version "3.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" + integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs= dependencies: base64-js "0.0.8" ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^4.3.0, buffer@^4.9.0: +buffer@^4.9.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1281,6 +1357,7 @@ buffer@^4.3.0, buffer@^4.9.0: buffer@^5.0.5: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" + integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1288,18 +1365,17 @@ buffer@^5.0.5: builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -1314,50 +1390,47 @@ cache-base@^1.0.1: caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= dependencies: callsites "^0.2.0" callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - -camelcase@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= caminte@0.3.7: version "0.3.7" resolved "https://registry.yarnpkg.com/caminte/-/caminte-0.3.7.tgz#ec1ec0457664a0f092643b7c646c457d5cd6f693" + integrity sha1-7B7ARXZkoPCSZDt8ZGxFfVzW9pM= dependencies: bluebird "^3.4.6" uuid "^3.0.1" caniuse-lite@^1.0.30000844: - version "1.0.30000890" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000890.tgz#86a18ffcc65d79ec6a437e985761b8bf1c4efeaf" + version "1.0.30000923" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000923.tgz#148f9bda508024b5ce957b463ae2e8302b451bb2" + integrity sha512-j5ur7eeluOFjjPUkydtXP4KFAsmH3XaQNch5tvWSO+dLHYt5PE+VgJZLWtbVOodfWij6m6zas28T4gB/cLYq1w== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -1365,17 +1438,19 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== charenc@~0.0.1: version "0.0.2" @@ -1385,12 +1460,14 @@ charenc@~0.0.1: checkpoint-store@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= dependencies: functional-red-black-tree "^1.0.1" chokidar@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= dependencies: anymatch "^1.3.0" async-each "^1.0.0" @@ -1403,32 +1480,15 @@ chokidar@^1.6.0: optionalDependencies: fsevents "^1.0.0" -chokidar@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" - dependencies: - anymatch "^2.0.0" - async-each "^1.0.0" - braces "^2.3.0" - glob-parent "^3.1.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - lodash.debounce "^4.0.8" - normalize-path "^2.1.1" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - upath "^1.0.5" - optionalDependencies: - fsevents "^1.2.2" - -chownr@^1.0.1: +chownr@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" + integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -1436,19 +1496,22 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" isobject "^3.0.0" static-extend "^0.1.1" -cli-color@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.3.0.tgz#cd2ec212efbd1a0eeb5b017f17d4e2d15e91420f" +cli-color@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.4.0.tgz#7d10738f48526824f8fe7da51857cb0f572fe01f" + integrity sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w== dependencies: ansi-regex "^2.1.1" d "1" @@ -1460,24 +1523,19 @@ cli-color@^1.2.0: cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -1486,6 +1544,7 @@ cliui@^3.2.0: cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" @@ -1494,18 +1553,22 @@ cliui@^4.0.0: clone@2.x, clone@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= coinstring@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" + integrity sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q= dependencies: bs58 "^2.0.1" create-hash "^1.1.1" @@ -1513,6 +1576,7 @@ coinstring@^2.0.0: collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -1520,142 +1584,143 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= colors@^1.1.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" + version "1.3.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" + integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== -combined-stream@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - dependencies: - delayed-stream "~1.0.0" - -combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== dependencies: delayed-stream "~1.0.0" commander@2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== commander@2.15.1: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== -commander@^2.11.0, commander@^2.14.1, commander@^2.15.0, commander@^2.8.1, commander@^2.9.0: +commander@^2.14.1, commander@^2.15.0, commander@^2.19.0, commander@^2.8.1, commander@^2.9.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== commander@~2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" + integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= dependencies: graceful-readlink ">= 1.0.0" compare-versions@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" + integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg== component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -concat-stream@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - dependencies: - date-now "^0.1.4" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== dependencies: safe-buffer "~5.1.1" cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= cookiejar@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" + integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0, core-js@^2.5.0: - version "2.5.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + version "2.6.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.1.tgz#87416ae817de957a3f249b3b5ca475d4aaed6042" + integrity sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cors@^2.8.1: - version "2.8.4" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== dependencies: object-assign "^4" vary "^1" -coveralls@^3.0.1: +coveralls@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" + integrity sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw== dependencies: growl "~> 1.10.0" js-yaml "^3.11.0" @@ -1667,6 +1732,7 @@ coveralls@^3.0.1: create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== dependencies: bn.js "^4.1.0" elliptic "^6.0.0" @@ -1674,6 +1740,7 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -1684,6 +1751,7 @@ create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -1692,18 +1760,23 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cron-parser@^2.4.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.6.0.tgz#ae2514ceda9ccb540256e201bdd23ae814e03674" +cron-parser@^2.7.3: + version "2.7.3" + resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.7.3.tgz#12603f89f5375af353a9357be2543d3172eac651" + integrity sha512-t9Kc7HWBWPndBzvbdQ1YG9rpPRB37Tb/tTviziUOh1qs3TARGh3b1p+tnkOHNe1K5iI3oheBPgLqwotMM7+lpg== dependencies: is-nan "^1.2.1" - moment-timezone "^0.5.0" + moment-timezone "^0.5.23" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" -crypt@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= - cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -1715,9 +1788,15 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -crypto-browserify@3.12.0, crypto-browserify@^3.11.0: +crypt@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= + +crypto-browserify@3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -1734,96 +1813,96 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0: crypto-js@^3.1.4, crypto-js@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" - -crypto-js@^3.1.9-1: - version "3.1.9-1" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8" + integrity sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU= crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= csextends@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/csextends/-/csextends-1.2.0.tgz#6374b210984b54d4495f29c99d3dd069b80543e5" + integrity sha512-S/8k1bDTJIwuGgQYmsRoE+8P+ohV32WhQ0l4zqrc0XDdxOhjQQD7/wTZwCzoZX53jSX3V/qwjT+OkPTxWQcmjg== + +csv-parse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-4.2.0.tgz#6f3c09c5a46c06f19ca642a7b3104908d45b048c" + integrity sha512-t8KGN+ZKIYUUqXznAIZ723KI3IBILImjhN8VUfAod/VCtn/IpW3R24PYCxl81g4/z4R9DruTVyvavyiw2VRLgw== cycle@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" + integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= dependencies: es5-ext "^0.10.9" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" -date-extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/date-extended/-/date-extended-0.0.6.tgz#23802d57dd1bf7818813fe0c32e851a86da267c9" - dependencies: - array-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - death@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" + integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= debug@*, debug@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" + integrity sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg== dependencies: ms "^2.1.1" debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" -debug@^3.0.1, debug@^3.1.0: +debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" -decamelize@^1.0.0, decamelize@^1.1.1: +decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - -declare.js@~0.0.4: - version "0.0.8" - resolved "https://registry.yarnpkg.com/declare.js/-/declare.js-0.0.8.tgz#0478adff9564c004f51df73d8bc134019d28dcde" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: mimic-response "^1.0.0" decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== dependencies: file-type "^5.2.0" is-stream "^1.1.0" @@ -1832,6 +1911,7 @@ decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: decompress-tarbz2@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== dependencies: decompress-tar "^4.1.0" file-type "^6.1.0" @@ -1842,6 +1922,7 @@ decompress-tarbz2@^4.0.0: decompress-targz@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== dependencies: decompress-tar "^4.1.1" file-type "^5.2.0" @@ -1850,6 +1931,7 @@ decompress-targz@^4.0.0: decompress-unzip@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= dependencies: file-type "^3.8.0" get-stream "^2.2.0" @@ -1859,6 +1941,7 @@ decompress-unzip@^4.0.1: decompress@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" + integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= dependencies: decompress-tar "^4.0.0" decompress-tarbz2 "^4.0.0" @@ -1869,55 +1952,58 @@ decompress@^4.0.0: pify "^2.3.0" strip-dirs "^2.0.0" -deep-assign@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-2.0.0.tgz#ebe06b1f07f08dae597620e3dd1622f371a1c572" - dependencies: - is-obj "^1.0.0" - deep-equal@~0.2.1: version "0.2.2" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" + integrity sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0= deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= deferred-leveldown@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== dependencies: abstract-leveldown "~2.6.0" define-properties@^1.1.1, define-properties@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" @@ -1925,38 +2011,32 @@ define-property@^2.0.2: defined@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= delimit-stream@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" + integrity sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs= depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -1964,28 +2044,34 @@ des.js@^1.0.0: destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= dependencies: repeating "^2.0.0" detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= diff@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" @@ -1994,6 +2080,7 @@ diffie-hellman@^5.0.0: doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= dependencies: esutils "^2.0.2" isarray "^1.0.0" @@ -2001,20 +2088,19 @@ doctrine@1.5.0: doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= drbg.js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" + integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= dependencies: browserify-aes "^1.0.6" create-hash "^1.1.2" @@ -2023,16 +2109,19 @@ drbg.js@^1.0.1: duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= eachr@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/eachr/-/eachr-2.0.4.tgz#466f7caa10708f610509e32c807aafe57fc122bf" + integrity sha1-Rm98qhBwj2EFCeMsgHqv5X/BIr8= dependencies: typechecker "^2.0.8" ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" @@ -2040,25 +2129,30 @@ ecc-jsbn@~0.1.1: editions@^1.1.1, editions@^1.3.3, editions@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" + integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== -editions@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/editions/-/editions-2.0.2.tgz#54fdac6fb24b0a1a72ffc1ba0126c10602c3e0bd" +editions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/editions/-/editions-2.1.0.tgz#5c6f6341ef19ee362a3bcbb907fe68e696dbc69e" + integrity sha512-yKrimWcvOXcYXtqsOeebbMLynm9qbYVd0005wveGU2biPxJaJoxA0jtaZrxiMe3mAanLr5lxoYFVz5zjv9JdnA== dependencies: - errlop "^1.0.2" - semver "^5.5.0" + errlop "^1.0.3" + semver "^5.6.0" ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.47: - version "1.3.78" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.78.tgz#ecb72b5b166ba6598efb384461d63cad74678ebf" + version "1.3.95" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.95.tgz#79fac438813ca7f3db182a525c2ab432934f6484" + integrity sha512-0JZEDKOQAE05EO/4rk3vLAE+PYFI9OLCVLAS4QAq1y+Bb2y1N6MyQJz62ynzHN/y0Ka/nO5jVJcahbCEdfiXLQ== elliptic@6.3.3: version "6.3.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" + integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2068,6 +2162,7 @@ elliptic@6.3.3: elliptic@=6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" + integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2080,6 +2175,7 @@ elliptic@=6.4.0: elliptic@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-3.1.0.tgz#c21682ef762769b56a74201609105da11d5f60cc" + integrity sha1-whaC73YnabVqdCAWCRBdoR1fYMw= dependencies: bn.js "^2.0.3" brorand "^1.0.1" @@ -2089,6 +2185,7 @@ elliptic@^3.1.0: elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: version "6.4.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" + integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2098,60 +2195,55 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= dependencies: iconv-lite "~0.4.13" end-of-stream@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: once "^1.4.0" -enhanced-resolve@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.4.0" - object-assign "^4.0.1" - tapable "^0.2.7" - eol@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" + integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== -errlop@^1.0.2: +errlop@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/errlop/-/errlop-1.0.3.tgz#dba29c90cf832c3d2ce469fe515d7e5eef2c6676" + integrity sha512-5VTnt0yikY4LlQEfCXVSqfE6oLj1HVM4zVSvAKMnoYjL/zrb6nqiLowZS4XlG7xENfyj7lpYWvT+wfSCr6dtlA== dependencies: editions "^1.3.4" -errno@^0.1.3, errno@~0.1.1: +errno@~0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== dependencies: prr "~1.0.1" error-ex@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" es-abstract@^1.5.0: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" + integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" @@ -2162,6 +2254,7 @@ es-abstract@^1.5.0: es-to-primitive@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -2170,50 +2263,33 @@ es-to-primitive@^1.1.1: es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: version "0.10.46" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572" + integrity sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw== dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" next-tick "1" -es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: +es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= dependencies: d "1" es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: +es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= dependencies: d "1" es5-ext "~0.10.14" -es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: +es6-weak-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8= dependencies: d "1" es5-ext "^0.10.14" @@ -2223,14 +2299,17 @@ es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= dependencies: esprima "^2.7.1" estraverse "^1.9.1" @@ -2239,22 +2318,15 @@ escodegen@1.8.x: optionalDependencies: source-map "~0.2.0" -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-config-standard@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz#87ee0d3c9d95382dc761958cbb23da9eea31e0ba" +eslint-config-standard@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz#638b4c65db0bd5a41319f96bba1f15ddad2107d9" + integrity sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ== eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== dependencies: debug "^2.6.9" resolve "^1.5.0" @@ -2262,21 +2334,23 @@ eslint-import-resolver-node@^0.3.1: eslint-module-utils@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" + integrity sha1-snA2LNiLGkitMIl2zn+lTphBF0Y= dependencies: debug "^2.6.8" pkg-dir "^1.0.0" eslint-plugin-es@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.3.1.tgz#5acb2565db4434803d1d46a9b4cbc94b345bd028" - integrity sha512-9XcVyZiQRVeFjqHw8qHNDAZcQLqaHlOGGpeYqzYh8S4JYCWTCO3yzyen8yVmA5PratfzTRWDwCOFphtDEG+w/w== + version "1.4.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz#475f65bb20c993fc10e8c8fe77d1d60068072da6" + integrity sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw== dependencies: eslint-utils "^1.3.0" - regexpp "^2.0.0" + regexpp "^2.0.1" -eslint-plugin-import@^2.10.0: +eslint-plugin-import@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" + integrity sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g== dependencies: contains-path "^0.1.0" debug "^2.6.8" @@ -2289,9 +2363,10 @@ eslint-plugin-import@^2.10.0: read-pkg-up "^2.0.0" resolve "^1.6.0" -eslint-plugin-node@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz#bf19642298064379315d7a4b2a75937376fa05e4" +eslint-plugin-node@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-8.0.0.tgz#fb9e8911f4543514f154bb6a5924b599aa645568" + integrity sha512-Y+ln8iQ52scz9+rSPnSWRaAxeWaoJZ4wIveDR0vLHkuSZGe44Vk1J4HX7WvEP5Cm+iXPE8ixo7OM7gAO3/OKpQ== dependencies: eslint-plugin-es "^1.3.1" eslint-utils "^1.3.1" @@ -2300,17 +2375,20 @@ eslint-plugin-node@^6.0.1: resolve "^1.8.1" semver "^5.5.0" -eslint-plugin-promise@^3.7.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" +eslint-plugin-promise@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz#2d074b653f35a23d1ba89d8e976a985117d1c6a2" + integrity sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg== -eslint-plugin-standard@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz#2a9e21259ba4c47c02d53b2d0c9135d4b1022d47" +eslint-plugin-standard@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c" + integrity sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA== -eslint-scope@^3.7.1: - version "3.7.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" +eslint-scope@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" + integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2323,10 +2401,12 @@ eslint-utils@^1.3.0, eslint-utils@^1.3.1: eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== -eslint@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" +eslint@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.10.0.tgz#24adcbe92bf5eb1fc2d2f2b1eebe0c5e0713903a" + integrity sha512-HpqzC+BHULKlnPwWae9MaVZ5AXJKpkxCVXQHrFaRw3hbDj26V/9ArYM4Rr/SQ8pi6qUPLXSSXC4RBJlyq2Z2OQ== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.5.3" @@ -2337,7 +2417,7 @@ eslint@^4.19.1: eslint-scope "^4.0.0" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" - espree "^4.0.0" + espree "^5.0.0" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^2.0.0" @@ -2347,7 +2427,6 @@ eslint@^4.19.1: ignore "^4.0.6" imurmurhash "^0.1.4" inquirer "^6.1.0" - is-resolvable "^1.1.0" js-yaml "^3.12.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" @@ -2367,9 +2446,10 @@ eslint@^4.19.1: table "^5.0.2" text-table "^0.2.0" -espree@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" +espree@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.0.tgz#fc7f984b62b36a0f543b13fb9cd7b9f4a7f5b65c" + integrity sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA== dependencies: acorn "^6.0.2" acorn-jsx "^5.0.0" @@ -2378,42 +2458,51 @@ espree@^3.5.4: esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== dependencies: estraverse "^4.1.0" estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eth-block-tracker@^2.2.2: version "2.3.1" resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz#ab6d177e5b50128fa06d7ae9e0489c7484bac95e" + integrity sha512-NamWuMBIl8kmkJFVj8WzGatySTzQPQag4Xr677yFxdVtIxACFbL/dQowk0MzEqIKk93U1TwY3MjVU6mOcwZnKA== dependencies: async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c eth-query "^2.1.0" @@ -2427,6 +2516,7 @@ eth-block-tracker@^2.2.2: eth-lib@0.1.27, eth-lib@^0.1.26: version "0.1.27" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" + integrity sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA== dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2439,6 +2529,7 @@ eth-lib@0.1.27, eth-lib@^0.1.26: eth-lib@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" + integrity sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco= dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2447,6 +2538,7 @@ eth-lib@0.2.7: eth-lightwallet@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eth-lightwallet/-/eth-lightwallet-3.0.1.tgz#297022932aa568f4e4eb0873bff257f5e5b78709" + integrity sha512-79vVCETy+4l1b6wuOWwjqPW3Bom5ZK46BgkUNwaXhiMG1rrMRHjpjYEWMqH0JHeCzOzB4HBIFz7eK1/4s6w5nA== dependencies: bitcore-lib "^0.15.0" bitcore-mnemonic "^1.5.0" @@ -2463,6 +2555,7 @@ eth-lightwallet@^3.0.1: eth-query@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= dependencies: json-rpc-random-id "^1.0.0" xtend "^4.0.1" @@ -2470,6 +2563,7 @@ eth-query@^2.1.0: eth-sig-util@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= dependencies: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" @@ -2477,6 +2571,7 @@ eth-sig-util@^1.4.2: ethereum-bridge@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/ethereum-bridge/-/ethereum-bridge-0.6.1.tgz#53c93ed7c0e21752a91e5f089a5997e1d6fea228" + integrity sha512-yDTivI85618BoLI71yNRzW6iVcVN2rjnviCIzs0QOCOENj4XpYQhMDGhdqDi8XWDdzTd0Ja/Canuuh3vfE2IcA== dependencies: async "^2.4.1" borc "^2.0.2" @@ -2507,14 +2602,17 @@ ethereum-bridge@^0.6.1: ethereum-common@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= ethereumjs-abi@0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.4.tgz#9ba1bb056492d00c27279f6eccd4d58275912c1a" + integrity sha1-m6G7BWSS0AwnJ59uzNTVgnWRLBo= dependencies: bn.js "^4.10.0" ethereumjs-util "^4.3.0" @@ -2529,14 +2627,16 @@ ethereumjs-abi@^0.6.5, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereu ethereumjs-account@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== dependencies: ethereumjs-util "^5.0.0" rlp "^2.0.0" safe-buffer "^5.1.1" -ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: +ethereumjs-block@^1.2.2: version "1.7.1" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== dependencies: async "^2.0.1" ethereum-common "0.2.0" @@ -2544,25 +2644,33 @@ ethereumjs-block@^1.2.2, ethereumjs-block@~1.7.0: ethereumjs-util "^5.0.0" merkle-patricia-tree "^2.1.2" -ethereumjs-common@~0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-0.4.1.tgz#27690a24a817b058cc3a2aedef9392e8d7d63984" +ethereumjs-block@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.1.0.tgz#71d1b19e18061f14cf6371bf34ba31a359931360" + integrity sha512-ip+x4/7hUInX+TQfhEKsQh9MJK1Dbjp4AuPjf1UdX3udAV4beYD4EMCNIPzBLCsGS8WQZYXLpo83tVTISYNpow== + dependencies: + async "^2.0.1" + ethereumjs-common "^0.6.0" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-common@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-0.6.1.tgz#ec98edf315a7f107afb6acc48e937a8266979fae" + integrity sha512-4jOrfDu9qOBTTGGb3zrfT1tE1Hyc6a8LJpEk0Vk9AYlLkBY7crjVICyJpRvjNI+KLDMpMITMw3eWVZOLMtZdhw== ethereumjs-testrpc-sc@6.1.6: version "6.1.6" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.6.tgz#290595380b5182814564d4aa38f35b7788aab070" + integrity sha512-iv2qiGBFgk9mn5Nq2enX8dG5WQ7Lk+FCqpnxfPfH4Ns8KLPwttmNOy264nh3SXDJJvcQwz/XnlLteDQVILotbg== dependencies: source-map-support "^0.5.3" -ethereumjs-testrpc@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/ethereumjs-testrpc/-/ethereumjs-testrpc-6.0.3.tgz#7a0b87bf3670f92f607f98fa6a78801d9741b124" - dependencies: - webpack "^3.0.0" - ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@^1.3.3, ethereumjs-tx@^1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== dependencies: ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" @@ -2570,6 +2678,7 @@ ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@ ethereumjs-util@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" + integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= dependencies: bn.js "^4.8.0" create-hash "^1.1.2" @@ -2580,6 +2689,7 @@ ethereumjs-util@^4.3.0: ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.3, ethereumjs-util@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" + integrity sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA== dependencies: bn.js "^4.11.0" create-hash "^1.1.2" @@ -2589,16 +2699,30 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum safe-buffer "^5.1.1" secp256k1 "^3.0.1" +ethereumjs-util@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.0.0.tgz#f14841c182b918615afefd744207c7932c8536c0" + integrity sha512-E3yKUyl0Fs95nvTFQZe/ZSNcofhDzUsDlA5y2uoRmf1+Ec7gpGhNCsgKkZBRh7Br5op8mJcYF/jFbmjj909+nQ== + dependencies: + bn.js "^4.11.0" + create-hash "^1.1.2" + ethjs-util "^0.1.6" + keccak "^1.0.2" + rlp "^2.0.0" + safe-buffer "^5.1.1" + secp256k1 "^3.0.1" + ethereumjs-vm@^2.0.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.4.0.tgz#244f1e35f2755e537a13546111d1a4c159d34b13" + version "2.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.5.0.tgz#71dde54a093bd813c9defdc6d45ceb8fcca2f603" + integrity sha512-Cp1do4J2FIJFnbofqLsKb/aoZKG+Q8NBIbTa1qwZPQkQxzeR3DZVpFk/VbE1EUO6Ha0kSClJ1jzfj07z3cScSQ== dependencies: async "^2.1.2" async-eventemitter "^0.2.2" ethereumjs-account "^2.0.3" - ethereumjs-block "~1.7.0" - ethereumjs-common "~0.4.0" - ethereumjs-util "^5.2.0" + ethereumjs-block "~2.1.0" + ethereumjs-common "^0.6.0" + ethereumjs-util "^6.0.0" fake-merkle-patricia-tree "^1.0.1" functional-red-black-tree "^1.0.1" merkle-patricia-tree "^2.1.2" @@ -2606,21 +2730,24 @@ ethereumjs-vm@^2.0.2: safe-buffer "^5.1.1" ethereumjs-wallet@^0.6.0: - version "0.6.2" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz#67244b6af3e8113b53d709124b25477b64aeccda" + version "0.6.3" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz#b0eae6f327637c2aeb9ccb9047b982ac542e6ab1" + integrity sha512-qiXPiZOsStem+Dj/CQHbn5qex+FVkuPmGH7SvSnA9F3tdRDt8dLMyvIj3+U05QzVZNPYh4HXEdnzoYI4dZkr9w== dependencies: aes-js "^3.1.1" bs58check "^2.1.2" - ethereumjs-util "^5.2.0" - hdkey "^1.0.0" + ethereumjs-util "^6.0.0" + hdkey "^1.1.0" + randombytes "^2.0.6" safe-buffer "^5.1.2" - scrypt.js "^0.2.0" + scrypt.js "^0.3.0" utf8 "^3.0.0" uuid "^3.3.2" -ethers@^3.0.15: - version "3.0.29" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-3.0.29.tgz#ce8139955b4ed44456eb6764b089bb117c86775d" +ethers@^4.0.20: + version "4.0.20" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.20.tgz#2b072b283bb19f4870daf42cf5593e5375697504" + integrity sha512-1XEejqGYWlcXoVCPFPRfJmf1QQGHW7TNfprtdT1Up66nSuqWE/lYSLgvTNvH/nbSTMRFZqM6ANAbv/1+eUDb7g== dependencies: "@types/node" "^10.3.2" aes-js "3.0.0" @@ -2633,31 +2760,26 @@ ethers@^3.0.15: uuid "2.0.1" xmlhttprequest "1.8.0" -ethjs-abi@0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.1.8.tgz#cd288583ed628cdfadaf8adefa3ba1dbcbca6c18" - dependencies: - bn.js "4.11.6" - js-sha3 "0.5.5" - number-to-bn "1.7.0" - ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= dependencies: bn.js "4.11.6" number-to-bn "1.7.0" -ethjs-util@^0.1.3: +ethjs-util@^0.1.3, ethjs-util@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== dependencies: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" -event-emitter@^0.3.5, event-emitter@~0.3.5: +event-emitter@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= dependencies: d "1" es5-ext "~0.10.14" @@ -2665,18 +2787,17 @@ event-emitter@^0.3.5, event-emitter@~0.3.5: eventemitter3@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" - -events@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + integrity sha1-R3hr2qCHyvext15zq8XH1UAVjNA= events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" @@ -2684,6 +2805,7 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -2696,12 +2818,14 @@ execa@^0.7.0: expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= dependencies: is-posix-bracket "^0.1.0" expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -2714,12 +2838,14 @@ expand-brackets@^2.1.4: expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= dependencies: fill-range "^2.1.0" express@^4.14.0: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" + integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== dependencies: accepts "~1.3.5" array-flatten "1.1.1" @@ -2755,12 +2881,14 @@ express@^4.14.0: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -2768,28 +2896,19 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - -extended@0.0.6, extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/extended/-/extended-0.0.6.tgz#7fb8bf7b9dae397586e48570acfd642c78e50669" - dependencies: - extender "~0.0.5" - -extender@~0.0.5: - version "0.0.10" - resolved "https://registry.yarnpkg.com/extender/-/extender-0.0.10.tgz#589c07482be61a1460b6d81f9c24aa67e8f324cd" - dependencies: - declare.js "~0.0.4" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== extendr@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/extendr/-/extendr-2.1.0.tgz#301aa0bbea565f4d2dc8f570f2a22611a8527b56" + integrity sha1-MBqgu+pWX00tyPVw8qImEahSe1Y= dependencies: typechecker "~2.0.1" -external-editor@^2.0.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" +external-editor@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" + integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -2798,12 +2917,14 @@ external-editor@^2.0.4: extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= dependencies: is-extglob "^1.0.0" extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -2817,73 +2938,77 @@ extglob@^2.0.4: extract-opts@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d" + integrity sha1-H6KOunNSxttID4hc63GkaBC+bX0= dependencies: typechecker "~2.0.1" extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= eyes@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= fake-merkle-patricia-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= dependencies: checkpoint-store "^1.1.0" -fast-csv@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-2.4.1.tgz#bd7dd268391f729367b59445b8dd0ad026881b26" - dependencies: - extended "0.0.6" - is-extended "0.0.10" - object-extended "0.0.7" - string-extended "0.0.8" - fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= dependencies: pend "~1.2.0" fetch-ponyfill@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= dependencies: node-fetch "~1.7.1" figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" @@ -2891,22 +3016,27 @@ file-entry-cache@^2.0.0: file-type@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= file-type@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + integrity sha1-LdvqfHP/42No365J3DOMBYwritY= file-type@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= fill-range@^2.1.0: version "2.2.4" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== dependencies: is-number "^2.1.0" isobject "^2.0.0" @@ -2917,6 +3047,7 @@ fill-range@^2.1.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -2926,6 +3057,7 @@ fill-range@^4.0.0: finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" + integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== dependencies: debug "2.6.9" encodeurl "~1.0.2" @@ -2938,6 +3070,7 @@ finalhandler@1.1.1: find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" @@ -2945,41 +3078,48 @@ find-up@^1.0.0: find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" flat-cache@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + version "1.3.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" + integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== dependencies: circular-json "^0.3.1" - del "^2.0.2" graceful-fs "^4.1.2" + rimraf "~2.6.2" write "^0.2.1" for-each@^0.3.2, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= dependencies: for-in "^1.0.1" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.6" @@ -2988,24 +3128,29 @@ form-data@~2.3.2: forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3016,21 +3161,15 @@ fs-extra@^0.30.0: fs-extra@^2.0.0, fs-extra@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" + integrity sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3039,12 +3178,14 @@ fs-extra@^5.0.0: fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== dependencies: minipass "^2.2.1" fs-promise@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" + integrity sha1-9k5PhUvPaJqovdy6JokW2z20aFQ= dependencies: any-promise "^1.3.0" fs-extra "^2.0.0" @@ -3054,14 +3195,17 @@ fs-promise@^2.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fs@0.0.1-security: - version "0.0.1-security" - resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" +fs@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.2.tgz#e1f244ef3933c1b2a64bd4799136060d0f5914f8" + integrity sha1-4fJE7zkzwbKmS9R5kTYGDQ9ZFPg= -fsevents@^1.0.0, fsevents@^1.2.2: +fsevents@^1.0.0: version "1.2.4" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -3069,6 +3213,7 @@ fsevents@^1.0.0, fsevents@^1.2.2: fstream@^1.0.2, fstream@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -3078,20 +3223,26 @@ fstream@^1.0.2, fstream@^1.0.8: function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= ganache-cli@^6.1.8: - version "6.1.8" - resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.8.tgz#49a8a331683a9652183f82ef1378d17e1814fcd3" + version "6.2.4" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.2.4.tgz#0ec3d5d993a85c9f252fb632105ab7ffe7668638" + integrity sha512-Yxi+G+Qktr8s1BML0BEC2oIseMP/svWXmojajrdHNG8k84cyihvemuW4DLM7XA/ZOqi88mKt3n/mWTi0RbYpOQ== dependencies: - source-map-support "^0.5.3" + bn.js "4.11.8" + source-map-support "0.5.9" + yargs "11.1.0" gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -3105,10 +3256,12 @@ gauge@~2.7.3: get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= dependencies: object-assign "^4.0.1" pinkie-promise "^2.0.0" @@ -3116,20 +3269,24 @@ get-stream@^2.2.0: get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= dependencies: glob-parent "^2.0.0" is-glob "^2.0.0" @@ -3137,19 +3294,14 @@ glob-base@^0.3.0: glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= dependencies: is-glob "^2.0.0" -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3161,6 +3313,7 @@ glob@7.1.2: glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= dependencies: inflight "^1.0.4" inherits "2" @@ -3168,9 +3321,10 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: +glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3182,6 +3336,7 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: glob@~6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= dependencies: inflight "^1.0.4" inherits "2" @@ -3192,32 +3347,25 @@ glob@~6.0.4: global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= dependencies: min-document "^2.19.0" process "~0.5.1" globals@^11.7.0: - version "11.8.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" + version "11.9.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249" + integrity sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg== globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== got@7.1.0, got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== dependencies: decompress-response "^3.2.0" duplexer3 "^0.1.4" @@ -3235,24 +3383,29 @@ got@7.1.0, got@^7.1.0: url-to-options "^1.0.1" graceful-fs@*, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= growl@1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" + integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== growl@1.10.5, "growl@~> 1.10.0": version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: version "4.0.12" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" + integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA== dependencies: async "^2.5.0" optimist "^0.6.1" @@ -3263,53 +3416,64 @@ handlebars@^4.0.1: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== dependencies: - ajv "^5.3.0" + ajv "^6.5.5" har-schema "^2.0.0" has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= has-to-string-tag-x@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== dependencies: has-symbol-support-x "^1.4.1" has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -3318,6 +3482,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -3326,10 +3491,12 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -3337,12 +3504,14 @@ has-values@^1.0.0: has@^1.0.1, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -3356,15 +3525,17 @@ hash.js@1.1.3: minimalistic-assert "^1.0.0" hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hdkey@^1.0.0: +hdkey@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.0.tgz#e74e7b01d2c47f797fa65d1d839adb7a44639f29" + integrity sha512-E7aU8pNlWUJbXGjTz/+lKf1LkMcA3hUrC5ZleeizrmLSd++kvf8mSOe3q8CmBDA9j4hdfXO5iY6hGiTUCOV2jQ== dependencies: coinstring "^2.0.0" safe-buffer "^5.1.1" @@ -3373,10 +3544,12 @@ hdkey@^1.0.0: he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -3385,6 +3558,7 @@ hmac-drbg@^1.0.0: home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.1" @@ -3392,10 +3566,12 @@ home-or-tmp@^2.0.0: hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" @@ -3405,22 +3581,21 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: http-https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - i18n@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/i18n/-/i18n-0.8.3.tgz#2d8cf1c24722602c2041d01ba6ae5eaa51388f0e" + integrity sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4= dependencies: debug "*" make-plural "^3.0.3" @@ -3432,36 +3607,48 @@ i18n@^0.8.3: i@0.3.x: version "0.3.6" resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d" + integrity sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0= iconv-lite@0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" ieee754@^1.1.4, ieee754@^1.1.8: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" + integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== dependencies: minimatch "^3.0.4" -ignore@^3.3.3, ignore@^3.3.6: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.0.2: + version "5.0.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.4.tgz#33168af4a21e99b00c5d41cbadb6a6cb49903a45" + integrity sha512-WLsTMEhsQuXpCiG173+f3aymI43SXa+fB1rSfbzyP4GkPP+ZFVuO0/3sFUGNBtifisPeDcl/uD/Y2NxZ7xFq4g== ignorefs@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ignorefs/-/ignorefs-1.2.0.tgz#da59fb858976e4a5e43702ccd1f282fdbc9e5756" + integrity sha1-2ln7hYl25KXkNwLM0fKC/byeV1Y= dependencies: editions "^1.3.3" ignorepatterns "^1.1.0" @@ -3469,22 +3656,22 @@ ignorefs@^1.0.0: ignorepatterns@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ignorepatterns/-/ignorepatterns-1.1.0.tgz#ac8f436f2239b5dfb66d5f0d3a904a87ac67cc5e" + integrity sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4= immediate@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" @@ -3492,18 +3679,22 @@ inflight@^1.0.4: inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -inherits@2.0.1, inherits@=2.0.1: +inherits@=2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -inquirer@^3.0.6: - version "3.3.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" +inquirer@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.1.tgz#9943fc4882161bdb0b0c9276769c75b32dbfcd52" + integrity sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -3516,82 +3707,97 @@ inquirer@^3.0.6: run-async "^2.2.0" rxjs "^6.1.0" string-width "^2.1.0" - strip-ansi "^4.0.0" + strip-ansi "^5.0.0" through "^2.3.6" interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" + integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= dependencies: builtin-modules "^1.0.0" is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -3600,6 +3806,7 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -3608,216 +3815,206 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= dependencies: is-primitive "^2.0.0" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" -is-extended@0.0.10, is-extended@~0.0.3, is-extended@~0.0.8: - version "0.0.10" - resolved "https://registry.yarnpkg.com/is-extended/-/is-extended-0.0.10.tgz#244e140df75bb1c9a3106f412ff182fb534a6d62" - dependencies: - extended "~0.0.3" - is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= dependencies: number-is-nan "^1.0.0" is-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - dependencies: - is-extglob "^2.1.1" + is-extglob "^1.0.0" is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= is-nan@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" + integrity sha1-n69ltvttskt/XAYoR16nH5iEAeI= dependencies: define-properties "^1.1.1" is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= dependencies: kind-of "^3.0.2" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - -is-path-in-cwd@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - dependencies: - path-is-inside "^1.0.1" + integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= is-promise@^2.1, is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= dependencies: has "^1.0.1" -is-resolvable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== dependencies: has-symbols "^1.0.0" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= dependencies: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" @@ -3825,10 +4022,12 @@ isomorphic-fetch@^2.2.0: isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" + integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= dependencies: abbrev "1.0.x" async "1.x" @@ -3848,37 +4047,40 @@ istanbul@^0.4.5: isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== dependencies: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -js-sha3@0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a" - js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= -js-sha3@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" +js-sha3@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.6.1.tgz#5b89f77a7477679877f58c4a075240934b1f95c0" + integrity sha1-W4n3enR3Z5h39YxKB1JAk0sflcA= js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -3886,22 +4088,22 @@ js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.12.0: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - -json-loader@^0.5.4: - version "0.5.7" - resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-rpc-engine@^3.6.0: version "3.8.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== dependencies: async "^2.0.1" babel-preset-env "^1.7.0" @@ -3913,68 +4115,82 @@ json-rpc-engine@^3.6.0: json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" + integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= dependencies: inherits "^2.0.1" json-rpc-random-id@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= dependencies: jsonify "~0.0.0" json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json-text-sequence@^0.1: version "0.1.1" resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" + integrity sha1-py8hfcSvxGKf/1/rME3BvVGi89I= dependencies: delimit-stream "0.1.0" -json5@^0.5.0, json5@^0.5.1: +json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= optionalDependencies: graceful-fs "^4.1.6" jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= optionalDependencies: graceful-fs "^4.1.6" jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" extsprintf "1.3.0" @@ -3984,6 +4200,7 @@ jsprim@^1.2.2: keccak@^1.0.2: version "1.4.0" resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" + integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== dependencies: bindings "^1.2.1" inherits "^2.0.3" @@ -3991,71 +4208,79 @@ keccak@^1.0.2: safe-buffer "^5.1.0" keccakjs@^0.2.0, keccakjs@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" + version "0.2.3" + resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72" + integrity sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg== dependencies: - browserify-sha3 "^0.0.1" - sha3 "^1.1.0" + browserify-sha3 "^0.0.4" + sha3 "^1.2.2" kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= optionalDependencies: graceful-fs "^4.1.9" -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" + integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM= level-codec@~7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== level-errors@^1.0.3: version "1.1.2" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== dependencies: errno "~0.1.1" level-errors@~1.0.3: version "1.0.5" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== dependencies: errno "~0.1.1" level-iterator-stream@~1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= dependencies: inherits "^2.0.1" level-errors "^1.0.3" @@ -4065,6 +4290,7 @@ level-iterator-stream@~1.3.0: level-ws@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= dependencies: readable-stream "~1.0.15" xtend "~2.1.1" @@ -4072,6 +4298,7 @@ level-ws@0.0.0: levelup@^1.2.1: version "1.3.9" resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== dependencies: deferred-leveldown "~1.2.1" level-codec "~7.0.0" @@ -4084,6 +4311,7 @@ levelup@^1.2.1: levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -4091,6 +4319,7 @@ levn@^0.3.0, levn@~0.3.0: load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4101,27 +4330,17 @@ load-json-file@^1.0.0: load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" pify "^2.0.0" strip-bom "^3.0.0" -loader-runner@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.1.tgz#026f12fe7c3115992896ac02ba022ba92971b979" - -loader-utils@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" - dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -4129,44 +4348,44 @@ locate-path@^2.0.0: lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - -lodash@4.x, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5: +lodash@4.x, lodash@=4.17.11, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== lodash@=4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= log-driver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== long-timeout@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" - -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ= loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lru-cache@^4.0.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -4174,48 +4393,57 @@ lru-cache@^4.0.1: lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= dependencies: es5-ext "~0.10.2" ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== dependencies: pify "^3.0.0" make-plural@^3.0.3, make-plural@~3.0.3: version "3.0.6" resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-3.0.6.tgz#2033a03bac290b8f3bb91258f65b9df7e8b01ca7" + integrity sha1-IDOgO6wpC487uRJY9lud9+iwHKc= optionalDependencies: minimist "^1.2.0" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" math-interval-parser@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-interval-parser/-/math-interval-parser-1.1.0.tgz#dbeda5b06b3249973c6df6170fde2386f0afd893" + integrity sha1-2+2lsGsySZc8bfYXD94jhvCv2JM= dependencies: xregexp "^2.0.0" math-random@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -4233,16 +4461,19 @@ md5@^2.1.0: media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= dependencies: mimic-fn "^1.0.0" memdown@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" + integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= dependencies: abstract-leveldown "~2.7.1" functional-red-black-tree "^1.0.1" @@ -4254,6 +4485,7 @@ memdown@^1.0.0: memoizee@^0.4.14: version "0.4.14" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" + integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== dependencies: d "1" es5-ext "^0.10.45" @@ -4264,24 +4496,20 @@ memoizee@^0.4.14: next-tick "1" timers-ext "^0.1.5" -memory-fs@^0.4.0, memory-fs@~0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= merkle-patricia-tree@^2.1.2: version "2.3.2" resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== dependencies: async "^1.4.2" ethereumjs-util "^5.0.0" @@ -4295,6 +4523,7 @@ merkle-patricia-tree@^2.1.2: messageformat@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/messageformat/-/messageformat-0.3.1.tgz#e58fff8245e9b3971799e5b43db58b3e9417f5a2" + integrity sha1-5Y//gkXps5cXmeW0PbWLPpQX9aI= dependencies: async "~1.5.2" glob "~6.0.4" @@ -4305,10 +4534,12 @@ messageformat@^0.3.1: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@^2.1.5: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= dependencies: arr-diff "^2.0.0" array-unique "^0.2.1" @@ -4324,9 +4555,10 @@ micromatch@^2.1.5: parse-glob "^3.0.4" regex-cache "^0.4.2" -micromatch@^3.1.10, micromatch@^3.1.4: +micromatch@^3.1.10: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4345,80 +4577,96 @@ micromatch@^3.1.10, micromatch@^3.1.4: miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" +mime-db@~1.37.0: + version "1.37.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" + integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: - version "2.1.20" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" + version "2.1.21" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" + integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== dependencies: mime-db "~1.37.0" mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= dependencies: dom-walk "^0.1.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@^1.2.0, minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.2.1, minipass@^2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957" +minipass@^2.2.1, minipass@^2.3.4: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" +minizlib@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" + integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== dependencies: minipass "^2.2.1" mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -4426,12 +4674,14 @@ mixin-deep@^1.2.0: mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" @@ -4449,6 +4699,7 @@ mocha-junit-reporter@^1.18.0: mocha@^4.0.1, mocha@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" + integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== dependencies: browser-stdout "1.3.0" commander "2.11.0" @@ -4464,6 +4715,7 @@ mocha@^4.0.1, mocha@^4.1.0: mocha@^5.0.1: version "5.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== dependencies: browser-stdout "1.3.1" commander "2.15.1" @@ -4480,51 +4732,62 @@ mocha@^5.0.1: mock-fs@^4.1.0: version "4.7.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" + integrity sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA== -moment-timezone@^0.5.0: - version "0.5.21" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.21.tgz#3cba247d84492174dbf71de2a9848fa13207b845" +moment-timezone@^0.5.23: + version "0.5.23" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.23.tgz#7cbb00db2c14c71b19303cb47b0fb0a6d8651463" + integrity sha512-WHFH85DkCfiNMDX5D3X7hpNH3/PUhjTGcD0U1SgfBGZxJ3qUmJh5FdvaFjcClxOvB3rzdfj4oRffbI38jEnC1w== dependencies: moment ">= 2.9.0" "moment@>= 2.9.0", moment@^2.22.2: - version "2.22.2" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" + version "2.23.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.23.0.tgz#759ea491ac97d54bac5ad776996e2a58cc1bc225" + integrity sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA== mout@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" + integrity sha1-ujYR318OWx/7/QEWa48C0fX6K5k= ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== multihashes@^0.4.5: version "0.4.14" resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.14.tgz#774db9a161f81a8a27dc60788f91248e020f5244" + integrity sha512-V/g/EIN6nALXfS/xHUAgtfPP3mn3sPIF/i9beuGKf25QXS2QZYCpeVJbDPEannkz32B2fihzCe2D/KMrbcmefg== dependencies: bs58 "^4.0.1" varint "^5.0.0" mustache@*: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.0.tgz#3de22dd9ba38152f7355399a953dd4528c403338" + version "3.0.1" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.1.tgz#873855f23aa8a95b150fb96d9836edbc5a1d248a" + integrity sha512-jFI/4UVRsRYdUbuDTKT7KzfOp7FiD5WzYmmwNwXyUVypC0xjoTL78Fqc0jHUPIvvGD+6DQSPHIt1NE7D1ArsqA== mustache@^2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" + integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" object-assign "^4.0.1" @@ -4533,18 +4796,22 @@ mz@^2.6.0: nan@2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== nan@^2.0.8, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: - version "2.11.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" + integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4561,14 +4828,17 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= ncp@1.0.x: version "1.0.1" - resolved "http://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" + resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" + integrity sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY= needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" + integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== dependencies: debug "^2.1.2" iconv-lite "^0.4.4" @@ -4577,14 +4847,12 @@ needle@^2.2.1: negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - -neo-async@^2.5.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc" + integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= nice-try@^1.0.4: version "1.0.5" @@ -4594,10 +4862,12 @@ nice-try@^1.0.4: node-async-loop@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/node-async-loop/-/node-async-loop-1.2.2.tgz#c5870299bf6477b780c88b431aa5b37733f55a3d" + integrity sha1-xYcCmb9kd7eAyItDGqWzdzP1Wj0= node-cache@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.0.tgz#48ac796a874e762582692004a376d26dfa875811" + integrity sha512-obRu6/f7S024ysheAjoYFEEBqqDWv4LOMNJEuO8vMeEw2AT4z+NCzO4hlc2lhI4vATzbCQv6kke9FVdx0RbCOw== dependencies: clone "2.x" lodash "4.x" @@ -4605,41 +4875,15 @@ node-cache@^4.1.1: node-fetch@^1.0.1, node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== dependencies: encoding "^0.1.11" is-stream "^1.0.1" -node-libs-browser@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^1.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.0" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" - node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -4653,22 +4897,25 @@ node-pre-gyp@^0.10.0: tar "^4" node-schedule@^1.2.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-1.3.0.tgz#e7a7e816a7f2550d5b170bd106e765db28bdf030" + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-1.3.1.tgz#6909dd644211bca153b15afc62e1dc0afa7d28be" + integrity sha512-cdNNePwKoisAi4DT00BB11H6IJ/WtA603YZ7+tLJcb/zCmCSxYKcvc+/GTyxC46jN/0ft7741vmMQrvxP8Sd+A== dependencies: - cron-parser "^2.4.0" + cron-parser "^2.7.3" long-timeout "0.1.1" sorted-array-functions "^1.0.0" nopt@3.x, nopt@~3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" osenv "^0.1.4" @@ -4676,25 +4923,29 @@ nopt@^4.0.1: normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: +normalize-path@^2.0.0, normalize-path@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" + integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" + integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -4702,12 +4953,14 @@ npm-packlist@^1.1.6: npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" @@ -4717,10 +4970,12 @@ npmlog@^4.0.2: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -4728,48 +4983,48 @@ number-to-bn@1.7.0: oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" -object-extended@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/object-extended/-/object-extended-0.0.7.tgz#84fd23f56b15582aeb3e88b05cb55d2432d68a33" - dependencies: - array-extended "~0.0.4" - extended "~0.0.3" - is-extended "~0.0.3" - object-inspect@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= dependencies: for-own "^0.1.4" is-extendable "^0.1.1" @@ -4777,40 +5032,47 @@ object.omit@^2.0.0: object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" oboe@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" + integrity sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8= dependencies: http-https "^1.0.0" on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" openzeppelin-solidity@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-1.10.0.tgz#d77eee6653f5958d051318a61ba0b436f92216c0" + integrity sha512-igkrumQQ2lrN2zjeQV4Dnb0GpTBj1fzMcd8HPyBUqwI0hhuscX/HzXiqKT6gFQl1j9Wy/ppVVs9fqL/foF7Gmg== optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= dependencies: minimist "~0.0.1" wordwrap "~0.0.2" @@ -4818,6 +5080,7 @@ optimist@^0.6.1: optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" @@ -4829,24 +5092,24 @@ optionator@^0.8.1, optionator@^0.8.2: original-require@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-DxMEcVhM0zURxew4yNWSE/msXiA= os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== dependencies: execa "^0.7.0" lcid "^1.0.0" @@ -4855,10 +5118,12 @@ os-locale@^2.0.0: os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -4866,40 +5131,43 @@ osenv@^0.1.4: p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= dependencies: p-limit "^1.1.0" p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= dependencies: p-finally "^1.0.0" p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - -pako@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= parse-asn1@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" + integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -4910,6 +5178,7 @@ parse-asn1@^5.0.0: parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= dependencies: glob-base "^0.3.0" is-dotfile "^1.0.0" @@ -4919,6 +5188,7 @@ parse-glob@^3.0.4: parse-headers@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" + integrity sha1-aug6eqJanZtwCswoaYzR8e1+lTY= dependencies: for-each "^0.3.2" trim "0.0.1" @@ -4926,58 +5196,61 @@ parse-headers@^2.0.0: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-parse@^1.0.5: +path-parse@^1.0.5, path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -4986,12 +5259,14 @@ path-type@^1.0.0: path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= dependencies: pify "^2.0.0" pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" + integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -5002,98 +5277,116 @@ pbkdf2@^3.0.3: pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" + integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= dependencies: find-up "^1.0.0" pkginfo@0.3.x: version "0.3.1" resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" + integrity sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE= pkginfo@0.x.x: version "0.4.1" resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" + integrity sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8= pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= pragma-singleton@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pragma-singleton/-/pragma-singleton-1.0.3.tgz#6894317bb8d47157e59de2a4a009db7e6f63e30e" + integrity sha1-aJQxe7jUcVflneKkoAnbfm9j4w4= prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= -prettier@^1.14.3: - version "1.14.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" +prettier@^1.15.3: + version "1.15.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a" + integrity sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg== private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== process@~0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== promise-to-callback@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= dependencies: is-fn "^1.0.0" set-immediate-shim "^1.0.1" @@ -5101,6 +5394,7 @@ promise-to-callback@^1.0.0: prompt@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe" + integrity sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4= dependencies: colors "^1.1.2" pkginfo "0.x.x" @@ -5112,6 +5406,7 @@ prompt@^1.0.0: prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" + integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== dependencies: loose-envify "^1.3.1" object-assign "^4.1.1" @@ -5119,6 +5414,7 @@ prop-types@^15.6.2: proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" + integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== dependencies: forwarded "~0.1.2" ipaddr.js "1.8.0" @@ -5126,18 +5422,22 @@ proxy-addr@~2.0.4: prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -psl@^1.1.24: - version "1.1.29" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" +psl@^1.1.24, psl@^1.1.28: + version "1.1.31" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" + integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -5146,55 +5446,50 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - -punycode@^1.2.4, punycode@^1.4.1: +punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== dependencies: decode-uri-component "^0.2.0" object-assign "^4.1.0" strict-uri-encode "^1.0.0" -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - randomatic@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116" + version "3.1.1" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" + integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== dependencies: is-number "^4.0.0" kind-of "^6.0.0" math-random "^1.0.1" -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" + integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -5202,14 +5497,17 @@ randomfill@^1.0.3: randomhex@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" + integrity sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU= range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" + integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== dependencies: bytes "3.0.0" http-errors "1.6.3" @@ -5219,6 +5517,7 @@ raw-body@2.3.3: rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" ini "~1.3.0" @@ -5226,26 +5525,29 @@ rc@^1.2.7: strip-json-comments "~2.0.1" react-dom@^16.2.0: - version "16.5.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.5.2.tgz#b69ee47aa20bab5327b2b9d7c1fe2a30f2cfa9d7" + version "16.7.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.7.0.tgz#a17b2a7ca89ee7390bc1ed5eb81783c7461748b8" + integrity sha512-D0Ufv1ExCAmF38P2Uh1lwpminZFRXEINJe53zRAbm4KPwSyd6DY/uDoS0Blj9jvPpn1+wivKpZYc8aAAN/nAkg== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.10.0" + scheduler "^0.12.0" react@^16.2.0: - version "16.5.2" - resolved "https://registry.yarnpkg.com/react/-/react-16.5.2.tgz#19f6b444ed139baa45609eee6dc3d318b3895d42" + version "16.7.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.7.0.tgz#b674ec396b0a5715873b350446f7ea0802ab6381" + integrity sha512-StCz3QY8lxTb5cl2HJxjwLFOXPIFQp+p+hxQfc8WE0QiLfCtIlKj8/+5tjjKm8uSTlAW+fCPaavGFS06V9Ar3A== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.10.0" + scheduler "^0.12.0" read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -5253,6 +5555,7 @@ read-pkg-up@^1.0.1: read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= dependencies: find-up "^2.0.0" read-pkg "^2.0.0" @@ -5260,6 +5563,7 @@ read-pkg-up@^2.0.0: read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" @@ -5268,6 +5572,7 @@ read-pkg@^1.0.0: read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" @@ -5276,21 +5581,24 @@ read-pkg@^2.0.0: read@1.0.x: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= dependencies: mute-stream "~0.0.4" readable-stream@^1.0.33: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -5303,6 +5611,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5312,36 +5621,38 @@ readable-stream@~1.0.15: readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" readable-stream "^2.0.2" -readline-sync@^1.4.9: - version "1.4.9" - resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.9.tgz#3eda8e65f23cd2a17e61301b1f0003396af5ecda" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" regenerate@^1.2.1: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" + integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" @@ -5350,23 +5661,27 @@ regenerator-transform@^0.10.0: regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== dependencies: is-equal-shallow "^0.1.3" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= dependencies: regenerate "^1.2.1" regjsgen "^0.2.0" @@ -5375,52 +5690,62 @@ regexpu-core@^2.0.0: regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= regjsparser@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= dependencies: is-finite "^1.0.0" req-cwd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-1.0.1.tgz#0d73aeae9266e697a78f7976019677e76acf0fff" + integrity sha1-DXOurpJm5penj3l2AZZ352rPD/8= dependencies: req-from "^1.0.1" req-from@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-from/-/req-from-1.0.1.tgz#bf81da5147947d32d13b947dc12a58ad4587350e" + integrity sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4= dependencies: resolve-from "^2.0.0" request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" + integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= dependencies: lodash "^4.13.1" request-promise@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" + integrity sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ= dependencies: bluebird "^3.5.0" request-promise-core "1.1.1" @@ -5430,6 +5755,7 @@ request-promise@^4.2.2: request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -5455,18 +5781,22 @@ request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.8 require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" @@ -5474,34 +5804,41 @@ require-uncached@^1.0.3: resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.1.6, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + version "1.9.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06" + integrity sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ== dependencies: - path-parse "^1.0.5" + path-parse "^1.0.6" resolve@~1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" + integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw== dependencies: path-parse "^1.0.5" restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" signal-exit "^3.0.2" @@ -5509,107 +5846,115 @@ restore-cursor@^2.0.0: resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= dependencies: through "~2.3.4" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== revalidator@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" + integrity sha1-/s5hv6DBtSoga9axgZgYS91SOjs= -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - dependencies: - align-text "^0.1.1" - -rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.6.1: +rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.6.1, rimraf@~2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== dependencies: glob "^7.0.5" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" rlp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9" + version "2.2.1" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.1.tgz#9cacf53ad2579163cc56fba64b1f4336f1f2fa46" + integrity sha512-nqB/qy+YjXdp/zj1CjCiDwfLMBPv/XFDol0ir/7O/+Ix90++rvi+QoK1CDJcn8JoqCu2WrPPeRucu4qyIDzALg== dependencies: safe-buffer "^5.1.1" run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= dependencies: is-promise "^2.1.0" rustbn.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" +rxjs@^6.1.0: + version "6.3.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" + integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw== dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + tslib "^1.9.0" safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-event-emitter@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== dependencies: events "^3.0.0" safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" safe@^0.4.5: version "0.4.6" resolved "https://registry.yarnpkg.com/safe/-/safe-0.4.6.tgz#1d5580cf2635c5cb940ea48fb5081ae3c25b1be1" + integrity sha1-HVWAzyY1xcuUDqSPtQga48JbG+E= safefs@^3.1.2: version "3.2.2" resolved "https://registry.yarnpkg.com/safefs/-/safefs-3.2.2.tgz#8170c1444d7038e08caea05a374fae2fa349e15c" + integrity sha1-gXDBRE1wOOCMrqBaN0+uL6NJ4Vw= dependencies: graceful-fs "*" "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== scandirectory@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/scandirectory/-/scandirectory-2.5.0.tgz#6ce03f54a090b668e3cbedbf20edf9e310593e72" + integrity sha1-bOA/VKCQtmjjy+2/IO354xBZPnI= dependencies: ignorefs "^1.0.0" safefs "^3.1.2" taskgroup "^4.0.5" -schedule@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.5.0.tgz#c128fffa0b402488b08b55ae74bb9df55cc29cc8" +scheduler@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.12.0.tgz#8ab17699939c0aedc5a196a657743c496538647b" + integrity sha512-t7MBR28Akcp4Jm+QoR63XgAi9YgCUmgvDHqf5otgAj4QvdoBE4ImCX0ffehefePPG+aitiYHp0g/mW6s4Tp+dw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5617,33 +5962,48 @@ schedule@^0.5.0: scrypt-async@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-1.3.1.tgz#a11fd6fac981b4b823ee01dee0221169500ddae9" + integrity sha1-oR/W+smBtLgj7gHe4CIRaVAN2uk= -scrypt-js@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" +scrypt-js@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" + integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== -scrypt.js@0.2.0, scrypt.js@^0.2.0: +scrypt.js@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" + integrity sha1-r40UZbcemZARC+38WTuUeeA6ito= dependencies: scrypt "^6.0.2" scryptsy "^1.2.1" +scrypt.js@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.3.0.tgz#6c62d61728ad533c8c376a2e5e3e86d41a95c4c0" + integrity sha512-42LTc1nyFsyv/o0gcHtDztrn+aqpkaCNt5Qh7ATBZfhEZU7IC/0oT/qbBH+uRNoAPvs2fwiOId68FDEoSRA8/A== + dependencies: + scryptsy "^1.2.1" + optionalDependencies: + scrypt "^6.0.2" + scrypt@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" + integrity sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0= dependencies: nan "^2.0.8" scryptsy@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= dependencies: pbkdf2 "^3.0.3" secp256k1@^3.0.1: version "3.5.2" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.2.tgz#f95f952057310722184fe9c914e6b71281f2f2ae" + integrity sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ== dependencies: bindings "^1.2.1" bip66 "^1.1.3" @@ -5657,24 +6017,29 @@ secp256k1@^3.0.1: seek-bzip@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" + integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= dependencies: commander "~2.8.1" semaphore@>=1.0.1, semaphore@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== semver@~5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== dependencies: debug "2.6.9" depd "~1.1.2" @@ -5693,6 +6058,7 @@ send@0.16.2: serve-static@1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" @@ -5702,6 +6068,7 @@ serve-static@1.13.2: servify@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== dependencies: body-parser "^1.16.0" cors "^2.8.1" @@ -5712,14 +6079,17 @@ servify@^0.1.12: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -5729,6 +6099,7 @@ set-value@^0.4.3: set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -5738,49 +6109,58 @@ set-value@^2.0.0: setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= -setimmediate@^1.0.4, setimmediate@^1.0.5: +setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" -sha3@^1.1.0: +sha3@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" + integrity sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k= dependencies: nan "2.10.0" shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shelljs@^0.7.4: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= dependencies: glob "^7.0.0" interpret "^1.0.0" rechoir "^0.6.2" shelljs@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" + version "0.8.3" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" + integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -5789,14 +6169,17 @@ shelljs@^0.8.1: signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= simple-get@^2.7.0: version "2.8.1" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" + integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== dependencies: decompress-response "^3.3.0" once "^1.3.1" @@ -5805,16 +6188,21 @@ simple-get@^2.7.0: slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" +slice-ansi@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.0.0.tgz#5373bdb8559b45676e8541c66916cdd6251612e7" + integrity sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ== dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -5823,12 +6211,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -5842,29 +6232,34 @@ snapdragon@^0.8.1: sol-digger@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" + integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= sol-explore@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" + integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= sol-explore@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.2.tgz#43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2" + integrity sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI= -sol-merger@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-0.1.2.tgz#1f12500f42d427dc0ec8e4c113392acd8a6f62d9" - dependencies: - bluebird "^3.5.0" - cli-color "^1.2.0" - commander "^2.11.0" - debug "^3.0.1" - fs-extra "^4.0.2" +sol-merger@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-0.1.3.tgz#184284ba4811aebe8950f510df4e8218f568b35f" + integrity sha512-mEirUbl1mZJt2iNBqptsBpxb8n7ZD0trNlnV/+CBAQH8TIFhHIKXdBE8ykD1v+8My18sq7GqHYPmpHE9ckB2Jw== + dependencies: + bluebird "^3.5.3" + cli-color "^1.4.0" + commander "^2.19.0" + debug "^3.2.6" + fs-extra "^7.0.1" glob "^7.1.2" solc@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.24.tgz#354f14b269b38cbaa82a47d1ff151723502b954e" + integrity sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -5872,9 +6267,10 @@ solc@0.4.24: semver "^5.3.0" yargs "^4.7.1" -solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: +solc@^0.4.2: version "0.4.25" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.25.tgz#06b8321f7112d95b4b903639b1138a4d292f5faa" + integrity sha512-jU1YygRVy6zatgXrLY2rRm7HW1d7a8CkkEgNJwvH2VLpWhMFsMdWcJn6kUqZwcSz/Vm+w89dy7Z/aB5p6AFTrg== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -5885,6 +6281,7 @@ solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: solidity-coverage@^0.5.11: version "0.5.11" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" + integrity sha512-qikdsSi6+9XbfvwA0aI7HUVpF9fIFNqRWTw23M89GMDY+b6Gj0wWU9IngJS0fimoZIAdEp3bfChxvpfVcrUesg== dependencies: death "^1.1.0" ethereumjs-testrpc-sc "6.1.6" @@ -5900,6 +6297,7 @@ solidity-coverage@^0.5.11: solidity-docgen@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/solidity-docgen/-/solidity-docgen-0.1.0.tgz#f3a56ff074e8c7d832af3a3d462c3b5abf0f64cb" + integrity sha512-F7ufNWmlP5c5hIi66Ijv9tc+HNosyO7ijWq6pRtyBR1WqyJBH/0DJkD6QZI8HkE8p6LEXiPKxGBWbAeVT9Nu9g== dependencies: commander "^2.14.1" lodash "^4.17.5" @@ -5912,6 +6310,7 @@ solidity-docgen@^0.1.0: solidity-parser-sc@0.4.11: version "0.4.11" resolved "https://registry.yarnpkg.com/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz#86734c9205537007f4d6201b57176e41696ee607" + integrity sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw== dependencies: mocha "^4.1.0" pegjs "^0.10.0" @@ -5920,10 +6319,12 @@ solidity-parser-sc@0.4.11: solium-plugin-security@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" + integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== -solium@^1.1.6: +solium@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/solium/-/solium-1.1.8.tgz#35d30a15c572a233ce8a90226d6cfccb762fadb7" + integrity sha512-fn0lusM6of14CytIDDHK73SGjn6NsVTaCVJjaKCKJyqKhT00rH/hDtvnIeZ2ZTD9z/xaXd4Js2brW3az6AV9RA== dependencies: ajv "^5.2.2" chokidar "^1.6.0" @@ -5941,6 +6342,7 @@ solium@^1.1.6: solparse@2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.5.tgz#72709c867cd6bfc50ec2325f4b81d2b3ea365d99" + integrity sha512-t7tvtR6KU6QfPYLMv1nlCh9DA8HYIu5tbjHpKu0fhGFZ1NuSp0KKDHfFHv07g6v1xgcuUY3rVqNFjZt5b9+5qA== dependencies: mocha "^4.0.1" pegjs "^0.10.0" @@ -5949,14 +6351,12 @@ solparse@2.2.5: sorted-array-functions@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.2.0.tgz#43265b21d6e985b7df31621b1c11cc68d8efc7c3" - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-sWpjPhIZJtqO77GN+LD8dDsDKcWZ9GCOJNqKzi1tvtjGIzwfoyuRH8S0psunmc6Z5P+qfDqztSbwYR5X/e1UTg== source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== dependencies: atob "^2.1.1" decode-uri-component "^0.2.0" @@ -5964,40 +6364,47 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - dependencies: - source-map "^0.5.6" - -source-map-support@^0.5.3: +source-map-support@0.5.9, source-map-support@^0.5.3: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" + integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: +source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= dependencies: amdefine ">=0.0.4" spdx-correct@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -6005,35 +6412,42 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f" + version "3.0.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz#a59efc09784c2a5bada13cfeaf5c75dd214044d2" + integrity sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@>=1.0.3: - version "1.1.1" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" + version "1.1.2" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" + integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: - version "1.15.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2" + version "1.15.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.2.tgz#c946d6bd9b1a39d0e8635763f5242d6ed6dcb629" + integrity sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -6048,10 +6462,12 @@ sshpk@^1.7.0: stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -6059,52 +6475,32 @@ static-extend@^0.1.1: "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== stdio@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/stdio/-/stdio-0.2.7.tgz#a1c57da10fe1cfaa0c3bf683c9d0743d1b660839" + integrity sha1-ocV9oQ/hz6oMO/aDydB0PRtmCDk= stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - -stream-browserify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - -string-extended@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/string-extended/-/string-extended-0.0.8.tgz#741957dff487b0272a79eec5a44f239ee6f17ccd" - dependencies: - array-extended "~0.0.5" - date-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -6113,6 +6509,7 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" @@ -6120,100 +6517,118 @@ string-width@^1.0.1: string.prototype.trim@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" + integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= dependencies: define-properties "^1.1.2" es-abstract "^1.5.0" function-bind "^1.0.2" -string_decoder@^1.0.0, string_decoder@~1.1.1: +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" + integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow== + dependencies: + ansi-regex "^4.0.0" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== dependencies: is-natural-number "^4.0.1" strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= dependencies: is-hex-prefixed "1.0.0" strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= supports-color@4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" + integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== dependencies: has-flag "^2.0.0" supports-color@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== dependencies: has-flag "^3.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" -supports-color@^4.2.1: - version "4.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - dependencies: - has-flag "^2.0.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" swarm-js@0.1.37: version "0.1.37" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" + integrity sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ== dependencies: bluebird "^3.5.0" buffer "^5.0.5" @@ -6229,22 +6644,20 @@ swarm-js@0.1.37: tar.gz "^1.0.5" xhr-request-promise "^0.1.2" -table@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" +table@^5.0.2: + version "5.1.1" + resolved "https://registry.yarnpkg.com/table/-/table-5.1.1.tgz#92030192f1b7b51b6eeab23ed416862e47b70837" + integrity sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw== dependencies: - ajv "^6.5.3" - lodash "^4.17.10" - slice-ansi "1.0.0" + ajv "^6.6.1" + lodash "^4.17.11" + slice-ansi "2.0.0" string-width "^2.1.1" -tapable@^0.2.7: - version "0.2.8" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" - tape@^4.4.0, tape@^4.6.3: version "4.9.1" resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9" + integrity sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw== dependencies: deep-equal "~1.0.1" defined "~1.0.0" @@ -6263,6 +6676,7 @@ tape@^4.4.0, tape@^4.6.3: tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== dependencies: bl "^1.0.0" buffer-alloc "^1.2.0" @@ -6275,6 +6689,7 @@ tar-stream@^1.5.2: tar.gz@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" + integrity sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg== dependencies: bluebird "^2.9.34" commander "^2.8.1" @@ -6285,19 +6700,21 @@ tar.gz@^1.0.5: tar@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= dependencies: block-stream "*" fstream "^1.0.2" inherits "2" tar@^4: - version "4.4.6" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" + version "4.4.8" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" + integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== dependencies: - chownr "^1.0.1" + chownr "^1.1.1" fs-minipass "^1.2.5" - minipass "^2.3.3" - minizlib "^1.1.0" + minipass "^2.3.4" + minizlib "^1.1.1" mkdirp "^0.5.0" safe-buffer "^5.1.2" yallist "^3.0.2" @@ -6305,6 +6722,7 @@ tar@^4: taskgroup@^4.0.5, taskgroup@^4.2.0: version "4.3.1" resolved "https://registry.yarnpkg.com/taskgroup/-/taskgroup-4.3.1.tgz#7de193febd768273c457730497024d512c27915a" + integrity sha1-feGT/r12gnPEV3MElwJNUSwnkVo= dependencies: ambi "^2.2.0" csextends "^1.0.3" @@ -6312,36 +6730,36 @@ taskgroup@^4.0.5, taskgroup@^4.2.0: text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= thenify-all@^1.0.0, thenify-all@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.0" resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= dependencies: any-promise "^1.0.0" through@^2.3.6, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - -timers-browserify@^2.0.4: - version "2.0.10" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - dependencies: - setimmediate "^1.0.4" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-ext@^0.1.5: version "0.1.7" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== dependencies: es5-ext "~0.10.46" next-tick "1" @@ -6349,6 +6767,7 @@ timers-ext@^0.1.5: tingodb@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/tingodb/-/tingodb-0.6.1.tgz#f63336259af7dfa6c90dfe2556a0dfb0d4eede59" + integrity sha1-9jM2JZr336bJDf4lVqDfsNTu3lk= dependencies: lodash "^4.17.5" safe "^0.4.5" @@ -6359,30 +6778,31 @@ tingodb@^0.6.1: tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - to-buffer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -6390,60 +6810,48 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" regex-not "^1.0.2" safe-regex "^1.1.0" -tough-cookie@>=2.3.3, tough-cookie@~2.4.3: +tough-cookie@>=2.3.3: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: psl "^1.1.24" punycode "^1.4.1" tree-kill@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" + version "1.2.1" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" + integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= -truffle-blockchain-utils@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/truffle-blockchain-utils/-/truffle-blockchain-utils-0.0.5.tgz#a4e5c064dadd69f782a137f3d276d21095da7a47" - -truffle-contract-schema@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/truffle-contract-schema/-/truffle-contract-schema-2.0.1.tgz#9bf821d32e26e674ba15eb5d40f96b10b1c9d568" - dependencies: - ajv "^5.1.1" - crypto-js "^3.1.9-1" - debug "^3.1.0" - -truffle-contract@^3.0.4: - version "3.0.6" - resolved "https://registry.yarnpkg.com/truffle-contract/-/truffle-contract-3.0.6.tgz#2ef6fc32d7faafa9f4aed8e50001a9fdea342192" - dependencies: - ethjs-abi "0.1.8" - truffle-blockchain-utils "^0.0.5" - truffle-contract-schema "^2.0.1" - truffle-error "^0.0.3" - web3 "0.20.6" - -truffle-error@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/truffle-error/-/truffle-error-0.0.3.tgz#4bf55242e14deee1c7194932709182deff2c97ca" - -truffle-hdwallet-provider-privkey@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider-privkey/-/truffle-hdwallet-provider-privkey-0.1.0.tgz#9417047a74ad37d923df926154b6486ffb57f6c9" +truffle-hdwallet-provider-privkey@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider-privkey/-/truffle-hdwallet-provider-privkey-0.3.0.tgz#6688f5f3db5dce2cb9f502f7b52dab7b5e2522a3" + integrity sha512-rXwYWz9/lgmZQft0lAwj1JTATzG9FErhvI4xy/Vz5gNFjQCGC7yu3aYBc3XI8g2nrIyYUFqaZbrgHmYcAjw/1A== dependencies: ethereumjs-tx "^1.3.4" ethereumjs-wallet "^0.6.0" @@ -6453,6 +6861,7 @@ truffle-hdwallet-provider-privkey@^0.1.0: truffle-wallet-provider@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-wallet-provider/-/truffle-wallet-provider-0.0.5.tgz#db59ce6fa1c558766011137509a94dfca8d1408e" + integrity sha1-21nOb6HFWHZgERN1CalN/KjRQI4= dependencies: ethereumjs-wallet "^0.6.0" web3 "^0.18.2" @@ -6461,6 +6870,7 @@ truffle-wallet-provider@0.0.5: truffle@4.1.14: version "4.1.14" resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.14.tgz#8d2c298e29abf9b1e486e44ff9faca6d34bb9030" + integrity sha512-e7tTLvKP3bN9dE7MagfWyFjy4ZgoEGbeujECy1me1ENBzbj/aO/+45gs72qsL3+3IkCNNcWNOJjjrm8BYZZNNg== dependencies: mocha "^4.1.0" original-require "1.0.1" @@ -6471,33 +6881,34 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.13.2.tgz#453161770469d45cd266c36404e2bc99a8fa9944" + integrity sha1-RTFhdwRp1FzSZsNkBOK8maj6mUQ= tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" + integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== dependencies: media-typer "0.3.0" mime-types "~2.1.18" @@ -6505,62 +6916,44 @@ type-is@~1.6.16: typechecker@^2.0.8: version "2.1.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.1.0.tgz#d1c2093a54ff8a19f58cff877eeaa54f2242d383" + integrity sha1-0cIJOlT/ihn1jP+HfuqlTyJC04M= typechecker@^4.3.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.6.0.tgz#d245d9c2df21147d5e2a942fff170b68ece73c87" + version "4.7.0" + resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.7.0.tgz#5249f427358f45b7250c4924fd4d01ed9ba435e9" + integrity sha512-4LHc1KMNJ6NDGO+dSM/yNfZQRtp8NN7psYrPHUblD62Dvkwsp3VShsbM78kOgpcmMkRTgvwdKOTjctS+uMllgQ== dependencies: - editions "^2.0.2" + editions "^2.1.0" typechecker@~2.0.1: version "2.0.8" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.0.8.tgz#e83da84bb64c584ccb345838576c40b0337db82e" + integrity sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4= typedarray-to-buffer@^3.1.2: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - -uglify-js@^2.8.29: - version "2.8.29" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - dependencies: - source-map "~0.5.1" - yargs "~3.10.0" - optionalDependencies: - uglify-to-browserify "~1.0.0" - uglify-js@^3.1.4: version "3.4.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" + integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== dependencies: commander "~2.17.1" source-map "~0.6.1" -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - -uglifyjs-webpack-plugin@^0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" - dependencies: - source-map "^0.5.6" - uglify-js "^2.8.29" - webpack-sources "^1.0.1" - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== unbzip2-stream@^1.0.9: version "1.3.1" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" + integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw== dependencies: buffer "^3.0.1" through "^2.3.6" @@ -6568,14 +6961,17 @@ unbzip2-stream@^1.0.9: underscore@1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= underscore@^1.8.3: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -6585,92 +6981,84 @@ union-value@^1.0.0: universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -unorm@^1.3.3: +unorm@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300" + integrity sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA= unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.0.5: - version "1.1.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= dependencies: prepend-http "^1.0.1" url-set-query@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - dependencies: - punycode "1.3.2" - querystring "0.2.0" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== utf8@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" + integrity sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g= utf8@^2.1.1, utf8@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" + integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY= utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - dependencies: - inherits "2.0.1" - -util@^0.10.3: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - dependencies: - inherits "2.0.3" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= utile@0.3.x: version "0.3.0" resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a" + integrity sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo= dependencies: async "~0.9.0" deep-equal "~0.2.1" @@ -6682,22 +7070,22 @@ utile@0.3.x: utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - -valid-url@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" @@ -6705,36 +7093,26 @@ validate-npm-package-license@^3.0.1: varint@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf" + integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8= vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - dependencies: - indexof "0.0.1" - -watchpack@^1.4.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - dependencies: - chokidar "^2.0.2" - graceful-fs "^4.1.2" - neo-async "^2.5.0" - watchr@~2.4.13: version "2.4.13" resolved "https://registry.yarnpkg.com/watchr/-/watchr-2.4.13.tgz#d74847bb4d6f90f61fe2c74f9f68662aa0e07601" + integrity sha1-10hHu01vkPYf4sdPn2hmKqDgdgE= dependencies: eachr "^2.0.2" extendr "^2.1.0" @@ -6748,6 +7126,7 @@ watchr@~2.4.13: web3-bzz@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.34.tgz#068d37777ab65e5c60f8ec8b9a50cfe45277929c" + integrity sha1-Bo03d3q2Xlxg+OyLmlDP5FJ3kpw= dependencies: got "7.1.0" swarm-js "0.1.37" @@ -6756,6 +7135,7 @@ web3-bzz@1.0.0-beta.34: web3-core-helpers@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz#b168da00d3e19e156bc15ae203203dd4dfee2d03" + integrity sha1-sWjaANPhnhVrwVriAyA91N/uLQM= dependencies: underscore "1.8.3" web3-eth-iban "1.0.0-beta.34" @@ -6764,6 +7144,7 @@ web3-core-helpers@1.0.0-beta.34: web3-core-method@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz#ec163c8a2c490fa02a7ec15559fa7307fc7cc6dd" + integrity sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -6774,6 +7155,7 @@ web3-core-method@1.0.0-beta.34: web3-core-promievent@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz#a4f4fa6784bb293e82c60960ae5b56a94cd03edc" + integrity sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw= dependencies: any-promise "1.3.0" eventemitter3 "1.1.1" @@ -6781,6 +7163,7 @@ web3-core-promievent@1.0.0-beta.34: web3-core-requestmanager@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz#01f8f6cf2ae6b6f0b70c38bae1ef741b5bab215c" + integrity sha1-Afj2zyrmtvC3DDi64e90G1urIVw= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -6791,6 +7174,7 @@ web3-core-requestmanager@1.0.0-beta.34: web3-core-subscriptions@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz#9fed144033f221c3cf21060302ffdaf5ef2de2de" + integrity sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4= dependencies: eventemitter3 "1.1.1" underscore "1.8.3" @@ -6799,6 +7183,7 @@ web3-core-subscriptions@1.0.0-beta.34: web3-core@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.34.tgz#121be8555e9fb00d2c5d05ddd3381d0c9e46987e" + integrity sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4= dependencies: web3-core-helpers "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -6808,6 +7193,7 @@ web3-core@1.0.0-beta.34: web3-eth-abi@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz#034533e3aa2f7e59ff31793eaea685c0ed5af67a" + integrity sha1-A0Uz46ovfln/MXk+rqaFwO1a9no= dependencies: bn.js "4.11.6" underscore "1.8.3" @@ -6817,6 +7203,7 @@ web3-eth-abi@1.0.0-beta.34: web3-eth-accounts@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz#e09142eeecc797ac3459b75e9b23946d3695f333" + integrity sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM= dependencies: any-promise "1.3.0" crypto-browserify "3.12.0" @@ -6832,6 +7219,7 @@ web3-eth-accounts@1.0.0-beta.34: web3-eth-contract@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz#9dbb38fae7643a808427a20180470ec7415c91e6" + integrity sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -6845,6 +7233,7 @@ web3-eth-contract@1.0.0-beta.34: web3-eth-iban@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz#9af458605867ccf74ea979aaf326b38ba6a5ba0c" + integrity sha1-mvRYYFhnzPdOqXmq8yazi6alugw= dependencies: bn.js "4.11.6" web3-utils "1.0.0-beta.34" @@ -6852,6 +7241,7 @@ web3-eth-iban@1.0.0-beta.34: web3-eth-personal@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz#9afba167342ebde5420bcd5895c3f6c34388f205" + integrity sha1-mvuhZzQuveVCC81YlcP2w0OI8gU= dependencies: web3-core "1.0.0-beta.34" web3-core-helpers "1.0.0-beta.34" @@ -6862,6 +7252,7 @@ web3-eth-personal@1.0.0-beta.34: web3-eth@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.34.tgz#74086000850c6fe6f535ef49837d6d4bb6113268" + integrity sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -6879,6 +7270,7 @@ web3-eth@1.0.0-beta.34: web3-net@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.34.tgz#427cea2f431881449c8e38d523290f173f9ff63d" + integrity sha1-QnzqL0MYgUScjjjVIykPFz+f9j0= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -6887,6 +7279,7 @@ web3-net@1.0.0-beta.34: web3-provider-engine@^13.8.0: version "13.8.0" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz#4c7c1ad2af5f1fe10343b8a65495879a2f9c00df" + integrity sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ== dependencies: async "^2.5.0" clone "^2.0.0" @@ -6911,6 +7304,7 @@ web3-provider-engine@^13.8.0: web3-provider-engine@^8.4.0: version "8.6.1" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz#4d86e19e30caaf97df351511ec0f60136e5b30eb" + integrity sha1-TYbhnjDKr5ffNRUR7A9gE25bMOs= dependencies: async "^2.1.2" clone "^2.0.0" @@ -6930,6 +7324,7 @@ web3-provider-engine@^8.4.0: web3-providers-http@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz#e561b52bbb43766282007d40285bfe3550c27e7a" + integrity sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno= dependencies: web3-core-helpers "1.0.0-beta.34" xhr2 "0.1.4" @@ -6937,6 +7332,7 @@ web3-providers-http@1.0.0-beta.34: web3-providers-ipc@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz#a1b77f1a306d73649a9c039052e40cb71328d00a" + integrity sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao= dependencies: oboe "2.1.3" underscore "1.8.3" @@ -6945,6 +7341,7 @@ web3-providers-ipc@1.0.0-beta.34: web3-providers-ws@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz#7de70f1b83f2de36476772156becfef6e3516eb3" + integrity sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -6953,6 +7350,7 @@ web3-providers-ws@1.0.0-beta.34: web3-shh@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.34.tgz#975061d71eaec42ccee576f7bd8f70f03844afe0" + integrity sha1-l1Bh1x6uxCzO5Xb3vY9w8DhEr+A= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -6962,6 +7360,7 @@ web3-shh@1.0.0-beta.34: web3-utils@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.34.tgz#9411fc39aaef39ca4e06169f762297d9ff020970" + integrity sha1-lBH8OarvOcpOBhafdiKX2f8CCXA= dependencies: bn.js "4.11.6" eth-lib "0.1.27" @@ -6974,6 +7373,7 @@ web3-utils@1.0.0-beta.34: web3@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/web3/-/web3-0.19.1.tgz#e763d5b1107c4bc24abd4f8cbee1ba3659e6eb31" + integrity sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE= dependencies: bignumber.js "^4.0.2" crypto-js "^3.1.4" @@ -6984,16 +7384,7 @@ web3@0.19.1: web3@0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.2.tgz#c54dac5fc0e377399c04c1a6ecbb12e4513278d6" - dependencies: - bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" - crypto-js "^3.1.4" - utf8 "^2.1.1" - xhr2 "*" - xmlhttprequest "*" - -web3@0.20.6: - version "0.20.6" - resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.6.tgz#3e97306ae024fb24e10a3d75c884302562215120" + integrity sha1-xU2sX8DjdzmcBMGm7LsS5FEyeNY= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7004,6 +7395,7 @@ web3@0.20.6: web3@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.34.tgz#347e561b784098cb5563315f490479a1d91f2ab1" + integrity sha1-NH5WG3hAmMtVYzFfSQR5odkfKrE= dependencies: web3-bzz "1.0.0-beta.34" web3-core "1.0.0-beta.34" @@ -7016,6 +7408,7 @@ web3@1.0.0-beta.34: web3@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" + integrity sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js#master" crypto-js "^3.1.4" @@ -7025,6 +7418,7 @@ web3@^0.16.0: web3@^0.18.2, web3@^0.18.4: version "0.18.4" resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" + integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" crypto-js "^3.1.4" @@ -7035,6 +7429,7 @@ web3@^0.18.2, web3@^0.18.4: web3@^0.20.6: version "0.20.7" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.7.tgz#1605e6d81399ed6f85a471a4f3da0c8be57df2f7" + integrity sha512-VU6/DSUX93d1fCzBz7WP/SGCQizO1rKZi4Px9j/3yRyfssHyFcZamMw2/sj4E8TlfMXONvZLoforR8B4bRoyTQ== dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7042,40 +7437,6 @@ web3@^0.20.6: xhr2-cookies "^1.1.0" xmlhttprequest "*" -webpack-sources@^1.0.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack@^3.0.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.12.0.tgz#3f9e34360370602fcf639e97939db486f4ec0d74" - dependencies: - acorn "^5.0.0" - acorn-dynamic-import "^2.0.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - async "^2.1.2" - enhanced-resolve "^3.4.0" - escope "^3.6.0" - interpret "^1.0.0" - json-loader "^0.5.4" - json5 "^0.5.1" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - mkdirp "~0.5.0" - node-libs-browser "^2.0.0" - source-map "^0.5.3" - supports-color "^4.2.1" - tapable "^0.2.7" - uglifyjs-webpack-plugin "^0.4.6" - watchpack "^1.4.0" - webpack-sources "^1.0.1" - yargs "^8.0.2" - "websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": version "1.0.26" resolved "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" @@ -7088,38 +7449,41 @@ webpack@^3.0.0: whatwg-fetch@>=0.10.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" + integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@^1.1.1, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= winston@2.1.x: version "2.1.1" - resolved "http://registry.npmjs.org/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" + resolved "https://registry.yarnpkg.com/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" + integrity sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4= dependencies: async "~1.0.0" colors "1.0.x" @@ -7132,6 +7496,7 @@ winston@2.1.x: winston@^2.3.1: version "2.4.4" resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.4.tgz#a01e4d1d0a103cf4eada6fc1f886b3110d71c34b" + integrity sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q== dependencies: async "~1.0.0" colors "1.0.x" @@ -7140,21 +7505,20 @@ winston@^2.3.1: isstream "0.1.x" stack-trace "0.0.x" -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - wordwrap@^1.0.0, wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -7162,16 +7526,19 @@ wrap-ansi@^2.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= dependencies: mkdirp "^0.5.1" ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" @@ -7180,12 +7547,14 @@ ws@^3.0.0: xhr-request-promise@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" + integrity sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0= dependencies: xhr-request "^1.0.1" xhr-request@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== dependencies: buffer-to-arraybuffer "^0.0.5" object-assign "^4.1.1" @@ -7198,16 +7567,19 @@ xhr-request@^1.0.1: xhr2-cookies@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= dependencies: cookiejar "^2.1.1" xhr2@*, xhr2@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" + integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8= xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: version "2.5.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" + integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== dependencies: global "~4.3.0" is-function "^1.0.1" @@ -7222,65 +7594,71 @@ xml@^1.0.0: xmlhttprequest@*, xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= xregexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" + integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= dependencies: object-keys "~0.4.0" y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= dependencies: camelcase "^3.0.0" lodash.assign "^4.0.6" -yargs-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - dependencies: - camelcase "^4.1.0" - yargs-parser@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== dependencies: camelcase "^4.1.0" yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= dependencies: camelcase "^4.1.0" -yargs@^10.0.3: - version "10.1.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" +yargs@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" + integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -7293,11 +7671,12 @@ yargs@^10.0.3: string-width "^2.0.0" which-module "^2.0.0" y18n "^3.2.1" - yargs-parser "^8.1.0" + yargs-parser "^9.0.2" -yargs@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" +yargs@^10.0.3: + version "10.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -7310,11 +7689,12 @@ yargs@^11.0.0: string-width "^2.0.0" which-module "^2.0.0" y18n "^3.2.1" - yargs-parser "^9.0.2" + yargs-parser "^8.1.0" yargs@^4.6.0, yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= dependencies: cliui "^3.2.0" decamelize "^1.1.1" @@ -7331,36 +7711,10 @@ yargs@^4.6.0, yargs@^4.7.1: y18n "^3.2.1" yargs-parser "^2.4.1" -yargs@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - read-pkg-up "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^7.0.0" - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" - yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" From 213c4981bc64bdbddde29616b72e49e694e93b55 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Thu, 20 Dec 2018 18:09:37 +0000 Subject: [PATCH 452/582] Add balances & claim amounts to getters --- .../modules/Checkpoint/DividendCheckpoint.sol | 62 ++++++++++++++----- test/e_erc20_dividends.js | 1 + 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 6f1887693..929bf977c 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -251,14 +251,33 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { claimedAmounts = new uint256[](dividends.length); names = new bytes32[](dividends.length); for (uint256 i = 0; i < dividends.length; i++) { - createds[i] = dividends[i].created; - maturitys[i] = dividends[i].maturity; - expirys[i] = dividends[i].expiry; - amounts[i] = dividends[i].amount; - claimedAmounts[i] = dividends[i].claimedAmount; - names[i] = dividends[i].name; + (createds[i], maturitys[i], expirys[i], amounts[i], claimedAmounts[i], names[i]) = getDividendData(i); } - return (createds, maturitys, expirys, amounts, claimedAmounts, names); + } + + /** + * @notice Get static dividend data + * @return uint256 timestamp of dividend creation + * @return uint256 timestamp of dividend maturity + * @return uint256 timestamp of dividend expiry + * @return uint256 amount of dividend + * @return uint256 claimed amount of dividend + * @return bytes32 name of dividend + */ + function getDividendData(uint256 _dividendIndex) public view returns ( + uint256 created, + uint256 maturity, + uint256 expiry, + uint256 amount, + uint256 claimedAmount, + bytes32 name) + { + created = dividends[_dividendIndex].created; + maturity = dividends[_dividendIndex].maturity; + expiry = dividends[_dividendIndex].expiry; + amount = dividends[_dividendIndex].amount; + claimedAmount = dividends[_dividendIndex].claimedAmount; + name = dividends[_dividendIndex].name; } /** @@ -268,21 +287,30 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @return bool[] whether investor has claimed * @return bool[] whether investor is excluded * @return uint256[] amount of withheld tax + * @return uint256[] investor balance + * @return uint256[] amount to be claimed including withheld tax */ - function getDividendProgress(uint256 _dividendIndex) external view returns (address[], bool[], bool[], uint256[]) { + function getDividendProgress(uint256 _dividendIndex) external view returns (address[] memory investors, bool[] memory resultClaimed, bool[] memory resultExcluded, uint256[] memory resultWithheld, uint256[] memory resultBalance, uint256[] memory resultAmount) { require(_dividendIndex < dividends.length, "Invalid dividend"); //Get list of Investors - uint256 checkpointId = dividends[_dividendIndex].checkpointId; - address[] memory investors = ISecurityToken(securityToken).getInvestorsAt(checkpointId); - bool[] memory resultClaimed = new bool[](investors.length); - bool[] memory resultExcluded = new bool[](investors.length); - uint256[] memory resultWithheld = new uint256[](investors.length); + Dividend storage dividend = dividends[_dividendIndex]; + uint256 checkpointId = dividend.checkpointId; + investors = ISecurityToken(securityToken).getInvestorsAt(checkpointId); + resultClaimed = new bool[](investors.length); + resultExcluded = new bool[](investors.length); + resultWithheld = new uint256[](investors.length); + resultBalance = new uint256[](investors.length); + resultAmount = new uint256[](investors.length); for (uint256 i; i < investors.length; i++) { - resultClaimed[i] = dividends[_dividendIndex].claimed[investors[i]]; - resultExcluded[i] = dividends[_dividendIndex].dividendExcluded[investors[i]]; - resultWithheld[i] = dividends[_dividendIndex].withheld[investors[i]]; + resultClaimed[i] = dividend.claimed[investors[i]]; + resultExcluded[i] = dividend.dividendExcluded[investors[i]]; + resultBalance[i] = ISecurityToken(securityToken).balanceOfAt(investors[i], dividend.checkpointId); + if (!resultExcluded[i]) { + resultWithheld[i] = dividend.withheld[investors[i]]; + resultAmount[i] = resultBalance[i].mul(dividend.amount).div(dividend.totalSupply); + } } - return (investors, resultClaimed, resultExcluded, resultWithheld); + /* return (investors, resultClaimed, resultExcluded, resultWithheld, resultBalance, resultAmount); */ } /** diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 192e13598..3ec86dadc 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -844,6 +844,7 @@ contract("ERC20DividendCheckpoint", accounts => { it("Issuer reclaims withholding tax", async () => { let info = await I_ERC20DividendCheckpoint.getDividendProgress.call(3); + console.log(info); assert.equal(info[0][0], account_investor1, "account match"); assert.equal(info[0][1], account_investor2, "account match"); assert.equal(info[0][2], account_temp, "account match"); From a1ed6323619f7291d35daf9b04dfef89bed2abc1 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 20 Dec 2018 16:37:50 -0300 Subject: [PATCH 453/582] CLI - Flow change and updates for dividends_manager --- CLI/commands/dividends_manager.js | 1158 ++++++++++------- ...xclusions_data.csv => exclusions_data.csv} | 0 CLI/data/Checkpoint/tax_withholding_data.csv | 10 + 3 files changed, 709 insertions(+), 459 deletions(-) rename CLI/data/Checkpoint/{dividendsExclusions_data.csv => exclusions_data.csv} (100%) create mode 100644 CLI/data/Checkpoint/tax_withholding_data.csv diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 19ef24910..f021d6e2c 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -1,487 +1,601 @@ -var readlineSync = require('readline-sync'); -var chalk = require('chalk'); -var moment = require('moment'); -var common = require('./common/common_functions'); -var gbl = require('./common/global'); -var contracts = require('./helpers/contract_addresses'); -var abis = require('./helpers/contract_abis'); +const readlineSync = require('readline-sync'); +const chalk = require('chalk'); +const moment = require('moment'); +const common = require('./common/common_functions'); +const gbl = require('./common/global'); +const contracts = require('./helpers/contract_addresses'); +const abis = require('./helpers/contract_abis'); +const csvParse = require('./helpers/csv'); +const { table } = require('table') + +const EXCLUSIONS_DATA_CSV = `${__dirname}/../data/Checkpoint/exclusions_data.csv`; +const TAX_WITHHOLDING_DATA_CSV = `${__dirname}/../data/Checkpoint/tax_withholding_data.csv`; // App flow let tokenSymbol; let securityToken; let polyToken; let securityTokenRegistry; -let generalTransferManager; +let moduleRegistry; let currentDividendsModule; -async function executeApp(type) { - dividendsType = type; +let dividendsType; - common.logAsciiBull(); - console.log("**********************************************"); - console.log("Welcome to the Command-Line Dividends Manager."); - console.log("**********************************************"); - console.log("Issuer Account: " + Issuer.address + "\n"); +async function executeApp() { + console.log('\n', chalk.blue('Dividends Manager - Main Menu', '\n')); - await setup(); - try { - await start_explorer(); - } catch (err) { - console.log(err); - return; + let tmModules = await getAllModulesByType(gbl.constants.MODULES_TYPES.DIVIDENDS); + let nonArchivedModules = tmModules.filter(m => !m.archived); + if (nonArchivedModules.length > 0) { + console.log(`Dividends modules attached:`); + nonArchivedModules.map(m => console.log(`- ${m.name} at ${m.address}`)) + } else { + console.log(`There are no dividends modules attached`); } -}; -async function setup() { - try { - let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); - let securityTokenRegistryABI = abis.securityTokenRegistry(); - securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - securityTokenRegistry.setProvider(web3.currentProvider); - - let polyTokenAddress = await contracts.polyToken(); - let polyTokenABI = abis.polyToken(); - polyToken = new web3.eth.Contract(polyTokenABI, polyTokenAddress); - polyToken.setProvider(web3.currentProvider); - } catch (err) { - console.log(err) - console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); - process.exit(0); + let currentCheckpoint = await securityToken.methods.currentCheckpointId().call(); + if (currentCheckpoint > 0) { + console.log(`\nCurrent checkpoint: ${currentCheckpoint}`); } -} - -async function start_explorer() { - console.log('\n\x1b[34m%s\x1b[0m', "Dividends Manager - Main Menu"); - if (!tokenSymbol) - tokenSymbol = readlineSync.question('Enter the token symbol: '); - - let result = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); - if (result == "0x0000000000000000000000000000000000000000") { - tokenSymbol = undefined; - console.log(chalk.red(`Token symbol provided is not a registered Security Token.`)); - } else { - let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI, result); + let options = ['Create checkpoint', 'Explore address balances']; - // Get the GTM - result = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); - if (result.length == 0) { - console.log(chalk.red(`General Transfer Manager is not attached.`)); - } else { - generalTransferManagerAddress = result[0]; - let generalTransferManagerABI = abis.generalTransferManager(); - generalTransferManager = new web3.eth.Contract(generalTransferManagerABI, generalTransferManagerAddress); - generalTransferManager.setProvider(web3.currentProvider); - - let typeOptions = ['POLY', 'ETH']; - if (!typeOptions.includes(dividendsType)) { - let index = readlineSync.keyInSelect(typeOptions, 'What type of dividends do you want work with?', { cancel: false }); - dividendsType = typeOptions[index]; - console.log(`Selected: ${dividendsType}`) - } + if (nonArchivedModules.length > 0) { + options.push('Config existing modules'); + } + options.push('Add new dividends module'); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'EXIT' }); + let optionSelected = index != -1 ? options[index] : 'EXIT'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Create checkpoint': + await createCheckpointFromST(); + break; + case 'Explore address balances': + await exploreAddress(currentCheckpoint); + break; + case 'Config existing modules': + await configExistingModules(nonArchivedModules); + break; + case 'Add new dividends module': + await addDividendsModule(); + break; + case 'EXIT': + return; + } - let currentCheckpoint = await securityToken.methods.currentCheckpointId().call(); - console.log(chalk.yellow(`\nToken is at checkpoint: ${currentCheckpoint}`)); + await executeApp(); +} - let options = ['Mint tokens', 'Transfer tokens', 'Create checkpoint', 'Set default exclusions for dividends', 'Tax holding settings', 'Create dividends'] +async function createCheckpointFromST() { + let createCheckpointAction = securityToken.methods.createCheckpoint(); + let receipt = await common.sendTransaction(createCheckpointAction); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'CheckpointCreated'); + console.log(chalk.green(`Checkpoint ${event._checkpointId} has been created successfully!`)); +} - if (currentCheckpoint > 0) { - options.push('Explore account at checkpoint', 'Explore total supply at checkpoint') - } +async function exploreAddress(currentCheckpoint) { + let address = readlineSync.question('Enter address to explore: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + }); + let checkpoint = null; + if (currentCheckpoint > 0) { + checkpoint = await selectCheckpoint(false); + } - // Only show dividend options if divididenModule is already attached - if (await isDividendsModuleAttached()) { - options.push('Push dividends to accounts', - `Explore ${dividendsType} balance`, 'Reclaim expired dividends') - } + let balance = web3.utils.fromWei(await securityToken.methods.balanceOf(address).call()); + let totalSupply = web3.utils.fromWei(await securityToken.methods.totalSupply().call()); + console.log(`Balance of ${address} is: ${balance} ${tokenSymbol}`); + console.log(`TotalSupply is: ${totalSupply} ${tokenSymbol}`); - let index = readlineSync.keyInSelect(options, 'What do you want to do?'); - let selected = index != -1 ? options[index] : 'Cancel'; - console.log('Selected:', selected, '\n'); - switch (selected) { - case 'Mint tokens': - let _to = readlineSync.question('Enter beneficiary of minting: '); - let _amount = readlineSync.question('Enter amount of tokens to mint: '); - await mintTokens(_to, _amount); - break; - case 'Transfer tokens': - let _to2 = readlineSync.question('Enter beneficiary of tranfer: '); - let _amount2 = readlineSync.question('Enter amount of tokens to transfer: '); - await transferTokens(_to2, _amount2); - break; - case 'Create checkpoint': - let createCheckpointAction = securityToken.methods.createCheckpoint(); - await common.sendTransaction(createCheckpointAction); - break; - case 'Set default exclusions for dividends': - await setDefaultExclusions(); - break; - case 'Tax holding settings': - await taxHoldingMenu(); - break; - case 'Create dividends': - let divName = readlineSync.question(`Enter a name or title to indetify this dividend: `); - let dividend = readlineSync.question(`How much ${dividendsType} would you like to distribute to token holders?: `); - await checkBalance(dividend); - let checkpointId = currentCheckpoint == 0 ? 0 : await selectCheckpoint(true); // If there are no checkpoints, it must create a new one - await createDividends(divName, dividend, checkpointId); - break; - case 'Explore account at checkpoint': - let _address = readlineSync.question('Enter address to explore: '); - let _checkpoint = await selectCheckpoint(false); - await exploreAddress(_address, _checkpoint); - break; - case 'Explore total supply at checkpoint': - let _checkpoint2 = await selectCheckpoint(false); - await exploreTotalSupply(_checkpoint2); - break; - case 'Push dividends to accounts': - let _dividend = await selectDividend({ valid: true, expired: false, reclaimed: false, withRemaining: true }); - if (_dividend !== null) { - let _addresses = readlineSync.question('Enter addresses to push dividends to (ex- add1,add2,add3,...): '); - await pushDividends(_dividend, _addresses); - } - break; - case `Explore ${dividendsType} balance`: - let _address3 = readlineSync.question('Enter address to explore: '); - let _dividend3 = await selectDividend(); - if (_dividend3 !== null) { - let dividendAmounts = await currentDividendsModule.methods.calculateDividend(_dividend3.index, _address3).call(); - let dividendBalance = dividendAmounts[0]; - let dividendTax = dividendAmounts[1]; - let balance = await getBalance(_address3); - console.log(` - ${dividendsType} Balance: ${web3.utils.fromWei(balance)} ${dividendsType} - Dividends owned: ${web3.utils.fromWei(dividendBalance)} ${dividendsType} - Tax withheld: ${web3.utils.fromWei(dividendTax)} ${dividendsType} - `); - } - break; - case 'Reclaim expired dividends': - let _dividend4 = await selectDividend({ expired: true, reclaimed: false }); - if (_dividend4 !== null) { - await reclaimedDividend(_dividend4); - } - break; - case 'Cancel': - process.exit(0); - break; - } - } + if (checkpoint) { + let balanceAt = web3.utils.fromWei(await securityToken.methods.balanceOfAt(address, checkpoint).call()); + let totalSupplyAt = web3.utils.fromWei(await securityToken.methods.totalSupplyAt(checkpoint).call()); + console.log(`Balance of ${address} at checkpoint ${checkpoint}: ${balanceAt} ${tokenSymbol}`); + console.log(`TotalSupply at checkpoint ${checkpoint} is: ${totalSupplyAt} ${tokenSymbol}`); } - //Restart - await start_explorer(); } -async function mintTokens(address, amount) { - if (await securityToken.methods.mintingFrozen().call()) { - console.log(chalk.red("Minting is not possible - Minting has been permanently frozen by issuer")); - } else { - await whitelistAddress(address); - - try { - let mintAction = securityToken.methods.mint(address, web3.utils.toWei(amount)); - let receipt = await common.sendTransaction(mintAction); - let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); - console.log(` - Minted ${web3.utils.fromWei(event.value)} tokens - to account ${event.to}` - ); - } catch (err) { - console.log(err); - console.log(chalk.red("There was an error processing the transfer transaction. \n The most probable cause for this error is one of the involved accounts not being in the whitelist or under a lockup period.")); - } +async function configExistingModules(dividendModules) { + let options = dividendModules.map(m => `${m.name} at ${m.address}`); + let index = readlineSync.keyInSelect(options, 'Which module do you want to config? ', { cancel: 'RETURN' }); + console.log('Selected:', index != -1 ? options[index] : 'RETURN', '\n'); + let moduleNameSelected = index != -1 ? dividendModules[index].name : 'RETURN'; + switch (moduleNameSelected) { + case 'ERC20DividendCheckpoint': + currentDividendsModule = new web3.eth.Contract(abis.erc20DividendCheckpoint(), dividendModules[index].address); + currentDividendsModule.setProvider(web3.currentProvider); + dividendsType = 'ERC20'; + break; + case 'EtherDividendCheckpoint': + currentDividendsModule = new web3.eth.Contract(abis.etherDividendCheckpoint(), dividendModules[index].address); + currentDividendsModule.setProvider(web3.currentProvider); + dividendsType = 'ETH'; + break; } + + await dividendsManager(); } -async function transferTokens(address, amount) { - await whitelistAddress(address); +async function dividendsManager() { + console.log(chalk.blue(`Dividends module at ${currentDividendsModule.options.address}`), '\n'); - try { - let transferAction = securityToken.methods.transfer(address, web3.utils.toWei(amount)); - let receipt = await common.sendTransaction(transferAction, { factor: 1.5 }); - let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); - console.log(` - Account ${event.from} - transferred ${web3.utils.fromWei(event.value)} tokens - to account ${event.to}` - ); - } catch (err) { - console.log(err); - console.log(chalk.red("There was an error processing the transfer transaction. \n The most probable cause for this error is one of the involved accounts not being in the whitelist or under a lockup period.")); + let currentDividends = await getDividends(); + let defaultExcluded = await currentDividendsModule.methods.getDefaultExcluded().call(); + + console.log(`- Current dividends: ${currentDividends.length}`); + console.log(`- Default exclusions: ${defaultExcluded.length}`); + + let options = ['Create checkpoint']; + if (defaultExcluded.length > 0) { + options.push('Show current default exclusions'); } -} + options.push( + 'Set default exclusions', + 'Set tax withholding' + ); + if (currentDividends.length > 0) { + options.push('Manage existing dividends'); + } + options.push('Create new dividends'); -async function exploreAddress(address, checkpoint) { - let balance = await securityToken.methods.balanceOf(address).call(); - balance = web3.utils.fromWei(balance); - console.log(`Balance of ${address} is: ${balance} (Using balanceOf)`); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let selected = index != -1 ? options[index] : 'RETURN'; + console.log('Selected:', selected, '\n'); + switch (selected) { + case 'Create checkpoint': + await createCheckpointFromDividendModule(); + break; + case 'Show current default exclusions': + showExcluded(defaultExcluded); + break; + case 'Set default exclusions': + await setDefaultExclusions(); + break; + case 'Set tax withholding': + await taxWithholding(); + break; + case 'Manage existing dividends': + let selectedDividend = await selectDividend(currentDividends); + if (selectedDividend) { + await manageExistingDividend(selectedDividend.index); + } + break; + case 'Create new dividends': + await createDividends(); + break; + case 'RETURN': + return; + } - let balanceAt = await securityToken.methods.balanceOfAt(address, checkpoint).call(); - balanceAt = web3.utils.fromWei(balanceAt); - console.log(`Balance of ${address} is: ${balanceAt} (Using balanceOfAt - checkpoint ${checkpoint})`); + await dividendsManager(); } -async function exploreTotalSupply(checkpoint) { - let totalSupply = await securityToken.methods.totalSupply().call(); - totalSupply = web3.utils.fromWei(totalSupply); - console.log(`TotalSupply is: ${totalSupply} (Using totalSupply)`); - - let totalSupplyAt = await securityToken.methods.totalSupplyAt(checkpoint).call(); - totalSupplyAt = web3.utils.fromWei(totalSupplyAt); - console.log(`TotalSupply is: ${totalSupplyAt} (Using totalSupplyAt - checkpoint ${checkpoint})`); +async function createCheckpointFromDividendModule() { + let createCheckpointAction = securityToken.methods.createCheckpoint(); + await common.sendTransaction(createCheckpointAction); + console.log(chalk.green(`Checkpoint have been created successfully!`)); } async function setDefaultExclusions() { - await addDividendsModule(); - - let excluded = await currentDividendsModule.methods.getDefaultExcluded().call(); - showExcluded(excluded); - - console.log(chalk.yellow(`Excluded addresses will be loaded from 'dividendsExclusions_data.csv'. Please check your data before continue.`)); + console.log(chalk.yellow(`Excluded addresses will be loaded from 'exclusions_data.csv'. Please check your data before continue.`)); if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { let excluded = getExcludedFromDataFile(); - let setDefaultExclusionsActions = currentDividendsModule.methods.setDefaultExcluded(excluded); + let setDefaultExclusionsActions = currentDividendsModule.methods.setDefaultExcluded(excluded[0]); let receipt = await common.sendTransaction(setDefaultExclusionsActions); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'SetDefaultExcludedAddresses'); - console.log(chalk.green(`Exclusions were successfully set.`)); + console.log(chalk.green(`Exclusions have been set successfully!`)); showExcluded(event._excluded); } } -async function taxHoldingMenu() { - await addDividendsModule(); +async function manageExistingDividend(dividendIndex) { + // Show current data - let options = ['Set a % to withhold from dividends sent to an address', 'Withdraw withholding for dividend', 'Return to main menu']; - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: false }); - let selected = options[index]; - console.log("Selected:", selected); - switch (selected) { - case 'Set a % to withhold from dividends sent to an address': - let address = readlineSync.question('Enter the address of the investor: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address", - }); - let percentage = readlineSync.question('Enter the percentage of dividends to withhold (number between 0-100): ', { - limit: function (input) { - return (parseInt(input) >= 0 && parseInt(input) <= 100); - }, - limitMessage: "Must be a value between 0 and 100", - }); - let percentageWei = web3.utils.toWei((percentage / 100).toString()); - let setWithHoldingFixedAction = currentDividendsModule.methods.setWithholdingFixed([address], percentageWei); - let receipt = await common.sendTransaction(setWithHoldingFixedAction); - console.log(chalk.green(`Successfully set tax withholding of ${percentage}% for ${address}.`)); + let dividend = await currentDividendsModule.methods.dividends(dividendIndex).call(); + let dividendTokenAddress = gbl.constants.ADDRESS_ZERO; + let dividendTokenSymbol = 'ETH'; + if (dividendsType === 'ERC20') { + dividendTokenAddress = await currentDividendsModule.methods.dividendTokens(dividendIndex).call(); + let erc20token = new web3.eth.Contract(abis.erc20(), dividendTokenAddress); + dividendTokenSymbol = await erc20token.methods.symbol().call(); + } + let progress = await currentDividendsModule.methods.getDividendProgress(dividendIndex).call(); + let investorArray = progress[0]; + let claimedArray = progress[1]; + let excludedArray = progress[2]; + let withheldArray = progress[3]; + let balanceArray = progress[4]; + let amountArray = progress[5]; + + console.log(`- Name: ${web3.utils.hexToUtf8(dividend.name)}`); + console.log(`- Created: ${moment.unix(dividend.created).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- Maturity: ${moment.unix(dividend.maturity).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- Expiry: ${moment.unix(dividend.expiry).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- At checkpoint: ${dividend.checkpointId}`); + console.log(`- Amount: ${web3.utils.fromWei(dividend.amount)} ${dividendTokenSymbol}`); + console.log(`- Claimed amount: ${web3.utils.fromWei(dividend.claimedAmount)} ${dividendTokenSymbol}`); + console.log(`- Withheld: ${web3.utils.fromWei(dividend.totalWithheld)} ${dividendTokenSymbol}`); + console.log(`- Withheld claimed: ${web3.utils.fromWei(dividend.totalWithheldWithdrawn)} ${dividendTokenSymbol}`); + console.log(`- Total investors: ${investorArray.length}`); + console.log(` Have already claimed: ${claimedArray.filter(c => c).length}`); + console.log(` Excluded: ${excludedArray.filter(e => e).length} `); + // ------------------ + + + let options = ['Show investors', 'Show report', 'Explore account']; + if (isValidDividend(dividend) && hasRemaining(dividend) && !isExpiredDividend(dividend) && !dividend.reclaimed) { + options.push('Push dividends to accounts'); + } + if (hasRemainingWithheld(dividend)) { + options.push('Withdraw withholding'); + } + if (isExpiredDividend(dividend) && !dividend.reclaimed) { + options.push('Reclaim expired dividends'); + } + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Show investors': + showInvestors(investorArray, claimedArray, excludedArray); break; - case 'Withdraw withholding for dividend': - let _dividend = await selectDividend({ withRemainingWithheld: true }); - if (_dividend !== null) { - let withdrawWithholdingAction = currentDividendsModule.methods.withdrawWithholding(_dividend.index); - let receipt = await common.sendTransaction(withdrawWithholdingAction); - let eventName; - if (dividendsType == 'POLY') { - eventName = 'ERC20DividendWithholdingWithdrawn'; - } else if (dividendsType == 'ETH') { - eventName = 'EtherDividendWithholdingWithdrawn'; - } - let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, eventName); - console.log(chalk.green(`Successfully withdrew ${web3.utils.fromWei(event._withheldAmount)} ${dividendsType} from dividend ${_dividend.index} tax withholding.`)); - } + case 'Show report': + showReport( + web3.utils.hexToUtf8(dividend.name), + dividendTokenSymbol, + dividend.amount, // Total amount of dividends sent + dividend.totalWithheld, // Total amount of taxes withheld + dividend.claimedAmount, // Total amount of dividends distributed + investorArray, // Per Address(Amount sent, Taxes withheld (%), Taxes withheld ($/ETH/# Tokens), Amount received, Withdrawn (TRUE/FALSE) + claimedArray, + excludedArray, + withheldArray, + amountArray + ); + break; + case 'Push dividends to accounts': + await pushDividends(dividendIndex, dividend.checkpointId); + break; + case 'Explore account': + await exploreAccount(dividendIndex, dividendTokenAddress, dividendTokenSymbol); break; - case 'Return to main menu': + case 'Withdraw withholding': + await withdrawWithholding(dividendIndex, dividendTokenSymbol); break; + case 'Reclaim expired dividends': + await reclaimedDividend(dividendIndex, dividendTokenSymbol); + return; + case 'RETURN': + return; } -} - -async function createDividends(name, dividend, checkpointId) { - await addDividendsModule(); - let time = Math.floor(Date.now() / 1000); - let maturityTime = readlineSync.questionInt('Enter the dividend maturity time from which dividend can be paid (Unix Epoch time)\n(Now = ' + time + ' ): ', { defaultInput: time }); - let defaultTime = time + gbl.constants.DURATION.minutes(10); - let expiryTime = readlineSync.questionInt('Enter the dividend expiry time (Unix Epoch time)\n(10 minutes from now = ' + defaultTime + ' ): ', { defaultInput: defaultTime }); + await manageExistingDividend(dividendIndex); +} - let useDefaultExcluded = readlineSync.keyInYNStrict(`Do you want to use the default excluded addresses for this dividend? If not, data from 'dividendsExclusions_data.csv' will be used instead.`); +async function taxWithholding() { + let addresses = readlineSync.question(`Enter addresses to set tax withholding to(ex - add1, add2, add3, ...) or leave empty to read from 'tax_withholding_data.csv': `, { + limit: function (input) { + return input === '' || (input.split(',').every(a => web3.utils.isAddress(a))); + }, + limitMessage: `All addresses must be valid` + }).split(','); + if (addresses[0] !== '') { + let percentage = readlineSync.question('Enter the percentage of dividends to withhold (number between 0-100): ', { + limit: function (input) { + return (parseFloat(input) >= 0 && parseFloat(input) <= 100); + }, + limitMessage: 'Must be a value between 0 and 100', + }); + let percentageWei = web3.utils.toWei((percentage / 100).toString()); + let setWithHoldingFixedAction = currentDividendsModule.methods.setWithholdingFixed(addresses, percentageWei); + let receipt = await common.sendTransaction(setWithHoldingFixedAction); + let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'SetWithholdingFixed'); + console.log(chalk.green(`Successfully set tax rate of ${web3.utils.fromWei(event._withholding)}% for: `)); + console.log(chalk.green(event._investors)); + } else { + let parsedData = csvParse(TAX_WITHHOLDING_DATA_CSV); + let validData = parsedData.filter(row => + web3.utils.isAddress(row[0]) && + !isNaN(row[1]) + ); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, 100); + let [investorArray, taxArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + taxArray[batch] = taxArray[batch].map(t => web3.utils.toWei((t / 100).toString())); + console.log(`Batch ${batch + 1} - Attempting to set multiple tax rates to accounts: \n\n`, investorArray[batch], '\n'); + let action = await currentDividendsModule.methods.setWithholding(investorArray[batch], taxArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Multiple tax rates have benn set successfully!')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } + } +} - let createDividendAction; - if (dividendsType == 'POLY') { - let approveAction = polyToken.methods.approve(currentDividendsModule._address, web3.utils.toWei(dividend)); - await common.sendTransaction(approveAction); - if (checkpointId > 0) { - if (useDefaultExcluded) { - createDividendAction = currentDividendsModule.methods.createDividendWithCheckpoint(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), checkpointId, web3.utils.toHex(name)); - } else { - let excluded = getExcludedFromDataFile(); - createDividendAction = currentDividendsModule.methods.createDividendWithCheckpointAndExclusions(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), checkpointId, excluded, web3.utils.toHex(name)); - } - } else { - if (useDefaultExcluded) { - createDividendAction = currentDividendsModule.methods.createDividend(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), web3.utils.toHex(name)); - } else { - let excluded = getExcludedFromDataFile(); - createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, polyToken._address, web3.utils.toWei(dividend), excluded, web3.utils.toHex(name)); +async function createDividends() { + let dividendName = readlineSync.question(`Enter a name or title to indetify this dividend: `); + let dividendToken = gbl.constants.ADDRESS_ZERO; + let dividendSymbol = 'ETH'; + let token; + if (dividendsType === 'ERC20') { + do { + dividendToken = readlineSync.question(`Enter the address of ERC20 token in which dividend will be denominated(POLY = ${polyToken.options.address}): `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid ERC20 address", + defaultInput: polyToken.options.address + }); + token = new web3.eth.Contract(abis.erc20(), dividendToken); + try { + dividendSymbol = await token.methods.symbol().call(); + } catch { + console.log(chalk.red(`${dividendToken} is not a valid ERC20 token address!!`)); } - } - let receipt = await common.sendTransaction(createDividendAction); - let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'ERC20DividendDeposited'); - console.log(chalk.green(`Dividend ${event._dividendIndex} deposited`)); - } else if (dividendsType == 'ETH') { - if (checkpointId > 0) { - if (useDefaultExcluded) { - createDividendAction = currentDividendsModule.methods.createDividendWithCheckpoint(maturityTime, expiryTime, checkpointId, web3.utils.toHex(name)); + } while (dividendSymbol === 'ETH'); + } + let dividendAmount = readlineSync.question(`How much ${dividendSymbol} would you like to distribute to token holders ? `); + + let dividendAmountBN = new web3.utils.BN(dividendAmount); + let issuerBalance = new web3.utils.BN(web3.utils.fromWei(await getBalance(Issuer.address, dividendToken))); + if (issuerBalance.lt(dividendAmountBN)) { + console.log(chalk.red(`You have ${issuerBalance} ${dividendSymbol}.You need ${dividendAmountBN.sub(issuerBalance)} ${dividendSymbol} more!`)); + } else { + let checkpointId = await selectCheckpoint(true); // If there are no checkpoints, it must create a new one + let now = Math.floor(Date.now() / 1000); + let maturityTime = readlineSync.questionInt('Enter the dividend maturity time from which dividend can be paid (Unix Epoch time)\n(Now = ' + now + ' ): ', { defaultInput: now }); + let defaultTime = now + gbl.constants.DURATION.minutes(10); + let expiryTime = readlineSync.questionInt('Enter the dividend expiry time (Unix Epoch time)\n(10 minutes from now = ' + defaultTime + ' ): ', { defaultInput: defaultTime }); + + let useDefaultExcluded = !readlineSync.keyInYNStrict(`Do you want to use data from 'dividends_exclusions_data.csv' for this dividend ? If not, default exclusions will apply.`); + + let createDividendAction; + if (dividendsType == 'ERC20') { + let approveAction = token.methods.approve(currentDividendsModule._address, web3.utils.toWei(dividendAmountBN)); + await common.sendTransaction(approveAction); + if (checkpointId > 0) { + if (useDefaultExcluded) { + createDividendAction = currentDividendsModule.methods.createDividendWithCheckpoint(maturityTime, expiryTime, token.options.address, web3.utils.toWei(dividendAmountBN), checkpointId, web3.utils.toHex(dividendName)); + } else { + let excluded = getExcludedFromDataFile(); + createDividendAction = currentDividendsModule.methods.createDividendWithCheckpointAndExclusions(maturityTime, expiryTime, token.options.address, web3.utils.toWei(dividendAmountBN), checkpointId, excluded[0], web3.utils.toHex(dividendName)); + } } else { - let excluded = getExcludedFromDataFile(); - createDividendAction = currentDividendsModule.methods.createDividendWithCheckpointAndExclusions(maturityTime, expiryTime, checkpointId, excluded, web3.utils.toHex(name)); + if (useDefaultExcluded) { + createDividendAction = currentDividendsModule.methods.createDividend(maturityTime, expiryTime, token.options.address, web3.utils.toWei(dividendAmountBN), web3.utils.toHex(dividendName)); + } else { + let excluded = getExcludedFromDataFile(); + createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, token.options.address, web3.utils.toWei(dividendAmountBN), excluded[0], web3.utils.toHex(dividendName)); + } } + let receipt = await common.sendTransaction(createDividendAction); + let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'ERC20DividendDeposited'); + console.log(chalk.green(`Dividend ${event._dividendIndex} deposited`)); } else { - if (useDefaultExcluded) { - createDividendAction = currentDividendsModule.methods.createDividend(maturityTime, expiryTime, web3.utils.toHex(name)); + if (checkpointId > 0) { + if (useDefaultExcluded) { + createDividendAction = currentDividendsModule.methods.createDividendWithCheckpoint(maturityTime, expiryTime, checkpointId, web3.utils.toHex(dividendName)); + } else { + let excluded = getExcludedFromDataFile(); + createDividendAction = currentDividendsModule.methods.createDividendWithCheckpointAndExclusions(maturityTime, expiryTime, checkpointId, excluded, web3.utils.toHex(dividendName)); + } } else { - let excluded = getExcludedFromDataFile(); - createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, excluded, web3.utils.toHex(name)); + if (useDefaultExcluded) { + createDividendAction = currentDividendsModule.methods.createDividend(maturityTime, expiryTime, web3.utils.toHex(dividendName)); + } else { + let excluded = getExcludedFromDataFile(); + createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, excluded, web3.utils.toHex(dividendName)); + } } + let receipt = await common.sendTransaction(createDividendAction, { value: web3.utils.toWei(dividendAmountBN) }); + let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'EtherDividendDeposited'); + console.log(` +Dividend ${ event._dividendIndex} deposited` + ); } - let receipt = await common.sendTransaction(createDividendAction, { value: web3.utils.toWei(dividend) }); - let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'EtherDividendDeposited'); - console.log(` - Dividend ${event._dividendIndex} deposited` - ); } } -async function pushDividends(dividend, account) { - let accs = account.split(','); - let pushDividendPaymentToAddressesAction = currentDividendsModule.methods.pushDividendPaymentToAddresses(dividend.index, accs); - let receipt = await common.sendTransaction(pushDividendPaymentToAddressesAction); - let successEventName; - if (dividendsType == 'POLY') { - successEventName = 'ERC20DividendClaimed'; - } else if (dividendsType == 'ETH') { - successEventName = 'EtherDividendClaimed'; - let failedEventName = 'EtherDividendClaimFailed'; - let failedEvents = common.getMultipleEventsFromLogs(currentDividendsModule._jsonInterface, receipt.logs, failedEventName); - for (const event of failedEvents) { - console.log(` - Failed to claim ${web3.utils.fromWei(event._amount)} ${dividendsType} - to account ${event._payee}` - ); - } +function showInvestors(investorsArray, claimedArray, excludedArray) { + let dataTable = [['Investor', 'Has claimed', 'Is excluded']]; + for (let i = 0; i < investorsArray.length; i++) { + dataTable.push([ + investorsArray[i], + claimedArray[i] ? 'YES' : 'NO', + excludedArray[i] ? 'YES' : 'NO' + ]); + } + console.log(); + console.log(table(dataTable)); +} + +function showReport(_name, _tokenSymbol, _amount, _witthheld, _claimed, _investorArray, _claimedArray, _excludedArray, _withheldArray, _amountArray) { + let title = `${_name.toUpperCase()} DIVIDEND REPORT`; + let dataTable = + [[ + 'Investor', + 'Amount sent', + 'Taxes withheld (%)', + `Taxes withheld(${_tokenSymbol})`, + 'Amount received', + 'Withdrawn' + ]]; + for (let i = 0; i < _investorArray.length; i++) { + let investor = _investorArray[i]; + let excluded = _excludedArray[i]; + let amount = !excluded ? web3.utils.fromWei(_amountArray[i]) : 0; + let withheld = !excluded ? web3.utils.fromWei(_withheldArray[i]) : 'NA'; + let withheldPercentage = !excluded ? web3.utils.toBN(_withheldArray[i]).div(web3.utils.toBN(_amountArray[i])).muln(100) : 'NA'; + let received = !excluded ? web3.utils.fromWei(web3.utils.toBN(_amountArray[i]).sub(web3.utils.toBN(_withheldArray[i]))) : 0; + let withdrawn = _claimedArray[i] ? 'YES' : 'NO'; + dataTable.push([ + investor, + amount, + withheldPercentage, + withheld, + received, + withdrawn + ]); } + console.log(chalk.yellow(`-----------------------------------------------------------------------------------------------------------------------------------------------------------`)); + console.log(title.padStart((50 - title.length) / 2, '*').padEnd((50 - title.length) / 2, '*')); + console.log(); + console.log(`- Total amount of dividends sent: ${web3.utils.fromWei(_amount)} ${_tokenSymbol} `); + console.log(`- Total amount of taxes withheld: ${web3.utils.fromWei(_witthheld)} ${_tokenSymbol} `); + console.log(`- Total amount of dividends distributed: ${web3.utils.fromWei(_claimed)} ${_tokenSymbol} `); + console.log(`- Total amount of investors: ${_investorArray.length} `); + console.log(); + console.log(table(dataTable)); + console.log(chalk.yellow(`-----------------------------------------------------------------------------------------------------------------------------------------------------------`)); + console.log(); +} - let successEvents = common.getMultipleEventsFromLogs(currentDividendsModule._jsonInterface, receipt.logs, successEventName); - for (const event of successEvents) { - console.log(` - Claimed ${web3.utils.fromWei(event._amount)} ${dividendsType} - to account ${event._payee} - ${web3.utils.fromWei(event._withheld)} ${dividendsType} of tax withheld` - ); +async function pushDividends(dividendIndex, checkpointId) { + let accounts = readlineSync.question('Enter addresses to push dividends to (ex- add1,add2,add3,...) or leave empty to push to all addresses: ', { + limit: function (input) { + return input === '' || (input.split(',').every(a => web3.utils.isAddress(a))); + }, + limitMessage: `All addresses must be valid` + }).split(','); + if (accounts[0] !== '') { + let action = currentDividendsModule.methods.pushDividendPaymentToAddresses(dividendIndex, accounts); + let receipt = await common.sendTransaction(action); + logPushResults(receipt); + } else { + let investorsAtCheckpoint = await securityToken.methods.getInvestorsAt(checkpointId).call(); + console.log(`There are ${investorsAtCheckpoint.length} investors at checkpoint ${checkpointId} `); + let batchSize = readlineSync.questionInt(`How many investors per transaction do you want to push to ? `); + for (let i = 0; i < investorsAtCheckpoint.length; i += batchSize) { + let action = currentDividendsModule.methods.pushDividendPayment(dividendIndex, i, batchSize); + let receipt = await common.sendTransaction(action); + logPushResults(receipt); + } } } -async function reclaimedDividend(dividend) { - let reclaimDividendAction = currentDividendsModule.methods.reclaimDividend(dividend.index); - let receipt = await common.sendTransaction(reclaimDividendAction); - let eventName; - if (dividendsType == 'POLY') { - eventName = 'ERC20DividendReclaimed'; - } else if (dividendsType == 'ETH') { - eventName = 'EtherDividendReclaimed'; +async function exploreAccount(dividendIndex, dividendTokenAddress, dividendTokenSymbol) { + let account = readlineSync.question('Enter address to explore: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + }); + let isExcluded = await currentDividendsModule.methods.isExcluded(account, dividendIndex).call(); + let hasClaimed = await currentDividendsModule.methods.isClaimed(account, dividendIndex).call(); + let dividendAmounts = await currentDividendsModule.methods.calculateDividend(dividendIndex, account).call(); + let dividendBalance = dividendAmounts[0]; + let dividendTax = dividendAmounts[1]; + let dividendTokenBalance = await getBalance(account, dividendTokenAddress); + let securityTokenBalance = await getBalance(account, securityToken.options.address); + + console.log(); + console.log(`Security token balance: ${web3.utils.fromWei(securityTokenBalance)} ${tokenSymbol} `); + console.log(`Dividend token balance: ${web3.utils.fromWei(dividendTokenBalance)} ${dividendTokenSymbol} `); + console.log(`Is excluded: ${isExcluded ? 'YES' : 'NO'} `); + if (!isExcluded) { + console.log(`Has claimed: ${hasClaimed ? 'YES' : 'NO'} `); + if (!hasClaimed) { + console.log(`Dividends available: ${web3.utils.fromWei(dividendBalance)} ${dividendTokenSymbol} `); + console.log(`Tax withheld: ${web3.utils.fromWei(dividendTax)} ${dividendTokenSymbol} `); + } } + console.log(); +} + +async function withdrawWithholding(dividendIndex, dividendTokenSymbol) { + let action = currentDividendsModule.methods.withdrawWithholding(dividendIndex); + let receipt = await common.sendTransaction(action); + let eventName = dividendsType === 'ERC20' ? 'ERC20DividendWithholdingWithdrawn' : 'EtherDividendWithholdingWithdrawn'; + let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, eventName); + console.log(chalk.green(`Successfully withdrew ${web3.utils.fromWei(event._withheldAmount)} ${dividendTokenSymbol} from dividend ${event._dividendIndex} tax withholding.`)); +} + +async function reclaimedDividend(dividendIndex, dividendTokenSymbol) { + let action = currentDividendsModule.methods.reclaimDividend(dividendIndex); + let receipt = await common.sendTransaction(action); + let eventName = dividendsType === 'ERC20' ? 'ERC20DividendReclaimed' : 'EtherDividendReclaimed'; let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, eventName); console.log(` - Reclaimed Amount ${web3.utils.fromWei(event._claimedAmount)} ${dividendsType} - to account ${event._claimer}` +Reclaimed amount ${ web3.utils.fromWei(event._claimedAmount)} ${dividendTokenSymbol} +to account ${ event._claimer} ` ); } -async function whitelistAddress(address) { - let now = Math.floor(Date.now() / 1000); - let modifyWhitelistAction = generalTransferManager.methods.modifyWhitelist(address, now, now, now + 31536000, true); - await common.sendTransaction(modifyWhitelistAction); - console.log(chalk.green(`\nWhitelisting successful for ${address}.`)); +async function addDividendsModule() { + let availableModules = await moduleRegistry.methods.getModulesByTypeAndToken(gbl.constants.MODULES_TYPES.DIVIDENDS, securityToken.options.address).call(); + let options = await Promise.all(availableModules.map(async function (m) { + let moduleFactoryABI = abis.moduleFactory(); + let moduleFactory = new web3.eth.Contract(moduleFactoryABI, m); + return web3.utils.hexToUtf8(await moduleFactory.methods.name().call()); + })); + + let index = readlineSync.keyInSelect(options, 'Which dividends module do you want to add? ', { cancel: 'Return' }); + if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module ? `)) { + let bytes = web3.utils.fromAscii('', 16); + + let selectedDividendFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.DIVIDENDS, options[index]); + let addModuleAction = securityToken.methods.addModule(selectedDividendFactoryAddress, bytes, 0, 0); + let receipt = await common.sendTransaction(addModuleAction); + let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); + console.log(chalk.green(`Module deployed at address: ${event._module} `)); + } } // Helper functions -async function getBalance(address) { - let balance; - if (dividendsType == 'POLY') { - balance = (await polyToken.methods.balanceOf(address).call()).toString(); - } else if (dividendsType == 'ETH') { - balance = (await web3.eth.getBalance(address)).toString(); - } - - return balance; -} -async function checkBalance(_dividend) { - let issuerBalance = await getBalance(Issuer.address); - if (parseInt(web3.utils.fromWei(issuerBalance)) < parseInt(_dividend)) { - console.log(chalk.red(` - You have ${web3.utils.fromWei(issuerBalance)} ${dividendsType} need ${(parseInt(_dividend) - parseInt(web3.utils.fromWei(issuerBalance)))} more ${dividendsType} - `)); - process.exit(0); +async function getBalance(address, tokenAddress) { + if (tokenAddress !== gbl.constants.ADDRESS_ZERO) { + let token = new web3.eth.Contract(abis.erc20(), tokenAddress); + return await token.methods.balanceOf(address).call(); + } else { + return await web3.eth.getBalance(address); } } -async function isDividendsModuleAttached() { - let dividendsModuleName; - if (dividendsType == 'POLY') { - dividendsModuleName = 'ERC20DividendCheckpoint'; - } else if (dividendsType == 'ETH') { - dividendsModuleName = 'EtherDividendCheckpoint'; +function logPushResults(receipt) { + let successEventName; + if (dividendsType == 'ERC20') { + successEventName = 'ERC20DividendClaimed'; } - - let result = await securityToken.methods.getModulesByName(web3.utils.toHex(dividendsModuleName)).call(); - if (result.length > 0) { - let dividendsModuleAddress = result[0]; - let dividendsModuleABI; - if (dividendsType == 'POLY') { - dividendsModuleABI = abis.erc20DividendCheckpoint(); - } else if (dividendsType == 'ETH') { - dividendsModuleABI = abis.etherDividendCheckpoint(); + else if (dividendsType == 'ETH') { + successEventName = 'EtherDividendClaimed'; + let failedEventName = 'EtherDividendClaimFailed'; + let failedEvents = common.getMultipleEventsFromLogs(currentDividendsModule._jsonInterface, receipt.logs, failedEventName); + for (const event of failedEvents) { + console.log(chalk.red(`Failed to claim ${web3.utils.fromWei(event._amount)} ${dividendsType} to account ${event._payee} `, '\n')); } - currentDividendsModule = new web3.eth.Contract(dividendsModuleABI, dividendsModuleAddress); - currentDividendsModule.setProvider(web3.currentProvider); } - - return (typeof currentDividendsModule !== 'undefined'); -} - -async function addDividendsModule() { - if (!(await isDividendsModuleAttached())) { - let dividendsFactoryName; - let dividendsModuleABI; - if (dividendsType == 'POLY') { - dividendsFactoryName = 'ERC20DividendCheckpoint'; - dividendsModuleABI = abis.erc20DividendCheckpoint(); - } else if (dividendsType == 'ETH') { - dividendsFactoryName = 'EtherDividendCheckpoint'; - dividendsModuleABI = abis.etherDividendCheckpoint(); - } - - let dividendsFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.DIVIDENDS, dividendsFactoryName); - let addModuleAction = securityToken.methods.addModule(dividendsFactoryAddress, web3.utils.fromAscii('', 16), 0, 0); - let receipt = await common.sendTransaction(addModuleAction); - let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); - console.log(`Module deployed at address: ${event._module}`); - currentDividendsModule = new web3.eth.Contract(dividendsModuleABI, event._module); - currentDividendsModule.setProvider(web3.currentProvider); + let successEvents = common.getMultipleEventsFromLogs(currentDividendsModule._jsonInterface, receipt.logs, successEventName); + for (const event of successEvents) { + console.log(chalk.green(` Claimed ${web3.utils.fromWei(event._amount)} ${dividendsType} +to account ${ event._payee} +${ web3.utils.fromWei(event._withheld)} ${dividendsType} of tax withheld`, '\n')); } } async function selectCheckpoint(includeCreate) { - let options = []; - let fix = 1; //Checkpoint 0 is not included, so I need to add 1 to fit indexes for checkpoints and options - let checkpoints = (await getCheckpoints()).map(function (c) { return c.timestamp }); - if (includeCreate) { - options.push('Create new checkpoint'); - fix = 0; //If this option is added, fix isn't needed. - } - options = options.concat(checkpoints); + if (await securityToken.methods.currentCheckpointId().call() > 0) { + let options = []; + let fix = 1; //Checkpoint 0 is not included, so I need to add 1 to fit indexes for checkpoints and options + let checkpoints = (await getCheckpoints()).map(function (c) { return c.timestamp }); + if (includeCreate) { + options.push('Create new checkpoint'); + fix = 0; //If this option is added, fix isn't needed. + } + options = options.concat(checkpoints); - return readlineSync.keyInSelect(options, 'Select a checkpoint:', { cancel: false }) + fix; + return readlineSync.keyInSelect(options, 'Select a checkpoint:', { cancel: false }) + fix; + } else { + return 0; + } } async function getCheckpoints() { @@ -498,91 +612,217 @@ async function getCheckpoints() { return result.sort((a, b) => a.id - b.id); } -async function selectDividend(filter) { - let result = null; - let dividends = await getDividends(); +function isValidDividend(dividend) { + let now = Math.floor(Date.now() / 1000); + return now > dividend.maturity; +} +function isExpiredDividend(dividend) { let now = Math.floor(Date.now() / 1000); - if (typeof filter !== 'undefined') { - if (typeof filter.valid !== 'undefined') { - dividends = dividends.filter(d => filter.valid == (now > d.maturity)); - } - if (typeof filter.expired !== 'undefined') { - dividends = dividends.filter(d => filter.expired == (d.expiry < now)); - } - if (typeof filter.reclaimed !== 'undefined') { - dividends = dividends.filter(d => filter.reclaimed == d.reclaimed); - } - if (typeof filter.withRemainingWithheld !== 'undefined') { - dividends = dividends.filter(d => new web3.utils.BN(d.dividendWithheld).sub(new web3.utils.BN(d.dividendWithheldReclaimed)) > 0); - } - if (typeof filter.withRemaining !== 'undefined') { - dividends = dividends.filter(d => new web3.utils.BN(d.amount).sub(new web3.utils.BN(d.claimedAmount)) > 0); - } - } + return now > dividend.expiry; +} - if (dividends.length > 0) { - let options = dividends.map(function (d) { - return `${web3.utils.toAscii(d.name)} - Created: ${moment.unix(d.created).format('MMMM Do YYYY, HH:mm:ss')} - Maturity: ${moment.unix(d.maturity).format('MMMM Do YYYY, HH:mm:ss')} - Expiry: ${moment.unix(d.expiry).format('MMMM Do YYYY, HH:mm:ss')} - At checkpoint: ${d.checkpointId} - Amount: ${web3.utils.fromWei(d.amount)} ${dividendsType} - Claimed Amount: ${web3.utils.fromWei(d.claimedAmount)} ${dividendsType} - Withheld: ${web3.utils.fromWei(d.dividendWithheld)} ${dividendsType} - Withheld claimed: ${web3.utils.fromWei(d.dividendWithheldReclaimed)} ${dividendsType}` - }); +function hasRemaining(dividend) { + return Number(new web3.utils.BN(dividend.amount).sub(new web3.utils.BN(dividend.claimedAmount))).toFixed(10) > 0; +} - let index = readlineSync.keyInSelect(options, 'Select a dividend:'); - if (index != -1) { - result = dividends[index]; - } - } else { - console.log(chalk.red(`No dividends were found meeting the requirements`)) - console.log(chalk.red(`Requirements: Valid: ${filter.valid} - Expired: ${filter.expired} - Reclaimed: ${filter.reclaimed} - WithRemainingWithheld: ${filter.withRemainingWithheld} - WithRemaining: ${filter.withRemaining}\n`)) +function hasRemainingWithheld(dividend) { + return Number(new web3.utils.BN(dividend.dividendWithheld).sub(new web3.utils.BN(dividend.dividendWithheldReclaimed))).toFixed(10) > 0; +} + +async function selectDividend(dividends) { + let result = null; + let options = dividends.map(function (d) { + return `${d.name} + Amount: ${ web3.utils.fromWei(d.amount)} ${dividendsType} + Status: ${ isExpiredDividend(d) ? 'Expired' : hasRemaining(d) ? 'In progress' : 'Completed'} + Token: ${ d.tokenSymbol} + Created: ${ moment.unix(d.created).format('MMMM Do YYYY, HH:mm:ss')} + Expiry: ${ moment.unix(d.expiry).format('MMMM Do YYYY, HH:mm:ss')} ` + }); + + let index = readlineSync.keyInSelect(options, 'Select a dividend:', { cancel: 'RETURN' }); + if (index != -1) { + result = dividends[index]; } return result; } async function getDividends() { - let result = []; + function DividendData(_index, _created, _maturity, _expiry, _amount, _claimedAmount, _name, _tokenSymbol) { + this.index = _index; + this.created = _created; + this.maturity = _maturity; + this.expiry = _expiry; + this.amount = _amount; + this.claimedAmount = _claimedAmount; + this.name = _name; + this.tokenSymbol = _tokenSymbol; + } - let currentCheckpoint = await securityToken.methods.currentCheckpointId().call(); - for (let index = 1; index <= currentCheckpoint; index++) { - let dividendIndexes = await currentDividendsModule.methods.getDividendIndex(index).call(); - for (const i of dividendIndexes) { - let dividend = await currentDividendsModule.methods.dividends(i).call(); - dividend.index = i; - result.push(dividend); + let dividends = []; + let dividendsData = await currentDividendsModule.methods.getDividendsData().call(); + let createdArray = dividendsData.createds; + let maturityArray = dividendsData.maturitys; + let expiryArray = dividendsData.expirys; + let amountArray = dividendsData.amounts; + let claimedAmountArray = dividendsData.claimedAmounts; + let nameArray = dividendsData.names; + for (let i = 0; i < nameArray.length; i++) { + let tokenSymbol = 'ETH'; + if (dividendsType === 'ERC20') { + let tokenAddress = await currentDividendsModule.methods.dividendTokens(i).call(); + let erc20token = new web3.eth.Contract(abis.erc20(), tokenAddress); + tokenSymbol = await erc20token.methods.symbol().call(); } + dividends.push( + new DividendData( + i, + createdArray[i], + maturityArray[i], + expiryArray[i], + amountArray[i], + claimedAmountArray[i], + web3.utils.hexToUtf8(nameArray[i]), + tokenSymbol + ) + ); } - return result; + return dividends; } function getExcludedFromDataFile() { - let excludedFromFile = require('fs').readFileSync(`${__dirname}/../data/dividendsExclusions_data.csv`).toString().split("\n"); - let excluded = excludedFromFile.filter(function (address) { - return web3.utils.isAddress(address); - }); - return excluded; + let parsedData = csvParse(EXCLUSIONS_DATA_CSV); + let validData = parsedData.filter(row => web3.utils.isAddress(row[0])); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, validData.length); + let [data] = common.transposeBatches(batches); + + return data; } function showExcluded(excluded) { - if (excluded.length > 0) { - console.log('Current default excluded addresses:') - excluded.map(function (address) { console.log(' ', address) }); + console.log('Current default excluded addresses:') + excluded.map(address => console.log(address)); + console.log(); +} + +async function getAllModulesByType(type) { + function ModuleInfo(_moduleType, _name, _address, _factoryAddress, _archived, _paused) { + this.name = _name; + this.type = _moduleType; + this.address = _address; + this.factoryAddress = _factoryAddress; + this.archived = _archived; + this.paused = _paused; + } + + let modules = []; + + let allModules = await securityToken.methods.getModulesByType(type).call(); + + for (let i = 0; i < allModules.length; i++) { + let details = await securityToken.methods.getModule(allModules[i]).call(); + let nameTemp = web3.utils.hexToUtf8(details[0]); + let pausedTemp = null; + if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER) { + let abiTemp = JSON.parse(require('fs').readFileSync(`${__dirname} /../../ build / contracts / ${nameTemp}.json`).toString()).abi; + let contractTemp = new web3.eth.Contract(abiTemp, details[1]); + pausedTemp = await contractTemp.methods.paused().call(); + } + modules.push(new ModuleInfo(type, nameTemp, details[1], details[2], details[3], pausedTemp)); + } + + return modules; +} + +async function initialize(_tokenSymbol) { + welcome(); + await setup(); + if (typeof _tokenSymbol === 'undefined') { + tokenSymbol = await selectToken(); } else { - console.log('There are not default excluded addresses.') + tokenSymbol = _tokenSymbol; } - console.log(); + let securityTokenAddress = await securityTokenRegistry.methods.getSecurityTokenAddress(tokenSymbol).call(); + if (securityTokenAddress == '0x0000000000000000000000000000000000000000') { + console.log(chalk.red(`Selected Security Token ${tokenSymbol} does not exist.`)); + process.exit(0); + } + let securityTokenABI = abis.securityToken(); + securityToken = new web3.eth.Contract(securityTokenABI, securityTokenAddress); + securityToken.setProvider(web3.currentProvider); +} + +function welcome() { + common.logAsciiBull(); + console.log("**********************************************"); + console.log("Welcome to the Command-Line Dividends Manager."); + console.log("**********************************************"); + console.log("Issuer Account: " + Issuer.address + "\n"); +} + +async function setup() { + try { + let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); + let securityTokenRegistryABI = abis.securityTokenRegistry(); + securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); + securityTokenRegistry.setProvider(web3.currentProvider); + + let polyTokenAddress = await contracts.polyToken(); + let polyTokenABI = abis.polyToken(); + polyToken = new web3.eth.Contract(polyTokenABI, polyTokenAddress); + polyToken.setProvider(web3.currentProvider); + + let moduleRegistryAddress = await contracts.moduleRegistry(); + let moduleRegistryABI = abis.moduleRegistry(); + moduleRegistry = new web3.eth.Contract(moduleRegistryABI, moduleRegistryAddress); + moduleRegistry.setProvider(web3.currentProvider); + } catch (err) { + console.log(err) + console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); + process.exit(0); + } +} + +async function selectToken() { + let result = null; + + let userTokens = await securityTokenRegistry.methods.getTokensByOwner(Issuer.address).call(); + let tokenDataArray = await Promise.all(userTokens.map(async function (t) { + let tokenData = await securityTokenRegistry.methods.getSecurityTokenData(t).call(); + return { symbol: tokenData[0], address: t }; + })); + let options = tokenDataArray.map(function (t) { + return `${t.symbol} - Deployed at ${t.address} `; + }); + options.push('Enter token symbol manually'); + + let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); + let selected = index != -1 ? options[index] : 'Exit'; + switch (selected) { + case 'Enter token symbol manually': + result = readlineSync.question('Enter the token symbol: '); + break; + case 'Exit': + process.exit(); + break; + default: + result = tokenDataArray[index].symbol; + break; + } + + return result; } module.exports = { - executeApp: async function (type) { - return executeApp(type); + executeApp: async function (_tokenSymbol) { + await initialize(_tokenSymbol); + return executeApp(); } } diff --git a/CLI/data/Checkpoint/dividendsExclusions_data.csv b/CLI/data/Checkpoint/exclusions_data.csv similarity index 100% rename from CLI/data/Checkpoint/dividendsExclusions_data.csv rename to CLI/data/Checkpoint/exclusions_data.csv diff --git a/CLI/data/Checkpoint/tax_withholding_data.csv b/CLI/data/Checkpoint/tax_withholding_data.csv new file mode 100644 index 000000000..10c2928c8 --- /dev/null +++ b/CLI/data/Checkpoint/tax_withholding_data.csv @@ -0,0 +1,10 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,0.5 +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,1 +0xac297053173b02b02a737d47f7b4a718e5b170ef,2 +0x49fc0b78238dab644698a90fa351b4c749e123d2,10 +0x10223927009b8add0960359dd90d1449415b7ca9,15 +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,50 +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,0 +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,23 +0x56be93088141b16ebaa9416122fd1d928da25ecf,45 +0xbb276b6f68f0a41d54b7e0a608fe8eb1ebdee7b0,67 \ No newline at end of file From 86c2a28f04ac3908c8c9b931db827780883095cf Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 21 Dec 2018 10:28:03 +0530 Subject: [PATCH 454/582] Updated test script --- scripts/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test.sh b/scripts/test.sh index 9f595d0ba..2a0d7623b 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -88,11 +88,11 @@ else fi fi -if [ "$COVERAGE" = true ]; then +if [ "$COVERAGE" = true ] || [ [ "TRAVIS_PULL_REQUEST" = true ] && ![ "NOT_FORK" = true ] ]; then curl -o node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js node_modules/.bin/solidity-coverage if [ "$CIRCLECI" = true ]; then - cat coverage/lcov.info | node_modules/.bin/coveralls + cat coverage/lcov.info | node_modules/.bin/coveralls || echo 'Failed to report coverage to Coveralls' fi else if [ "$CIRCLECI" = true ]; then # using mocha junit reporter for parallelism in CircleCI From 4d7cc1a35561713033cf868e51b63e9faf6f21b9 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 21 Dec 2018 10:40:53 +0530 Subject: [PATCH 455/582] Script updated --- scripts/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test.sh b/scripts/test.sh index 2a0d7623b..e1af3091f 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -88,7 +88,7 @@ else fi fi -if [ "$COVERAGE" = true ] || [ [ "TRAVIS_PULL_REQUEST" = true ] && ![ "NOT_FORK" = true ] ]; then +if [ "$COVERAGE" = true ] || [ "TRAVIS_PULL_REQUEST" = true ] && [ "NOT_FORK" != true ]; then curl -o node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js node_modules/.bin/solidity-coverage if [ "$CIRCLECI" = true ]; then From 4e1e37b3fb985e03c1b6302a7d320aacbf86dc32 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 21 Dec 2018 12:33:10 +0700 Subject: [PATCH 456/582] fixed bug with the initial test --- ...zer_volumn_restriction_transfer_manager.js | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index b606ad1bf..645856e52 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -211,7 +211,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); // Mint some tokens and transferred to whitelisted addresses - await I_SecurityToken.mint(account_investor1, web3.utils.toWei("40", "ether"), {from: token_owner}); + await I_SecurityToken.mint(account_investor1, web3.utils.toWei("100", "ether"), {from: token_owner}); await I_SecurityToken.mint(account_investor2, web3.utils.toWei("30", "ether"), {from: token_owner}); await I_SecurityToken.mint(account_investor3, web3.utils.toWei("30", "ether"), {from: token_owner}); @@ -224,20 +224,20 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should work with multiple transaction within 1 day with Individual and daily Restrictions", async() => { // let snapId = await takeSnapshot(); - var testRepeat = 2; + var testRepeat = 5; for (var i = 0; i < testRepeat; i++) { console.log("fuzzer number " + i); - var individualRestrictTotalAmount = 7; - var dailyRestrictionAmount = 6; - var rollingPeriod = 2; + var individualRestrictTotalAmount = Math.floor(Math.random() * 10); + var dailyRestrictionAmount = Math.floor(Math.random() * 10); + var rollingPeriod = 2; var sumOfLastPeriod = 0; + console.log("a"); // 1 - add individual restriction with a random number - let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei(individualRestrictTotalAmount.toString()), @@ -250,7 +250,7 @@ contract('VolumeRestrictionTransferManager', accounts => { } ); - + console.log("b"); tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor1, web3.utils.toWei(dailyRestrictionAmount.toString()), @@ -262,8 +262,8 @@ contract('VolumeRestrictionTransferManager', accounts => { } ); - - var txNumber = 3; // define fuzz test amount for tx within 24 hrs + console.log("c"); + var txNumber = 10; //define fuzz test amount for tx within 24 hrs for (var j=0; j { } console.log("2"); } + + // await revertToSnapshot(snapId); + await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor1, {from: token_owner}); + await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor1, {from: token_owner}); } - // await revertToSnapshot(snapId); + }); }); From 99984f1f050290744212179f88a18414a954223c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 21 Dec 2018 11:22:54 +0530 Subject: [PATCH 457/582] Update test.sh --- scripts/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test.sh b/scripts/test.sh index e1af3091f..b6c846a03 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -88,7 +88,7 @@ else fi fi -if [ "$COVERAGE" = true ] || [ "TRAVIS_PULL_REQUEST" = true ] && [ "NOT_FORK" != true ]; then +if [ "$COVERAGE" = true ] || [ "$TRAVIS_PULL_REQUEST" = true ] && [ "$NOT_FORK" != true ]; then curl -o node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js node_modules/.bin/solidity-coverage if [ "$CIRCLECI" = true ]; then @@ -109,4 +109,4 @@ else else node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js` fi -fi \ No newline at end of file +fi From 61086f7a3dcb7b1944acc00f8c4da104120e33a1 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 21 Dec 2018 12:09:43 +0530 Subject: [PATCH 458/582] Script updated --- scripts/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test.sh b/scripts/test.sh index b6c846a03..0fbdbe6b1 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -88,7 +88,7 @@ else fi fi -if [ "$COVERAGE" = true ] || [ "$TRAVIS_PULL_REQUEST" = true ] && [ "$NOT_FORK" != true ]; then +if [ "$COVERAGE" = true ] || [ "$TRAVIS_PULL_REQUEST" > 0 ] && [ "$NOT_FORK" != true ]; then curl -o node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js node_modules/.bin/solidity-coverage if [ "$CIRCLECI" = true ]; then From c84edf487ff9d5f6448b5063d09ffac640786977 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 21 Dec 2018 13:07:37 +0530 Subject: [PATCH 459/582] coverage block gas limit increased --- scripts/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test.sh b/scripts/test.sh index 0fbdbe6b1..bf86ef857 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -56,7 +56,7 @@ start_testrpc() { --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501209,1000000000000000000000000" ) - if [ "$COVERAGE" = true ]; then + if [ "$COVERAGE" = true ] || [ "$TRAVIS_PULL_REQUEST" > 0 ] && [ "$NOT_FORK" != true ]; then node_modules/.bin/testrpc-sc --gasLimit 0xfffffffffff --port "$testrpc_port" "${accounts[@]}" > /dev/null & else node_modules/.bin/ganache-cli --gasLimit 8000000 "${accounts[@]}" > /dev/null & From 42eb3246afa526482a68ff0e86d15e01c5785b15 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 21 Dec 2018 09:49:20 +0200 Subject: [PATCH 460/582] ganache-cli 6.2.5 --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index fdf975a9d..d518d6f8e 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "eslint-plugin-standard": "^4.0.0", "ethereum-bridge": "^0.6.1", "ethereumjs-abi": "^0.6.5", - "ganache-cli": "^6.1.8", + "ganache-cli": "^6.2.5", "mocha-junit-reporter": "^1.18.0", "prettier": "^1.15.3", "request": "^2.88.0", diff --git a/yarn.lock b/yarn.lock index d18ea0c04..a8a3aa60d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -253,7 +253,7 @@ async-eventemitter@^0.2.2: dependencies: async "^2.4.0" -"async-eventemitter@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c": +async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c: version "0.2.3" resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c" dependencies: @@ -1024,13 +1024,13 @@ bignumber.js@^7.2.1: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== -"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": +"bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" - resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9" -"bignumber.js@git+https://github.com/debris/bignumber.js.git#master": +"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": version "2.0.7" - resolved "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9" + resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" "bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git": version "2.0.7" @@ -3230,10 +3230,10 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -ganache-cli@^6.1.8: - version "6.2.4" - resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.2.4.tgz#0ec3d5d993a85c9f252fb632105ab7ffe7668638" - integrity sha512-Yxi+G+Qktr8s1BML0BEC2oIseMP/svWXmojajrdHNG8k84cyihvemuW4DLM7XA/ZOqi88mKt3n/mWTi0RbYpOQ== +ganache-cli@^6.2.5: + version "6.2.5" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.2.5.tgz#efda5115fa3a0c62d7f5729fdd78da70ca55b1ad" + integrity sha512-E4SP8QNeuc2N/ojFoCK+08OYHX8yrtGeFtipZmJPPTQ6U8Hmq3JcbXZDxQfChPQUY5mtbRSwptJa4EtiQyJjAQ== dependencies: bn.js "4.11.8" source-map-support "0.5.9" From c379132ef6bea8aa375b47f567cbe61696509f3c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 21 Dec 2018 14:22:07 +0530 Subject: [PATCH 461/582] Travis submit coverage --- scripts/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test.sh b/scripts/test.sh index bf86ef857..9a3ab5838 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -91,7 +91,7 @@ fi if [ "$COVERAGE" = true ] || [ "$TRAVIS_PULL_REQUEST" > 0 ] && [ "$NOT_FORK" != true ]; then curl -o node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js node_modules/.bin/solidity-coverage - if [ "$CIRCLECI" = true ]; then + if [ "$CIRCLECI" = true ] || [ "$TRAVIS_PULL_REQUEST" > 0 ] && [ "$NOT_FORK" != true ]; then cat coverage/lcov.info | node_modules/.bin/coveralls || echo 'Failed to report coverage to Coveralls' fi else From 2de1bb869518aefc5ad5ae1d9b6354cada092320 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 21 Dec 2018 16:07:45 +0700 Subject: [PATCH 462/582] added scenario 2 and 3 --- ...zer_volumn_restriction_transfer_manager.js | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index 645856e52..61ea5c32a 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -308,6 +308,248 @@ contract('VolumeRestrictionTransferManager', accounts => { } }); + + + it("Should work with fuzz test for individual restriction and general restriction", async() => { + // let snapId = await takeSnapshot(); + + var testRepeat = 5; + + for (var i = 0; i < testRepeat; i++) { + + console.log("fuzzer number " + i); + + var individualRestrictTotalAmount = Math.floor(Math.random() * 10); + var defaultRestrictionAmount = Math.floor(Math.random() * 10); + var rollingPeriod = 2; + var sumOfLastPeriod = 0; + + console.log("a"); + + // 1 - add individual restriction with a random number + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei(individualRestrictTotalAmount.toString()), + latestTime() + duration.seconds(1), + rollingPeriod, + latestTime() + duration.days(3), + 0, + { + from: token_owner + } + ); + + console.log("b"); + tx = await I_VolumeRestrictionTM.addDefaultRestriction( + account_investor1, + latestTime() + duration.seconds(1), + rollingPeriod, + latestTime() + duration.days(4), + 0, + { + from: token_owner + } + ); + + console.log("c"); + var txNumber = 10; //define fuzz test amount for tx + + for (var j=0; j individualRestrictTotalAmount || accumulatedTxValue > defaultRestrictionAmount){ + + console.log("tx should fail"); + + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) + ); + + console.log("tx failed as expected due to over limit"); + + } else if (accumulatedTxValue <= individualRestrictTotalAmount ){ + + console.log("tx should succeed"); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); + + sumOfLastPeriod = sumOfLastPeriod + transactionAmount; + + console.log("tx succeeded"); + } + console.log("3"); + }; + + + // remove individual restriction and it should fall to default restriction + await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor1, {from: token_owner}); + console.log("individual restriction now removed --> fall back to default restriction"); + + for (var j=0; j defaultRestrictionAmount){ + + console.log("tx should fail"); + + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) + ); + + console.log("tx failed as expected due to over limit"); + + } else if ( accumulatedTxValue <= defaultRestrictionAmount ){ + + console.log("tx should succeed"); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); + + sumOfLastPeriod = sumOfLastPeriod + transactionAmount; + + console.log("tx succeeded"); + } + console.log("5"); + } + + + // await revertToSnapshot(snapId); + await I_VolumeRestrictionTM.removeDefaultRestriction(account_investor1, {from: token_owner}); + } + + }); + + + + it("Should work with fuzz test for randomly adding / removing individual daily restriction and perform multipel transactions", async() => { + + + var testRepeat = 5; + var txNumber = 10; + var dailyRestriction = false; + var startTime = 1; + var sumOfLastPeriod = 0; + var accumulatedTimeIncrease = 0; + var dailyLimitUsed = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + + for (var i = 0; i < testRepeat; i++) { + + //randomly add or removing existing daily restriction + var random_action = Math.random() >= 0.5; // true -> add false -> remove + + if ( dailyRestriction == false && random_action == true ){ + + console.log("1"); + + var dailyRestrictionAmount = Math.floor(Math.random() * 10); + + //add daily restriction + let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor1, + web3.utils.toWei(dailyRestrictionAmount.toString()), + latestTime() + duration.seconds(startTime), + latestTime() + duration.days(50), + 0, + { + from: token_owner + } + ); + + dailyRestriction = true; + + console.log("added daily restriction"); + + } else if ( dailyRestriction == true && random_action == false ) { + + console.log("2"); + + //remove daily restriction + await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor1, {from: token_owner}); + console.log("removed daily restriction"); + + dailyRestriction = false; + } + + + // perform multiple transactions + + for (var j=0; j dailyRestrictionAmount){ + + console.log("tx should fail"); + + await catchRevert( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) + ); + + console.log("tx failed as expected due to over limit"); + + } else if ( (todayLimitUsed + transactionAmount) <= dailyRestrictionAmount ){ + + console.log("tx should succeed"); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); + + dailyLimitUsed[dayNumber] = dailyLimitUsed[dayNumber] + transactionAmount; + + console.log("tx succeeded"); + } + console.log("5"); + } + + if ( dailyRestriction == true ) { + + //remove daily restriction + await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor1, {from: token_owner}); + console.log("removed daily restriction"); + } + + } + + + + }); + + + }); }); \ No newline at end of file From 40343b9fed447906ae935da57f47a57a950cd296 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 21 Dec 2018 16:34:27 +0700 Subject: [PATCH 463/582] fix input random number issue --- ...zer_volumn_restriction_transfer_manager.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index 61ea5c32a..def755227 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -231,7 +231,14 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log("fuzzer number " + i); var individualRestrictTotalAmount = Math.floor(Math.random() * 10); + if ( individualRestrictTotalAmount == 0 ) { + individualRestrictTotalAmount = 1; + } + var dailyRestrictionAmount = Math.floor(Math.random() * 10); + if ( dailyRestrictionAmount == 0 ) { + dailyRestrictionAmount = 1; + } var rollingPeriod = 2; var sumOfLastPeriod = 0; @@ -313,13 +320,16 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should work with fuzz test for individual restriction and general restriction", async() => { // let snapId = await takeSnapshot(); - var testRepeat = 5; + var testRepeat = 0; for (var i = 0; i < testRepeat; i++) { console.log("fuzzer number " + i); var individualRestrictTotalAmount = Math.floor(Math.random() * 10); + if ( individualRestrictTotalAmount == 0 ) { + individualRestrictTotalAmount = 1; + } var defaultRestrictionAmount = Math.floor(Math.random() * 10); var rollingPeriod = 2; var sumOfLastPeriod = 0; @@ -443,7 +453,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should work with fuzz test for randomly adding / removing individual daily restriction and perform multipel transactions", async() => { - var testRepeat = 5; + var testRepeat = 0; var txNumber = 10; var dailyRestriction = false; var startTime = 1; @@ -461,6 +471,9 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log("1"); var dailyRestrictionAmount = Math.floor(Math.random() * 10); + if ( dailyRestrictionAmount == 0) { + dailyRestrictionAmount = 1; + } //add daily restriction let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( @@ -535,7 +548,7 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log("5"); } - if ( dailyRestriction == true ) { + if ( dailyRestriction == true ) { //remove daily restriction await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor1, {from: token_owner}); From e5fab1f14b8e4ed799aede84463afd98fbf6c426 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Fri, 21 Dec 2018 10:01:35 +0000 Subject: [PATCH 464/582] Add more test cases --- .../modules/Checkpoint/DividendCheckpoint.sol | 9 ++++++++- test/e_erc20_dividends.js | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 929bf977c..4aa939c20 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -290,7 +290,14 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @return uint256[] investor balance * @return uint256[] amount to be claimed including withheld tax */ - function getDividendProgress(uint256 _dividendIndex) external view returns (address[] memory investors, bool[] memory resultClaimed, bool[] memory resultExcluded, uint256[] memory resultWithheld, uint256[] memory resultBalance, uint256[] memory resultAmount) { + function getDividendProgress(uint256 _dividendIndex) external view returns ( + address[] memory investors, + bool[] memory resultClaimed, + bool[] memory resultExcluded, + uint256[] memory resultWithheld, + uint256[] memory resultBalance, + uint256[] memory resultAmount) + { require(_dividendIndex < dividends.length, "Invalid dividend"); //Get list of Investors Dividend storage dividend = dividends[_dividendIndex]; diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 3ec86dadc..bc52e3886 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -719,7 +719,7 @@ contract("ERC20DividendCheckpoint", accounts => { dividendName, { from: token_owner } ); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 3"); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), 4, "Dividend should be created at checkpoint 4"); }); it("Should not create new dividend with duplicate exclusion", async () => { @@ -853,6 +853,22 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(info[3][1].toNumber(), web3.utils.toWei("0.2", "ether"), "withheld match"); assert.equal(info[3][2].toNumber(), web3.utils.toWei("0.2", "ether"), "withheld match"); assert.equal(info[3][3].toNumber(), 0, "withheld match"); + + console.log(info[4][0].toNumber()); + console.log(info[4][1].toNumber()); + console.log(info[4][2].toNumber()); + console.log(info[4][3].toNumber()); + + assert.equal(info[4][0].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor1, 4)).toNumber(), "balance match"); + assert.equal(info[4][1].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor2, 4)).toNumber(), "balance match"); + assert.equal(info[4][2].toNumber(), (await I_SecurityToken.balanceOfAt(account_temp, 4)).toNumber(), "balance match"); + assert.equal(info[4][3].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor3, 4)).toNumber(), "balance match"); + + assert.equal(info[5][0].toNumber(), 0, "excluded"); + assert.equal(info[5][1].toNumber(), web3.utils.toWei("2", "ether"), "claim match"); + assert.equal(info[5][2].toNumber(), web3.utils.toWei("1", "ether"), "claim match"); + assert.equal(info[5][3].toNumber(), web3.utils.toWei("7", "ether"), "claim match"); + let issuerBalance = new BigNumber(await I_PolyToken.balanceOf(token_owner)); await I_ERC20DividendCheckpoint.withdrawWithholding(3, { from: token_owner, gasPrice: 0 }); let issuerBalanceAfter = new BigNumber(await I_PolyToken.balanceOf(token_owner)); From 2ba0db0c83431134ba6d0c64da71f08f6a240458 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 21 Dec 2018 08:58:18 -0300 Subject: [PATCH 465/582] CLI Minor fixes --- CLI/commands/dividends_manager.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index f021d6e2c..f65074f88 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -338,12 +338,12 @@ async function createDividends() { token = new web3.eth.Contract(abis.erc20(), dividendToken); try { dividendSymbol = await token.methods.symbol().call(); - } catch { + } catch (err) { console.log(chalk.red(`${dividendToken} is not a valid ERC20 token address!!`)); } } while (dividendSymbol === 'ETH'); } - let dividendAmount = readlineSync.question(`How much ${dividendSymbol} would you like to distribute to token holders ? `); + let dividendAmount = readlineSync.question(`How much ${dividendSymbol} would you like to distribute to token holders? `); let dividendAmountBN = new web3.utils.BN(dividendAmount); let issuerBalance = new web3.utils.BN(web3.utils.fromWei(await getBalance(Issuer.address, dividendToken))); @@ -356,7 +356,7 @@ async function createDividends() { let defaultTime = now + gbl.constants.DURATION.minutes(10); let expiryTime = readlineSync.questionInt('Enter the dividend expiry time (Unix Epoch time)\n(10 minutes from now = ' + defaultTime + ' ): ', { defaultInput: defaultTime }); - let useDefaultExcluded = !readlineSync.keyInYNStrict(`Do you want to use data from 'dividends_exclusions_data.csv' for this dividend ? If not, default exclusions will apply.`); + let useDefaultExcluded = !readlineSync.keyInYNStrict(`Do you want to use data from 'dividends_exclusions_data.csv' for this dividend? If not, default exclusions will apply.`); let createDividendAction; if (dividendsType == 'ERC20') { @@ -425,7 +425,7 @@ function showReport(_name, _tokenSymbol, _amount, _witthheld, _claimed, _investo 'Investor', 'Amount sent', 'Taxes withheld (%)', - `Taxes withheld(${_tokenSymbol})`, + `Taxes withheld (${_tokenSymbol})`, 'Amount received', 'Withdrawn' ]]; @@ -434,7 +434,7 @@ function showReport(_name, _tokenSymbol, _amount, _witthheld, _claimed, _investo let excluded = _excludedArray[i]; let amount = !excluded ? web3.utils.fromWei(_amountArray[i]) : 0; let withheld = !excluded ? web3.utils.fromWei(_withheldArray[i]) : 'NA'; - let withheldPercentage = !excluded ? web3.utils.toBN(_withheldArray[i]).div(web3.utils.toBN(_amountArray[i])).muln(100) : 'NA'; + let withheldPercentage = !excluded ? (withheld !== '0' ? parseFloat(withheld) / parseFloat(amount) * 100 : 0) : 'NA'; let received = !excluded ? web3.utils.fromWei(web3.utils.toBN(_amountArray[i]).sub(web3.utils.toBN(_withheldArray[i]))) : 0; let withdrawn = _claimedArray[i] ? 'YES' : 'NO'; dataTable.push([ @@ -473,7 +473,7 @@ async function pushDividends(dividendIndex, checkpointId) { } else { let investorsAtCheckpoint = await securityToken.methods.getInvestorsAt(checkpointId).call(); console.log(`There are ${investorsAtCheckpoint.length} investors at checkpoint ${checkpointId} `); - let batchSize = readlineSync.questionInt(`How many investors per transaction do you want to push to ? `); + let batchSize = readlineSync.questionInt(`How many investors per transaction do you want to push to? `); for (let i = 0; i < investorsAtCheckpoint.length; i += batchSize) { let action = currentDividendsModule.methods.pushDividendPayment(dividendIndex, i, batchSize); let receipt = await common.sendTransaction(action); @@ -539,7 +539,7 @@ async function addDividendsModule() { })); let index = readlineSync.keyInSelect(options, 'Which dividends module do you want to add? ', { cancel: 'Return' }); - if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module ? `)) { + if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module? `)) { let bytes = web3.utils.fromAscii('', 16); let selectedDividendFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.DIVIDENDS, options[index]); From b29a42cdb28a1855a500fe858a5961ee1b6f5e2e Mon Sep 17 00:00:00 2001 From: Devashish Tomar <40403260+dev1644@users.noreply.github.com> Date: Fri, 21 Dec 2018 19:15:19 +0530 Subject: [PATCH 466/582] 483 484 fix (#488) * Removed the Redundant functions from eternal storage contract as mentioned in Issue#483, Converted Internal functions to public ones as mentioned in #484 & there was a function named getArrayString, I have removed that function because it was returning Array of String, which is not possible as it isn't supported by Current ABIENCODER. * Removed the Redundant functions from eternal storage contract as mentioned in Issue#483, Converted Internal functions to public ones as mentioned in #484 & there was a function named getArrayString, I have removed that function because it was returning Array of String, which is not possible as it isn't supported by Current ABIENCODER. --- contracts/ModuleRegistry.sol | 36 +++++----- contracts/SecurityTokenRegistry.sol | 90 ++++++++++++------------- contracts/storage/EternalStorage.sol | 68 ++++++------------- test/k_module_registry.js | 26 +++---- test/n_security_token_registry.js | 32 ++++----- test/t_security_token_registry_proxy.js | 4 +- test/u_module_registry_proxy.js | 4 +- 7 files changed, 115 insertions(+), 145 deletions(-) diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 65de42fa6..966937c52 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -105,7 +105,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } function initialize(address _polymathRegistry, address _owner) external payable { - require(!getBool(Encoder.getKey("initialised")),"already initialized"); + require(!getBoolValue(Encoder.getKey("initialised")),"already initialized"); require(_owner != address(0) && _polymathRegistry != address(0), "0x address is invalid"); set(Encoder.getKey("polymathRegistry"), _polymathRegistry); set(Encoder.getKey("owner"), _owner); @@ -122,11 +122,11 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { */ function useModule(address _moduleFactory) external { // This if statement is required to be able to add modules from the token proxy contract during deployment - if (ISecurityTokenRegistry(getAddress(Encoder.getKey("securityTokenRegistry"))).isSecurityToken(msg.sender)) { - if (IFeatureRegistry(getAddress(Encoder.getKey("featureRegistry"))).getFeatureStatus("customModulesAllowed")) { - require(getBool(Encoder.getKey("verified", _moduleFactory)) || IOwnable(_moduleFactory).owner() == IOwnable(msg.sender).owner(),"ModuleFactory must be verified or SecurityToken owner must be ModuleFactory owner"); + if (ISecurityTokenRegistry(getAddressValue(Encoder.getKey("securityTokenRegistry"))).isSecurityToken(msg.sender)) { + if (IFeatureRegistry(getAddressValue(Encoder.getKey("featureRegistry"))).getFeatureStatus("customModulesAllowed")) { + require(getBoolValue(Encoder.getKey("verified", _moduleFactory)) || IOwnable(_moduleFactory).owner() == IOwnable(msg.sender).owner(),"ModuleFactory must be verified or SecurityToken owner must be ModuleFactory owner"); } else { - require(getBool(Encoder.getKey("verified", _moduleFactory)), "ModuleFactory must be verified"); + require(getBoolValue(Encoder.getKey("verified", _moduleFactory)), "ModuleFactory must be verified"); } require(_isCompatibleModule(_moduleFactory, msg.sender), "Version should within the compatible range of ST"); pushArray(Encoder.getKey("reputation", _moduleFactory), msg.sender); @@ -148,12 +148,12 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @param _moduleFactory is the address of the module factory to be registered */ function registerModule(address _moduleFactory) external whenNotPausedOrOwner { - if (IFeatureRegistry(getAddress(Encoder.getKey("featureRegistry"))).getFeatureStatus("customModulesAllowed")) { + if (IFeatureRegistry(getAddressValue(Encoder.getKey("featureRegistry"))).getFeatureStatus("customModulesAllowed")) { require(msg.sender == IOwnable(_moduleFactory).owner() || msg.sender == owner(),"msg.sender must be the Module Factory owner or registry curator"); } else { require(msg.sender == owner(), "Only owner allowed to register modules"); } - require(getUint(Encoder.getKey("registry", _moduleFactory)) == 0, "Module factory should not be pre-registered"); + require(getUintValue(Encoder.getKey("registry", _moduleFactory)) == 0, "Module factory should not be pre-registered"); IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); //Enforce type uniqueness uint256 i; @@ -181,14 +181,14 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @param _moduleFactory is the address of the module factory to be deleted from the registry */ function removeModule(address _moduleFactory) external whenNotPausedOrOwner { - uint256 moduleType = getUint(Encoder.getKey("registry", _moduleFactory)); + uint256 moduleType = getUintValue(Encoder.getKey("registry", _moduleFactory)); require(moduleType != 0, "Module factory should be registered"); require( msg.sender == IOwnable(_moduleFactory).owner() || msg.sender == owner(), "msg.sender must be the Module Factory owner or registry curator" ); - uint256 index = getUint(Encoder.getKey("moduleListIndex", _moduleFactory)); + uint256 index = getUintValue(Encoder.getKey("moduleListIndex", _moduleFactory)); uint256 last = getArrayAddress(Encoder.getKey("moduleList", moduleType)).length - 1; address temp = getArrayAddress(Encoder.getKey("moduleList", moduleType))[last]; @@ -220,7 +220,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @return bool */ function verifyModule(address _moduleFactory, bool _verified) external onlyOwner { - require(getUint(Encoder.getKey("registry", _moduleFactory)) != uint256(0), "Module factory must be registered"); + require(getUintValue(Encoder.getKey("registry", _moduleFactory)) != uint256(0), "Module factory must be registered"); set(Encoder.getKey("verified", _moduleFactory), _verified); emit ModuleVerified(_moduleFactory, _verified); } @@ -303,15 +303,15 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { function getModulesByTypeAndToken(uint8 _moduleType, address _securityToken) public view returns (address[]) { uint256 _len = getArrayAddress(Encoder.getKey("moduleList", uint256(_moduleType))).length; address[] memory _addressList = getArrayAddress(Encoder.getKey("moduleList", uint256(_moduleType))); - bool _isCustomModuleAllowed = IFeatureRegistry(getAddress(Encoder.getKey("featureRegistry"))).getFeatureStatus("customModulesAllowed"); + bool _isCustomModuleAllowed = IFeatureRegistry(getAddressValue(Encoder.getKey("featureRegistry"))).getFeatureStatus("customModulesAllowed"); uint256 counter = 0; for (uint256 i = 0; i < _len; i++) { if (_isCustomModuleAllowed) { - if (IOwnable(_addressList[i]).owner() == IOwnable(_securityToken).owner() || getBool(Encoder.getKey("verified", _addressList[i]))) + if (IOwnable(_addressList[i]).owner() == IOwnable(_securityToken).owner() || getBoolValue(Encoder.getKey("verified", _addressList[i]))) if(_isCompatibleModule(_addressList[i], _securityToken)) counter++; } - else if (getBool(Encoder.getKey("verified", _addressList[i]))) { + else if (getBoolValue(Encoder.getKey("verified", _addressList[i]))) { if(_isCompatibleModule(_addressList[i], _securityToken)) counter++; } @@ -320,14 +320,14 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { counter = 0; for (uint256 j = 0; j < _len; j++) { if (_isCustomModuleAllowed) { - if (IOwnable(_addressList[j]).owner() == IOwnable(_securityToken).owner() || getBool(Encoder.getKey("verified", _addressList[j]))) { + if (IOwnable(_addressList[j]).owner() == IOwnable(_securityToken).owner() || getBoolValue(Encoder.getKey("verified", _addressList[j]))) { if(_isCompatibleModule(_addressList[j], _securityToken)) { _tempArray[counter] = _addressList[j]; counter ++; } } } - else if (getBool(Encoder.getKey("verified", _addressList[j]))) { + else if (getBoolValue(Encoder.getKey("verified", _addressList[j]))) { if(_isCompatibleModule(_addressList[j], _securityToken)) { _tempArray[counter] = _addressList[j]; counter ++; @@ -370,7 +370,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @notice Stores the contract addresses of other key contracts from the PolymathRegistry */ function updateFromRegistry() external onlyOwner { - address _polymathRegistry = getAddress(Encoder.getKey("polymathRegistry")); + address _polymathRegistry = getAddressValue(Encoder.getKey("polymathRegistry")); set(Encoder.getKey("securityTokenRegistry"), IPolymathRegistry(_polymathRegistry).getAddress("SecurityTokenRegistry")); set(Encoder.getKey("featureRegistry"), IPolymathRegistry(_polymathRegistry).getAddress("FeatureRegistry")); set(Encoder.getKey("polyToken"), IPolymathRegistry(_polymathRegistry).getAddress("PolyToken")); @@ -391,7 +391,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @return address owner */ function owner() public view returns(address) { - return getAddress(Encoder.getKey("owner")); + return getAddressValue(Encoder.getKey("owner")); } /** @@ -399,6 +399,6 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @return bool */ function isPaused() public view returns(bool) { - return getBool(Encoder.getKey("paused")); + return getBoolValue(Encoder.getKey("paused")); } } diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index d13fbb2b6..81f74abde 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -175,7 +175,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { external payable { - require(!getBool(INITIALIZE),"already initialized"); + require(!getBoolValue(INITIALIZE),"already initialized"); require( _STFactory != address(0) && _polyToken != address(0) && _owner != address(0) && _polymathRegistry != address(0), "Invalid address" @@ -210,7 +210,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { // Attempt to charge the reg fee if it is > 0 POLY uint256 tickerFee = getTickerRegistrationFee(); if (tickerFee > 0) - require(IERC20(getAddress(POLYTOKEN)).transferFrom(msg.sender, address(this), tickerFee), "Insufficent allowance"); + require(IERC20(getAddressValue(POLYTOKEN)).transferFrom(msg.sender, address(this), tickerFee), "Insufficent allowance"); string memory ticker = Util.upper(_ticker); require(_tickerAvailable(ticker), "Ticker is reserved"); // Check whether ticker was previously registered (and expired) @@ -286,13 +286,13 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { } // If status is true, there must be a security token linked to the ticker already if (_status) { - require(getAddress(Encoder.getKey("tickerToSecurityToken", _ticker)) != address(0), "Token not registered"); + require(getAddressValue(Encoder.getKey("tickerToSecurityToken", _ticker)) != address(0), "Token not registered"); } _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true, uint256(0)); } function _tickerOwner(string _ticker) internal view returns(address) { - return getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); + return getAddressValue(Encoder.getKey("registeredTickers_owner", _ticker)); } /** @@ -318,7 +318,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { function _tickerAvailable(string _ticker) internal view returns(bool) { if (_tickerOwner(_ticker) != address(0)) { /*solium-disable-next-line security/no-block-members*/ - if ((now > getUint(Encoder.getKey("registeredTickers_expiryDate", _ticker))) && !_tickerStatus(_ticker)) { + if ((now > getUintValue(Encoder.getKey("registeredTickers_expiryDate", _ticker))) && !_tickerStatus(_ticker)) { return true; } else return false; @@ -327,7 +327,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { } function _tickerStatus(string _ticker) internal view returns(bool) { - return getBool(Encoder.getKey("registeredTickers_status", _ticker)); + return getBoolValue(Encoder.getKey("registeredTickers_status", _ticker)); } /** @@ -341,7 +341,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { pushArray(_ownerKey, Util.stringToBytes32(_ticker)); set(Encoder.getKey("tickerIndex", _ticker), length); bytes32 seenKey = Encoder.getKey("seenUsers", _owner); - if (!getBool(seenKey)) { + if (!getBoolValue(seenKey)) { pushArray(Encoder.getKey("activeUsers"), _owner); set(seenKey, true); } @@ -359,19 +359,19 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { bool _status ) internal { bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); - if (getAddress(key) != _owner) + if (getAddressValue(key) != _owner) set(key, _owner); key = Encoder.getKey("registeredTickers_registrationDate", _ticker); - if (getUint(key) != _registrationDate) + if (getUintValue(key) != _registrationDate) set(key, _registrationDate); key = Encoder.getKey("registeredTickers_expiryDate", _ticker); - if (getUint(key) != _expiryDate) + if (getUintValue(key) != _expiryDate) set(key, _expiryDate); key = Encoder.getKey("registeredTickers_tokenName", _ticker); - if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) + if (Encoder.getKey(getStringValue(key)) != Encoder.getKey(_tokenName)) set(key, _tokenName); key = Encoder.getKey("registeredTickers_status", _ticker); - if (getBool(key) != _status) + if (getBoolValue(key) != _status) set(key, _status); } @@ -384,9 +384,9 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { string memory ticker = Util.upper(_ticker); require(_newOwner != address(0), "Invalid address"); bytes32 ownerKey = Encoder.getKey("registeredTickers_owner", ticker); - require(getAddress(ownerKey) == msg.sender, "Not authorised"); + require(getAddressValue(ownerKey) == msg.sender, "Not authorised"); if (_tickerStatus(ticker)) - require(IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner"); + require(IOwnable(getAddressValue(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner"); _deleteTickerOwnership(msg.sender, ticker); _setTickerOwnership(_newOwner, ticker); set(ownerKey, _newOwner); @@ -397,7 +397,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @notice Internal - Removes the owner of a ticker */ function _deleteTickerOwnership(address _owner, string _ticker) internal { - uint256 index = uint256(getUint(Encoder.getKey("tickerIndex", _ticker))); + uint256 index = uint256(getUintValue(Encoder.getKey("tickerIndex", _ticker))); bytes32 ownerKey = Encoder.getKey("userToTickers", _owner); bytes32[] memory tickers = getArrayBytes32(ownerKey); assert(index < tickers.length); @@ -415,7 +415,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function changeExpiryLimit(uint256 _newExpiry) external onlyOwner { require(_newExpiry >= 1 days, "Expiry should >= 1 day"); - emit ChangeExpiryLimit(getUint(EXPIRYLIMIT), _newExpiry); + emit ChangeExpiryLimit(getUintValue(EXPIRYLIMIT), _newExpiry); set(EXPIRYLIMIT, _newExpiry); } @@ -430,7 +430,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { for (uint i = 0; i < tickers.length; i++) { string memory ticker = Util.bytes32ToString(tickers[i]); /*solium-disable-next-line security/no-block-members*/ - if (getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now || _tickerStatus(ticker)) { + if (getUintValue(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now || _tickerStatus(ticker)) { counter ++; } } @@ -439,7 +439,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { for (i = 0; i < tickers.length; i++) { ticker = Util.bytes32ToString(tickers[i]); /*solium-disable-next-line security/no-block-members*/ - if (getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now || _tickerStatus(ticker)) { + if (getUintValue(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now || _tickerStatus(ticker)) { tempList[counter] = tickers[i]; counter ++; } @@ -464,7 +464,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { for (i = 0; i < activeUsers.length; i++) { tickers = getArrayBytes32(Encoder.getKey("userToTickers", activeUsers[i])); for (j = 0; j < tickers.length; j++) { - token = getAddress(Encoder.getKey("tickerToSecurityToken", Util.bytes32ToString(tickers[j]))); + token = getAddressValue(Encoder.getKey("tickerToSecurityToken", Util.bytes32ToString(tickers[j]))); if (token != address(0)) { if (IOwnable(token).owner() == _owner) { count = count + 1; @@ -477,7 +477,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { for (i = 0; i < activeUsers.length; i++) { tickers = getArrayBytes32(Encoder.getKey("userToTickers", activeUsers[i])); for (j = 0; j < tickers.length; j++) { - token = getAddress(Encoder.getKey("tickerToSecurityToken", Util.bytes32ToString(tickers[j]))); + token = getAddressValue(Encoder.getKey("tickerToSecurityToken", Util.bytes32ToString(tickers[j]))); if (token != address(0)) { if (IOwnable(token).owner() == _owner) { result[index] = token; @@ -501,15 +501,15 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { function getTickerDetails(string _ticker) external view returns (address, uint256, uint256, string, bool) { string memory ticker = Util.upper(_ticker); bool tickerStatus = _tickerStatus(ticker); - uint256 expiryDate = getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)); + uint256 expiryDate = getUintValue(Encoder.getKey("registeredTickers_expiryDate", ticker)); /*solium-disable-next-line security/no-block-members*/ if ((tickerStatus == true) || (expiryDate > now)) { return ( _tickerOwner(ticker), - getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)), + getUintValue(Encoder.getKey("registeredTickers_registrationDate", ticker)), expiryDate, - getString(Encoder.getKey("registeredTickers_tokenName", ticker)), + getStringValue(Encoder.getKey("registeredTickers_tokenName", ticker)), tickerStatus ); } else @@ -531,15 +531,15 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(bytes(_name).length > 0 && bytes(_ticker).length > 0, "Ticker length > 0"); string memory ticker = Util.upper(_ticker); bytes32 statusKey = Encoder.getKey("registeredTickers_status", ticker); - require(!getBool(statusKey), "Already deployed"); + require(!getBoolValue(statusKey), "Already deployed"); set(statusKey, true); require(_tickerOwner(ticker) == msg.sender, "Not authorised"); /*solium-disable-next-line security/no-block-members*/ - require(getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now, "Ticker gets expired"); + require(getUintValue(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now, "Ticker gets expired"); uint256 launchFee = getSecurityTokenLaunchFee(); if (launchFee > 0) - require(IERC20(getAddress(POLYTOKEN)).transferFrom(msg.sender, address(this), launchFee), "Insufficient allowance"); + require(IERC20(getAddressValue(POLYTOKEN)).transferFrom(msg.sender, address(this), launchFee), "Insufficient allowance"); address newSecurityTokenAddress = ISTFactory(getSTFactoryAddress()).deployToken( _name, @@ -548,7 +548,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { _tokenDetails, msg.sender, _divisible, - getAddress(POLYMATHREGISTRY) + getAddressValue(POLYMATHREGISTRY) ); /*solium-disable-next-line security/no-block-members*/ @@ -583,8 +583,8 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(_deployedAt != 0 && _owner != address(0), "0 value params not allowed"); string memory ticker = Util.upper(_ticker); require(_securityToken != address(0), "ST address is 0x"); - uint256 registrationTime = getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)); - uint256 expiryTime = getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)); + uint256 registrationTime = getUintValue(Encoder.getKey("registeredTickers_registrationDate", ticker)); + uint256 expiryTime = getUintValue(Encoder.getKey("registeredTickers_expiryDate", ticker)); if (registrationTime == 0) { /*solium-disable-next-line security/no-block-members*/ registrationTime = now; @@ -611,7 +611,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @return bool */ function isSecurityToken(address _securityToken) external view returns (bool) { - return (keccak256(bytes(getString(Encoder.getKey("securityTokens_ticker", _securityToken)))) != keccak256("")); + return (keccak256(bytes(getStringValue(Encoder.getKey("securityTokens_ticker", _securityToken)))) != keccak256("")); } /** @@ -621,7 +621,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function getSecurityTokenAddress(string _ticker) external view returns (address) { string memory ticker = Util.upper(_ticker); - return getAddress(Encoder.getKey("tickerToSecurityToken", ticker)); + return getAddressValue(Encoder.getKey("tickerToSecurityToken", ticker)); } /** @@ -634,10 +634,10 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function getSecurityTokenData(address _securityToken) external view returns (string, address, string, uint256) { return ( - getString(Encoder.getKey("securityTokens_ticker", _securityToken)), + getStringValue(Encoder.getKey("securityTokens_ticker", _securityToken)), IOwnable(_securityToken).owner(), - getString(Encoder.getKey("securityTokens_tokenDetails", _securityToken)), - getUint(Encoder.getKey("securityTokens_deployedAt", _securityToken)) + getStringValue(Encoder.getKey("securityTokens_tokenDetails", _securityToken)), + getUintValue(Encoder.getKey("securityTokens_deployedAt", _securityToken)) ); } @@ -651,7 +651,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function transferOwnership(address _newOwner) external onlyOwner { require(_newOwner != address(0), "Invalid address"); - emit OwnershipTransferred(getAddress(OWNER), _newOwner); + emit OwnershipTransferred(getAddressValue(OWNER), _newOwner); set(OWNER, _newOwner); } @@ -678,7 +678,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _tickerRegFee is the registration fee in POLY tokens (base 18 decimals) */ function changeTickerRegistrationFee(uint256 _tickerRegFee) external onlyOwner { - uint256 fee = getUint(TICKERREGFEE); + uint256 fee = getUintValue(TICKERREGFEE); require(fee != _tickerRegFee, "Fee not changed"); emit ChangeTickerRegistrationFee(fee, _tickerRegFee); set(TICKERREGFEE, _tickerRegFee); @@ -689,7 +689,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _stLaunchFee is the registration fee in POLY tokens (base 18 decimals) */ function changeSecurityLaunchFee(uint256 _stLaunchFee) external onlyOwner { - uint256 fee = getUint(STLAUNCHFEE); + uint256 fee = getUintValue(STLAUNCHFEE); require(fee != _stLaunchFee, "Fee not changed"); emit ChangeSecurityLaunchFee(fee, _stLaunchFee); set(STLAUNCHFEE, _stLaunchFee); @@ -731,21 +731,21 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { uint24 _packedVersion = VersionUtils.pack(_major, _minor, _patch); require(VersionUtils.isValidVersion(getProtocolVersion(), _version),"In-valid version"); set(Encoder.getKey("latestVersion"), uint256(_packedVersion)); - set(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion"))), _STFactoryAddress); + set(Encoder.getKey("protocolVersionST", getUintValue(Encoder.getKey("latestVersion"))), _STFactoryAddress); } /** * @notice Returns the current STFactory Address */ function getSTFactoryAddress() public view returns(address) { - return getAddress(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion")))); + return getAddressValue(Encoder.getKey("protocolVersionST", getUintValue(Encoder.getKey("latestVersion")))); } /** * @notice Gets Protocol version */ function getProtocolVersion() public view returns(uint8[]) { - return VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))); + return VersionUtils.unpack(uint24(getUintValue(Encoder.getKey("latestVersion")))); } /** @@ -762,7 +762,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @return Fee amount */ function getSecurityTokenLaunchFee() public view returns(uint256) { - return getUint(STLAUNCHFEE); + return getUintValue(STLAUNCHFEE); } /** @@ -770,7 +770,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @return Fee amount */ function getTickerRegistrationFee() public view returns(uint256) { - return getUint(TICKERREGFEE); + return getUintValue(TICKERREGFEE); } /** @@ -778,7 +778,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @return Expiry limit */ function getExpiryLimit() public view returns(uint256) { - return getUint(EXPIRYLIMIT); + return getUintValue(EXPIRYLIMIT); } /** @@ -786,7 +786,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @return bool */ function isPaused() public view returns(bool) { - return getBool(PAUSED); + return getBoolValue(PAUSED); } /** @@ -794,7 +794,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @return address owner */ function owner() public view returns(address) { - return getAddress(OWNER); + return getAddressValue(OWNER); } } diff --git a/contracts/storage/EternalStorage.sol b/contracts/storage/EternalStorage.sol index 637b5f2f3..a3f76203b 100644 --- a/contracts/storage/EternalStorage.sol +++ b/contracts/storage/EternalStorage.sol @@ -57,39 +57,6 @@ contract EternalStorage { stringStorage[_key] = _value; } - //////////////////// - /// get functions - //////////////////// - /// @notice Get function use to get the value of the singleton state variables - /// Ex1- string public version = "0.0.1"; - /// string _version = getString(keccak256(abi.encodePacked("version")); - /// Ex2 - assert(temp1 == temp2); replace to - /// assert(getUint(keccak256(abi.encodePacked(temp1)) == getUint(keccak256(abi.encodePacked(temp2)); - /// Ex3 - mapping(string => SymbolDetails) registeredSymbols; where SymbolDetails is the structure having different type of values as - /// {uint256 date, string name, address owner} etc. - /// string _name = getString(keccak256(abi.encodePacked("registeredSymbols_name", "TOKEN")); - - function getBool(bytes32 _key) internal view returns (bool) { - return boolStorage[_key]; - } - - function getUint(bytes32 _key) internal view returns (uint256) { - return uintStorage[_key]; - } - - function getAddress(bytes32 _key) internal view returns (address) { - return addressStorage[_key]; - } - - function getString(bytes32 _key) internal view returns (string) { - return stringStorage[_key]; - } - - function getBytes32(bytes32 _key) internal view returns (bytes32) { - return bytes32Storage[_key]; - } - - //////////////////////////// // deleteArray functions //////////////////////////// @@ -192,19 +159,15 @@ contract EternalStorage { /// Ex2- uint256 _len = tokensOwnedByOwner[0x1].length; replace with /// getArrayBytes32(keccak256(abi.encodePacked("tokensOwnedByOwner", 0x1)).length; - function getArrayAddress(bytes32 _key) internal view returns(address[]) { + function getArrayAddress(bytes32 _key) public view returns(address[]) { return addressArrayStorage[_key]; } - function getArrayBytes32(bytes32 _key) internal view returns(bytes32[]) { + function getArrayBytes32(bytes32 _key) public view returns(bytes32[]) { return bytes32ArrayStorage[_key]; } - function getArrayString(bytes32 _key) internal view returns(string[]) { - return stringArrayStorage[_key]; - } - - function getArrayUint(bytes32 _key) internal view returns(uint[]) { + function getArrayUint(bytes32 _key) public view returns(uint[]) { return uintArrayStorage[_key]; } @@ -232,31 +195,38 @@ contract EternalStorage { stringArrayStorage[_key][_index] = _value; } - ///////////////////////////// - /// Public getters functions - ///////////////////////////// + /// Public getters functions + //////////////////// + /// @notice Get function use to get the value of the singleton state variables + /// Ex1- string public version = "0.0.1"; + /// string _version = getString(keccak256(abi.encodePacked("version")); + /// Ex2 - assert(temp1 == temp2); replace to + /// assert(getUint(keccak256(abi.encodePacked(temp1)) == getUint(keccak256(abi.encodePacked(temp2)); + /// Ex3 - mapping(string => SymbolDetails) registeredSymbols; where SymbolDetails is the structure having different type of values as + /// {uint256 date, string name, address owner} etc. + /// string _name = getString(keccak256(abi.encodePacked("registeredSymbols_name", "TOKEN")); - function getUintValues(bytes32 _variable) public view returns(uint256) { + function getUintValue(bytes32 _variable) public view returns(uint256) { return uintStorage[_variable]; } - function getBoolValues(bytes32 _variable) public view returns(bool) { + function getBoolValue(bytes32 _variable) public view returns(bool) { return boolStorage[_variable]; } - function getStringValues(bytes32 _variable) public view returns(string) { + function getStringValue(bytes32 _variable) public view returns(string) { return stringStorage[_variable]; } - function getAddressValues(bytes32 _variable) public view returns(address) { + function getAddressValue(bytes32 _variable) public view returns(address) { return addressStorage[_variable]; } - function getBytes32Values(bytes32 _variable) public view returns(bytes32) { + function getBytes32Value(bytes32 _variable) public view returns(bytes32) { return bytes32Storage[_variable]; } - function getBytesValues(bytes32 _variable) public view returns(bytes) { + function getBytesValue(bytes32 _variable) public view returns(bytes) { return bytesStorage[_variable]; } diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 3ec2d0a0d..ba3d55155 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -199,33 +199,33 @@ contract("ModuleRegistry", accounts => { it("Should successfully update the registry contract addresses", async () => { await I_MRProxied.updateFromRegistry({ from: account_polymath }); assert.equal( - await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("securityTokenRegistry")), + await I_MRProxied.getAddressValue.call(web3.utils.soliditySha3("securityTokenRegistry")), I_SecurityTokenRegistryProxy.address ); assert.equal( - await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("featureRegistry")), + await I_MRProxied.getAddressValue.call(web3.utils.soliditySha3("featureRegistry")), I_FeatureRegistry.address ); - assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), I_PolyToken.address); + assert.equal(await I_MRProxied.getAddressValue.call(web3.utils.soliditySha3("polyToken")), I_PolyToken.address); }); }); describe("Test the state variables", async () => { it("Should be the right owner", async () => { - let _owner = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("owner")); + let _owner = await I_MRProxied.getAddressValue.call(web3.utils.soliditySha3("owner")); assert.equal(_owner, account_polymath, "Owner should be the correct"); }); it("Should be the expected value of the paused and intialised variable", async () => { - let _paused = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + let _paused = await I_MRProxied.getBoolValue.call(web3.utils.soliditySha3("paused")); assert.isFalse(_paused, "Should be the false"); - let _intialised = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); + let _intialised = await I_MRProxied.getBoolValue.call(web3.utils.soliditySha3("initialised")); assert.isTrue(_intialised, "Values should be the true"); }); it("Should be the expected value of the polymath registry", async () => { - let _polymathRegistry = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); + let _polymathRegistry = await I_MRProxied.getAddressValue.call(web3.utils.soliditySha3("polymathRegistry")); assert.equal( _polymathRegistry, I_PolymathRegistry.address, @@ -496,10 +496,10 @@ contract("ModuleRegistry", accounts => { // re-ordering assert.equal(sto3_end, sto3); // delete related data - assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto4)), 0); + assert.equal(await I_MRProxied.getUintValue.call(web3.utils.soliditySha3("registry", sto4)), 0); assert.equal(await I_MRProxied.getReputationByFactory.call(sto4), 0); assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); - assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto4)), false); + assert.equal(await I_MRProxied.getBoolValue.call(web3.utils.soliditySha3("verified", sto4)), false); await revertToSnapshot(snap); }); @@ -522,10 +522,10 @@ contract("ModuleRegistry", accounts => { // re-ordering assert.equal(sto1_end, sto1); // delete related data - assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto2)), 0); + assert.equal(await I_MRProxied.getUintValue.call(web3.utils.soliditySha3("registry", sto2)), 0); assert.equal(await I_MRProxied.getReputationByFactory.call(sto2), 0); assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); - assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto2)), false); + assert.equal(await I_MRProxied.getBoolValue.call(web3.utils.soliditySha3("verified", sto2)), false); }); it("Should fail if module already removed", async () => { @@ -568,7 +568,7 @@ contract("ModuleRegistry", accounts => { it("Should successfully pause the contract", async () => { await I_MRProxied.pause({ from: account_polymath }); - let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + let status = await I_MRProxied.getBoolValue.call(web3.utils.soliditySha3("paused")); assert.isOk(status); }); @@ -578,7 +578,7 @@ contract("ModuleRegistry", accounts => { it("Should successfully unpause the contract", async () => { await I_MRProxied.unpause({ from: account_polymath }); - let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + let status = await I_MRProxied.getBoolValue.call(web3.utils.soliditySha3("paused")); assert.isNotOk(status); }); }); diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index de8b7d733..4bea414db 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -291,25 +291,25 @@ contract("SecurityTokenRegistry", accounts => { describe(" Test cases of the registerTicker", async () => { it("verify the intial parameters", async () => { - let intialised = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); + let intialised = await I_STRProxied.getBoolValue.call(web3.utils.soliditySha3("initialised")); assert.isTrue(intialised, "Should be true"); - let expiry = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit")); + let expiry = await I_STRProxied.getUintValue.call(web3.utils.soliditySha3("expiryLimit")); assert.equal(expiry.toNumber(), 5184000, "Expiry limit should be equal to 60 days"); - let polytoken = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")); + let polytoken = await I_STRProxied.getAddressValue.call(web3.utils.soliditySha3("polyToken")); assert.equal(polytoken, I_PolyToken.address, "Should be the polytoken address"); - let stlaunchFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("stLaunchFee")); + let stlaunchFee = await I_STRProxied.getUintValue.call(web3.utils.soliditySha3("stLaunchFee")); assert.equal(stlaunchFee.toNumber(), initRegFee, "Should be provided reg fee"); - let tickerRegFee = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee")); + let tickerRegFee = await I_STRProxied.getUintValue.call(web3.utils.soliditySha3("tickerRegFee")); assert.equal(tickerRegFee.toNumber(), tickerRegFee, "Should be provided reg fee"); - let polymathRegistry = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); + let polymathRegistry = await I_STRProxied.getAddressValue.call(web3.utils.soliditySha3("polymathRegistry")); assert.equal(polymathRegistry, I_PolymathRegistry.address, "Should be the address of the polymath registry"); - let owner = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("owner")); + let owner = await I_STRProxied.getAddressValue.call(web3.utils.soliditySha3("owner")); assert.equal(owner, account_polymath, "Should be the address of the registry owner"); }); @@ -424,7 +424,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should successfully set the expiry limit", async () => { await I_STRProxied.changeExpiryLimit(duration.days(10), { from: account_polymath }); assert.equal( - (await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), + (await I_STRProxied.getUintValue.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), duration.days(10), "Failed to change the expiry limit" ); @@ -619,7 +619,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should upgrade the logic contract into the STRProxy", async () => { await I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, { from: account_polymath }); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - assert.isTrue(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); + assert.isTrue(await I_STRProxied.getBoolValue.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); }); it("Should check the old data persist or not", async () => { @@ -631,7 +631,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should unpause the logic contract", async () => { await I_STRProxied.unpause({ from: account_polymath }); - assert.isFalse(await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); + assert.isFalse(await I_STRProxied.getBoolValue.call(web3.utils.soliditySha3("paused")), "Paused value should be false"); }); }); @@ -873,7 +873,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should able to change the STLaunchFee", async () => { let tx = await I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), { from: account_polymath }); assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("500")); - let stLaunchFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("stLaunchFee")); + let stLaunchFee = await I_STRProxied.getUintValue(web3.utils.soliditySha3("stLaunchFee")); assert.equal(stLaunchFee, web3.utils.toWei("500")); }); }); @@ -896,7 +896,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should able to change the ExpiryLimit", async () => { let tx = await I_STRProxied.changeExpiryLimit(duration.days(20), { from: account_polymath }); assert.equal(tx.logs[0].args._newExpiry, duration.days(20)); - let expiry = await I_STRProxied.getUintValues(web3.utils.soliditySha3("expiryLimit")); + let expiry = await I_STRProxied.getUintValue(web3.utils.soliditySha3("expiryLimit")); assert.equal(expiry, duration.days(20)); }); }); @@ -919,7 +919,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should able to change the TickerRegFee", async () => { let tx = await I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("400"), { from: account_polymath }); assert.equal(tx.logs[0].args._newFee, web3.utils.toWei("400")); - let tickerRegFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("tickerRegFee")); + let tickerRegFee = await I_STRProxied.getUintValue(web3.utils.soliditySha3("tickerRegFee")); assert.equal(tickerRegFee, web3.utils.toWei("400")); }); @@ -974,7 +974,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should successfully change the polytoken address", async () => { let _id = await takeSnapshot(); await I_STRProxied.updatePolyTokenAddress(dummy_token, { from: account_polymath }); - assert.equal(await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), dummy_token); + assert.equal(await I_STRProxied.getAddressValue.call(web3.utils.soliditySha3("polyToken")), dummy_token); await revertToSnapshot(_id); }); }); @@ -1122,7 +1122,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should successfully pause the contract", async () => { await I_STRProxied.pause({ from: account_polymath }); - let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + let status = await I_STRProxied.getBoolValue.call(web3.utils.soliditySha3("paused")); assert.isOk(status); }); @@ -1132,7 +1132,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should successfully unpause the contract", async () => { await I_STRProxied.unpause({ from: account_polymath }); - let status = await I_STRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + let status = await I_STRProxied.getBoolValue.call(web3.utils.soliditySha3("paused")); assert.isNotOk(status); }); }); diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 40b1cced8..30bacc759 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -125,12 +125,12 @@ contract("SecurityTokenRegistryProxy", accounts => { it("Verify the initialize data", async () => { assert.equal( - (await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), + (await I_STRProxied.getUintValue.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), 60 * 24 * 60 * 60, "Should equal to 60 days" ); assert.equal( - (await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee"))).toNumber(), + (await I_STRProxied.getUintValue.call(web3.utils.soliditySha3("tickerRegFee"))).toNumber(), web3.utils.toWei("250") ); }); diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 877d173d4..546200943 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -153,11 +153,11 @@ contract("ModuleRegistryProxy", accounts => { it("Verify the initialize data", async () => { assert.equal( - await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("owner")), + await I_MRProxied.getAddressValue.call(web3.utils.soliditySha3("owner")), account_polymath, "Should equal to right address" ); - assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")), I_PolymathRegistry.address); + assert.equal(await I_MRProxied.getAddressValue.call(web3.utils.soliditySha3("polymathRegistry")), I_PolymathRegistry.address); }); }); From 9aea06ba5df032425e6d75e34ba415dd5eb9e4bd Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Fri, 21 Dec 2018 17:13:13 +0000 Subject: [PATCH 467/582] Add getCheckpointData --- .../modules/Checkpoint/DividendCheckpoint.sol | 19 ++++++++++++++++- test/e_erc20_dividends.js | 21 +++++++++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 4aa939c20..8f8c75e2d 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -317,7 +317,24 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { resultAmount[i] = resultBalance[i].mul(dividend.amount).div(dividend.totalSupply); } } - /* return (investors, resultClaimed, resultExcluded, resultWithheld, resultBalance, resultAmount); */ + } + + /** + * @notice Retrieves list of investors, their balances, and their current withholding tax percentage + * @param _checkpointId Checkpoint Id to query for + * @return address[] list of investors + * @return uint256[] investor balances + * @return uint256[] investor withheld percentages + */ + function getCheckpointData(uint256 _checkpointId) external view returns (address[] memory investors, uint256[] memory balances, uint256[] memory withholdings) { + require(_checkpointId <= ISecurityToken(securityToken).currentCheckpointId(), "Invalid checkpoint"); + investors = ISecurityToken(securityToken).getInvestorsAt(_checkpointId); + balances = new uint256[](investors.length); + withholdings = new uint256[](investors.length); + for (uint256 i; i < investors.length; i++) { + balances[i] = ISecurityToken(securityToken).balanceOfAt(investors[i], _checkpointId); + withholdings[i] = withholdingTax[investors[i]]; + } } /** diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index bc52e3886..a13047fc0 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -854,11 +854,6 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(info[3][2].toNumber(), web3.utils.toWei("0.2", "ether"), "withheld match"); assert.equal(info[3][3].toNumber(), 0, "withheld match"); - console.log(info[4][0].toNumber()); - console.log(info[4][1].toNumber()); - console.log(info[4][2].toNumber()); - console.log(info[4][3].toNumber()); - assert.equal(info[4][0].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor1, 4)).toNumber(), "balance match"); assert.equal(info[4][1].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor2, 4)).toNumber(), "balance match"); assert.equal(info[4][2].toNumber(), (await I_SecurityToken.balanceOfAt(account_temp, 4)).toNumber(), "balance match"); @@ -1102,7 +1097,21 @@ contract("ERC20DividendCheckpoint", accounts => { dividendName, { from: account_manager } ); - assert.equal(tx.logs[0].args._checkpointId.toNumber(), 8); + let info = await I_ERC20DividendCheckpoint.getCheckpointData.call(checkpointID); + + assert.equal(info[0][0], account_investor1, "account match"); + assert.equal(info[0][1], account_investor2, "account match"); + assert.equal(info[0][2], account_temp, "account match"); + assert.equal(info[0][3], account_investor3, "account match"); + assert.equal(info[1][0].toNumber(), (await I_SecurityToken.balanceOfAt.call(account_investor1, checkpointID)).toNumber(), "balance match"); + assert.equal(info[1][1].toNumber(), (await I_SecurityToken.balanceOfAt.call(account_investor2, checkpointID)).toNumber(), "balance match"); + assert.equal(info[1][2].toNumber(), (await I_SecurityToken.balanceOfAt.call(account_temp, checkpointID)).toNumber(), "balance match"); + assert.equal(info[1][3].toNumber(), (await I_SecurityToken.balanceOfAt.call(account_investor3, checkpointID)).toNumber(), "balance match"); + assert.equal(info[2][0].toNumber(), 0, "withholding match"); + assert.equal(info[2][1].toNumber(), BigNumber(10 * 10 ** 16).toNumber(), "withholding match"); + assert.equal(info[2][2].toNumber(), BigNumber(20 * 10 ** 16).toNumber(), "withholding match"); + assert.equal(info[2][3].toNumber(), 0, "withholding match"); + assert.equal(tx.logs[0].args._checkpointId.toNumber(), checkpointID); }); it("should allow manager with permission to create dividend with exclusion", async () => { From 054d4414d59f1d36d91ab7e33c9ee2f16d3a59a6 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 21 Dec 2018 14:59:17 -0300 Subject: [PATCH 468/582] CLI minor changes --- CLI/commands/transfer_manager.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 45fa0acb4..7ef7b99e1 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -912,7 +912,7 @@ async function blacklistTransferManager() { let options = ['Add new blacklist']; if (currentBlacklists.length > 0) { - options.push('Manage existing blacklist'); + options.push('Manage existing blacklist', 'Explore account'); } options.push('Delete investors from all blacklists', 'Operate with multiple blacklists'); @@ -967,6 +967,23 @@ async function blacklistTransferManager() { await manageExistingBlacklist(currentBlacklists[index]); } break; + case 'Explore account': + let account = readlineSync.question(`Enter the address of the investor: `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: `Must be a valid address` + }); + let blacklistNamesToUser = await currentTransferManager.methods.getBlacklistNamesToUser(account).call(); + if (blacklistNamesToUser.length > 0) { + console.log(); + console.log(`**** Blacklists inlcuding ${account} ****`); + blacklistNamesToUser.map(n => console.log(web3.utils.hexToUtf8(n))); + } else { + console.log(chalk.yellow(`No blacklist includes ${account}`)); + } + console.log(); + break; case 'Delete investors from all blacklists': let investorsToRemove = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e. addr1,addr2,addr3): `, { limit: function (input) { @@ -976,9 +993,9 @@ async function blacklistTransferManager() { }).split(','); let deleteInvestorFromAllBlacklistAction; if (investorsToRemove.length === 1) { - deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.deleteInvestorFromAllBlacklist(investorsToAdd[0]); + deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.deleteInvestorFromAllBlacklist(investorsToRemove[0]); } else { - deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.deleteInvestorFromAllBlacklistMulti(nvestorsToAdd); + deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.deleteInvestorFromAllBlacklistMulti(investorsToRemove); } let deleteInvestorFromAllBlacklistReceipt = await common.sendTransaction(deleteInvestorFromAllBlacklistAction); let deleteInvestorFromAllBlacklistEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, deleteInvestorFromAllBlacklistReceipt.logs, 'DeleteInvestorFromBlacklist'); @@ -999,6 +1016,7 @@ async function manageExistingBlacklist(blacklistName) { let currentBlacklist = await currentTransferManager.methods.blacklists(blacklistName).call(); let investors = await currentTransferManager.methods.getListOfAddresses(blacklistName).call(); + console.log(); console.log(`- Name: ${web3.utils.hexToUtf8(blacklistName)}`); console.log(`- Start time: ${moment.unix(currentBlacklist.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); console.log(`- End time: ${moment.unix(currentBlacklist.endTime).format('MMMM Do YYYY, HH:mm:ss')}`); From 5c14bcb73568873e9f35b11702301ebaa9f6433b Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 21 Dec 2018 15:22:36 -0300 Subject: [PATCH 469/582] CLI typo fix --- CLI/commands/transfer_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 24a70cd24..befff8472 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -839,7 +839,7 @@ async function getApprovalsArray() { async function processApprovalsArray(array) { let result = [] - for (const item in array) { + for (const item of array) { let ap = await currentTransferManager.methods.approvals(item).call(); result.push(ap) }; From d6ed74766ed6242972dc1e49469e37e68089a547 Mon Sep 17 00:00:00 2001 From: satyam Date: Sat, 22 Dec 2018 00:37:37 +0530 Subject: [PATCH 470/582] bug fixes --- .../TransferManager/BlacklistTransferManager.sol | 10 +++++++--- test/z_blacklist_transfer_manager.js | 11 ++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index 3b0812cd7..ebde31583 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -223,6 +223,9 @@ contract BlacklistTransferManager is ITransferManager { function addInvestorToBlacklist(address _investor, bytes32 _blacklistName) public withPerm(ADMIN) { require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); require(_investor != address(0), "Invalid investor address"); + uint256 index = investorToIndex[_investor][_blacklistName]; + if (index < investorToBlacklist[_investor].length) + require(investorToBlacklist[_investor][index] != _blacklistName, "Blacklist already added to investor"); uint256 investorIndex = investorToBlacklist[_investor].length; // Add blacklist index to the investor investorToIndex[_investor][_blacklistName] = investorIndex; @@ -277,7 +280,8 @@ contract BlacklistTransferManager is ITransferManager { function deleteInvestorFromAllBlacklist(address _investor) public withPerm(ADMIN) { require(_investor != address(0), "Invalid investor address"); require(investorToBlacklist[_investor].length != 0, "Investor is not associated to any blacklist type"); - for(uint256 i = 0; i < investorToBlacklist[_investor].length; i++){ + uint256 index = investorToBlacklist[_investor].length - 1; + for (uint256 i = index; i >= 0 && i <= index; i--){ deleteInvestorFromBlacklist(_investor, investorToBlacklist[_investor][i]); } } @@ -304,7 +308,7 @@ contract BlacklistTransferManager is ITransferManager { // delete the investor from the blacklist type uint256 _blacklistIndex = blacklistToIndex[_blacklistName][_investor]; uint256 _len = blacklistToInvestor[_blacklistName].length; - if ( _blacklistIndex != _len) { + if ( _blacklistIndex < _len -1) { blacklistToInvestor[_blacklistName][_blacklistIndex] = blacklistToInvestor[_blacklistName][_len - 1]; blacklistToIndex[_blacklistName][blacklistToInvestor[_blacklistName][_blacklistIndex]] = _blacklistIndex; } @@ -314,7 +318,7 @@ contract BlacklistTransferManager is ITransferManager { // delete the blacklist from the investor uint256 _investorIndex = investorToIndex[_investor][_blacklistName]; _len = investorToBlacklist[_investor].length; - if ( _investorIndex != _len) { + if ( _investorIndex < _len -1) { investorToBlacklist[_investor][_investorIndex] = investorToBlacklist[_investor][_len - 1]; investorToIndex[_investor][investorToBlacklist[_investor][_investorIndex]] = _investorIndex; } diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index 07a5a3eb8..d8582c972 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -728,11 +728,11 @@ contract('BlacklistTransferManager', accounts => { }); it("Should delete the investor from all the associated blacklist", async() => { + let data = await I_BlacklistTransferManager.getBlacklistNamesToUser.call(account_investor1); await I_BlacklistTransferManager.addBlacklistType(latestTime()+1000, latestTime()+3000, "g_blacklist", 20, { from: token_owner }); await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, "g_blacklist", { from: token_owner }); let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklist(account_investor1, { from: token_owner }); assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in deleting the investor from the blacklist"); - }); it("Only owner has the permission to delete the investor from all the blacklist type", async() => { @@ -766,10 +766,9 @@ contract('BlacklistTransferManager', accounts => { let investor = [account_investor5,account_investor2]; let tx = await I_BlacklistTransferManager.deleteInvestorFromAllBlacklistMulti(investor, { from: token_owner }); let event_data = tx.logs; - for (var i = 0; i < event_data.length; i++) { - let investorName = event_data[i].args._investor; - assert.equal(investorName.toLowerCase(), investor[i].toLowerCase(), "Failed in deleting the blacklist"); - } + assert.equal(event_data[0].args._investor, investor[0], "Failed in deleting the blacklist"); + assert.equal(event_data[1].args._investor, investor[1], "Failed in deleting the blacklist"); + assert.equal(event_data[2].args._investor, investor[1], "Failed in deleting the blacklist"); }); it("Should fail in deleting the mutiple investor from all the associated blacklist because only owner can do it.", async() => { @@ -947,8 +946,6 @@ contract('BlacklistTransferManager', accounts => { let perm = await I_BlacklistTransferManager.getPermissions.call(); assert.equal(perm.length, 1); }); - - }); describe("Test cases for the factory", async() => { From fef44d0ad18f9592bc8a3076f193ec44cca801d6 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 21 Dec 2018 16:25:49 -0300 Subject: [PATCH 471/582] CLI updates --- CLI/commands/dividends_manager.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index f65074f88..15b624953 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -39,7 +39,6 @@ async function executeApp() { } let options = ['Create checkpoint', 'Explore address balances']; - if (nonArchivedModules.length > 0) { options.push('Config existing modules'); } @@ -126,11 +125,15 @@ async function dividendsManager() { let currentDividends = await getDividends(); let defaultExcluded = await currentDividendsModule.methods.getDefaultExcluded().call(); + let currentCheckpointId = await securityToken.methods.currentCheckpointId().call(); console.log(`- Current dividends: ${currentDividends.length}`); console.log(`- Default exclusions: ${defaultExcluded.length}`); let options = ['Create checkpoint']; + if (currentCheckpointId > 0) { + options.push('Explore checkpoint'); + } if (defaultExcluded.length > 0) { options.push('Show current default exclusions'); } @@ -150,6 +153,8 @@ async function dividendsManager() { case 'Create checkpoint': await createCheckpointFromDividendModule(); break; + case 'Explore checkpoint': + await exploreCheckpoint(); case 'Show current default exclusions': showExcluded(defaultExcluded); break; @@ -181,6 +186,22 @@ async function createCheckpointFromDividendModule() { console.log(chalk.green(`Checkpoint have been created successfully!`)); } +async function exploreCheckpoint() { + let checkpoint = await selectCheckpoint(false); + + let checkpointData = await currentDividendsModule.methods.getCheckpointData(checkpoint).call(); + let dataTable = [['Investor', `Balance at checkpoint (${tokenSymbol})`, 'Tax withholding set (%)']]; + for (let i = 0; i < checkpointData.investors.length; i++) { + dataTable.push([ + checkpointData.investors[i], + web3.utils.fromWei(checkpointData.balances[i]), + parseFloat(web3.utils.fromWei(checkpointData.withholdings[i])) * 100 + ]); + } + console.log(); + console.log(table(dataTable)); +} + async function setDefaultExclusions() { console.log(chalk.yellow(`Excluded addresses will be loaded from 'exclusions_data.csv'. Please check your data before continue.`)); if (readlineSync.keyInYNStrict(`Do you want to continue?`)) { @@ -432,11 +453,11 @@ function showReport(_name, _tokenSymbol, _amount, _witthheld, _claimed, _investo for (let i = 0; i < _investorArray.length; i++) { let investor = _investorArray[i]; let excluded = _excludedArray[i]; - let amount = !excluded ? web3.utils.fromWei(_amountArray[i]) : 0; - let withheld = !excluded ? web3.utils.fromWei(_withheldArray[i]) : 'NA'; - let withheldPercentage = !excluded ? (withheld !== '0' ? parseFloat(withheld) / parseFloat(amount) * 100 : 0) : 'NA'; - let received = !excluded ? web3.utils.fromWei(web3.utils.toBN(_amountArray[i]).sub(web3.utils.toBN(_withheldArray[i]))) : 0; let withdrawn = _claimedArray[i] ? 'YES' : 'NO'; + let amount = !excluded ? web3.utils.fromWei(_amountArray[i]) : 0; + let withheld = (!excluded && _claimedArray[i]) ? web3.utils.fromWei(_withheldArray[i]) : 'NA'; + let withheldPercentage = (!excluded && _claimedArray[i]) ? (withheld !== '0' ? parseFloat(withheld) / parseFloat(amount) * 100 : 0) : 'NA'; + let received = (!excluded && _claimedArray[i]) ? web3.utils.fromWei(web3.utils.toBN(_amountArray[i]).sub(web3.utils.toBN(_withheldArray[i]))) : 0; dataTable.push([ investor, amount, From 214863666bfa54258cf7d49db1ea12d922fff4af Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Mon, 31 Dec 2018 14:32:08 +0800 Subject: [PATCH 472/582] finished test case 4 --- ...zer_volumn_restriction_transfer_manager.js | 150 ++++++++++++------ 1 file changed, 102 insertions(+), 48 deletions(-) diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index def755227..4d8d5db76 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -224,7 +224,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should work with multiple transaction within 1 day with Individual and daily Restrictions", async() => { // let snapId = await takeSnapshot(); - var testRepeat = 5; + var testRepeat = 1; for (var i = 0; i < testRepeat; i++) { @@ -320,14 +320,14 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should work with fuzz test for individual restriction and general restriction", async() => { // let snapId = await takeSnapshot(); - var testRepeat = 0; + var testRepeat = 1; for (var i = 0; i < testRepeat; i++) { console.log("fuzzer number " + i); var individualRestrictTotalAmount = Math.floor(Math.random() * 10); - if ( individualRestrictTotalAmount == 0 ) { + if (individualRestrictTotalAmount == 0 ) { individualRestrictTotalAmount = 1; } var defaultRestrictionAmount = Math.floor(Math.random() * 10); @@ -362,33 +362,30 @@ contract('VolumeRestrictionTransferManager', accounts => { ); console.log("c"); - var txNumber = 10; //define fuzz test amount for tx - - for (var j=0; j individualRestrictTotalAmount || accumulatedTxValue > defaultRestrictionAmount){ - + if (accumulatedTxValue > individualRestrictTotalAmount || accumulatedTxValue > defaultRestrictionAmount) { console.log("tx should fail"); - await catchRevert( + await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) - ); + ); console.log("tx failed as expected due to over limit"); + } else if (accumulatedTxValue <= individualRestrictTotalAmount) { - } else if (accumulatedTxValue <= individualRestrictTotalAmount ){ - console.log("tx should succeed"); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); @@ -418,17 +415,13 @@ contract('VolumeRestrictionTransferManager', accounts => { // check against daily and total restrictions to determine if the transaction should pass or not - if(accumulatedTxValue > defaultRestrictionAmount){ - + if (accumulatedTxValue > defaultRestrictionAmount) { console.log("tx should fail"); - await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) - ); - + ); console.log("tx failed as expected due to over limit"); - - } else if ( accumulatedTxValue <= defaultRestrictionAmount ){ + } else if ( accumulatedTxValue <= defaultRestrictionAmount ) { console.log("tx should succeed"); @@ -453,29 +446,28 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should work with fuzz test for randomly adding / removing individual daily restriction and perform multipel transactions", async() => { - var testRepeat = 0; + var testRepeat = 1; var txNumber = 10; var dailyRestriction = false; var startTime = 1; var sumOfLastPeriod = 0; var accumulatedTimeIncrease = 0; - var dailyLimitUsed = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + var dailyLimitUsed = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (var i = 0; i < testRepeat; i++) { - //randomly add or removing existing daily restriction + // randomly add or removing existing daily restriction var random_action = Math.random() >= 0.5; // true -> add false -> remove - if ( dailyRestriction == false && random_action == true ){ - + if (dailyRestriction === false && random_action === true) { console.log("1"); var dailyRestrictionAmount = Math.floor(Math.random() * 10); - if ( dailyRestrictionAmount == 0) { + if (dailyRestrictionAmount === 0) { dailyRestrictionAmount = 1; } - //add daily restriction + // add daily restriction let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor1, web3.utils.toWei(dailyRestrictionAmount.toString()), @@ -490,24 +482,19 @@ contract('VolumeRestrictionTransferManager', accounts => { dailyRestriction = true; console.log("added daily restriction"); - - } else if ( dailyRestriction == true && random_action == false ) { - + } else if (dailyRestriction === true && random_action === false) { console.log("2"); - - //remove daily restriction + // remove daily restriction await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor1, {from: token_owner}); console.log("removed daily restriction"); dailyRestriction = false; } - // perform multiple transactions - for (var j=0; j { // generate a random amount var transactionAmount = Math.floor(Math.random() * 10); - //check today's limit + // check today's limit var dayNumber = Math.floor(accumulatedTimeIncrease/(24*3600)) + 1; var todayLimitUsed = dailyLimitUsed[dayNumber]; console.log("todayLimitUsed is " + todayLimitUsed + " transactionAmount is " + transactionAmount + " dayNumber is " + dayNumber + " dailyRestrictionAmount is " + dailyRestrictionAmount); - // check against daily and total restrictions to determine if the transaction should pass or not - if((todayLimitUsed + transactionAmount) > dailyRestrictionAmount){ - + if ((todayLimitUsed + transactionAmount) > dailyRestrictionAmount) { console.log("tx should fail"); - await catchRevert( + await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) - ); + ); console.log("tx failed as expected due to over limit"); - - } else if ( (todayLimitUsed + transactionAmount) <= dailyRestrictionAmount ){ - + } else if ((todayLimitUsed + transactionAmount) <= dailyRestrictionAmount) { + console.log("tx should succeed"); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); @@ -548,20 +532,90 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log("5"); } - if ( dailyRestriction == true ) { + if (dailyRestriction === true) { - //remove daily restriction + // remove daily restriction await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor1, {from: token_owner}); console.log("removed daily restriction"); } } + }); - }); + it("fuzz test exception list", async () => { + var testRepeat = 1; + + for (var i = 0; i < testRepeat; i++) { + console.log("fuzzer number " + i); + + var individualRestrictTotalAmount = Math.floor(Math.random() * 10); + if (individualRestrictTotalAmount === 0 ) { + individualRestrictTotalAmount = 1; + } + var defaultRestrictionAmount = Math.floor(Math.random() * 10); + var rollingPeriod = 2; + var sumOfLastPeriod = 0; + + console.log("a"); + + // 1 - add individual restriction with a random number + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei(individualRestrictTotalAmount.toString()), + latestTime() + duration.seconds(1), + rollingPeriod, + latestTime() + duration.days(3), + 0, + { + from: token_owner + } + ); + + tx = await I_VolumeRestrictionTM.changeExemptWalletList(account_investor1, true, {from: token_owner}); + + console.log("b"); + + var txNumber = 10; // define fuzz test amount for tx + + for (var j = 0; j < txNumber; j++) { + await increaseTime(duration.seconds(5)); + console.log("2"); + + // generate a random amount + var transactionAmount = Math.floor(Math.random() * 10); + var accumulatedTxValue = transactionAmount + sumOfLastPeriod; + + console.log("sumOfLastPeriod is " + sumOfLastPeriod + " transactionAmount is " + transactionAmount + " individualRestrictTotalAmount is " + individualRestrictTotalAmount + " defaultRestrictionAmount is " + defaultRestrictionAmount); + + // check against daily and total restrictions to determine if the transaction should pass or not + if (accumulatedTxValue > individualRestrictTotalAmount) { + console.log("tx should fail but still succeed due to investor in exempt list"); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); + + console.log("tx passed as expected"); + } else if (accumulatedTxValue <= individualRestrictTotalAmount) { + + console.log("tx should succeed"); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); + + sumOfLastPeriod = sumOfLastPeriod + transactionAmount; + + console.log("tx succeeded"); + } + console.log("3" + txNumber); + }; + + await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor1, {from: token_owner}); + console.log("removed daily restriction"); + } + + }); }); From 85bce980f7605607bbe242aa0322a8332d4da28a Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 2 Jan 2019 11:08:18 +0530 Subject: [PATCH 473/582] repeat period count from the startTime --- .../BlacklistTransferManager.sol | 15 ++++++-------- .../BlacklistTransferManagerFactory.sol | 2 +- test/z_blacklist_transfer_manager.js | 20 ++++++++++++------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/TransferManager/BlacklistTransferManager.sol index ebde31583..d88fea770 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManager.sol @@ -101,18 +101,14 @@ contract BlacklistTransferManager is ITransferManager { uint256 endTimeTemp = blacklists[investorToBlacklist[_from][i]].endTime; uint256 startTimeTemp = blacklists[investorToBlacklist[_from][i]].startTime; uint256 repeatPeriodTimeTemp = blacklists[investorToBlacklist[_from][i]].repeatPeriodTime * 1 days; - // blacklistTime time is used to find the new startTime and endTime - // suppose startTime=500,endTime=1500,repeatPeriodTime=500 then blacklistTime =1500 - // if you add blacklistTime to startTime and endTime i.e startTime = 2000 and endTime = 3000 - uint256 blacklistTime = (endTimeTemp.sub(startTimeTemp)).add(repeatPeriodTimeTemp); /*solium-disable-next-line security/no-block-members*/ if (now > startTimeTemp) { // Find the repeating parameter that will be used to calculate the new startTime and endTime // based on the new current time value /*solium-disable-next-line security/no-block-members*/ - uint256 repeater = (now.sub(startTimeTemp)).div(blacklistTime); + uint256 repeater = (now.sub(startTimeTemp)).div(repeatPeriodTimeTemp); /*solium-disable-next-line security/no-block-members*/ - if (startTimeTemp.add(blacklistTime.mul(repeater)) <= now && endTimeTemp.add(blacklistTime.mul(repeater)) >= now) { + if (startTimeTemp.add(repeatPeriodTimeTemp.mul(repeater)) <= now && endTimeTemp.add(repeatPeriodTimeTemp.mul(repeater)) >= now) { return Result.INVALID; } } @@ -150,9 +146,10 @@ contract BlacklistTransferManager is ITransferManager { /** * @notice Internal function */ - function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName) internal view { + function _validParams(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName, uint256 _repeatPeriodTime) internal view { require(_blacklistName != bytes32(0), "Invalid blacklist name"); require(_startTime >= now && _startTime < _endTime, "Invalid start or end date"); + require(_repeatPeriodTime.mul(1 days) >= _endTime.sub(_startTime) || _repeatPeriodTime == 0); } /** @@ -164,7 +161,7 @@ contract BlacklistTransferManager is ITransferManager { */ function modifyBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName, uint256 _repeatPeriodTime) public withPerm(ADMIN) { require(blacklists[_blacklistName].endTime != 0, "Blacklist type doesn't exist"); - _validParams(_startTime, _endTime, _blacklistName); + _validParams(_startTime, _endTime, _blacklistName, _repeatPeriodTime); blacklists[_blacklistName] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); emit ModifyBlacklistType(_startTime, _endTime, _blacklistName, _repeatPeriodTime); } @@ -342,7 +339,7 @@ contract BlacklistTransferManager is ITransferManager { function _addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName, uint256 _repeatPeriodTime) internal { require(blacklists[_blacklistName].endTime == 0, "Blacklist type already exist"); - _validParams(_startTime, _endTime, _blacklistName); + _validParams(_startTime, _endTime, _blacklistName, _repeatPeriodTime); blacklists[_blacklistName] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); allBlacklists.push(_blacklistName); emit AddBlacklistType(_startTime, _endTime, _blacklistName, _repeatPeriodTime); diff --git a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol index 86357c39c..cdb7c90eb 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol @@ -19,7 +19,7 @@ contract BlacklistTransferManagerFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + version = "2.1.0"; name = "BlacklistTransferManager"; title = "Blacklist Transfer Manager"; description = "Automate blacklist to restrict selling"; diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index d8582c972..0dff595be 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -378,6 +378,14 @@ contract('BlacklistTransferManager', accounts => { ); }); + it("Should fail in adding the blacklist because repeat period is less than the difference of start time and end time", async() => { + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(latestTime() + 1000, latestTime() + duration.days(2), "b_blacklist", 1, { + from: token_owner + }) + ); + }); + it("Should add the mutiple blacklist", async() => { //Add the new blacklist let startTime = [latestTime()+2000,latestTime()+3000]; @@ -562,7 +570,7 @@ contract('BlacklistTransferManager', accounts => { it("Should investor be able to transfer token as it is not in blacklist time period", async() => { // Jump time - await increaseTime(4000); + await increaseTime(duration.seconds(4000)); //Trasfer tokens await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); @@ -574,7 +582,7 @@ contract('BlacklistTransferManager', accounts => { it("Should fail in transfer the tokens as the investor in blacklist", async() => { // Jump time - await increaseTime(1727500); + await increaseTime(duration.days(20) - 1500); await catchRevert( I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 @@ -623,8 +631,7 @@ contract('BlacklistTransferManager', accounts => { it("Should investor fail in transfer token as it is in blacklist time period", async() => { // Jump time - await increaseTime(690800); - + await increaseTime(duration.days(8) - 1000); //Trasfer tokens await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei('1', 'ether'), { @@ -663,8 +670,7 @@ contract('BlacklistTransferManager', accounts => { it("Should investor fail in transfer token as it is in blacklist time period", async() => { // Jump time - await increaseTime(431600); - + await increaseTime(duration.days(5) - 3000); //Trasfer tokens await catchRevert( I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { @@ -966,7 +972,7 @@ contract('BlacklistTransferManager', accounts => { "Allows an issuer to blacklist the addresses.", "Wrong Module added"); assert.equal(await I_BlacklistTransferManagerFactory.version.call(), - "1.0.0", + "2.1.0", "Wrong Module added"); }); From 7b7f3ab18762199b75d7d52bb4b31a5ccd87d561 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 2 Jan 2019 13:53:44 +0800 Subject: [PATCH 474/582] WIP --- ...zer_volumn_restriction_transfer_manager.js | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index 4d8d5db76..0bb7b864c 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -219,12 +219,12 @@ contract('VolumeRestrictionTransferManager', accounts => { }); - describe("Fuzz test", async() => { + describe("Fuzz test", async () => { it("Should work with multiple transaction within 1 day with Individual and daily Restrictions", async() => { // let snapId = await takeSnapshot(); - var testRepeat = 1; + var testRepeat = 2; for (var i = 0; i < testRepeat; i++) { @@ -268,9 +268,9 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ); - + console.log("c"); - var txNumber = 10; //define fuzz test amount for tx within 24 hrs + var txNumber = 10; // define fuzz test amount for tx within 24 hrs for (var j=0; j { console.log("sumOfLastPeriod is " + sumOfLastPeriod + " transactionAmount is " + transactionAmount + " individualRestrictTotalAmount is " + individualRestrictTotalAmount + " dailyRestrictionAmount is " + dailyRestrictionAmount); - // check against daily and total restrictions to determine if the transaction should pass or not - if(accumulatedTxValue > individualRestrictTotalAmount || accumulatedTxValue > dailyRestrictionAmount){ - + if (accumulatedTxValue > individualRestrictTotalAmount || accumulatedTxValue > dailyRestrictionAmount) { console.log("tx should fail"); - await catchRevert( + await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) - ); + ); console.log("tx failed as expected due to over limit"); - } else if (accumulatedTxValue <= individualRestrictTotalAmount && accumulatedTxValue <= dailyRestrictionAmount ){ - + } else if (accumulatedTxValue <= individualRestrictTotalAmount && accumulatedTxValue <= dailyRestrictionAmount) { console.log("tx should succeed"); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); @@ -313,14 +310,11 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor1, {from: token_owner}); await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor1, {from: token_owner}); } - }); - it("Should work with fuzz test for individual restriction and general restriction", async() => { - // let snapId = await takeSnapshot(); - - var testRepeat = 1; + // let snapId = await takeSnapshot(); + var testRepeat = 0; for (var i = 0; i < testRepeat; i++) { @@ -446,7 +440,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should work with fuzz test for randomly adding / removing individual daily restriction and perform multipel transactions", async() => { - var testRepeat = 1; + var testRepeat = 0; var txNumber = 10; var dailyRestriction = false; var startTime = 1; @@ -546,8 +540,8 @@ contract('VolumeRestrictionTransferManager', accounts => { - it("fuzz test exception list", async () => { - var testRepeat = 1; + it("should work in all cases if a sender is added in the exception list", async () => { + var testRepeat = 0; for (var i = 0; i < testRepeat; i++) { console.log("fuzzer number " + i); From 6dcef1f1ff0323c62992a0497b7a3fade01a2dc9 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 2 Jan 2019 16:55:10 +0800 Subject: [PATCH 475/582] fixed functions getActiveApprovalsToUser and added getAllApprovals() both will return all approval details in multiple arrays as requested --- .../ManualApprovalTransferManager.sol | 48 +++++++++++++++++-- test/j_manual_approval_transfer_manager.js | 44 ++++++++++------- 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 486c8b1ef..7488e9c7b 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -312,23 +312,34 @@ contract ManualApprovalTransferManager is ITransferManager { * need to return * @return List of indexes */ - function getActiveApprovalsToUser(address _user) external view returns(uint256[]) { + function getActiveApprovalsToUser(address _user) external view returns(address[], address[], uint256[], uint256[], bytes32[]) { uint256 counter = 0; for (uint256 i = 0; i < approvals.length; i++) { if ((approvals[i].from == _user || approvals[i].to == _user) && approvals[i].expiryTime >= now) counter ++; } - uint256[] memory indexes = new uint256[](counter); + + address[] memory from = new address[](counter); + address[] memory to = new address[](counter); + uint256[] memory allowance = new uint256[](counter); + uint256[] memory expiryTime = new uint256[](counter); + bytes32[] memory description = new bytes32[](counter); + counter = 0; for (i = 0; i < approvals.length; i++) { if ((approvals[i].from == _user || approvals[i].to == _user) && approvals[i].expiryTime >= now) { - indexes[counter] = i; + + from[counter]=approvals[i].from; + to[counter]=approvals[i].to; + allowance[counter]=approvals[i].allowance; + expiryTime[counter]=approvals[i].expiryTime; + description[counter]=approvals[i].description; counter ++; } } - return indexes; + return (from, to, allowance, expiryTime, description); } /** @@ -361,6 +372,35 @@ contract ManualApprovalTransferManager is ITransferManager { return approvals.length; } + /** + * @notice Get the details of all approvals + * @return address[] addresses from + * @return address[] addresses to + * @return uint256[] allowances provided to the approvals + * @return uint256[] expiry times provided to the approvals + * @return bytes32[] descriptions provided to the approvals + */ + function getAllApprovals() external view returns(address[], address[], uint256[], uint256[], bytes32[]) { + address[] memory from = new address[](approvals.length); + address[] memory to = new address[](approvals.length); + uint256[] memory allowance = new uint256[](approvals.length); + uint256[] memory expiryTime = new uint256[](approvals.length); + bytes32[] memory description = new bytes32[](approvals.length); + + for (uint256 i = 0; i < approvals.length; i++) { + + from[i]=approvals[i].from; + to[i]=approvals[i].to; + allowance[i]=approvals[i].allowance; + expiryTime[i]=approvals[i].expiryTime; + description[i]=approvals[i].description; + + } + + return (from, to, allowance, expiryTime, description); + + } + /** * @notice Returns the permissions flag that are associated with ManualApproval transfer manager */ diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index d08389c20..7b93ac773 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -361,14 +361,24 @@ contract("ManualApprovalTransferManager", accounts => { } ); assert.equal((await I_ManualApprovalTransferManager.getTotalApprovalsLength.call()).toNumber(), 1); - let data = await I_ManualApprovalTransferManager.approvals.call(0); - assert.equal(data[0], account_investor1); - assert.equal(data[1], account_investor4); - assert.equal(data[2], web3.utils.toWei("3")); - assert.equal(web3.utils.toUtf8(data[4]), "DESCRIPTION"); - assert.equal((await I_ManualApprovalTransferManager.approvalIndex.call(account_investor1, account_investor4)).toNumber(), 1); }); + it("Should return all approvals correctly", async () => { + + console.log("current approval length is " + (await I_ManualApprovalTransferManager.getTotalApprovalsLength.call()).toNumber()); + + let tx = await I_ManualApprovalTransferManager.getAllApprovals({from: token_owner }); + assert.equal(tx[0][0], account_investor1); + console.log("1"); + assert.equal(tx[1][0], account_investor4); + console.log("2"); + assert.equal(tx[2][0], web3.utils.toWei("3")); + console.log("3"); + assert.equal(tx[3][0], latestTime() + duration.days(1)); + console.log("4"); + assert.equal(web3.utils.toUtf8(tx[4][0]), "DESCRIPTION"); + }) + it("Should try to add the same manual approval for the same `_from` & `_to` address", async() => { await catchRevert( I_ManualApprovalTransferManager.addManualApproval( @@ -424,10 +434,12 @@ contract("ManualApprovalTransferManager", accounts => { let newBal4 = await I_SecurityToken.balanceOf.call(account_investor4); assert.equal((newBal4.minus(oldBal4)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1); - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4)).length, 1) - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor1)).length, 1) - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4))[0], 0); - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor1))[0], 0); + + let tx = await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor1); + let tx2 = await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4); + + assert.equal(tx2[0].length, 1); + assert.equal(tx[0].length, 1); }); it("Should fail to transact after the approval get expired", async() => { @@ -454,7 +466,7 @@ contract("ManualApprovalTransferManager", accounts => { }); it("Should attach the manual approval for the investor4 again", async() => { - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4)).length, 0); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4))[0].length, 0); await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, @@ -594,8 +606,8 @@ contract("ManualApprovalTransferManager", accounts => { it("Should revoke the manual Approval b/w investor4 and 1", async() => { await I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: token_owner}); - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor1)).length, 0); - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4)).length, 0); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor1))[0].length, 0); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4))[0].length, 0); }); it("Should fail to revoke the same manual approval again", async() => { @@ -693,9 +705,9 @@ contract("ManualApprovalTransferManager", accounts => { ); assert.equal(await I_ManualApprovalTransferManager.getTotalApprovalsLength.call(), 2); - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor3)).length , 2); - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor3))[0], 0); - assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor3))[1], 1); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor3))[0].length , 2); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor3))[0][1], account_investor3); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor3))[1][0], account_investor3); let approvalDetail = await I_ManualApprovalTransferManager.getApprovalDetails.call(account_investor2, account_investor3); assert.equal(approvalDetail[0].toNumber(), time); assert.equal(approvalDetail[1].toNumber(), web3.utils.toWei("2", "ether")); From bb3cdefecab1859fa24d71e6fe14524307f9f342 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 2 Jan 2019 16:58:22 +0800 Subject: [PATCH 476/582] edited function description --- .../TransferManager/ManualApprovalTransferManager.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 7488e9c7b..f660ac639 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -310,7 +310,11 @@ contract ManualApprovalTransferManager is ITransferManager { * @notice Returns the all active approvals corresponds to an address * @param _user Address of the holder corresponds to whom list of manual approvals * need to return - * @return List of indexes + * @return address[] addresses from + * @return address[] addresses to + * @return uint256[] allowances provided to the approvals + * @return uint256[] expiry times provided to the approvals + * @return bytes32[] descriptions provided to the approvals */ function getActiveApprovalsToUser(address _user) external view returns(address[], address[], uint256[], uint256[], bytes32[]) { uint256 counter = 0; From babc783f45ba0f4942e1b032cd6a191b5f190055 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 2 Jan 2019 17:09:48 +0530 Subject: [PATCH 477/582] Bumped cappedSTO version --- contracts/modules/STO/CappedSTOFactory.sol | 2 +- test/b_capped_sto.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 3dcd0af72..273389737 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -16,7 +16,7 @@ contract CappedSTOFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + version = "2.1.0"; name = "CappedSTO"; title = "Capped STO"; description = "This smart contract creates a maximum number of tokens (i.e. hard cap) which the total aggregate of tokens acquired by all investors cannot exceed. Security tokens are sent to the investor upon reception of the funds (ETH or POLY), and any security tokens left upon termination of the offering will not be minted."; diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index f5788a7a1..13dff7d85 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -868,7 +868,7 @@ contract("CappedSTO", accounts => { ); let tags = await I_CappedSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "Capped"); - assert.equal(await I_CappedSTOFactory.version.call(), "1.0.0"); + assert.equal(await I_CappedSTOFactory.version.call(), "2.1.0"); }); it("Should fail to change the title -- bad owner", async () => { From 48213f6b2b04ac21625a71b0d49fb160d5966b35 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 2 Jan 2019 17:11:26 +0530 Subject: [PATCH 478/582] MATM version bumped --- .../TransferManager/ManualApprovalTransferManagerFactory.sol | 2 +- test/j_manual_approval_transfer_manager.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 9c5513ee7..3fd33a39b 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -18,7 +18,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "2.0.1"; + version = "2.1.0"; name = "ManualApprovalTransferManager"; title = "Manual Approval Transfer Manager"; description = "Manage transfers using single approvals / blocking"; diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 5779a1c13..dae21b9c1 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -541,7 +541,7 @@ contract("ManualApprovalTransferManager", accounts => { "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.", "Wrong Module added" ); - assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.0.1"); + assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.1.0"); }); it("Should get the tags of the factory", async () => { From cad45621b43b9baae8f88d7466195066987e100c Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 2 Jan 2019 09:28:42 -0300 Subject: [PATCH 479/582] CLI update --- CLI/commands/transfer_manager.js | 44 ++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index befff8472..5e97cd7a9 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -829,38 +829,50 @@ async function getApprovalsArray() { if (address == gbl.constants.ADDRESS_ZERO) { return await getApprovals(); } else { - let approvalsIndex = await getApprovalsToAnAddress(address); - if (!approvalsIndex.length) { + let approvals = await getApprovalsToAnAddress(address); + if (!approvals.length) { console.log(chalk.red(`\nThe address is not listed\n`)) } - return await processApprovalsArray(approvalsIndex) + return approvals; } } -async function processApprovalsArray(array) { - let result = [] - for (const item of array) { - let ap = await currentTransferManager.methods.approvals(item).call(); - result.push(ap) - }; - return result -} - function printMatmRow(from, to, allowance, time, description) { console.log(`\nDescription: ${web3.utils.toAscii(description)}\nFrom ${from} to ${to}\nAllowance: ${web3.utils.fromWei(allowance)}\nExpiry time: ${moment.unix(time).format('MMMM Do YYYY HH:mm')}\n`); } async function getApprovals() { - let totalApprovals = await currentTransferManager.methods.getTotalApprovalsLength().call(); + function ApprovalDetail(_from, _to, _allowance, _expiryTime, _description) { + this.from = _from; + this.to = _to; + this.allowance = _allowance; + this.expiryTime = _expiryTime; + this.description = _description; + } + let results = []; - for (let i = 0; i < totalApprovals; i++) { - results.push(await currentTransferManager.methods.approvals(i).call()); + let approvalDetails = await currentTransferManager.methods.getAllApprovals().call(); + for (let i = 0; i < approvalDetails[0].length; i++) { + results.push(new ApprovalDetail(approvalDetails[0][i], approvalDetails[1][i], approvalDetails[2][i], approvalDetails[3][i], approvalDetails[4][i])); } return results; } async function getApprovalsToAnAddress(address) { - return await currentTransferManager.methods.getActiveApprovalsToUser(address).call(); + function ApprovalDetail(_from, _to, _allowance, _expiryTime, _description) { + this.from = _from; + this.to = _to; + this.allowance = _allowance; + this.expiryTime = _expiryTime; + this.description = _description; + } + + let results = []; + let approvals = await currentTransferManager.methods.getActiveApprovalsToUser(address).call(); + for (let i = 0; i < approvals[0].length; i++) { + results.push(new ApprovalDetail(approvals[0][i], approvals[1][i], approvals[2][i], approvals[3][i], approvals[4][i])); + } + return results; } async function getManualApproval(_from, _to) { From ad29c1b8dfa6626c7f81aec98bdbdb9f5d383063 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 2 Jan 2019 18:21:42 +0530 Subject: [PATCH 480/582] test case fixed --- test/j_manual_approval_transfer_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 9f9904096..82c64ca8d 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -374,7 +374,7 @@ contract("ManualApprovalTransferManager", accounts => { console.log("2"); assert.equal(tx[2][0], web3.utils.toWei("3")); console.log("3"); - assert.equal(tx[3][0], latestTime() + duration.days(1)); + assert.equal(tx[3][0].toNumber(), latestTime() + duration.days(1)); console.log("4"); assert.equal(web3.utils.toUtf8(tx[4][0]), "DESCRIPTION"); }) From 927990cd5d95da92c0f6270bcac2361e0bbb4896 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 2 Jan 2019 19:49:54 +0530 Subject: [PATCH 481/582] Update j_manual_approval_transfer_manager.js --- test/j_manual_approval_transfer_manager.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 82c64ca8d..49a2f9645 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -69,6 +69,7 @@ contract("ManualApprovalTransferManager", accounts => { const stoKey = 3; let expiryTimeMA; + let approvalTime; // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -350,11 +351,12 @@ contract("ManualApprovalTransferManager", accounts => { }); it("Add a manual approval for a 4th investor & return correct length", async () => { + approvalTime = latestTime() + duration.days(1); await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, web3.utils.toWei("3", "ether"), - latestTime() + duration.days(1), + approvalTime, "DESCRIPTION", { from: token_owner @@ -374,7 +376,7 @@ contract("ManualApprovalTransferManager", accounts => { console.log("2"); assert.equal(tx[2][0], web3.utils.toWei("3")); console.log("3"); - assert.equal(tx[3][0].toNumber(), latestTime() + duration.days(1)); + assert.equal(tx[3][0].toNumber(), approvalTime); console.log("4"); assert.equal(web3.utils.toUtf8(tx[4][0]), "DESCRIPTION"); }) From 40cfa3df5d2ea2537d1905ddf57bb0d919363b30 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 3 Jan 2019 10:58:28 +0800 Subject: [PATCH 482/582] WIP --- ...zer_volumn_restriction_transfer_manager.js | 94 ++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index 0bb7b864c..ce668ad26 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -224,7 +224,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should work with multiple transaction within 1 day with Individual and daily Restrictions", async() => { // let snapId = await takeSnapshot(); - var testRepeat = 2; + var testRepeat = 0; for (var i = 0; i < testRepeat; i++) { @@ -605,6 +605,98 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log("3" + txNumber); }; + await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor1, {from: token_owner}); + console.log("removed daily restriction"); + } + }); + + it("should work if IR is modified", async () => { + var testRepeat = 1; + + for (var i = 0; i < testRepeat; i++) { + console.log("fuzzer number " + i); + + var individualRestrictTotalAmount = Math.floor(Math.random() * 10); + if (individualRestrictTotalAmount === 0 ) { + individualRestrictTotalAmount = 1; + } + var defaultRestrictionAmount = Math.floor(Math.random() * 10); + var rollingPeriod = 2; + var sumOfLastPeriod = 0; + + console.log("a"); + + // 1 - add individual restriction with a random number + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei(individualRestrictTotalAmount.toString()), + latestTime() + duration.days(2), + rollingPeriod, + latestTime() + duration.days(5), + 0, + { + from: token_owner + } + ); + + console.log("b"); + + var txNumber = 10; // define fuzz test amount for tx + + for (var j = 0; j < txNumber; j++) { + console.log("starting test number "+j); + + // modify IR + var newIR = Math.floor(Math.random() * 10); + if (newIR === 0 ) { + newIR = 1; + } + + console.log("3"); + console.log(latestTime()); + console.log((await I_VolumeRestrictionTM.individualRestriction(account_investor1, {from: token_owner}))); + console.log(latestTime() + duration.days(1+j)); + await I_VolumeRestrictionTM.modifyIndividualRestriction( + account_investor1, + web3.utils.toWei(newIR.toString()), + latestTime() + duration.days(1+j), + rollingPeriod, + latestTime() + duration.days(5+j), + 0, + { from: token_owner } + ); + + console.log("4"); + let snapId = await takeSnapshot(); + await increaseTime(duration.days(2+j)); + + // generate a random amount + var transactionAmount = Math.floor(Math.random() * 10); + var accumulatedTxValue = transactionAmount + sumOfLastPeriod; + + console.log("sumOfLastPeriod is " + sumOfLastPeriod + " transactionAmount is " + transactionAmount + " individualRestrictTotalAmount is " + individualRestrictTotalAmount + " defaultRestrictionAmount is " + defaultRestrictionAmount); + + // check against daily and total restrictions to determine if the transaction should pass or not + if (accumulatedTxValue > newIR) { + console.log("tx should fail but still succeed due to investor in exempt list"); + + await catchRevert (I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1})); + + console.log("tx failed as expected"); + } else if (accumulatedTxValue <= newIR) { + + console.log("tx should succeed"); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); + + sumOfLastPeriod = sumOfLastPeriod + transactionAmount; + + console.log("tx succeeded"); + } + await revertToSnapshot(snapId); + console.log("finished test number "+j); + }; + await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor1, {from: token_owner}); console.log("removed daily restriction"); } From b13e08ca9032c6de7313427b5c2b91bcf9da1514 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 3 Jan 2019 13:44:47 +0530 Subject: [PATCH 483/582] reinvent the test case --- ...zer_volumn_restriction_transfer_manager.js | 77 +++-- yarn.lock | 319 ++++++------------ 2 files changed, 152 insertions(+), 244 deletions(-) diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index ce668ad26..b03ab6fdc 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -100,6 +100,16 @@ contract('VolumeRestrictionTransferManager', accounts => { return sum; } + async function printIR(data) { + console.log(` + Allowed Tokens : ${data[0].dividedBy(new BigNumber(10).pow(18)).toNumber()} + StartTime : ${data[1].toNumber()} + Rolling Period : ${data[2].toNumber()} + EndTime : ${data[3].toNumber()} + Restriction Type: ${data[4].toNumber() == 0 ? "Fixed" : "Percentage"} + `) + } + before(async() => { // Accounts setup account_polymath = accounts[0]; @@ -610,26 +620,25 @@ contract('VolumeRestrictionTransferManager', accounts => { } }); - it("should work if IR is modified", async () => { + it("Should work if IR is modified", async () => { + + console.log(`\t\t Starting of the IR modification test case`.blue); + var testRepeat = 1; for (var i = 0; i < testRepeat; i++) { - console.log("fuzzer number " + i); - - var individualRestrictTotalAmount = Math.floor(Math.random() * 10); - if (individualRestrictTotalAmount === 0 ) { - individualRestrictTotalAmount = 1; - } - var defaultRestrictionAmount = Math.floor(Math.random() * 10); + console.log("\t\t fuzzer number " + i); + let precision = 100; + var individualRestrictionTotalAmount = Math.floor(Math.random() * (10 * precision - 1 * precision) + 1 * precision) / (1*precision); var rollingPeriod = 2; var sumOfLastPeriod = 0; - console.log("a"); - + console.log(`\t\t Add individual restriction with TotalAmount: ${individualRestrictionTotalAmount}\n`.green); + // 1 - add individual restriction with a random number let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, - web3.utils.toWei(individualRestrictTotalAmount.toString()), + web3.utils.toWei(individualRestrictionTotalAmount.toString()), latestTime() + duration.days(2), rollingPeriod, latestTime() + duration.days(5), @@ -639,23 +648,20 @@ contract('VolumeRestrictionTransferManager', accounts => { } ); - console.log("b"); + console.log(`\t\t Restriction successfully added \n`); var txNumber = 10; // define fuzz test amount for tx for (var j = 0; j < txNumber; j++) { - console.log("starting test number "+j); + console.log(`\t\t Test number: ${j}\n`); // modify IR - var newIR = Math.floor(Math.random() * 10); - if (newIR === 0 ) { - newIR = 1; - } + var newIR = Math.floor(Math.random() * (10 * precision - 1 * precision) + 1 * precision) / (1*precision); - console.log("3"); - console.log(latestTime()); - console.log((await I_VolumeRestrictionTM.individualRestriction(account_investor1, {from: token_owner}))); - console.log(latestTime() + duration.days(1+j)); + printIR(await I_VolumeRestrictionTM.individualRestriction(account_investor1, {from: token_owner})); + + console.log(`\t\t Modification of the IR with new startTime: ${latestTime() + duration.days(1+j)} and new total amount: ${newIR} `.green); + await I_VolumeRestrictionTM.modifyIndividualRestriction( account_investor1, web3.utils.toWei(newIR.toString()), @@ -666,39 +672,36 @@ contract('VolumeRestrictionTransferManager', accounts => { { from: token_owner } ); - console.log("4"); + console.log(`\t\t Successfully IR modified`); let snapId = await takeSnapshot(); await increaseTime(duration.days(2+j)); // generate a random amount - var transactionAmount = Math.floor(Math.random() * 10); - var accumulatedTxValue = transactionAmount + sumOfLastPeriod; - - console.log("sumOfLastPeriod is " + sumOfLastPeriod + " transactionAmount is " + transactionAmount + " individualRestrictTotalAmount is " + individualRestrictTotalAmount + " defaultRestrictionAmount is " + defaultRestrictionAmount); + var transactionAmount = Math.floor(Math.random() * (10 * precision - 1 * precision) + 1 * precision) / (1*precision); // check against daily and total restrictions to determine if the transaction should pass or not - if (accumulatedTxValue > newIR) { - console.log("tx should fail but still succeed due to investor in exempt list"); + if (transactionAmount > newIR) { + console.log("\t\t Tx should fail"); - await catchRevert (I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1})); + await catchRevert ( + I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}) + ); - console.log("tx failed as expected"); - } else if (accumulatedTxValue <= newIR) { + console.log("\t\t Tx failed as expected"); + } else if (transactionAmount <= newIR) { - console.log("tx should succeed"); + console.log("\t\t Tx should succeed"); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); - sumOfLastPeriod = sumOfLastPeriod + transactionAmount; - - console.log("tx succeeded"); + console.log("\t\t Tx succeeded"); } await revertToSnapshot(snapId); - console.log("finished test number "+j); + console.log("\t\t Finished test number "+j); }; await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor1, {from: token_owner}); - console.log("removed daily restriction"); + console.log("\t\t Removed daily restriction"); } }); diff --git a/yarn.lock b/yarn.lock index 63f3ead17..810d278d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,14 +5,12 @@ "@babel/code-frame@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== dependencies: "@babel/highlight" "^7.0.0" "@babel/highlight@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== dependencies: chalk "^2.0.0" esutils "^2.0.2" @@ -38,7 +36,6 @@ "@types/node@^10.3.2": version "10.12.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.2.tgz#d77f9faa027cadad9c912cd47f4f8b07b0fb0864" - integrity sha512-53ElVDSnZeFUUFIYzI8WLQ25IhWzb6vbddNp8UHlXQyU0ET2RhV5zg0NfubzU7iNMh5bBXb0htCzfvrSVNgzaQ== abbrev@1: version "1.1.1" @@ -73,15 +70,9 @@ acorn-dynamic-import@^2.0.0: dependencies: acorn "^4.0.3" -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - dependencies: - acorn "^3.0.4" - -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" +acorn-jsx@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" acorn@^4.0.3: version "4.0.13" @@ -94,7 +85,6 @@ acorn@^5.0.0: acorn@^6.0.2: version "6.0.4" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.4.tgz#77377e7353b72ec5104550aa2d2097a2fd40b754" - integrity sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg== aes-js@3.0.0: version "3.0.0" @@ -104,10 +94,6 @@ aes-js@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072" -ajv-keywords@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" @@ -130,6 +116,15 @@ ajv@^6.1.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.5.3, ajv@^6.6.1: + version "6.6.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -161,11 +156,15 @@ ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" +ansi-regex@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.2.1: +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: @@ -206,13 +205,6 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -arguments-extended@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/arguments-extended/-/arguments-extended-0.0.3.tgz#6107e4917d0eb6f0a4dd66320fc15afc72ef4946" - dependencies: - extended "~0.0.3" - is-extended "~0.0.8" - arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -231,14 +223,6 @@ arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" -array-extended@~0.0.3, array-extended@~0.0.4, array-extended@~0.0.5: - version "0.0.11" - resolved "https://registry.yarnpkg.com/array-extended/-/array-extended-0.0.11.tgz#d7144ae748de93ca726f121009dbff1626d164bd" - dependencies: - arguments-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -293,6 +277,10 @@ assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -982,19 +970,14 @@ big.js@^3.1.3: bignumber.js@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" - integrity sha512-KWTu6ZMVk9sxlDJQh2YH1UOnfDP8O8TpxUxgQG/vKASoSnEjK9aVuOueFaPcQEYQ5fyNXNTOYwYw3099RYebWg== bignumber.js@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" -bignumber.js@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" - -bignumber.js@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-6.0.0.tgz#bbfa047644609a5af093e9cbd83b0461fa3f6002" +bignumber.js@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" "bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" @@ -1092,7 +1075,7 @@ borc@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/borc/-/borc-2.0.3.tgz#08845ea73a6d3211120928ee3929f8dc2de9f52e" dependencies: - bignumber.js "^7.2.1" + bignumber.js "^6.0.0" commander "^2.15.0" ieee754 "^1.1.8" json-text-sequence "^0.1" @@ -1373,9 +1356,9 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" checkpoint-store@^1.1.0: version "1.1.0" @@ -1530,13 +1513,7 @@ colors@^1.1.2: version "1.3.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" -combined-stream@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - dependencies: - delayed-stream "~1.0.0" - -combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" dependencies: @@ -1576,15 +1553,6 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - console-browserify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" @@ -1705,7 +1673,6 @@ cross-spawn@^5.0.1: cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: nice-try "^1.0.4" path-key "^2.0.1" @@ -1761,14 +1728,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -date-extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/date-extended/-/date-extended-0.0.6.tgz#23802d57dd1bf7818813fe0c32e851a86da267c9" - dependencies: - array-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" - date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" @@ -1805,10 +1764,6 @@ decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" -declare.js@~0.0.4: - version "0.0.8" - resolved "https://registry.yarnpkg.com/declare.js/-/declare.js-0.0.8.tgz#0478adff9564c004f51df73d8bc134019d28dcde" - decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -2246,9 +2201,9 @@ escope@^3.6.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-config-standard@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz#87ee0d3c9d95382dc761958cbb23da9eea31e0ba" +eslint-config-standard@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz#638b4c65db0bd5a41319f96bba1f15ddad2107d9" eslint-import-resolver-node@^0.3.1: version "0.3.2" @@ -2267,7 +2222,6 @@ eslint-module-utils@^2.2.0: eslint-plugin-es@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.3.1.tgz#5acb2565db4434803d1d46a9b4cbc94b345bd028" - integrity sha512-9XcVyZiQRVeFjqHw8qHNDAZcQLqaHlOGGpeYqzYh8S4JYCWTCO3yzyen8yVmA5PratfzTRWDwCOFphtDEG+w/w== dependencies: eslint-utils "^1.3.0" regexpp "^2.0.0" @@ -2287,9 +2241,9 @@ eslint-plugin-import@^2.10.0: read-pkg-up "^2.0.0" resolve "^1.6.0" -eslint-plugin-node@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz#bf19642298064379315d7a4b2a75937376fa05e4" +eslint-plugin-node@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-8.0.0.tgz#fb9e8911f4543514f154bb6a5924b599aa645568" dependencies: eslint-plugin-es "^1.3.1" eslint-utils "^1.3.1" @@ -2298,17 +2252,17 @@ eslint-plugin-node@^6.0.1: resolve "^1.8.1" semver "^5.5.0" -eslint-plugin-promise@^3.7.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" +eslint-plugin-promise@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz#2d074b653f35a23d1ba89d8e976a985117d1c6a2" -eslint-plugin-standard@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz#2a9e21259ba4c47c02d53b2d0c9135d4b1022d47" +eslint-plugin-standard@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c" -eslint-scope@^3.7.1: - version "3.7.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" +eslint-scope@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2316,15 +2270,14 @@ eslint-scope@^3.7.1: eslint-utils@^1.3.0, eslint-utils@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" - integrity sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q== eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" -eslint@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" +eslint@^5.8.0: + version "5.11.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.11.1.tgz#8deda83db9f354bf9d3f53f9677af7e0e13eadda" dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.5.3" @@ -2335,7 +2288,7 @@ eslint@^4.19.1: eslint-scope "^4.0.0" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" - espree "^4.0.0" + espree "^5.0.0" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^2.0.0" @@ -2345,7 +2298,6 @@ eslint@^4.19.1: ignore "^4.0.6" imurmurhash "^0.1.4" inquirer "^6.1.0" - is-resolvable "^1.1.0" js-yaml "^3.12.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" @@ -2365,9 +2317,9 @@ eslint@^4.19.1: table "^5.0.2" text-table "^0.2.0" -espree@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" +espree@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.0.tgz#fc7f984b62b36a0f543b13fb9cd7b9f4a7f5b65c" dependencies: acorn "^6.0.2" acorn-jsx "^5.0.0" @@ -2616,9 +2568,9 @@ ethereumjs-wallet@^0.6.0: utf8 "^3.0.0" uuid "^3.3.2" -ethers@^3.0.15: - version "3.0.29" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-3.0.29.tgz#ce8139955b4ed44456eb6764b089bb117c86775d" +ethers@^4.0.7: + version "4.0.20" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.20.tgz#2b072b283bb19f4870daf42cf5593e5375697504" dependencies: "@types/node" "^10.3.2" aes-js "3.0.0" @@ -2767,27 +2719,15 @@ extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" -extended@0.0.6, extended@~0.0.3: - version "0.0.6" - resolved "https://registry.yarnpkg.com/extended/-/extended-0.0.6.tgz#7fb8bf7b9dae397586e48570acfd642c78e50669" - dependencies: - extender "~0.0.5" - -extender@~0.0.5: - version "0.0.10" - resolved "https://registry.yarnpkg.com/extender/-/extender-0.0.10.tgz#589c07482be61a1460b6d81f9c24aa67e8f324cd" - dependencies: - declare.js "~0.0.4" - extendr@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/extendr/-/extendr-2.1.0.tgz#301aa0bbea565f4d2dc8f570f2a22611a8527b56" dependencies: typechecker "~2.0.1" -external-editor@^2.0.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" +external-editor@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -2836,15 +2776,6 @@ fake-merkle-patricia-tree@^1.0.1: dependencies: checkpoint-store "^1.1.0" -fast-csv@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-2.4.1.tgz#bd7dd268391f729367b59445b8dd0ad026881b26" - dependencies: - extended "0.0.6" - is-extended "0.0.10" - object-extended "0.0.7" - string-extended "0.0.8" - fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" @@ -2980,7 +2911,7 @@ form-data@~2.3.2: resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" dependencies: asynckit "^0.4.0" - combined-stream "^1.0.6" + combined-stream "1.0.6" mime-types "^2.1.12" forwarded@~0.1.2: @@ -3053,9 +2984,9 @@ fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -fs@0.0.1-security: - version "0.0.1-security" - resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" +fs@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.2.tgz#e1f244ef3933c1b2a64bd4799136060d0f5914f8" fsevents@^1.0.0, fsevents@^1.2.2: version "1.2.4" @@ -3348,7 +3279,6 @@ hash-base@^3.0.0: hash.js@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.0" @@ -3453,9 +3383,13 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.3.3, ignore@^3.3.6: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + +ignore@^5.0.2: + version "5.0.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.4.tgz#33168af4a21e99b00c5d41cbadb6a6cb49903a45" ignorefs@^1.0.0: version "1.2.0" @@ -3499,9 +3433,9 @@ ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" -inquirer@^3.0.6: - version "3.3.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" +inquirer@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.1.tgz#9943fc4882161bdb0b0c9276769c75b32dbfcd52" dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -3514,7 +3448,7 @@ inquirer@^3.0.6: run-async "^2.2.0" rxjs "^6.1.0" string-width "^2.1.0" - strip-ansi "^4.0.0" + strip-ansi "^5.0.0" through "^2.3.6" interpret@^1.0.0: @@ -3623,12 +3557,6 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extended@0.0.10, is-extended@~0.0.3, is-extended@~0.0.8: - version "0.0.10" - resolved "https://registry.yarnpkg.com/is-extended/-/is-extended-0.0.10.tgz#244e140df75bb1c9a3106f412ff182fb534a6d62" - dependencies: - extended "~0.0.3" - is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" @@ -3761,10 +3689,6 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" -is-resolvable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" @@ -4132,7 +4056,7 @@ lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" -lodash@4.x, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5: +lodash@4.x, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" @@ -4338,15 +4262,15 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" +mime-db@~1.37.0: + version "1.37.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.20" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" dependencies: - mime-db "~1.37.0" + mime-db "~1.36.0" mime@1.4.1: version "1.4.1" @@ -4567,7 +4491,6 @@ next-tick@1: nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== node-async-loop@^1.2.2: version "1.2.2" @@ -4719,14 +4642,6 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-extended@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/object-extended/-/object-extended-0.0.7.tgz#84fd23f56b15582aeb3e88b05cb55d2432d68a33" - dependencies: - array-extended "~0.0.4" - extended "~0.0.3" - is-extended "~0.0.3" - object-inspect@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" @@ -5210,7 +5125,7 @@ react-dom@^16.2.0: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.10.0" + schedule "^0.5.0" react@^16.2.0: version "16.5.2" @@ -5219,7 +5134,7 @@ react@^16.2.0: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.10.0" + schedule "^0.5.0" read-pkg-up@^1.0.1: version "1.0.1" @@ -5338,9 +5253,9 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" +regexpp@^2.0.0, regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" regexpu-core@^2.0.0: version "2.0.0" @@ -5533,15 +5448,11 @@ rustbn.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" +rxjs@^6.1.0: + version "6.3.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + tslib "^1.9.0" safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" @@ -5585,9 +5496,9 @@ scandirectory@^2.5.0: safefs "^3.1.2" taskgroup "^4.0.5" -schedule@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.5.0.tgz#c128fffa0b402488b08b55ae74bb9df55cc29cc8" +scheduler@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.10.0.tgz#7988de90fe7edccc774ea175a783e69c40c521e1" dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5596,9 +5507,9 @@ scrypt-async@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-1.3.1.tgz#a11fd6fac981b4b823ee01dee0221169500ddae9" -scrypt-js@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" +scrypt-js@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" scrypt.js@0.2.0, scrypt.js@^0.2.0: version "0.2.0" @@ -5784,10 +5695,12 @@ slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" +slice-ansi@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.0.0.tgz#5373bdb8559b45676e8541c66916cdd6251612e7" dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: @@ -6071,15 +5984,6 @@ strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" -string-extended@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/string-extended/-/string-extended-0.0.8.tgz#741957dff487b0272a79eec5a44f239ee6f17ccd" - dependencies: - array-extended "~0.0.5" - date-extended "~0.0.3" - extended "~0.0.3" - is-extended "~0.0.3" - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -6125,6 +6029,12 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" + dependencies: + ansi-regex "^4.0.0" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -6207,13 +6117,13 @@ swarm-js@0.1.37: tar.gz "^1.0.5" xhr-request-promise "^0.1.2" -table@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" +table@^5.0.2: + version "5.1.1" + resolved "https://registry.yarnpkg.com/table/-/table-5.1.1.tgz#92030192f1b7b51b6eeab23ed416862e47b70837" dependencies: - ajv "^6.5.3" - lodash "^4.17.10" - slice-ansi "1.0.0" + ajv "^6.6.1" + lodash "^4.17.11" + slice-ansi "2.0.0" string-width "^2.1.1" tapable@^0.2.7: @@ -6419,9 +6329,9 @@ truffle-error@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/truffle-error/-/truffle-error-0.0.3.tgz#4bf55242e14deee1c7194932709182deff2c97ca" -truffle-hdwallet-provider-privkey@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider-privkey/-/truffle-hdwallet-provider-privkey-0.1.0.tgz#9417047a74ad37d923df926154b6486ffb57f6c9" +truffle-hdwallet-provider-privkey@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider-privkey/-/truffle-hdwallet-provider-privkey-0.2.0.tgz#91e9e8a6a5005970a5b442fa89fc198ecd1f71ef" dependencies: ethereumjs-tx "^1.3.4" ethereumjs-wallet "^0.6.0" @@ -6447,7 +6357,6 @@ truffle@4.1.14: tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== tty-browserify@0.0.0: version "0.0.0" @@ -6500,10 +6409,6 @@ typedarray-to-buffer@^3.1.2: dependencies: is-typedarray "^1.0.0" -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" From 1299ca3102486701d6da95eba770e6262e54e1c8 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 3 Jan 2019 09:55:42 -0300 Subject: [PATCH 484/582] Merge conflicts --- CLI/commands/helpers/contract_abis.js | 53 +-- CLI/commands/transfer_manager.js | 543 ++++++++++++++++++++------ 2 files changed, 446 insertions(+), 150 deletions(-) diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index 86b42cea7..e394b2eac 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -22,32 +22,34 @@ let ownableABI; let iSTOABI; let iTransferManagerABI; let moduleFactoryABI; +let erc20ABI; try { - polymathRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolymathRegistry.json').toString()).abi; - securityTokenRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/SecurityTokenRegistry.json').toString()).abi; - featureRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/FeatureRegistry.json').toString()).abi; - moduleRegistryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleRegistry.json').toString()).abi; - securityTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/SecurityToken.json').toString()).abi; - stoInterfaceABI = JSON.parse(require('fs').readFileSync('./build/contracts/ISTO.json').toString()).abi; - cappedSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTO.json').toString()).abi; - usdTieredSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTO.json').toString()).abi; - generalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralTransferManager.json').toString()).abi; - manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ManualApprovalTransferManager.json').toString()).abi; - countTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/CountTransferManager.json').toString()).abi; - percentageTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/PercentageTransferManager.json').toString()).abi; - volumeRestrictionTMABI = JSON.parse(require('fs').readFileSync('./build/contracts/VolumeRestrictionTM.json').toString()).abi; - generalPermissionManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/GeneralPermissionManager.json').toString()).abi; - polyTokenABI = JSON.parse(require('fs').readFileSync('./build/contracts/PolyTokenFaucet.json').toString()).abi; - cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/CappedSTOFactory.json').toString()).abi; - usdTieredSTOFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/USDTieredSTOFactory.json').toString()).abi; - erc20DividendCheckpointABI = JSON.parse(require('fs').readFileSync('./build/contracts/ERC20DividendCheckpoint.json').toString()).abi; - etherDividendCheckpointABI = JSON.parse(require('fs').readFileSync('./build/contracts/EtherDividendCheckpoint.json').toString()).abi; - moduleInterfaceABI = JSON.parse(require('fs').readFileSync('./build/contracts/IModule.json').toString()).abi; - ownableABI = JSON.parse(require('fs').readFileSync('./build/contracts/Ownable.json').toString()).abi; - iSTOABI = JSON.parse(require('fs').readFileSync('./build/contracts/ISTO.json').toString()).abi - iTransferManagerABI = JSON.parse(require('fs').readFileSync('./build/contracts/ITransferManager.json').toString()).abi - moduleFactoryABI = JSON.parse(require('fs').readFileSync('./build/contracts/ModuleFactory.json').toString()).abi; + polymathRegistryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PolymathRegistry.json`).toString()).abi; + securityTokenRegistryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/SecurityTokenRegistry.json`).toString()).abi; + featureRegistryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/FeatureRegistry.json`).toString()).abi; + moduleRegistryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ModuleRegistry.json`).toString()).abi; + securityTokenABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/SecurityToken.json`).toString()).abi; + stoInterfaceABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ISTO.json`).toString()).abi; + cappedSTOABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/CappedSTO.json`).toString()).abi; + usdTieredSTOABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/USDTieredSTO.json`).toString()).abi; + generalTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/GeneralTransferManager.json`).toString()).abi; + manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ManualApprovalTransferManager.json`).toString()).abi; + countTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/CountTransferManager.json`).toString()).abi; + percentageTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PercentageTransferManager.json`).toString()).abi; + volumeRestrictionTMABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/VolumeRestrictionTM.json`).toString()).abi; + generalPermissionManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/GeneralPermissionManager.json`).toString()).abi; + polyTokenABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PolyTokenFaucet.json`).toString()).abi; + cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/CappedSTOFactory.json`).toString()).abi; + usdTieredSTOFactoryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/USDTieredSTOFactory.json`).toString()).abi; + erc20DividendCheckpointABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ERC20DividendCheckpoint.json`).toString()).abi; + etherDividendCheckpointABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/EtherDividendCheckpoint.json`).toString()).abi; + moduleInterfaceABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/IModule.json`).toString()).abi; + ownableABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/Ownable.json`).toString()).abi; + iSTOABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ISTO.json`).toString()).abi + iTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ITransferManager.json`).toString()).abi + moduleFactoryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ModuleFactory.json`).toString()).abi; + erc20ABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/DetailedERC20.json`).toString()).abi; } catch (err) { console.log('\x1b[31m%s\x1b[0m', "Couldn't find contracts' artifacts. Make sure you ran truffle compile first"); throw err; @@ -125,5 +127,8 @@ module.exports = { }, moduleFactory: function () { return moduleFactoryABI; + }, + erc20: function () { + return erc20ABI; } } \ No newline at end of file diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 3d6dd8906..378ab2d22 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -10,6 +10,7 @@ const { table } = require('table') /////////////////// // Constants +<<<<<<< HEAD const WHITELIST_DATA_CSV = './CLI/data/Transfer/GTM/whitelist_data.csv'; const PERCENTAGE_WHITELIST_DATA_CSV = './CLI/data/Transfer/PercentageTM/whitelist_data.csv'; const ADD_DAILY_RESTRICTIONS_DATA_CSV = './CLI/data/Transfer/VRTM/add_daily_restriction_data.csv'; @@ -20,6 +21,25 @@ const MODIFY_RESTRICTIONS_DATA_CSV = './CLI/data/Transfer/VRTM/modify_restrictio const REMOVE_RESTRICTIONS_DATA_CSV = './CLI/data/Transfer/VRTM/remove_restriction_data.csv'; const RESTRICTION_TYPES = ['Fixed', 'Percentage']; +======= +const WHITELIST_DATA_CSV = `${__dirname}/../data/Transfer/GTM/whitelist_data.csv`; +const PERCENTAGE_WHITELIST_DATA_CSV = `${__dirname}/../data/Transfer/PercentageTM/whitelist_data.csv`; +const ADD_MANUAL_APPROVAL_DATA_CSV = `${__dirname}/../data/Transfer/MATM/add_manualapproval_data.csv`; +const MODIFY_MANUAL_APPROVAL_DATA_CSV = `${__dirname}/../data/Transfer/MATM/modify_manualapproval_data.csv`; +const REVOKE_MANUAL_APPROVAL_DATA_CSV = `${__dirname}/../data/Transfer/MATM/revoke_manualapproval_data.csv`; + +const MATM_MENU_ADD = 'Add new manual approval'; +const MATM_MENU_MANAGE = 'Manage existing approvals'; +const MATM_MENU_EXPLORE = 'Explore account'; +const MATM_MENU_OPERATE = 'Operate with multiple approvals'; +const MATM_MENU_MANAGE_INCRESE = 'Increase allowance'; +const MATM_MENU_MANAGE_DECREASE = 'Decrease allowance'; +const MATM_MENU_MANAGE_TIME = 'Modify expiry time and/or description'; +const MATM_MENU_MANAGE_REVOKE = 'Revoke this approval'; +const MATM_MENU_OPERATE_ADD = 'Add multiple approvals in batch'; +const MATM_MENU_OPERATE_MODIFY = 'Modify multiple approvals in batch'; +const MATM_MENU_OPERATE_REVOKE = 'Revoke multiple approvals in batch'; +>>>>>>> dev-2.1.0 // App flow let tokenSymbol; @@ -477,17 +497,27 @@ function showWhitelistTable(investorsArray, fromTimeArray, toTimeArray, expiryTi console.log(table(dataTable)); } -async function modifyWhitelistInBatch() { - let csvFilePath = readlineSync.question(`Enter the path for csv data file (${WHITELIST_DATA_CSV}): `, { - defaultInput: WHITELIST_DATA_CSV - }); - let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { - limit: function (input) { - return parseInt(input) > 0; - }, - limitMessage: 'Must be greater than 0', - defaultInput: gbl.constants.DEFAULT_BATCH_SIZE - }); +async function modifyWhitelistInBatch(_csvFilePath, _batchSize) { + let csvFilePath; + if (typeof _csvFilePath === 'undefined') { + csvFilePath = readlineSync.question(`Enter the path for csv data file (${WHITELIST_DATA_CSV}): `, { + defaultInput: WHITELIST_DATA_CSV + }); + } else { + csvFilePath = _csvFilePath; + } + let batchSize; + if (typeof _batchSize === 'undefined') { + batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + } else { + batchSize = _batchSize; + } let parsedData = csvParse(csvFilePath); let validData = parsedData.filter(row => web3.utils.isAddress(row[0]) && @@ -514,38 +544,27 @@ async function modifyWhitelistInBatch() { async function manualApprovalTransferManager() { console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address} `), '\n'); - let options = ['Check manual approval', 'Add manual approval', 'Revoke manual approval', - 'Check manual blocking', 'Add manual blocking', 'Revoke manual blocking']; + let totalApprovals = await currentTransferManager.methods.getTotalApprovalsLength().call(); + console.log(`- Current active approvals: ${totalApprovals}`); + + let matmOptions = [ + MATM_MENU_ADD, + MATM_MENU_MANAGE, + MATM_MENU_EXPLORE, + MATM_MENU_OPERATE + ]; + + let index = readlineSync.keyInSelect(matmOptions, 'What do you want to do?', { + cancel: 'RETURN' + }); + let optionSelected = index != -1 ? matmOptions[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Return' }); - let optionSelected = options[index]; - console.log('Selected:', index != -1 ? optionSelected : 'Return', '\n'); - let from; - let to; switch (optionSelected) { - case 'Check manual approval': - from = readlineSync.question('Enter the address from which transfers would be approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers would be approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - console.log(); - let manualApproval = await getManualApproval(from, to); - if (manualApproval) { - console.log(`Manual approval found!`); - console.log(`Allowance: ${web3.utils.fromWei(manualApproval.allowance)}`); - console.log(`Expiry time: ${moment.unix(manualApproval.expiryTime).format('MMMM Do YYYY, HH:mm:ss')}`); - } else { - console.log(chalk.yellow(`There are no manual approvals from ${from} to ${to}.`)); - } + case MATM_MENU_ADD: + await matmAdd(); break; +<<<<<<< HEAD case 'Add manual approval': from = readlineSync.question('Enter the address from which transfers will be approved: ', { limit: function (input) { @@ -570,64 +589,86 @@ async function manualApprovalTransferManager() { } else { console.log(chalk.red(`A manual approval already exists from ${from} to ${to}.Revoke it first if you want to add a new one.`)); } +======= + case MATM_MENU_MANAGE: + await matmManage(); +>>>>>>> dev-2.1.0 break; - case 'Revoke manual approval': - from = readlineSync.question('Enter the address from which transfers were approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers were approved: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - if (await getManualApproval(from, to)) { - let revokeManualApprovalAction = currentTransferManager.methods.revokeManualApproval(from, to); - let revokeManualApprovalReceipt = await common.sendTransaction(revokeManualApprovalAction); - let revokeManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, revokeManualApprovalReceipt.logs, 'RevokeManualApproval'); - console.log(chalk.green(`Manual approval has been revoked successfully!`)); - } else { - console.log(chalk.red(`Manual approval from ${from} to ${to} does not exist.`)); - } + case MATM_MENU_EXPLORE: + await matmExplore(); break; - case 'Check manual blocking': - from = readlineSync.question('Enter the address from which transfers would be blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers would be blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - console.log(); - let manualBlocking = await getManualBlocking(from, to); - if (manualBlocking) { - console.log(`Manual blocking found!`); - console.log(`Expiry time: ${moment.unix(manualBlocking).format('MMMM Do YYYY, HH:mm:ss')}; `) - } else { - console.log(chalk.yellow(`There are no manual blockings from ${from} to ${to}.`)); - } + case MATM_MENU_OPERATE: + await matmOperate(); break; - case 'Add manual blocking': - from = readlineSync.question('Enter the address from which transfers will be blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers will be blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" + case 'RETURN': + return; + } + + await manualApprovalTransferManager(); +} + +async function matmAdd() { + let from = readlineSync.question('Enter the address from which transfers will be approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let to = readlineSync.question('Enter the address to which transfers will be approved: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + if (!await getManualApproval(from, to)) { + let description = readlineSync.question('Enter the description for the manual approval: ', { + limit: function (input) { + return input != "" && getBinarySize(input) < 33 + }, + limitMessage: "Description is required" + }); + let allowance = readlineSync.question('Enter the amount of tokens which will be approved: '); + let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); + let expiryTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) until which the transfer is allowed (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let addManualApprovalAction = currentTransferManager.methods.addManualApproval(from, to, web3.utils.toWei(allowance), expiryTime, web3.utils.fromAscii(description)); + let addManualApprovalReceipt = await common.sendTransaction(addManualApprovalAction); + let addManualApprovalEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addManualApprovalReceipt.logs, 'AddManualApproval'); + console.log(chalk.green(`Manual approval has been added successfully!`)); + } else { + console.log(chalk.red(`A manual approval already exists from ${from} to ${to}. Revoke it first if you want to add a new one or modify the existing one.`)); + } +} + +async function matmManage() { + + let manageOptions = [ + MATM_MENU_MANAGE_INCRESE, + MATM_MENU_MANAGE_DECREASE, + MATM_MENU_MANAGE_TIME, + MATM_MENU_MANAGE_REVOKE + ]; + + let getApprovals = await getApprovalsArray(); + + if (getApprovals.length > 0) { + let options = [] + getApprovals.forEach((item) => { + options.push(`${web3.utils.toAscii(item.description)}\n From: ${item.from}\n To: ${item.to}\n Amount: ${web3.utils.fromWei(item.allowance)} ${tokenSymbol}\n Expiry date: ${moment.unix(item.expiryTime).format('MM/DD/YYYY HH:mm')}\n`) + }) + + let index = readlineSync.keyInSelect(options, 'Select an existing approval: ', { + cancel: 'RETURN' + }); + let optionSelected = index != -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + + if (optionSelected !== 'RETURN') { + let selectedApproval = getApprovals[index]; + + let index2 = readlineSync.keyInSelect(manageOptions, 'What do you want to do?', { + cancel: 'RETURN' }); +<<<<<<< HEAD if (!await getManualBlocking(from, to)) { let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); let expiryTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) until which the transfer is blocked (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); @@ -637,53 +678,295 @@ async function manualApprovalTransferManager() { console.log(chalk.green(`Manual blocking has been added successfully!`)); } else { console.log(chalk.red(`A manual blocking already exists from ${from} to ${to}.Revoke it first if you want to add a new one.`)); +======= + let optionSelected2 = index2 != -1 ? manageOptions[index2] : 'RETURN'; + console.log('Selected:', optionSelected2, '\n'); + + if (optionSelected2 !== 'RETURN') { + switch (optionSelected2) { + case MATM_MENU_MANAGE_INCRESE: + await matmManageIncrese(selectedApproval); + break; + case MATM_MENU_MANAGE_DECREASE: + await matmManageDecrease(selectedApproval); + break; + case MATM_MENU_MANAGE_TIME: + await matmManageTimeOrDescription(selectedApproval); + break; + case MATM_MENU_MANAGE_REVOKE: + await matmManageRevoke(selectedApproval); + break; + } +>>>>>>> dev-2.1.0 } + } + } else { + console.log(chalk.yellow(`There are no existing approvals to show`)); + } +} + +async function matmExplore() { + let getApprovals = await getApprovalsArray(); + getApprovals.forEach((item) => { + printMatmRow(item.from, item.to, item.allowance, item.expiryTime, item.description); + }) +} + +async function matmOperate() { + let operateOptions = [ + MATM_MENU_OPERATE_ADD, + MATM_MENU_OPERATE_MODIFY, + MATM_MENU_OPERATE_REVOKE + ]; + + let index = readlineSync.keyInSelect(operateOptions, 'What do you want to do?', { + cancel: 'RETURN' + }); + let optionSelected = index != -1 ? operateOptions[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + + switch (optionSelected) { + case MATM_MENU_OPERATE_ADD: + await addManualApproveInBatch(); break; - case 'Revoke manual blocking': - from = readlineSync.question('Enter the address from which transfers were blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - to = readlineSync.question('Enter the address to which transfers were blocked: ', { - limit: function (input) { - return web3.utils.isAddress(input); - }, - limitMessage: "Must be a valid address" - }); - if (await getManualBlocking(from, to)) { - let revokeManualBlockingAction = currentTransferManager.methods.revokeManualBlocking(from, to); - let revokeManualBlockingReceipt = await common.sendTransaction(revokeManualBlockingAction); - let revokeManualBlockingEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, revokeManualBlockingReceipt.logs, 'RevokeManualBlocking'); - console.log(chalk.green(`Manual blocking has been revoked successfully!`)); - } else { - console.log(chalk.red(`Manual blocking from ${from} to ${to} does not exist.`)); - } + case MATM_MENU_OPERATE_MODIFY: + await modifyManualApproveInBatch(); break; + case MATM_MENU_OPERATE_REVOKE: + await revokeManualApproveInBatch(); + break; + } +} + +async function matmManageIncrese(selectedApproval) { + let allowance = readlineSync.question(`Enter a value to increase allowance (current allowance = ${web3.utils.fromWei(selectedApproval.allowance)}): `, { + limit: function (input) { + return parseFloat(input) > 0 + }, + limitMessage: "Amount must be bigger than 0" + }); + + if (readlineSync.keyInYNStrict(`Do you want to modify expiry time or description?`)) { + let { expiryTime, description } = readExpiryTimeAndDescription(selectedApproval); + selectedApproval.expiryTime = expiryTime; + selectedApproval.description = web3.utils.fromAscii(description); + } + + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(selectedApproval.expiryTime), web3.utils.toWei(allowance), selectedApproval.description, 1); + await common.sendTransaction(modifyManualApprovalAction); + console.log(chalk.green(`The approval allowance has been increased successfully!`)); +} + +async function matmManageDecrease(selectedApproval) { + let allowance = readlineSync.question(`Enter a value to decrease allowance (current allowance = ${web3.utils.fromWei(selectedApproval.allowance)}): `, { + limit: function (input) { + return parseFloat(input) > 0 + }, + limitMessage: "Amount must be bigger than 0" + }); + + if (readlineSync.keyInYNStrict(`Do you want to modify expiry time or description?`)) { + let { expiryTime, description } = readExpiryTimeAndDescription(selectedApproval); + selectedApproval.expiryTime = expiryTime; + selectedApproval.description = web3.utils.fromAscii(description); + } + + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(selectedApproval.expiryTime), web3.utils.toWei(allowance), selectedApproval.description, 0); + await common.sendTransaction(modifyManualApprovalAction); + console.log(chalk.green(`The approval allowance has been decreased successfully!`)); +} + +async function matmManageTimeOrDescription(selectedApproval) { + let { expiryTime, description } = readExpiryTimeAndDescription(selectedApproval); + + let modifyManualApprovalAction = currentTransferManager.methods.modifyManualApproval(selectedApproval.from, selectedApproval.to, parseInt(expiryTime), selectedApproval.allowance, web3.utils.fromAscii(description), 2); + await common.sendTransaction(modifyManualApprovalAction); + console.log(chalk.green(`The approval expiry time has been modified successfully!`)); +} + +function readExpiryTimeAndDescription(selectedApproval) { + let expiryTime = readlineSync.questionInt(`Enter the new expiry time (Unix Epoch time) until which the transfer is allowed or leave empty to keep the current (${selectedApproval.expiryTime}): `, { + limit: function (input) { + return parseFloat(input) > 0; + }, + limitMessage: "Enter Unix Epoch time", + defaultInput: selectedApproval.expiryTime + }); + let description = readlineSync.question(`Enter the new description for the manual approval or leave empty to keep the current (${web3.utils.toAscii(selectedApproval.description)}): `, { + limit: function (input) { + return input != "" && getBinarySize(input) < 33; + }, + limitMessage: "Description is required" + }); + return { expiryTime, description }; +} + +async function matmManageRevoke(selectedApproval) { + let modifyManualApprovalAction = currentTransferManager.methods.revokeManualApproval(selectedApproval.from, selectedApproval.to); + await common.sendTransaction(modifyManualApprovalAction); + console.log(chalk.green(`The approval has been revoked successfully!`)); +} + +async function getApprovalsArray() { + let address = readlineSync.question('Enter an address to filter or leave empty to get all the approvals: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: gbl.constants.ADDRESS_ZERO + }); + if (address == gbl.constants.ADDRESS_ZERO) { + return await getApprovals(); + } else { + let approvals = await getApprovalsToAnAddress(address); + if (!approvals.length) { + console.log(chalk.red(`\nThe address is not listed\n`)) + } + return approvals; + } +} + +function printMatmRow(from, to, allowance, time, description) { + console.log(`\nDescription: ${web3.utils.toAscii(description)}\nFrom ${from} to ${to}\nAllowance: ${web3.utils.fromWei(allowance)}\nExpiry time: ${moment.unix(time).format('MMMM Do YYYY HH:mm')}\n`); +} + +async function getApprovals() { + function ApprovalDetail(_from, _to, _allowance, _expiryTime, _description) { + this.from = _from; + this.to = _to; + this.allowance = _allowance; + this.expiryTime = _expiryTime; + this.description = _description; + } + + let results = []; + let approvalDetails = await currentTransferManager.methods.getAllApprovals().call(); + for (let i = 0; i < approvalDetails[0].length; i++) { + results.push(new ApprovalDetail(approvalDetails[0][i], approvalDetails[1][i], approvalDetails[2][i], approvalDetails[3][i], approvalDetails[4][i])); } + return results; +} + +async function getApprovalsToAnAddress(address) { + function ApprovalDetail(_from, _to, _allowance, _expiryTime, _description) { + this.from = _from; + this.to = _to; + this.allowance = _allowance; + this.expiryTime = _expiryTime; + this.description = _description; + } + + let results = []; + let approvals = await currentTransferManager.methods.getActiveApprovalsToUser(address).call(); + for (let i = 0; i < approvals[0].length; i++) { + results.push(new ApprovalDetail(approvals[0][i], approvals[1][i], approvals[2][i], approvals[3][i], approvals[4][i])); + } + return results; } async function getManualApproval(_from, _to) { let result = null; - let manualApproval = await currentTransferManager.methods.manualApprovals(_from, _to).call(); - if (manualApproval.expiryTime !== "0") { + let manualApproval = await currentTransferManager.methods.getApprovalDetails(_from, _to).call(); + if ((manualApproval[0] >= new Date()) && (manualApproval[1] != 0)) { result = manualApproval; } - return result; } -async function getManualBlocking(_from, _to) { - let result = null; +async function matmGenericCsv(path, f) { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${path}): `, { + defaultInput: path + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => f(row)); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + return common.splitIntoBatches(validData, batchSize); +} - let manualBlocking = await currentTransferManager.methods.manualBlockings(_from, _to).call(); - if (manualBlocking !== "0") { - result = manualBlocking; +async function addManualApproveInBatch() { + + var f = (row) => { + return (web3.utils.isAddress(row[0]) && + web3.utils.isAddress(row[1]) && + parseFloat(row[2]) > 0 && + moment.unix(row[3]).isValid() && + typeof row[4] === 'string' && + getBinarySize(row[4]) < 33) } - return result; + let batches = await matmGenericCsv(ADD_MANUAL_APPROVAL_DATA_CSV, f) + + let [fromArray, toArray, allowanceArray, expiryArray, descriptionArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add manual approvals: \n\n`, descriptionArray[batch], '\n'); + descriptionArray[batch] = descriptionArray[batch].map(d => web3.utils.fromAscii(d)); + allowanceArray[batch] = allowanceArray[batch].map(a => web3.utils.toWei(new web3.utils.BN(a))); + let action = await currentTransferManager.methods.addManualApprovalMulti(fromArray[batch], toArray[batch], allowanceArray[batch], expiryArray[batch], descriptionArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add multiple manual approvals transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function revokeManualApproveInBatch() { + + var f = (row) => { + return (web3.utils.isAddress(row[0]) && + web3.utils.isAddress(row[1])) + } + + let batches = await matmGenericCsv(REVOKE_MANUAL_APPROVAL_DATA_CSV, f) + + let [fromArray, toArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to revoke manual approvals`, '\n'); + let action = await currentTransferManager.methods.revokeManualApprovalMulti(fromArray[batch], toArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Revoke multip;e manual approvals transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function modifyManualApproveInBatch() { + + var f = (row) => { + return (web3.utils.isAddress(row[0]) && + web3.utils.isAddress(row[1]) && + moment.unix(row[2]).isValid() && + parseFloat(row[3]) > 0 && + typeof row[4] === 'string' && + getBinarySize(row[4]) < 33 && + typeof parseInt(row[5])) === 'number' + } + + let batches = await matmGenericCsv(MODIFY_MANUAL_APPROVAL_DATA_CSV, f) + + let [fromArray, toArray, expiryArray, allowanceArray, descriptionArray, changesArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to modify manual approvals: \n\n`, descriptionArray[batch], '\n'); + descriptionArray[batch] = descriptionArray[batch].map(d => web3.utils.fromAscii(d)); + allowanceArray[batch] = allowanceArray[batch].map(a => web3.utils.toWei(new web3.utils.BN(a))); + changesArray[batch] = changesArray[batch].map(c => parseInt(c)); + let action = await currentTransferManager.methods.modifyManualApprovalMulti(fromArray[batch], toArray[batch], expiryArray[batch], allowanceArray[batch], descriptionArray[batch], changesArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Modify multiple manual approvals transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +function getBinarySize(string) { + return Buffer.byteLength(string, 'utf8'); } async function countTransferManager() { @@ -1484,7 +1767,7 @@ async function getAllModulesByType(type) { let nameTemp = web3.utils.hexToUtf8(details[0]); let pausedTemp = null; if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER) { - let abiTemp = JSON.parse(require('fs').readFileSync(`./build/contracts/${nameTemp}.json`).toString()).abi; + let abiTemp = JSON.parse(require('fs').readFileSync(`${__dirname}/../../build/contracts/${nameTemp}.json`).toString()).abi; let contractTemp = new web3.eth.Contract(abiTemp, details[1]); pausedTemp = await contractTemp.methods.paused().call(); } @@ -1586,6 +1869,14 @@ module.exports = { }, addTransferManagerModule: async function (_tokenSymbol) { await initialize(_tokenSymbol); - return addTransferManagerModule() + return addTransferManagerModule(); + }, + modifyWhitelistInBatch: async function (_tokenSymbol, _csvFilePath, _batchSize) { + await initialize(_tokenSymbol); + let gmtModules = await securityToken.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + let generalTransferManagerAddress = gmtModules[0]; + currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), generalTransferManagerAddress); + currentTransferManager.setProvider(web3.currentProvider); + return modifyWhitelistInBatch(_csvFilePath, _batchSize); } } \ No newline at end of file From c4a0af605681443728facfdda5901b09ed1ab442 Mon Sep 17 00:00:00 2001 From: Satyam Agrawal Date: Thu, 3 Jan 2019 19:59:55 +0530 Subject: [PATCH 485/582] indexing the param (#500) --- .../modules/Checkpoint/ERC20DividendCheckpoint.sol | 6 +++--- .../modules/Checkpoint/EtherDividendCheckpoint.sol | 10 +++++----- .../modules/TransferManager/GeneralTransferManager.sol | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 174498537..19be8a606 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -25,20 +25,20 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec ); event ERC20DividendClaimed( address indexed _payee, - uint256 _dividendIndex, + uint256 indexed _dividendIndex, address indexed _token, uint256 _amount, uint256 _withheld ); event ERC20DividendReclaimed( address indexed _claimer, - uint256 _dividendIndex, + uint256 indexed _dividendIndex, address indexed _token, uint256 _claimedAmount ); event ERC20DividendWithholdingWithdrawn( address indexed _claimer, - uint256 _dividendIndex, + uint256 indexed _dividendIndex, address indexed _token, uint256 _withheldAmount ); diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index 3397f208b..81d94d3ce 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -17,13 +17,13 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, uint256 _amount, uint256 _totalSupply, - uint256 _dividendIndex, + uint256 indexed _dividendIndex, bytes32 indexed _name ); - event EtherDividendClaimed(address indexed _payee, uint256 _dividendIndex, uint256 _amount, uint256 _withheld); - event EtherDividendReclaimed(address indexed _claimer, uint256 _dividendIndex, uint256 _claimedAmount); - event EtherDividendClaimFailed(address indexed _payee, uint256 _dividendIndex, uint256 _amount, uint256 _withheld); - event EtherDividendWithholdingWithdrawn(address indexed _claimer, uint256 _dividendIndex, uint256 _withheldAmount); + event EtherDividendClaimed(address indexed _payee, uint256 indexed _dividendIndex, uint256 _amount, uint256 _withheld); + event EtherDividendReclaimed(address indexed _claimer, uint256 indexed _dividendIndex, uint256 _claimedAmount); + event EtherDividendClaimFailed(address indexed _payee, uint256 indexed _dividendIndex, uint256 _amount, uint256 _withheld); + event EtherDividendWithholdingWithdrawn(address indexed _claimer, uint256 indexed _dividendIndex, uint256 _withheldAmount); /** * @notice Constructor diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 12bfa72ca..ef7d15e98 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -32,9 +32,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag // if allowAllWhitelistTransfers is TRUE, then _toTime and _fromTime is ignored when sending or receiving tokens // in any case, any investor sending or receiving tokens, must have a _expiryTime in the future event ModifyWhitelist( - address _investor, + address indexed _investor, uint256 _dateAdded, - address _addedBy, + address indexed _addedBy, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, From 2aaa03d2fa75598d5ea70ac7093b983533058132 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 3 Jan 2019 13:59:14 -0300 Subject: [PATCH 486/582] Permissions update --- CLI/commands/common/permissions_list.js | 56 ++++++++++++--------- docs/permissions_list.md | 65 ++++++++++++------------- 2 files changed, 63 insertions(+), 58 deletions(-) diff --git a/CLI/commands/common/permissions_list.js b/CLI/commands/common/permissions_list.js index 62c3c06a5..8f74c15e7 100644 --- a/CLI/commands/common/permissions_list.js +++ b/CLI/commands/common/permissions_list.js @@ -68,30 +68,20 @@ function getPermissionList() { setAllowPrimaryIssuance: "ADMIN", changeHolderPercentage: "ADMIN" }, - LockupVolumeRestrictionTM: { - addLockup: "ADMIN", - addLockUpMulti: "ADMIN", - removeLockUp: "ADMIN", - modifyLockUp: "ADMIN" - }, - SingleTradeVolumeRestrictionTM: { - setAllowPrimaryIssuance: "ADMIN", - changeTransferLimitToPercentage: "ADMIN", - changeTransferLimitToTokens: "ADMIN", - changeGlobalLimitInTokens: "ADMIN", - changeGlobalLimitInPercentage: "ADMIN", - addExemptWallet: "ADMIN", - removeExemptWallet: "ADMIN", - addExemptWalletMulti: "ADMIN", - removeExemptWalletMulti: "ADMIN", - setTransferLimitInTokens: "ADMIN", - setTransferLimitInPercentage: "ADMIN", - removeTransferLimitInPercentage: "ADMIN", - removeTransferLimitInTokens: "ADMIN", - setTransferLimitInTokensMulti: "ADMIN", - setTransferLimitInPercentageMulti: "ADMIN", - removeTransferLimitInTokensMulti: "ADMIN", - removeTransferLimitInPercentageMulti: "ADMIN" + VolumeRestrictionTM: { + changeExemptWalletList: "ADMIN", + addIndividualRestriction: "ADMIN", + addIndividualRestrictionMulti: "ADMIN", + addGlobalRestriction: "ADMIN", + addDailyGlobalRestriction: "ADMIN", + removeIndividualRestriction: "ADMIN", + removeIndividualRestrictionMulti: "ADMIN", + removeGlobalRestriction: "ADMIN", + removeDailyGlobalRestriction: "ADMIN", + modifyIndividualRestriction: "ADMIN", + modifyIndividualRestrictionMulti: "ADMIN", + modifyGlobalRestriction: "ADMIN", + modifyDailyGlobalRestriction: "ADMIN" }, BlacklistTransferManager: { addBlacklistType: "ADMIN", @@ -108,6 +98,24 @@ function getPermissionList() { deleteInvestorFromAllBlacklistMulti: "ADMIN", deleteInvestorFromBlacklist: "ADMIN", deleteMultiInvestorsFromBlacklistMulti: "ADMIN", + }, + VestingEscrowWallet: { + changeTreasuryWallet: "ONLY_OWNER", + depositTokens: "ADMIN", + sendToTreasury: "ADMIN", + pushAvailableTokens: "ADMIN", + addTemplate: "ADMIN", + removeTemplate: "ADMIN", + addSchedule: "ADMIN", + addScheduleFromTemplate: "ADMIN", + modifySchedule: "ADMIN", + revokeSchedule: "ADMIN", + revokeAllSchedules: "ADMIN", + pushAvailableTokensMulti: "ADMIN", + addScheduleMulti: "ADMIN", + addScheduleFromTemplateMulti: "ADMIN", + revokeSchedulesMulti: "ADMIN", + modifyScheduleMulti: "ADMIN" } } } diff --git a/docs/permissions_list.md b/docs/permissions_list.md index 623a38f18..9e7a213db 100644 --- a/docs/permissions_list.md +++ b/docs/permissions_list.md @@ -143,7 +143,7 @@ allocateTokensMulti() - TransferManager + TransferManager CountTransferManager changeHolderCount() withPerm(ADMIN) @@ -238,84 +238,81 @@ modifyDailyGlobalRestriction() - - removeTransferLimitInPercentageMulti - - + - Wallet - VestingEscrowWallet - changeTreasuryWallet() - onlyOwner + BlacklistTransferManager + addBlacklistType() + withPerm(ADMIN) - depositTokens() - withPerm(ADMIN) + addBlacklistTypeMulti() - sendToTreasury() + modifyBlacklistType() - pushAvailableTokens() + modifyBlacklistTypeMulti() - addTemplate() + deleteBlacklistType() - removeTemplate() + deleteBlacklistTypeMulti() - addSchedule() + addInvestorToBlacklist() - addScheduleFromTemplate() + addInvestorToBlacklistMulti() - modifySchedule() + addMultiInvestorToBlacklistMulti() - BlacklistTransferManager - addBlacklistType() - withPerm(ADMIN) + addInvestorToNewBlacklist() - addBlacklistTypeMulti() + deleteInvestorFromAllBlacklist() - modifyBlacklistType() + deleteInvestorFromAllBlacklistMulti() - modifyBlacklistTypeMulti() + deleteInvestorFromBlacklist() - deleteBlacklistType() + deleteMultiInvestorsFromBlacklistMulti() - deleteBlacklistTypeMulti() + Wallet + VestingEscrowWallet + changeTreasuryWallet() + onlyOwner - addInvestorToBlacklist() + depositTokens() + withPerm(ADMIN) - addInvestorToBlacklistMulti() + sendToTreasury() - addMultiInvestorToBlacklistMulti() + pushAvailableTokens() - addInvestorToNewBlacklist() + addTemplate() - deleteInvestorFromAllBlacklist() + removeTemplate() - deleteInvestorFromAllBlacklistMulti() + addSchedule() - deleteInvestorFromBlacklist() + addScheduleFromTemplate() - deleteMultiInvestorsFromBlacklistMulti() + modifySchedule() revokeSchedule() From 11d0f31b065e9589d45ac320ce5bcffa3fe1f772 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 4 Jan 2019 19:50:57 +0530 Subject: [PATCH 487/582] Removed redundant events --- .../LockupVolumeRestrictionTMFactory.sol | 2 +- contracts/modules/ModuleFactory.sol | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol index 5be77b6e0..73bd753f1 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol @@ -35,7 +35,7 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); LockupVolumeRestrictionTM lockupVolumeRestrictionTransferManager = new LockupVolumeRestrictionTM(msg.sender, address(polyToken)); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(lockupVolumeRestrictionTransferManager), getName(), address(this), msg.sender, now); + emit GenerateModuleFromFactory(address(lockupVolumeRestrictionTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(lockupVolumeRestrictionTransferManager); } diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index aca262621..9fc6cea02 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -28,18 +28,6 @@ contract ModuleFactory is IModuleFactory, Ownable { // @dev uint24 consists packed value of uint8 _major, uint8 _minor, uint8 _patch mapping(string => uint24) compatibleSTVersionRange; - event ChangeFactorySetupFee(uint256 _oldSetupCost, uint256 _newSetupCost, address _moduleFactory); - event ChangeFactoryUsageFee(uint256 _oldUsageCost, uint256 _newUsageCost, address _moduleFactory); - event ChangeFactorySubscriptionFee(uint256 _oldSubscriptionCost, uint256 _newMonthlySubscriptionCost, address _moduleFactory); - event GenerateModuleFromFactory( - address _module, - bytes32 indexed _moduleName, - address indexed _moduleFactory, - address _creator, - uint256 _timestamp - ); - event ChangeSTVersionBound(string _boundType, uint8 _major, uint8 _minor, uint8 _patch); - /** * @notice Constructor * @param _polyAddress Address of the polytoken From d71321a34e3fe57abad0b6ccee1639f150e6c619 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 7 Jan 2019 11:05:25 +0530 Subject: [PATCH 488/582] dual truffle coverage --- .circleci/config.yml | 4 ++-- scripts/test.sh | 2 ++ truffle-ci.js | 11 +++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a39d287a0..1bd95458a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -39,15 +39,15 @@ jobs: path: ./test-results/mocha/results.xml coverage: docker: - - image: circleci/node:8 + - image: maxsam4/solidity-kit:0.4.24 steps: - checkout - restore_cache: key: dependency-cache-{{ checksum "package.json" }} - run: yarn install - - run: sudo npm i truffle -g - run: node --version - run: truffle version + - run: node_modules/.bin/truffle version - run: command: npm run coverage no_output_timeout: 1h diff --git a/scripts/test.sh b/scripts/test.sh index 9a3ab5838..50996e900 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -90,6 +90,8 @@ fi if [ "$COVERAGE" = true ] || [ "$TRAVIS_PULL_REQUEST" > 0 ] && [ "$NOT_FORK" != true ]; then curl -o node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js + rm truffle-config.js + mv truffle-ci.js truffle-config.js node_modules/.bin/solidity-coverage if [ "$CIRCLECI" = true ] || [ "$TRAVIS_PULL_REQUEST" > 0 ] && [ "$NOT_FORK" != true ]; then cat coverage/lcov.info | node_modules/.bin/coveralls || echo 'Failed to report coverage to Coveralls' diff --git a/truffle-ci.js b/truffle-ci.js index f427eb332..16c8660d1 100644 --- a/truffle-ci.js +++ b/truffle-ci.js @@ -17,6 +17,17 @@ module.exports = { gasPrice: 0x01 // <-- Use this low gas price } }, + compilers: { + solc: { + version: "native", + settings: { + optimizer: { + enabled: true, + runs: 200 + } + } + } + }, solc: { optimizer: { enabled: true, From 8e951d6ac5049b4c460a1addfcd3a02e8ac4a994 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 7 Jan 2019 11:18:29 +0530 Subject: [PATCH 489/582] VRTM coverage fix --- .../TransferManager/VolumeRestrictionTM.sol | 41 ++++++++----------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index c452b4663..44534351d 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -955,31 +955,22 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { counter = counter.add(_diffDays); } else { for (i = 0; i < _diffDays; i++) { - counter++; - // This condition is to check whether the first rolling period is covered or not - // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting - // the earlier value at that index - if (counter >= _rollingPeriodInDays) { - // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod - // The below line subtracts (the traded volume on days no longer covered by rolling period) from sumOfLastPeriod. - // Every loop execution subtracts one day's trade volume. - // Loop starts from the first day covered in sumOfLastPeriod upto the day that is covered by rolling period. - sumOfLastPeriod = - sumOfLastPeriod.sub( - bucket[_from][_bucketDetails.lastTradedDayTime.sub( - ( - _bucketDetails.daysCovered.sub( - counter.sub( - _rollingPeriodInDays - ) - ) - ).mul(1 days) - )] - ); - } - // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand - // the alogrithm - //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); + counter++; + // This condition is to check whether the first rolling period is covered or not + // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting + // the earlier value at that index + if (counter >= _rollingPeriodInDays) { + // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod + // The below line subtracts (the traded volume on days no longer covered by rolling period) from sumOfLastPeriod. + // Every loop execution subtracts one day's trade volume. + // Loop starts from the first day covered in sumOfLastPeriod upto the day that is covered by rolling period. + uint256 temp = _bucketDetails.daysCovered.sub(counter.sub(_rollingPeriodInDays)); + temp = _bucketDetails.lastTradedDayTime.sub(temp.mul(1 days)); + sumOfLastPeriod = sumOfLastPeriod.sub(bucket[_from][temp]); + } + // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand + // the alogrithm + //_bucketDetails.sumOfLastPeriod = _bucketDetails.sumOfLastPeriod.add(uint256(0)); } } // calculating the timestamp that will used as an index of the next bucket From cbb8eb388f0c2b3271b73114a916b52eb1e0c8fd Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 7 Jan 2019 11:39:22 +0530 Subject: [PATCH 490/582] Added compile command --- .solcover.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.solcover.js b/.solcover.js index dac86d6e3..b69f5f074 100644 --- a/.solcover.js +++ b/.solcover.js @@ -3,6 +3,7 @@ module.exports = { port: 8545, copyPackages: ['openzeppelin-solidity'], testCommand: 'node ../node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js -and ! -name q_usd_tiered_sto_sim.js -and ! -name z_general_permission_manager_fuzzer.js` --network coverage', + compileCommand: 'truffle version && truffle compile', deepSkip: true, skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'libraries/BokkyPooBahsDateTimeLibrary.sol', 'storage', 'modules/Experimental'], forceParse: ['mocks', 'oracles', 'modules/Experimental'] From c1d2481ad15b5d179eac6f3422dcc51e4a8954a4 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 7 Jan 2019 11:46:19 +0530 Subject: [PATCH 491/582] Updated coverage script --- .circleci/config.yml | 2 +- scripts/test.sh | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1bd95458a..841b807b6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -49,7 +49,7 @@ jobs: - run: truffle version - run: node_modules/.bin/truffle version - run: - command: npm run coverage + command: scripts/coverage.sh no_output_timeout: 1h - save_cache: key: dependency-cache-{{ checksum "package.json" }} diff --git a/scripts/test.sh b/scripts/test.sh index 50996e900..0d8fa4505 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -90,8 +90,10 @@ fi if [ "$COVERAGE" = true ] || [ "$TRAVIS_PULL_REQUEST" > 0 ] && [ "$NOT_FORK" != true ]; then curl -o node_modules/solidity-coverage/lib/app.js https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js - rm truffle-config.js - mv truffle-ci.js truffle-config.js + if [ "$CIRCLECI" = true ]; then + rm truffle-config.js + mv truffle-ci.js truffle-config.js + fi node_modules/.bin/solidity-coverage if [ "$CIRCLECI" = true ] || [ "$TRAVIS_PULL_REQUEST" > 0 ] && [ "$NOT_FORK" != true ]; then cat coverage/lcov.info | node_modules/.bin/coveralls || echo 'Failed to report coverage to Coveralls' From 07a62e022392df253036f42b6b4803cc3256cefb Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 7 Jan 2019 11:49:44 +0530 Subject: [PATCH 492/582] removed compile command --- .solcover.js | 1 - 1 file changed, 1 deletion(-) diff --git a/.solcover.js b/.solcover.js index b69f5f074..dac86d6e3 100644 --- a/.solcover.js +++ b/.solcover.js @@ -3,7 +3,6 @@ module.exports = { port: 8545, copyPackages: ['openzeppelin-solidity'], testCommand: 'node ../node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js -and ! -name q_usd_tiered_sto_sim.js -and ! -name z_general_permission_manager_fuzzer.js` --network coverage', - compileCommand: 'truffle version && truffle compile', deepSkip: true, skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'libraries/BokkyPooBahsDateTimeLibrary.sol', 'storage', 'modules/Experimental'], forceParse: ['mocks', 'oracles', 'modules/Experimental'] From 742b9c2bd231d7d0e59f27f9e856051df6cf31d7 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 7 Jan 2019 12:24:38 +0530 Subject: [PATCH 493/582] Updated truffle config --- truffle-ci.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/truffle-ci.js b/truffle-ci.js index 16c8660d1..049deb0c6 100644 --- a/truffle-ci.js +++ b/truffle-ci.js @@ -35,10 +35,6 @@ module.exports = { }, }, mocha: { - enableTimeouts: false, - reporter: "mocha-junit-reporter", - reporterOptions: { - mochaFile: './test-results/mocha/results.xml' - } + enableTimeouts: false } }; From 7e0502196fcb92484aa30b889ee7cb5740ca9b55 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 7 Jan 2019 11:35:22 -0400 Subject: [PATCH 494/582] Pull accredited lists from USDSTO (#502) * WIP * Add getter * Update changelog * Remove commented code * CLI - Show accredited data * Update contracts/modules/STO/USDTieredSTOStorage.sol Co-Authored-By: adamdossa * Remove commented code --- CHANGELOG.md | 5 +- CLI/commands/investor_portal.js | 18 ++--- CLI/commands/sto_manager.js | 74 +++++++++++++------ contracts/modules/STO/USDTieredSTO.sol | 39 ++++++++-- contracts/modules/STO/USDTieredSTOStorage.sol | 22 ++++-- test/p_usd_tiered_sto.js | 56 ++++++++++---- 6 files changed, 153 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e1bbb0c4..4cd726971 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. * Removed individual mappings for tier data removed in UDSTSTO. * Removed the old Proxy deployment method of USDTieredSTO and adopt the new inherited proxy deployment approach. * Bump the version to `2.1.0` +* Added `getAccreditedData` to return accredited & non-accredited investor data ## GeneralTransferManager * `getInvestors`, `getAllInvestorsData`, `getInvestorsData` added to GTM to allow easy data queries. @@ -31,7 +32,7 @@ All notable changes to this project will be documented in this file. * Changed the version of `GeneralTransferManagerFactory` from `1.0.0` to `2.1.0`. ## Manual Approval TransferManager -* Removed `0x0` check for the `_from` address to `ManualApprovalTransferManager`. This allows for the Issuer/Transfer Agent to approve a one-off mint of tokens that otherwise would not be possible. +* Removed `0x0` check for the `_from` address to `ManualApprovalTransferManager`. This allows for the Issuer/Transfer Agent to approve a one-off mint of tokens that otherwise would not be possible. * Changed the version of `ManualApprovalTransferManagerFactory` from `1.0.0` to `2.1.0`. * Deployed 2.0.1 `ManualApprovalTransferManagerFactory` to address 0x6af2afad53cb334e62b90ddbdcf3a086f654c298 * Add `getActiveApprovalsToUser()` function to access all the active approvals for a user whether user is in the `from` or in `to`. @@ -97,7 +98,7 @@ volume traded in a given rolling period. * Removed investors list pruning * Remove `swarmHash` from the `registerTicker(), addCustomTicker(), generateSecurityToken(), addCustomSecurityToken()` functions of TickerRegistry.sol and SecurityTokenRegistry.sol. #230 * Remove `Log` prefix from all the event present in the ecosystem. -* Removed `addTagByModuleType` & `removeTagsByModuleType` from MR. +* Removed `addTagByModuleType` & `removeTagsByModuleType` from MR. ====== diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 613414a71..0cb02f681 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -245,7 +245,7 @@ async function processAddressWithBalance(array) { for (const address of array) { let symbol = await checkSymbol(address); let balance = await checkBalance(address); - list.push({'address': address, 'symbol': symbol, 'balance': balance}) + list.push({ 'address': address, 'symbol': symbol, 'balance': balance }) } return list } @@ -254,7 +254,7 @@ async function processAddress(array) { let list = []; for (const address of array) { let symbol = await checkSymbol(address); - list.push({"symbol": symbol, "address": address}) + list.push({ "symbol": symbol, "address": address }) } return list } @@ -277,8 +277,7 @@ async function checkBalance(address) { } } -async function showUserInfoForUSDTieredSTO() -{ +async function showUserInfoForUSDTieredSTO() { let stableSymbols = []; let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); @@ -306,11 +305,12 @@ async function showUserInfoForUSDTieredSTO() console.log(` - Whitelisted: ${(displayCanBuy) ? 'YES' : 'NO'}`); console.log(` - Valid KYC: ${(displayValidKYC) ? 'YES' : 'NO'}`); - let displayIsUserAccredited = await currentSTO.methods.accredited(User.address).call(); + let investorData = await currentSTO.methods.investors(User.address).call(); + let displayIsUserAccredited = investorData.accredited == 1; console.log(` - Accredited: ${(displayIsUserAccredited) ? "YES" : "NO"}`) - if (!await currentSTO.methods.accredited(User.address).call()) { - let displayOverrideNonAccreditedLimitUSD = web3.utils.fromWei(await currentSTO.methods.nonAccreditedLimitUSDOverride(User.address).call()) + if (!displayIsUserAccredited) { + let displayOverrideNonAccreditedLimitUSD = web3.utils.fromWei(investorData.nonAccreditedLimitUSDOverride); let displayNonAccreditedLimitUSD = displayOverrideNonAccreditedLimitUSD != 0 ? displayOverrideNonAccreditedLimitUSD : web3.utils.fromWei(await currentSTO.methods.nonAccreditedLimitUSD().call()); let displayTokensRemainingAllocation = displayNonAccreditedLimitUSD - displayInvestorInvestedUSD; console.log(` - Remaining allocation: ${(displayTokensRemainingAllocation > 0 ? displayTokensRemainingAllocation : 0)} USD`); @@ -402,7 +402,7 @@ async function showUSDTieredSTOInfo() { }) } else { displayFundsRaisedPerType += ` - ${type}:\t\t\t ${fundsRaised} ${type}`; + ${type}:\t\t\t ${fundsRaised} ${type}`; } //Only show sold per raise type is more than one are allowed if (raiseTypes.length > 1) { @@ -420,7 +420,7 @@ async function showUSDTieredSTOInfo() { let displayRaiseType = raiseTypes.join(' - '); //If STO has stable coins, we list them one by one if (stableSymbols.length) { - displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.map((obj) => {return obj.symbol}).toString().replace(`,`,` - `)}` + displayRaiseType = displayRaiseType.replace(STABLE, "") + `${stableSymbols.map((obj) => { return obj.symbol }).toString().replace(`,`, ` - `)}` } let now = Math.floor(Date.now() / 1000); diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index be809312e..f581b7339 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -5,6 +5,7 @@ const abis = require('./helpers/contract_abis'); const common = require('./common/common_functions'); const gbl = require('./common/global'); const csvParse = require('./helpers/csv'); +const { table } = require('table'); const STABLE = 'STABLE'; /////////////////// @@ -45,8 +46,8 @@ async function executeApp() { } options.push('Add new STO module'); - let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'Exit' }); - let optionSelected = index != -1 ? options[index] : 'Exit'; + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'EXIT' }); + let optionSelected = index != -1 ? options[index] : 'EXIT'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Show existing STO information': @@ -60,7 +61,7 @@ async function executeApp() { case 'Add new STO module': await addSTOModule(); break; - case 'Exit': + case 'EXIT': exit = true; break; } @@ -97,6 +98,7 @@ async function showSTO(selectedSTO, currentSTO) { break; case 'USDTieredSTO': await usdTieredSTO_status(currentSTO); + await showAccreditedData(currentSTO); break; } } @@ -126,8 +128,8 @@ async function addSTOModule(stoConfig) { let moduleFactory = new web3.eth.Contract(moduleFactoryABI, m); return web3.utils.hexToUtf8(await moduleFactory.methods.name().call()); })); - let index = readlineSync.keyInSelect(options, 'What type of STO do you want?', { cancel: 'Return' }); - optionSelected = index != -1 ? options[index] : 'Return'; + let index = readlineSync.keyInSelect(options, 'What type of STO do you want?', { cancel: 'RETURN' }); + optionSelected = index != -1 ? options[index] : 'RETURN'; } else { optionSelected = stoConfig.type; } @@ -271,8 +273,6 @@ async function cappedSTO_status(currentSTO) { - Tokens remaining: ${web3.utils.fromWei(displayCap.sub(displayTokensSold))} ${displayTokenSymbol.toUpperCase()} - Investor count: ${displayInvestorCount} `); - - console.log(chalk.green(`\n${(web3.utils.fromWei(await getBalance(Issuer.address, gbl.constants.FUND_RAISE_TYPES.POLY)))} POLY balance remaining at issuer address ${Issuer.address}`)); } //////////////////// @@ -579,6 +579,7 @@ async function usdTieredSTO_status(currentSTO) { let displayStartTime = await currentSTO.methods.startTime().call(); let displayEndTime = await currentSTO.methods.endTime().call(); let displayCurrentTier = parseInt(await currentSTO.methods.currentTier().call()) + 1; + let test = await currentSTO.methods.nonAccreditedLimitUSD().call(); let displayNonAccreditedLimitUSD = web3.utils.fromWei(await currentSTO.methods.nonAccreditedLimitUSD().call()); let displayMinimumInvestmentUSD = web3.utils.fromWei(await currentSTO.methods.minimumInvestmentUSD().call()); let displayWallet = await currentSTO.methods.wallet().call(); @@ -752,8 +753,6 @@ async function usdTieredSTO_status(currentSTO) { + displayFundsRaisedPerType + ` Total USD: ${displayFundsRaisedUSD} USD `); - - console.log(chalk.green(`\n${(web3.utils.fromWei(await getBalance(Issuer.address, gbl.constants.FUND_RAISE_TYPES.POLY)))} POLY balance remaining at issuer address ${Issuer.address}`)); } async function checkStableBalance(walletAddress, stableAddress) { @@ -789,9 +788,10 @@ async function usdTieredSTO_configure(currentSTO) { 'Modify limits configuration', 'Modify funding configuration'); } - let index = readlineSync.keyInSelect(options, 'What do you want to do?'); - switch (index) { - case 0: + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let selected = index != -1 ? options[index] : 'Exit'; + switch (selected) { + case 'Finalize STO': let reserveWallet = await currentSTO.methods.reserveWallet().call(); let isVerified = await securityToken.methods.verifyTransfer('0x0000000000000000000000000000000000000000', reserveWallet, 0, web3.utils.fromAscii("")).call(); if (isVerified) { @@ -803,7 +803,7 @@ async function usdTieredSTO_configure(currentSTO) { console.log(chalk.red(`Reserve wallet (${reserveWallet}) is not able to receive remaining tokens. Check if this address is whitelisted.`)); } break; - case 1: + case 'Change accredited account': let investor = readlineSync.question('Enter the address to change accreditation: '); let isAccredited = readlineSync.keyInYNStrict(`Is ${investor} accredited?`); let investors = [investor]; @@ -812,10 +812,10 @@ async function usdTieredSTO_configure(currentSTO) { // 2 GAS? await common.sendTransaction(changeAccreditedAction); break; - case 2: + case 'Change accredited in batch': await changeAccreditedInBatch(currentSTO); break; - case 3: + case 'Change non accredited limit for an account': let account = readlineSync.question('Enter the address to change non accredited limit: '); let limit = readlineSync.question(`Enter the limit in USD: `); let accounts = [account]; @@ -823,26 +823,26 @@ async function usdTieredSTO_configure(currentSTO) { let changeNonAccreditedLimitAction = currentSTO.methods.changeNonAccreditedLimit(accounts, limits); await common.sendTransaction(changeNonAccreditedLimitAction); break; - case 4: + case 'Change non accredited limits in batch': await changeNonAccreditedLimitsInBatch(currentSTO); break; - case 5: + case 'Modify times configuration': await modfifyTimes(currentSTO); await usdTieredSTO_status(currentSTO); break; - case 6: + case 'Modify tiers configuration': await modfifyTiers(currentSTO); await usdTieredSTO_status(currentSTO); break; - case 7: + case 'Modify addresses configuration': await modfifyAddresses(currentSTO); await usdTieredSTO_status(currentSTO); break; - case 8: + case 'Modify limits configuration': await modfifyLimits(currentSTO); await usdTieredSTO_status(currentSTO); break; - case 9: + case 'Modify funding configuration': await modfifyFunding(currentSTO); await usdTieredSTO_status(currentSTO); break; @@ -850,6 +850,33 @@ async function usdTieredSTO_configure(currentSTO) { } } +async function showAccreditedData(currentSTO) { + let accreditedData = await currentSTO.methods.getAccreditedData().call(); + let investorArray = accreditedData[0]; + let accreditedArray = accreditedData[1]; + let nonAccreditedLimitArray = accreditedData[2]; + + if (investorArray.length > 0) { + let dataTable = [['Investor', 'Is accredited', 'Non-accredited limit (USD)']]; + for (let i = 0; i < investorArray.length; i++) { + dataTable.push([ + investorArray[i], + accreditedArray[i] ? 'YES' : 'NO', + accreditedArray[i] ? 'N/A' : (nonAccreditedLimitArray[i] !== '0' ? web3.utils.fromWei(nonAccreditedLimitArray[i]) : 'default') + ]); + } + console.log(); + console.log(`************************************ ACCREDITED DATA *************************************`); + console.log(); + console.log(table(dataTable)); + } else { + console.log(); + console.log(chalk.yellow(`There is no accredited data to show`)); + console.log(); + } + +} + async function changeAccreditedInBatch(currentSTO) { let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ACCREDIT_DATA_CSV}): `, { defaultInput: ACCREDIT_DATA_CSV @@ -898,6 +925,7 @@ async function changeNonAccreditedLimitsInBatch(currentSTO) { let batches = common.splitIntoBatches(validData, batchSize); let [investorArray, limitArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { + limitArray[batch] = limitArray[batch].map(a => web3.utils.toWei(new web3.utils.BN(a))); console.log(`Batch ${batch + 1} - Attempting to change non accredited limit to accounts:\n\n`, investorArray[batch], '\n'); let action = currentSTO.methods.changeNonAccreditedLimit(investorArray[batch], limitArray[batch]); let receipt = await common.sendTransaction(action); @@ -1052,8 +1080,8 @@ async function selectToken() { }); options.push('Enter token symbol manually'); - let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'Exit' }); - let selected = index != -1 ? options[index] : 'Exit'; + let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'EXIT' }); + let selected = index != -1 ? options[index] : 'EXIT'; switch (selected) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 47e659299..b3a248da5 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -306,7 +306,12 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { function changeAccredited(address[] _investors, bool[] _accredited) public onlyOwner { require(_investors.length == _accredited.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { - accredited[_investors[i]] = _accredited[i]; + if (_accredited[i]) { + investors[_investors[i]].accredited = uint8(1); + } else { + investors[_investors[i]].accredited = uint8(0); + } + _addToInvestorsList(_investors[i]); emit SetAccredited(_investors[i], _accredited[i]); } } @@ -320,12 +325,36 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { //nonAccreditedLimitUSDOverride require(_investors.length == _nonAccreditedLimit.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { - require(_nonAccreditedLimit[i] > 0, "Limit = 0"); - nonAccreditedLimitUSDOverride[_investors[i]] = _nonAccreditedLimit[i]; + investors[_investors[i]].nonAccreditedLimitUSDOverride = _nonAccreditedLimit[i]; + _addToInvestorsList(_investors[i]); emit SetNonAccreditedLimit(_investors[i], _nonAccreditedLimit[i]); } } + function _addToInvestorsList(address _investor) internal { + if (investors[_investor].seen == uint8(0)) { + investors[_investor].seen = uint8(1); + investorsList.push(_investor); + } + } + + /** + * @notice Returns investor accredited & non-accredited override informatiomn + * @return address[] list of all configured investors + * @return bool[] whether investor is accredited + * @return uint256[] any USD overrides for non-accredited limits for the investor + */ + function getAccreditedData() external view returns (address[], bool[], uint256[]) { + bool[] memory accrediteds = new bool[](investorsList.length); + uint256[] memory nonAccreditedLimitUSDOverrides = new uint256[](investorsList.length); + uint256 i; + for (i = 0; i < investorsList.length; i++) { + accrediteds[i] = (investors[investorsList[i]].accredited == uint8(0)? false: true); + nonAccreditedLimitUSDOverrides[i] = investors[investorsList[i]].nonAccreditedLimitUSDOverride; + } + return (investorsList, accrediteds, nonAccreditedLimitUSDOverrides); + } + /** * @notice Function to set allowBeneficialInvestments (allow beneficiary to be different to funder) * @param _allowBeneficialInvestments Boolean to allow or disallow beneficial investments @@ -525,8 +554,8 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); netInvestedUSD = investedUSD; // Check for non-accredited cap - if (!accredited[_beneficiary]) { - uint256 investorLimitUSD = (nonAccreditedLimitUSDOverride[_beneficiary] == 0) ? nonAccreditedLimitUSD : nonAccreditedLimitUSDOverride[_beneficiary]; + if (investors[_beneficiary].accredited == uint8(0)) { + uint256 investorLimitUSD = (investors[_beneficiary].nonAccreditedLimitUSDOverride == 0) ? nonAccreditedLimitUSD : investors[_beneficiary].nonAccreditedLimitUSDOverride; require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Over Non-accredited investor limit"); if (investedUSD.add(investorInvestedUSD[_beneficiary]) > investorLimitUSD) netInvestedUSD = investorLimitUSD.sub(investorInvestedUSD[_beneficiary]); diff --git a/contracts/modules/STO/USDTieredSTOStorage.sol b/contracts/modules/STO/USDTieredSTOStorage.sol index 5d9581408..c9df0f24c 100644 --- a/contracts/modules/STO/USDTieredSTOStorage.sol +++ b/contracts/modules/STO/USDTieredSTOStorage.sol @@ -34,6 +34,15 @@ contract USDTieredSTOStorage { uint256 mintedDiscountPoly; } + struct Investor { + // Whether investor is accredited (0 = non-accredited, 1 = accredited) + uint8 accredited; + // Whether we have seen the investor before (already added to investors list) + uint8 seen; + // Overrides for default limit in USD for non-accredited investors multiplied by 10**18 (0 = no override) + uint256 nonAccreditedLimitUSDOverride; + } + mapping (bytes32 => mapping (bytes32 => string)) oracleKeys; // Determine whether users can invest on behalf of a beneficiary @@ -66,18 +75,19 @@ contract USDTieredSTOStorage { // Amount in fund raise type invested by each investor mapping (address => mapping (uint8 => uint256)) public investorInvested; - // List of accredited investors - mapping (address => bool) public accredited; + // Accredited & non-accredited investor data + mapping (address => Investor) public investors; // List of active stable coin addresses mapping (address => bool) public usdTokenEnabled; + // List of all addresses that have been added as accredited or non-accredited without + // the default limit + address[] public investorsList; + // Default limit in USD for non-accredited investors multiplied by 10**18 uint256 public nonAccreditedLimitUSD; - // Overrides for default limit in USD for non-accredited investors multiplied by 10**18 - mapping (address => uint256) public nonAccreditedLimitUSDOverride; - // Minimum investable amount in USD uint256 public minimumInvestmentUSD; @@ -87,4 +97,4 @@ contract USDTieredSTOStorage { // Array of Tiers Tier[] public tiers; -} \ No newline at end of file +} diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 5fad46f6f..ae1fbbbb0 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1408,20 +1408,31 @@ contract("USDTieredSTO", accounts => { it("should successfully modify accredited addresses for first STO", async () => { let stoId = 0; - - let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); - assert.equal(status1, false, "Initial accreditation is set to true"); + let investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(NONACCREDITED1); + let status1 = investorStatus[0].toNumber(); + assert.equal(status1, 0, "Initial accreditation is set to true"); await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1], [true], { from: ISSUER }); - let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); - assert.equal(status2, true, "Failed to set single address"); + investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(NONACCREDITED1); + let status2 = investorStatus[0].toNumber(); + assert.equal(status2, 1, "Failed to set single address"); await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); - let status3 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); - assert.equal(status3, false, "Failed to set multiple addresses"); - let status4 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); - assert.equal(status4, true, "Failed to set multiple addresses"); - + investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(NONACCREDITED1); + let status3 = investorStatus[0].toNumber(); + assert.equal(status3, 0, "Failed to set multiple addresses"); + investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(ACCREDITED1); + let status4 = investorStatus[0].toNumber(); + assert.equal(status4, 1, "Failed to set multiple addresses"); + + let totalStatus = await I_USDTieredSTO_Array[stoId].getAccreditedData.call(); + + assert.equal(totalStatus[0][0], NONACCREDITED1, "Account match"); + assert.equal(totalStatus[0][1], ACCREDITED1, "Account match"); + assert.equal(totalStatus[1][0], false, "Account match"); + assert.equal(totalStatus[1][1], true, "Account match"); + assert.equal(totalStatus[2][0].toNumber(), 0, "override match"); + assert.equal(totalStatus[2][1].toNumber(), 0, "override match"); await catchRevert(I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [true], { from: ISSUER })); }); @@ -1429,10 +1440,12 @@ contract("USDTieredSTO", accounts => { let stoId = 1; await I_USDTieredSTO_Array[stoId].changeAccredited([NONACCREDITED1, ACCREDITED1], [false, true], { from: ISSUER }); - let status1 = await I_USDTieredSTO_Array[stoId].accredited.call(NONACCREDITED1); - let status2 = await I_USDTieredSTO_Array[stoId].accredited.call(ACCREDITED1); - assert.equal(status1, false, "Failed to set multiple address"); - assert.equal(status2, true, "Failed to set multiple address"); + let investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(NONACCREDITED1); + let status1 = investorStatus[0].toNumber(); + investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(ACCREDITED1); + let status2 = investorStatus[0].toNumber(); + assert.equal(status1, 0, "Failed to set multiple address"); + assert.equal(status2, 1, "Failed to set multiple address"); }); }); @@ -2141,14 +2154,25 @@ contract("USDTieredSTO", accounts => { await I_USDTieredSTO_Array[stoId].changeNonAccreditedLimit([NONACCREDITED1], [_nonAccreditedLimitUSD[stoId].div(2)], { from: ISSUER }); - console.log("Current limit: " + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1)).toNumber()); + let investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(NONACCREDITED1); + console.log("Current limit: " + investorStatus[2].toNumber()); + let totalStatus = await I_USDTieredSTO_Array[stoId].getAccreditedData.call(); + + assert.equal(totalStatus[0][0], NONACCREDITED1, "Account match"); + assert.equal(totalStatus[0][1], ACCREDITED1, "Account match"); + assert.equal(totalStatus[1][0], false, "Account match"); + assert.equal(totalStatus[1][1], true, "Account match"); + assert.equal(totalStatus[2][0].toNumber(), _nonAccreditedLimitUSD[stoId].div(2), "override match"); + assert.equal(totalStatus[2][1].toNumber(), 0, "override match"); + }); it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async () => { let stoId = 0; let tierId = 0; - let investment_USD = await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1); //_nonAccreditedLimitUSD[stoId]; + let investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(NONACCREDITED1); + let investment_USD = investorStatus[2];//await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1); //_nonAccreditedLimitUSD[stoId]; let investment_Token = await convert(stoId, tierId, false, "USD", "TOKEN", investment_USD); let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); From 3eb609af8d74dfb6bc78125afd62ce715b6858e0 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 8 Jan 2019 15:53:00 +0530 Subject: [PATCH 495/582] add getRestrictedAddresses() function --- .../TransferManager/VolumeRestrictionTM.sol | 53 +++++++++++++++++++ .../VolumeRestrictionTMStorage.sol | 15 +++++- test/y_volume_restriction_tm.js | 43 ++++++++++++++- 3 files changed, 109 insertions(+), 2 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 44534351d..70ee114d0 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -205,6 +205,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _endTime, RestrictionType(_restrictionType) ); + _addRestrictionData(_holder, uint8(TypeOfPeriod.MultipleDays)); emit AddIndividualRestriction( _holder, _allowedTokens, @@ -215,6 +216,16 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ); } + function _addRestrictionData(address _holder, uint8 _callFrom) internal { + uint64 index = restrictedHolders[_holder].index; + if (restrictedHolders[_holder].seen == 0) { + restrictedAddresses.push(_holder); + index = uint64(restrictedAddresses.length); + } + uint8 _type = _getTypeOfPeriod(restrictedHolders[_holder].typeOfPeriod, _callFrom, _holder); + restrictedHolders[_holder] = RestrictedHolder(uint8(1), _type, index); + } + /** * @notice Use to add the new individual daily restriction for all token holder * @param _holder Address of the token holder, whom restriction will be implied @@ -270,6 +281,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _endTime, RestrictionType(_restrictionType) ); + _addRestrictionData(_holder, uint8(TypeOfPeriod.OneDay)); emit AddIndividualDailyRestriction( _holder, _allowedTokens, @@ -449,12 +461,28 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_holder != address(0), "Invalid address"); require(individualRestriction[_holder].endTime != 0, "Not present"); individualRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + _deleteHolderFromList(_holder, uint8(TypeOfPeriod.OneDay)); userToBucket[_holder].lastTradedDayTime = 0; userToBucket[_holder].sumOfLastPeriod = 0; userToBucket[_holder].daysCovered = 0; emit IndividualRestrictionRemoved(_holder); } + function _deleteHolderFromList(address _holder, uint8 _typeOfPeriod) internal { + if (restrictedHolders[_holder].typeOfPeriod != uint8(TypeOfPeriod.Both)) { + uint64 index = restrictedHolders[_holder].index; + uint256 _len = restrictedAddresses.length; + if (index != _len) { + restrictedHolders[restrictedAddresses[_len - 1]].index = index; + restrictedAddresses[index - 1] = restrictedAddresses[_len - 1]; + } + delete restrictedHolders[_holder]; + restrictedAddresses.length--; + } else { + restrictedHolders[_holder].typeOfPeriod = _typeOfPeriod; + } + } + /** * @notice use to remove the individual restriction for a given address * @param _holders Array of address of the user @@ -478,6 +506,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_holder != address(0), "Invalid address"); require(individualDailyRestriction[_holder].endTime != 0, "Not present"); individualDailyRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + _deleteHolderFromList(_holder, uint8(TypeOfPeriod.MultipleDays)); userToBucket[_holder].dailyLastTradedDayTime = 0; emit IndividualDailyRestrictionRemoved(_holder); } @@ -1153,6 +1182,28 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { return bytes4(0); } + function _getTypeOfPeriod(uint8 _currentTypeOfPeriod, uint8 _callFrom, address _holder) internal view returns(uint8) { + if (_currentTypeOfPeriod != _callFrom && individualRestriction[_holder].endTime != uint256(0)) + return uint8(TypeOfPeriod.Both); + else + return _callFrom; + } + + /** + * @notice use to get the list of token holders who are restricted by the VRTM + * @return address List of addresses that are restricted by the VRTM + * @return uint8 Array of the Type of period restriction on the addresses. 0 - address + * has only individual restriction, 1 - address has only individual daily restriction & 2 + * it means address has both type of restriction where rolling period is 24 hrs & multiple days as well + */ + function getRestrictedAddresses() external view returns(address[], uint8[]) { + uint8[] memory typeOfPeriodRestriction = new uint8[](restrictedAddresses.length); + for (uint256 i = 0; i < restrictedAddresses.length; i++) { + typeOfPeriodRestriction[i] = restrictedHolders[restrictedAddresses[i]].typeOfPeriod; + } + return (restrictedAddresses, typeOfPeriodRestriction); + } + /** * @notice Returns the permissions flag that are associated with Percentage transfer Manager */ @@ -1162,4 +1213,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { return allPermissions; } + + } \ No newline at end of file diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol index e995676a0..4e5d3512d 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol @@ -7,6 +7,8 @@ contract VolumeRestrictionTMStorage { enum RestrictionType { Fixed, Percentage } + enum TypeOfPeriod { MultipleDays, OneDay, Both } + struct VolumeRestriction { // If typeOfRestriction is `Percentage` then allowedTokens will be in // the % (w.r.t to totalSupply) with a multiplier of 10**16 . else it @@ -25,6 +27,15 @@ contract VolumeRestrictionTMStorage { uint256 dailyLastTradedDayTime; } + struct RestrictedHolder { + // 1 represent true & 0 for false + uint8 seen; + // Type of period will be enum index of TypeOfPeriod enum + uint8 typeOfPeriod; + // Index of the array where the holder address lives + uint64 index; + } + // Global restriction that applies to all token holders VolumeRestriction public defaultRestriction; // Daily global restriction that applies to all token holders (Total ST traded daily is restricted) @@ -41,5 +52,7 @@ contract VolumeRestrictionTMStorage { mapping(address => BucketDetails) internal defaultUserToBucket; // List of wallets that are exempted from all the restrictions applied by the this contract mapping(address => bool) public exemptList; - + mapping(address => RestrictedHolder) internal restrictedHolders; + address[] public restrictedAddresses; + } \ No newline at end of file diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 1075a64e4..004b58fa7 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -409,6 +409,10 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor1); assert.equal(tx.logs[0].args._typeOfRestriction, 0); + let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + assert.equal(data[0][0], account_investor1); + assert.equal(data[1][0].toNumber(), 0); + }); it("Should add the restriction for multiple investor -- failed because of bad owner", async() => { @@ -538,6 +542,9 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(), 3); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3))[2].toNumber(), 4); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor4))[2].toNumber(), 5); + + let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + assert.equal(data[0].length, 4); }); it("Should remove the restriction multi -- failed because of address is 0", async() => { @@ -554,6 +561,12 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should successfully remove the restriction", async() => { await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, {from: token_owner}); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 0); + let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + assert.equal(data[0].length, 3); + for (let i = 0; i < data.length; i++) { + assert.notEqual(data[0][i], account_investor2); + assert.equal(data[1][i], 0); + } }); it("Should remove the restriction -- failed because restriction not present anymore", async() => { @@ -569,6 +582,8 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ) + let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + assert.equal(data[0].length, 1); }); it("Should add the restriction succesfully after the expiry of previous one for investor 1", async() => { @@ -603,6 +618,9 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[1].args._holder, account_investor1); assert.equal(tx.logs[1].args._typeOfRestriction, 0); + let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + assert.equal(data[0].length, 1); + assert.equal(data[0][0], account_investor1); }); it("Should not successfully transact the tokens -- failed because volume is above the limit", async() => { @@ -717,6 +735,10 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor3); assert.equal(tx.logs[0].args._typeOfRestriction, 0); assert.equal((tx.logs[0].args._allowedTokens).toNumber(), web3.utils.toWei("6")); + let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + assert.equal(data[0].length, 2); + assert.equal(data[0][1], account_investor3); + assert.equal(data[1][1], 1); let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3); console.log(` *** Individual Daily restriction data *** @@ -793,6 +815,12 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor1); assert.equal((tx.logs[0].args._typeOfRestriction).toNumber(), 1); assert.equal((tx.logs[0].args._allowedTokens).dividedBy(new BigNumber(10).pow(16)).toNumber(), 5); + let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + assert.equal(data[0].length, 2); + assert.equal(data[0][1], account_investor3); + assert.equal(data[0][0], account_investor1); + assert.equal(data[1][1].toNumber(), 1); + assert.equal(data[1][0].toNumber(), 2); let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor1); console.log(` *** Individual Daily restriction data *** @@ -857,6 +885,13 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor3); assert.equal(tx.logs[0].args._typeOfRestriction, 1); + + let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + assert.equal(data[0].length, 2); + assert.equal(data[0][1], account_investor3); + assert.equal(data[0][0], account_investor1); + assert.equal(data[1][1].toNumber(), 2); + assert.equal(data[1][0].toNumber(), 2); }); it("Should transfer the token by the investor 3 with in the (Individual + Individual daily limit)", async() => { @@ -910,7 +945,13 @@ contract('VolumeRestrictionTransferManager', accounts => { // remove the Individual daily restriction let tx = await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, {from: token_owner}); assert.equal(tx.logs[0].args._holder, account_investor3); - + let dataAdd = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + assert.equal(dataAdd[0].length, 2); + assert.equal(dataAdd[0][0], account_investor1); + assert.equal(dataAdd[1][0].toNumber(), 2); + assert.equal(dataAdd[0][1], account_investor3); + assert.equal(dataAdd[1][1].toNumber(), 0); + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); // transfer more tokens on the same day From d85c5947176f1fe31378d95adeaec35506080c1e Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 8 Jan 2019 18:02:41 +0530 Subject: [PATCH 496/582] minor fix --- .../TransferManager/VolumeRestrictionTM.sol | 18 ++++++++++++------ .../VolumeRestrictionTMStorage.sol | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 70ee114d0..50c63624f 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -217,10 +217,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } function _addRestrictionData(address _holder, uint8 _callFrom) internal { - uint64 index = restrictedHolders[_holder].index; + uint128 index = restrictedHolders[_holder].index; if (restrictedHolders[_holder].seen == 0) { restrictedAddresses.push(_holder); - index = uint64(restrictedAddresses.length); + index = uint128(restrictedAddresses.length); } uint8 _type = _getTypeOfPeriod(restrictedHolders[_holder].typeOfPeriod, _callFrom, _holder); restrictedHolders[_holder] = RestrictedHolder(uint8(1), _type, index); @@ -469,8 +469,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } function _deleteHolderFromList(address _holder, uint8 _typeOfPeriod) internal { + // Deleting the holder if holder's type of Period is `Both` type otherwise + // it will assign the given type `_typeOfPeriod` to the _holder typeOfPeriod + // `_typeOfPeriod` it always be contrary to the removing restriction + // if removing restriction is individual then typeOfPeriod is TypeOfPeriod.OneDay + // in uint8 its value is 1. if removing restriction is daily individual then typeOfPeriod + // is TypeOfPeriod.MultipleDays in uint8 its value is 0. if (restrictedHolders[_holder].typeOfPeriod != uint8(TypeOfPeriod.Both)) { - uint64 index = restrictedHolders[_holder].index; + uint128 index = restrictedHolders[_holder].index; uint256 _len = restrictedAddresses.length; if (index != _len) { restrictedHolders[restrictedAddresses[_len - 1]].index = index; @@ -694,7 +700,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _startTimes.length == _holders.length && _holders.length == _endTimes.length && _endTimes.length == _restrictionTypes.length, - "Array length mismatch" + "Length mismatch" ); require(_holders.length == _allowedTokens.length, "Length mismatch"); for (uint256 i = 0; i < _holders.length; i++) { @@ -1110,7 +1116,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_endTime > _startTime, "Invalid times"); // Maximum limit for the rollingPeriod is 365 days require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365, "Invalid rollingperiod"); - require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays, "Invalid start & end time"); + require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays, "Invalid times"); } function _checkLengthOfArray( @@ -1128,7 +1134,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _startTimes.length == _rollingPeriodInDays.length && _rollingPeriodInDays.length == _endTimes.length && _endTimes.length == _restrictionTypes.length, - "Array length mismatch" + "Length mismatch" ); } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol index 4e5d3512d..ddc2b8e21 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol @@ -33,7 +33,7 @@ contract VolumeRestrictionTMStorage { // Type of period will be enum index of TypeOfPeriod enum uint8 typeOfPeriod; // Index of the array where the holder address lives - uint64 index; + uint128 index; } // Global restriction that applies to all token holders From 23e7d51227ec0a7378096595cf24e503193c578a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 8 Jan 2019 19:28:48 +0530 Subject: [PATCH 497/582] Fixed test file --- test/z_fuzz_test_adding_removing_modules_ST.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index 32d28c6ab..5b6c8b57d 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -20,7 +20,7 @@ const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager') // modules for test const CountTransferManager = artifacts.require("./CountTransferManager"); const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); -const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); +const VolumeRestrictionTransferManager = artifacts.require('./LockUpTransferManager'); const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); From f5992b42009f15bf9e7d0d160793b51b570cba27 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 8 Jan 2019 15:54:41 -0400 Subject: [PATCH 498/582] Add restrictions data to getRestrictedAddresses --- .../TransferManager/VolumeRestrictionTM.sol | 281 ++++++++++-------- test/y_volume_restriction_tm.js | 57 ++-- 2 files changed, 183 insertions(+), 155 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 50c63624f..eb9475360 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -6,7 +6,7 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../../libraries/BokkyPooBahsDateTimeLibrary.sol"; contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { - + using SafeMath for uint256; // permission definition @@ -115,25 +115,25 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (!paused && _from != address(0) && !exemptList[_from]) { // Function must only be called by the associated security token if _isTransfer == true require(msg.sender == securityToken || !_isTransfer); - // Checking the individual restriction if the `_from` comes in the individual category - if ((individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) + // Checking the individual restriction if the `_from` comes in the individual category + if ((individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) || (individualDailyRestriction[_from].endTime >= now && individualDailyRestriction[_from].startTime <= now)) { return _individualRestrictionCheck(_from, _amount, _isTransfer); // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically } else if ((defaultRestriction.endTime >= now && defaultRestriction.startTime <= now) || (defaultDailyRestriction.endTime >= now && defaultDailyRestriction.startTime <= now)) { - + return _defaultRestrictionCheck(_from, _amount, _isTransfer); } - } + } return Result.NA; } /** * @notice Add/Remove wallet address from the exempt list * @param _wallet Ethereum wallet/contract address that need to be exempted - * @param _change Boolean value used to add (i.e true) or remove (i.e false) from the list + * @param _change Boolean value used to add (i.e true) or remove (i.e false) from the list */ function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { require(_wallet != address(0), "Invalid address"); @@ -156,7 +156,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) external withPerm(ADMIN) @@ -178,29 +178,29 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) internal - { - - uint256 startTime = _startTime; + { + + /* uint256 startTime = _startTime; */ if (_startTime == 0) { - startTime = now; + _startTime = now; } require( individualRestriction[_holder].endTime < now, - "Already present" + "Not Allowed" ); require(_holder != address(0) && !exemptList[_holder], "Invalid address"); - require(startTime >= now, "Invalid startTime"); - _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType); - + /* require(_startTime >= now, "Invalid startTime"); */ + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); + if (individualRestriction[_holder].endTime != 0) { _removeIndividualRestriction(_holder); } individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, RestrictionType(_restrictionType) @@ -209,7 +209,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddIndividualRestriction( _holder, _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -239,11 +239,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) external withPerm(ADMIN) - { + { _addIndividualDailyRestriction( _holder, _allowedTokens, @@ -259,24 +259,24 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) internal - { + { - uint256 startTime = _startTime; + /* uint256 startTime = _startTime; */ if (_startTime == 0) { - startTime = now; + _startTime = now; } require( individualDailyRestriction[_holder].endTime < now, "Not Allowed" ); - require(startTime >= now, "Invalid startTime"); - _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); + /* require(startTime >= now, "Invalid startTime"); */ + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now); individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, - startTime, + _startTime, 1, _endTime, RestrictionType(_restrictionType) @@ -285,7 +285,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddIndividualDailyRestriction( _holder, _allowedTokens, - startTime, + _startTime, 1, _endTime, _restrictionType @@ -305,25 +305,26 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _allowedTokens, uint256[] _startTimes, uint256[] _endTimes, - uint256[] _restrictionTypes + uint256[] _restrictionTypes ) public withPerm(ADMIN) { - require( + _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); + /* require( _allowedTokens.length == _startTimes.length && _startTimes.length == _holders.length && _holders.length == _endTimes.length && _endTimes.length == _restrictionTypes.length, "Array length mismatch" - ); + ); */ for (uint256 i = 0; i < _holders.length; i++) { _addIndividualDailyRestriction( _holders[i], _allowedTokens[i], _startTimes[i], _endTimes[i], - _restrictionTypes[i] + _restrictionTypes[i] ); } } @@ -343,13 +344,13 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _startTimes, uint256[] _rollingPeriodInDays, uint256[] _endTimes, - uint256[] _restrictionTypes + uint256[] _restrictionTypes ) public withPerm(ADMIN) { - _checkLengthOfArray(_allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); - require(_holders.length == _allowedTokens.length, "Length mismatch"); + _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + /* require(_holders.length == _allowedTokens.length, "Length mismatch"); */ for (uint256 i = 0; i < _holders.length; i++) { _addIndividualRestriction( _holders[i], @@ -357,7 +358,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _startTimes[i], _rollingPeriodInDays[i], _endTimes[i], - _restrictionTypes[i] + _restrictionTypes[i] ); } } @@ -375,21 +376,21 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) external withPerm(ADMIN) - { + { uint256 startTime = _startTime; if (_startTime == 0) { startTime = now; } require( defaultRestriction.endTime < now, - "Not allowed" + "Not Allowed" ); - require(startTime >= now, "Invalid startTime"); - _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType); + /* require(startTime >= now, "Invalid startTime"); */ + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); defaultRestriction = VolumeRestriction( _allowedTokens, startTime, @@ -417,11 +418,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) external withPerm(ADMIN) - { + { uint256 startTime = _startTime; if (_startTime == 0) { startTime = now; @@ -430,8 +431,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { defaultDailyRestriction.endTime < now, "Not Allowed" ); - require(startTime >= now, "Invalid startTime"); - _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); + /* require(startTime >= now, "Invalid startTime"); */ + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, now); defaultDailyRestriction = VolumeRestriction( _allowedTokens, startTime, @@ -450,7 +451,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice use to remove the individual restriction for a given address - * @param _holder Address of the user + * @param _holder Address of the user */ function removeIndividualRestriction(address _holder) external withPerm(ADMIN) { _removeIndividualRestriction(_holder); @@ -491,7 +492,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice use to remove the individual restriction for a given address - * @param _holders Array of address of the user + * @param _holders Array of address of the user */ function removeIndividualRestrictionMulti(address[] _holders) external withPerm(ADMIN) { for (uint256 i = 0; i < _holders.length; i++) { @@ -501,7 +502,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice use to remove the individual daily restriction for a given address - * @param _holder Address of the user + * @param _holder Address of the user */ function removeIndividualDailyRestriction(address _holder) external withPerm(ADMIN) { _removeIndividualDailyRestriction(_holder); @@ -519,7 +520,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice use to remove the individual daily restriction for a given address - * @param _holders Array of address of the user + * @param _holders Array of address of the user */ function removeIndividualDailyRestrictionMulti(address[] _holders) external withPerm(ADMIN) { for (uint256 i = 0; i < _holders.length; i++) { @@ -543,7 +544,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(defaultDailyRestriction.endTime != 0); defaultDailyRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); emit DefaultDailyRestrictionRemoved(); - } + } /** * @notice Use to modify the existing individual restriction for a given token holder @@ -560,7 +561,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) external withPerm(ADMIN) @@ -582,20 +583,20 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) internal - { - uint256 startTime = _startTime; + { + /* uint256 startTime = _startTime; */ if (_startTime == 0) { - startTime = now; + _startTime = now; } - require(individualRestriction[_holder].startTime > now, "Not allowed"); - require(startTime >= now, "Invalid startTime"); - _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType); + require(individualRestriction[_holder].startTime > now, "Not Allowed"); + /* require(startTime >= now, "Invalid startTime"); */ + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, RestrictionType(_restrictionType) @@ -603,7 +604,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit ModifyIndividualRestriction( _holder, _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -625,7 +626,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) external withPerm(ADMIN) @@ -645,24 +646,26 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + uint256 _restrictionType ) internal - { - uint256 startTime = _startTime; + { + /* uint256 startTime = _startTime; */ if (_startTime == 0) { - startTime = now; + _startTime = now; } - _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); - // If old startTime is already passed then new startTime should be greater than or equal to the + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, + (individualDailyRestriction[_holder].startTime <= now ? individualDailyRestriction[_holder].startTime : now) + ); + // If old startTime is already passed then new startTime should be greater than or equal to the // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. - if (individualDailyRestriction[_holder].startTime <= now) + /* if (individualDailyRestriction[_holder].startTime <= now) require(startTime >= individualDailyRestriction[_holder].startTime, "Invalid StartTime"); - else - require(startTime >= now); + else + require(startTime >= now); */ individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, - startTime, + _startTime, 1, _endTime, RestrictionType(_restrictionType) @@ -670,7 +673,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit ModifyIndividualDailyRestriction( _holder, _allowedTokens, - startTime, + _startTime, 1, _endTime, _restrictionType @@ -690,7 +693,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _allowedTokens, uint256[] _startTimes, uint256[] _endTimes, - uint256[] _restrictionTypes + uint256[] _restrictionTypes ) public withPerm(ADMIN) @@ -709,10 +712,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _allowedTokens[i], _startTimes[i], _endTimes[i], - _restrictionTypes[i] + _restrictionTypes[i] ); } - } + } /** * @notice Use to modify the existing individual restriction for multiple token holders @@ -729,13 +732,13 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _startTimes, uint256[] _rollingPeriodInDays, uint256[] _endTimes, - uint256[] _restrictionTypes + uint256[] _restrictionTypes ) public withPerm(ADMIN) { - _checkLengthOfArray(_allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); - require(_holders.length == _allowedTokens.length, "Length mismatch"); + _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + /* require(_holders.length == _allowedTokens.length, "Length mismatch"); */ for (uint256 i = 0; i < _holders.length; i++) { _modifyIndividualRestriction( _holders[i], @@ -743,10 +746,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _startTimes[i], _rollingPeriodInDays[i], _endTimes[i], - _restrictionTypes[i] + _restrictionTypes[i] ); } - } + } /** * @notice Use to modify the global restriction for all token holder @@ -765,14 +768,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { - require(defaultRestriction.startTime > now, "Not allowed"); + { + require(defaultRestriction.startTime > now, "Not Allowed"); uint256 startTime = _startTime; if (_startTime == 0) { startTime = now; } - require(startTime >= now, "Invalid startTime"); - _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType); + /* require(startTime >= now, "Invalid startTime"); */ + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); defaultRestriction = VolumeRestriction( _allowedTokens, startTime, @@ -806,18 +809,20 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { + { uint256 startTime = _startTime; if (_startTime == 0) { startTime = now; } - _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType); - // If old startTime is already passed then new startTime should be greater than or equal to the + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, + (defaultDailyRestriction.startTime <= now ? defaultDailyRestriction.startTime : now) + ); + // If old startTime is already passed then new startTime should be greater than or equal to the // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. - if (defaultDailyRestriction.startTime <= now) + /* if (defaultDailyRestriction.startTime <= now) require(startTime >= defaultDailyRestriction.startTime, "Invalid StartTime"); - else - require(startTime >= now); + else + require(startTime >= now); */ defaultDailyRestriction = VolumeRestriction( _allowedTokens, startTime, @@ -838,7 +843,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @notice Internal function used to validate the transaction for a given address * If it validates then it also update the storage corressponds to the default restriction */ - function _defaultRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + function _defaultRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { // using the variable to avoid stack too deep error BucketDetails memory bucketDetails = defaultUserToBucket[_from]; uint256 daysCovered = defaultRestriction.rollingPeriodInDays; @@ -855,7 +860,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Picking up the last timestamp fromTimestamp = bucketDetails.lastTradedDayTime; } - + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod // re-using the local variables to avoid the stack too deep error. (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( @@ -871,7 +876,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } } (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, bucketDetails.dailyLastTradedDayTime, defaultDailyRestriction); - + if (_isTransfer) { _updateStorage( _from, @@ -891,7 +896,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @notice Internal function used to validate the transaction for a given address * If it validates then it also update the storage corressponds to the individual restriction */ - function _individualRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + function _individualRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { // using the variable to avoid stack too deep error BucketDetails memory bucketDetails = userToBucket[_from]; VolumeRestriction memory dailyRestriction = individualDailyRestriction[_from]; @@ -910,7 +915,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Picking up the last timestamp fromTimestamp = bucketDetails.lastTradedDayTime; } - + // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod // re-using the local variables to avoid the stack too deep error. (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( @@ -926,7 +931,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } } (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, bucketDetails.dailyLastTradedDayTime, dailyRestriction); - + if (_isTransfer) { _updateStorage( _from, @@ -948,14 +953,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 amount, uint256 dailyLastTradedDayTime, VolumeRestriction restriction - ) + ) internal view returns(bool, uint256) { // Checking whether the daily restriction is added or not if yes then calculate // the total amount get traded on a particular day (~ _fromTime) - if ( now <= restriction.endTime && now >= restriction.startTime) { + if ( now <= restriction.endTime && now >= restriction.startTime) { uint256 txSumOfDay = 0; if (dailyLastTradedDayTime == 0 || dailyLastTradedDayTime < restriction.startTime) // This if condition will be executed when the individual daily restriction executed first time @@ -997,7 +1002,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (counter >= _rollingPeriodInDays) { // Subtracting the former value(Sum of all the txn amount of that day) from the sumOfLastPeriod // The below line subtracts (the traded volume on days no longer covered by rolling period) from sumOfLastPeriod. - // Every loop execution subtracts one day's trade volume. + // Every loop execution subtracts one day's trade volume. // Loop starts from the first day covered in sumOfLastPeriod upto the day that is covered by rolling period. uint256 temp = _bucketDetails.daysCovered.sub(counter.sub(_rollingPeriodInDays)); temp = _bucketDetails.lastTradedDayTime.sub(temp.mul(1 days)); @@ -1009,7 +1014,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } } // calculating the timestamp that will used as an index of the next bucket - // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... + // i.e buckets period will be look like this T1 to T2-1, T2 to T3-1 .... // where T1,T2,T3 are timestamps having 24 hrs difference _fromTime = _fromTime.add(_diffDays.mul(1 days)); return (sumOfLastPeriod, _fromTime, counter); @@ -1019,11 +1024,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _sumOfLastPeriod, uint256 _amountToTransact, VolumeRestriction _restriction - ) + ) internal view returns (bool) - { + { uint256 _allowedAmount = 0; if (_restriction.typeOfRestriction == RestrictionType.Percentage) { _allowedAmount = (_restriction.allowedTokens.mul(ISecurityToken(securityToken).totalSupply())) / uint256(10) ** 18; @@ -1039,14 +1044,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _amount, uint256 _lastTradedDayTime, uint256 _sumOfLastPeriod, - uint256 _daysCovered, + uint256 _daysCovered, uint256 _dailyLastTradedDayTime, uint256 _endTime, bool isDefault ) - internal - { - + internal + { + if (isDefault){ BucketDetails storage defaultUserToBucketDetails = defaultUserToBucket[_from]; _updateStorageActual(_from, _amount, _lastTradedDayTime, _sumOfLastPeriod, _daysCovered, _dailyLastTradedDayTime, _endTime, defaultUserToBucketDetails); @@ -1062,13 +1067,13 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _amount, uint256 _lastTradedDayTime, uint256 _sumOfLastPeriod, - uint256 _daysCovered, + uint256 _daysCovered, uint256 _dailyLastTradedDayTime, uint256 _endTime, BucketDetails storage details ) - internal - { + internal + { // Cheap storage technique if (details.lastTradedDayTime != _lastTradedDayTime) { // Assigning the latest transaction timestamp of the day @@ -1091,20 +1096,22 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Increasing the total amount of the day by `_amount` bucket[_from][_dailyLastTradedDayTime] = bucket[_from][_dailyLastTradedDayTime].add(_amount); } - } + } } function _checkInputParams( uint256 _allowedTokens, - uint256 _startTime, - uint256 _rollingPeriodDays, + uint256 _startTime, + uint256 _rollingPeriodDays, uint256 _endTime, - uint256 _restrictionType - ) + uint256 _restrictionType, + uint256 _earliestStartTime + ) internal pure { require(_restrictionType == 0 || _restrictionType == 1, "Invalid type"); + require(_startTime >= _earliestStartTime, "Invalid startTime"); if (_restrictionType == uint256(RestrictionType.Fixed)) { require(_allowedTokens > 0, "Invalid value"); } else { @@ -1117,9 +1124,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Maximum limit for the rollingPeriod is 365 days require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365, "Invalid rollingperiod"); require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays, "Invalid times"); - } + } function _checkLengthOfArray( + address[] _holders, uint256[] _allowedTokens, uint256[] _startTimes, uint256[] _rollingPeriodInDays, @@ -1127,9 +1135,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _restrictionTypes ) internal - pure + pure { require( + _holders.length == _allowedTokens.length && _allowedTokens.length == _startTimes.length && _startTimes.length == _rollingPeriodInDays.length && _rollingPeriodInDays.length == _endTimes.length && @@ -1146,7 +1155,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 days covered * @return uint256 24h lastTradedDayTime */ - function getIndividualBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { + function getIndividualBucketDetailsToUser(address _user) public view returns(uint256, uint256, uint256, uint256) { return( userToBucket[_user].lastTradedDayTime, userToBucket[_user].sumOfLastPeriod, @@ -1163,7 +1172,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 days covered * @return uint256 24h lastTradedDayTime */ - function getDefaultBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { + function getDefaultBucketDetailsToUser(address _user) public view returns(uint256, uint256, uint256, uint256) { return( defaultUserToBucket[_user].lastTradedDayTime, defaultUserToBucket[_user].sumOfLastPeriod, @@ -1175,7 +1184,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice Use to get the volume of token that being traded at a particular day (`_at` + 24 hours) for a given user * @param _user Address of the token holder - * @param _at Timestamp + * @param _at Timestamp */ function getTotalTradedByUser(address _user, uint256 _at) external view returns(uint256) { return bucket[_user][_at]; @@ -1197,17 +1206,37 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice use to get the list of token holders who are restricted by the VRTM - * @return address List of addresses that are restricted by the VRTM - * @return uint8 Array of the Type of period restriction on the addresses. 0 - address + * @return address[] List of addresses that are restricted by the VRTM + * @return uint8[] Array of the Type of period restriction on the addresses. 0 - address * has only individual restriction, 1 - address has only individual daily restriction & 2 * it means address has both type of restriction where rolling period is 24 hrs & multiple days as well + * @return uint256[] List of lastTradedDayTime, first group for individuals, second group for default + * @return uint256[] List of sumOfLastPeriod, first group for individuals, second group for default + * @return uint256[] List of daysCovered, first group for individuals, second group for default + * @return uint256[] List of dailyLastTradedDayTime, first group for individuals, second group for default */ - function getRestrictedAddresses() external view returns(address[], uint8[]) { - uint8[] memory typeOfPeriodRestriction = new uint8[](restrictedAddresses.length); + function getRestrictedAddresses() external view returns( + address[] memory allAddresses, + uint8[] memory typeOfPeriodRestriction, + uint256[] memory lastTradedDayTime, + uint256[] memory sumOfLastPeriod, + uint256[] memory daysCovered, + uint256[] memory dailyLastTradedDayTime + ) { + allAddresses = restrictedAddresses; + typeOfPeriodRestriction = new uint8[](restrictedAddresses.length); + lastTradedDayTime = new uint256[](2 * restrictedAddresses.length); + sumOfLastPeriod = new uint256[](2 * restrictedAddresses.length); + daysCovered = new uint256[](2 * restrictedAddresses.length); + dailyLastTradedDayTime = new uint256[](2 * restrictedAddresses.length); for (uint256 i = 0; i < restrictedAddresses.length; i++) { typeOfPeriodRestriction[i] = restrictedHolders[restrictedAddresses[i]].typeOfPeriod; + (lastTradedDayTime[i], sumOfLastPeriod[i], daysCovered[i], dailyLastTradedDayTime[i]) = + getIndividualBucketDetailsToUser(restrictedAddresses[i]); + (lastTradedDayTime[i + restrictedAddresses.length], sumOfLastPeriod[i + restrictedAddresses.length], daysCovered[i + restrictedAddresses.length], dailyLastTradedDayTime[i + restrictedAddresses.length]) = + getDefaultBucketDetailsToUser(restrictedAddresses[i]); } - return (restrictedAddresses, typeOfPeriodRestriction); + /* return (allAddresses, typeOfPeriodRestriction, lastTradedDayTime, sumOfLastPeriod, daysCovered, dailyLastTradedDayTime); */ } /** @@ -1219,6 +1248,4 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { return allPermissions; } - - -} \ No newline at end of file +} diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 004b58fa7..146c1c2b3 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -214,8 +214,8 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_SecurityToken.mint(account_investor1, web3.utils.toWei("40", "ether"), {from: token_owner}); await I_SecurityToken.mint(account_investor2, web3.utils.toWei("30", "ether"), {from: token_owner}); await I_SecurityToken.mint(account_investor3, web3.utils.toWei("30", "ether"), {from: token_owner}); - - // Check the balance of the investors + + // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); let bal2 = await I_SecurityToken.balanceOf.call(account_investor2); // Verifying the balances @@ -406,10 +406,10 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ); - assert.equal(tx.logs[0].args._holder, account_investor1); assert.equal(tx.logs[0].args._typeOfRestriction, 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + console.log(data); assert.equal(data[0][0], account_investor1); assert.equal(data[1][0].toNumber(), 0); @@ -544,6 +544,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor4))[2].toNumber(), 5); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + console.log(data); assert.equal(data[0].length, 4); }); @@ -563,7 +564,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); assert.equal(data[0].length, 3); - for (let i = 0; i < data.length; i++) { + for (let i = 0; i < data[0].length; i++) { assert.notEqual(data[0][i], account_investor2); assert.equal(data[1][i], 0); } @@ -615,7 +616,7 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ); - + assert.equal(tx.logs[1].args._holder, account_investor1); assert.equal(tx.logs[1].args._typeOfRestriction, 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); @@ -639,14 +640,14 @@ contract('VolumeRestrictionTransferManager', accounts => { Gas estimation (Individual): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei('.3'), {from: account_investor1})}` ); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('.3'), {from: account_investor1}); - // Check the balance of the investors + // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 34.7); let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor1); await print(data, account_investor1); - + assert.equal( (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor1, data[0])) .dividedBy(new BigNumber(10).pow(18)).toNumber(), @@ -760,7 +761,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + await increaseTime(duration.minutes(15)); console.log(` @@ -780,7 +781,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should fail to transfer more tokens --because of the above limit", async() => { await catchRevert( I_SecurityToken.transfer(account_investor2, web3.utils.toWei(".1"), {from: account_investor3}) - ); + ); }); it("Should try to send after the one day completion", async() => { @@ -841,7 +842,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor1}); - // Check the balance of the investors + // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 32.7); @@ -882,7 +883,7 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ); - + assert.equal(tx.logs[0].args._holder, account_investor3); assert.equal(tx.logs[0].args._typeOfRestriction, 1); @@ -903,11 +904,11 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log(` Gas estimation (Individual + Individual daily): ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("4"), {from: account_investor3})}` ); - // Check the balance of the investors + // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor3); await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_investor3}); tempArray3.push(4); - // Check the balance of the investors + // Check the balance of the investors let bal2 = await I_SecurityToken.balanceOf.call(account_investor3); // Verifying the balances assert.equal(web3.utils.fromWei(((bal1.minus(bal2)).toNumber()).toString()), 4); @@ -951,7 +952,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(dataAdd[1][0].toNumber(), 2); assert.equal(dataAdd[0][1], account_investor3); assert.equal(dataAdd[1][1].toNumber(), 0); - + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); // transfer more tokens on the same day @@ -1041,7 +1042,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ) ); }); - + it("Should modify the individual daily restriction", async() => { await I_VolumeRestrictionTM.modifyIndividualDailyRestriction( account_investor3, @@ -1146,7 +1147,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should fail to transact tokens more than the allowed in the second rolling period", async() => { - await increaseTime(duration.days(4)); + await increaseTime(duration.days(4)); let i for (i = 0; i < 3; i++) { tempArray3.push(0); @@ -1167,7 +1168,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let allowedAmount = (tempArray3[0] + 1); //sell tokens upto the limit await I_SecurityToken.transfer(account_investor2, web3.utils.toWei(allowedAmount.toString()), {from: account_investor3}); - + tempArray3.push(allowedAmount); let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); @@ -1196,11 +1197,11 @@ contract('VolumeRestrictionTransferManager', accounts => { //sell tokens upto the limit await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("7"), {from: account_investor3}); - + tempArray3.push(7) let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); @@ -1231,7 +1232,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); @@ -1252,7 +1253,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); describe("Test cases for the Default restrictions", async() => { - + it("Should add the investor 4 in the whitelist", async() => { await I_GeneralTransferManager.modifyWhitelist( account_investor4, @@ -1302,10 +1303,10 @@ contract('VolumeRestrictionTransferManager', accounts => { let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); //sell tokens upto the limit await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3.57"), {from: account_investor4}); - + let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor4); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor4, data[3].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); @@ -1365,7 +1366,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); @@ -1421,7 +1422,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); @@ -1478,7 +1479,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); @@ -1593,5 +1594,5 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Maximum Volume"); }); }); - -}); \ No newline at end of file + +}); From ea5089a565c8f9cb54a81edd33cb000beedceab6 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 8 Jan 2019 16:17:14 -0400 Subject: [PATCH 499/582] Remove commented code and better tests --- .../TransferManager/VolumeRestrictionTM.sol | 36 ++----------------- test/y_volume_restriction_tm.js | 21 +++++++++-- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index eb9475360..e19f937ad 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -183,7 +183,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { internal { - /* uint256 startTime = _startTime; */ if (_startTime == 0) { _startTime = now; } @@ -192,7 +191,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { "Not Allowed" ); require(_holder != address(0) && !exemptList[_holder], "Invalid address"); - /* require(_startTime >= now, "Invalid startTime"); */ _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); if (individualRestriction[_holder].endTime != 0) { @@ -263,8 +261,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) internal { - - /* uint256 startTime = _startTime; */ if (_startTime == 0) { _startTime = now; } @@ -272,7 +268,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { individualDailyRestriction[_holder].endTime < now, "Not Allowed" ); - /* require(startTime >= now, "Invalid startTime"); */ _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now); individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, @@ -310,14 +305,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { public withPerm(ADMIN) { + //NB - we duplicate _startTimes below to allow function reuse _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); - /* require( - _allowedTokens.length == _startTimes.length && - _startTimes.length == _holders.length && - _holders.length == _endTimes.length && - _endTimes.length == _restrictionTypes.length, - "Array length mismatch" - ); */ for (uint256 i = 0; i < _holders.length; i++) { _addIndividualDailyRestriction( _holders[i], @@ -350,7 +339,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { withPerm(ADMIN) { _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); - /* require(_holders.length == _allowedTokens.length, "Length mismatch"); */ for (uint256 i = 0; i < _holders.length; i++) { _addIndividualRestriction( _holders[i], @@ -389,7 +377,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { defaultRestriction.endTime < now, "Not Allowed" ); - /* require(startTime >= now, "Invalid startTime"); */ _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); defaultRestriction = VolumeRestriction( _allowedTokens, @@ -431,7 +418,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { defaultDailyRestriction.endTime < now, "Not Allowed" ); - /* require(startTime >= now, "Invalid startTime"); */ _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, now); defaultDailyRestriction = VolumeRestriction( _allowedTokens, @@ -592,7 +578,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _startTime = now; } require(individualRestriction[_holder].startTime > now, "Not Allowed"); - /* require(startTime >= now, "Invalid startTime"); */ _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); individualRestriction[_holder] = VolumeRestriction( _allowedTokens, @@ -650,19 +635,12 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) internal { - /* uint256 startTime = _startTime; */ if (_startTime == 0) { _startTime = now; } _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, (individualDailyRestriction[_holder].startTime <= now ? individualDailyRestriction[_holder].startTime : now) ); - // If old startTime is already passed then new startTime should be greater than or equal to the - // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. - /* if (individualDailyRestriction[_holder].startTime <= now) - require(startTime >= individualDailyRestriction[_holder].startTime, "Invalid StartTime"); - else - require(startTime >= now); */ individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, _startTime, @@ -698,14 +676,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { public withPerm(ADMIN) { - require( - _allowedTokens.length == _startTimes.length && - _startTimes.length == _holders.length && - _holders.length == _endTimes.length && - _endTimes.length == _restrictionTypes.length, - "Length mismatch" - ); - require(_holders.length == _allowedTokens.length, "Length mismatch"); + //NB - we duplicate _startTimes below to allow function reuse + _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); for (uint256 i = 0; i < _holders.length; i++) { _modifyIndividualDailyRestriction( _holders[i], @@ -738,7 +710,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { withPerm(ADMIN) { _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); - /* require(_holders.length == _allowedTokens.length, "Length mismatch"); */ for (uint256 i = 0; i < _holders.length; i++) { _modifyIndividualRestriction( _holders[i], @@ -1236,7 +1207,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { (lastTradedDayTime[i + restrictedAddresses.length], sumOfLastPeriod[i + restrictedAddresses.length], daysCovered[i + restrictedAddresses.length], dailyLastTradedDayTime[i + restrictedAddresses.length]) = getDefaultBucketDetailsToUser(restrictedAddresses[i]); } - /* return (allAddresses, typeOfPeriodRestriction, lastTradedDayTime, sumOfLastPeriod, daysCovered, dailyLastTradedDayTime); */ } /** diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 146c1c2b3..c57ce68f5 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -89,6 +89,16 @@ contract('VolumeRestrictionTransferManager', accounts => { `) } + async function printAll(data) { + let investors = data[0]; + for (let i = 0; i < investors.length; i++) { + console.log("Individual Restrictions: "); + await print([data[2][i], data[3][i], data[4][i], data[5][i]], investors[i]); + console.log("Daily Restrictions: "); + await print([data[2][i + investors.length], data[3][i + investors.length], data[4][i + investors.length], data[5][i + investors.length]], investors[i]); + } + } + async function calculateSum(rollingPeriod, tempArray) { let sum = 0; let start = 0; @@ -409,7 +419,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor1); assert.equal(tx.logs[0].args._typeOfRestriction, 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - console.log(data); + await printAll(data); assert.equal(data[0][0], account_investor1); assert.equal(data[1][0].toNumber(), 0); @@ -544,7 +554,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor4))[2].toNumber(), 5); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - console.log(data); + await printAll(data); assert.equal(data[0].length, 4); }); @@ -563,6 +573,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, {from: token_owner}); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + await printAll(data); assert.equal(data[0].length, 3); for (let i = 0; i < data[0].length; i++) { assert.notEqual(data[0][i], account_investor2); @@ -584,6 +595,7 @@ contract('VolumeRestrictionTransferManager', accounts => { } ) let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + await printAll(data); assert.equal(data[0].length, 1); }); @@ -620,6 +632,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[1].args._holder, account_investor1); assert.equal(tx.logs[1].args._typeOfRestriction, 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + await printAll(data); assert.equal(data[0].length, 1); assert.equal(data[0][0], account_investor1); }); @@ -737,6 +750,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._typeOfRestriction, 0); assert.equal((tx.logs[0].args._allowedTokens).toNumber(), web3.utils.toWei("6")); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + await printAll(data); assert.equal(data[0].length, 2); assert.equal(data[0][1], account_investor3); assert.equal(data[1][1], 1); @@ -817,6 +831,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((tx.logs[0].args._typeOfRestriction).toNumber(), 1); assert.equal((tx.logs[0].args._allowedTokens).dividedBy(new BigNumber(10).pow(16)).toNumber(), 5); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + await printAll(data); assert.equal(data[0].length, 2); assert.equal(data[0][1], account_investor3); assert.equal(data[0][0], account_investor1); @@ -888,6 +903,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._typeOfRestriction, 1); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + await printAll(data); assert.equal(data[0].length, 2); assert.equal(data[0][1], account_investor3); assert.equal(data[0][0], account_investor1); @@ -947,6 +963,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, {from: token_owner}); assert.equal(tx.logs[0].args._holder, account_investor3); let dataAdd = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + await printAll(dataAdd); assert.equal(dataAdd[0].length, 2); assert.equal(dataAdd[0][0], account_investor1); assert.equal(dataAdd[1][0].toNumber(), 2); From dd39b51640793bf035733c4aea6164c64181fcd5 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 8 Jan 2019 17:47:38 -0300 Subject: [PATCH 500/582] 'succesfully' typo --- CLI/commands/permission_manager.js | 52 +- ...kup_volume_restriction_transfer_manager.js | 134 ++--- test/y_volume_restriction_tm.js | 520 +++++++++--------- 3 files changed, 353 insertions(+), 353 deletions(-) diff --git a/CLI/commands/permission_manager.js b/CLI/commands/permission_manager.js index ef3e2ea60..71ee21198 100644 --- a/CLI/commands/permission_manager.js +++ b/CLI/commands/permission_manager.js @@ -32,7 +32,7 @@ async function executeApp() { } }; -async function setup(){ +async function setup() { try { let securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -40,7 +40,7 @@ async function setup(){ securityTokenRegistry.setProvider(web3.currentProvider); } catch (err) { console.log(err) - console.log('\x1b[31m%s\x1b[0m',"There was a problem getting the contracts. Make sure they are deployed to the selected network."); + console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); process.exit(0); } } @@ -56,7 +56,7 @@ async function selectST() { await selectST(); } else { let securityTokenABI = abis.securityToken(); - securityToken = new web3.eth.Contract(securityTokenABI,result); + securityToken = new web3.eth.Contract(securityTokenABI, result); } } @@ -85,13 +85,13 @@ async function addPermissionModule() { } async function changePermissionStep() { - console.log('\n\x1b[34m%s\x1b[0m',"Permission Manager - Change Permission"); + console.log('\n\x1b[34m%s\x1b[0m', "Permission Manager - Change Permission"); let selectedDelegate = await selectDelegate(); if (isNewDelegate) { isNewDelegate = false; changePermissionAction(selectedDelegate); } else { - let selectFlow = readlineSync.keyInSelect(['Remove', 'Change permission'], 'Select an option:', {cancel: false}); + let selectFlow = readlineSync.keyInSelect(['Remove', 'Change permission'], 'Select an option:', { cancel: false }); if (selectFlow == 0) { await deleteDelegate(selectedDelegate); console.log("Delegate successfully deleted.") @@ -110,7 +110,7 @@ async function changePermissionAction(selectedDelegate) { async function deleteDelegate(address) { let deleteDelegateAction = generalPermissionManager.methods.deleteDelegate(address); - await common.sendTransaction(deleteDelegateAction, {factor: 2}); + await common.sendTransaction(deleteDelegateAction, { factor: 2 }); } // Helper functions @@ -118,10 +118,10 @@ async function selectDelegate() { let result; let delegates = await getDelegates(); let permissions = await getDelegatesAndPermissions(); - + let options = ['Add new delegate']; - options = options.concat(delegates.map(function(d) { + options = options.concat(delegates.map(function (d) { let perm = renderTable(permissions, d.address); return `Account: ${d.address} @@ -129,7 +129,7 @@ async function selectDelegate() { Permisions: ${perm}` })); - let index = readlineSync.keyInSelect(options, 'Select a delegate:', {cancel: false}); + let index = readlineSync.keyInSelect(options, 'Select a delegate:', { cancel: false }); if (index == 0) { let newDelegate = await addNewDelegate(); result = newDelegate; @@ -142,32 +142,32 @@ async function selectDelegate() { async function selectModule() { let modules = await getModulesWithPermissions(); - let options = modules.map(function(m) { + let options = modules.map(function (m) { return m.name; }); - let index = readlineSync.keyInSelect(options, 'Select a module:', {cancel: false}); + let index = readlineSync.keyInSelect(options, 'Select a module:', { cancel: false }); return modules[index]; } async function selectPermission(permissions) { - let options = permissions.map(function(p) { + let options = permissions.map(function (p) { return p }); - let index = readlineSync.keyInSelect(options, 'Select a permission:', {cancel: false}); + let index = readlineSync.keyInSelect(options, 'Select a permission:', { cancel: false }); return permissions[index]; } function isPermissionValid() { let options = ['Grant permission', 'Revoke permission']; - let index = readlineSync.keyInSelect(options, 'What do you want to do?', {cancel: false}); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: false }); return index == 0; } async function changePermission(delegate, moduleAddress, permission, isValid) { let changePermissionAction = generalPermissionManager.methods.changePermission(delegate, moduleAddress, web3.utils.asciiToHex(permission), isValid); - let receipt = await common.sendTransaction(changePermissionAction, {factor: 2}); + let receipt = await common.sendTransaction(changePermissionAction, { factor: 2 }); common.getEventFromLogs(generalPermissionManager._jsonInterface, receipt.logs, 'ChangePermission'); - console.log(`Permission changed succesfully,`); + console.log(`Permission changed successfully!`); } async function getDelegates() { @@ -199,7 +199,7 @@ async function addNewDelegate() { limitMessage: "Must be a valid address" }); let details = readlineSync.question('Enter the delegate details (i.e `Belongs to financial firm`): ', { - limit: function(input) { + limit: function (input) { return input.length > 0; }, limitMessage: "Must be a valid string" @@ -208,7 +208,7 @@ async function addNewDelegate() { let addPermissionAction = generalPermissionManager.methods.addDelegate(newDelegate, web3.utils.asciiToHex(details)); let receipt = await common.sendTransaction(addPermissionAction); let event = common.getEventFromLogs(generalPermissionManager._jsonInterface, receipt.logs, 'AddDelegate'); - console.log(`Delegate added succesfully: ${event._delegate} - ${web3.utils.hexToAscii(event._details)}`); + console.log(`Delegate added successfully: ${event._delegate} - ${web3.utils.hexToAscii(event._details)}`); isNewDelegate = true; return event._delegate; } @@ -216,14 +216,14 @@ async function addNewDelegate() { async function getModulesWithPermissions() { let modules = []; let moduleABI = abis.moduleInterface(); - + for (const type in gbl.constants.MODULES_TYPES) { let modulesAttached = await securityToken.methods.getModulesByType(gbl.constants.MODULES_TYPES[type]).call(); for (const m of modulesAttached) { let contractTemp = new web3.eth.Contract(moduleABI, m); let permissions = await contractTemp.methods.getPermissions().call(); if (permissions.length > 0) { - modules.push({ + modules.push({ name: web3.utils.hexToAscii((await securityToken.methods.getModule(m).call())[0]), address: m, permissions: permissions.map(function (p) { return web3.utils.hexToAscii(p) }) @@ -251,11 +251,11 @@ async function getDelegatesAndPermissions() { for (delegateAddr of allDelegates) { if (result[delegateAddr] == undefined) { result[delegateAddr] = [] - } + } if (result[delegateAddr][moduleName + '-' + module] == undefined) { - result[delegateAddr][moduleName + '-' + module] = [{permission: permissionName}] + result[delegateAddr][moduleName + '-' + module] = [{ permission: permissionName }] } else { - result[delegateAddr][moduleName + '-' + module].push({permission: permissionName}) + result[delegateAddr][moduleName + '-' + module].push({ permission: permissionName }) } } } @@ -283,7 +283,7 @@ function renderTable(permissions, address) { } module.exports = { - executeApp: async function() { - return executeApp(); - } + executeApp: async function () { + return executeApp(); + } } \ No newline at end of file diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index 358e5b702..9d8a429a9 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -67,7 +67,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); - before(async() => { + before(async () => { // Accounts setup account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -118,11 +118,11 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { `); }); - describe("Generate the SecurityToken", async() => { + describe("Generate the SecurityToken", async () => { it("Should register the ticker before the generation of the security token", async () => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from: token_owner }); assert.equal(tx.logs[0].args._owner, token_owner); assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); }); @@ -137,27 +137,27 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), + .replace(/\u0000/g, ''), "GeneralTransferManager" ); }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); }); - describe("Buy tokens using on-chain whitelist and test locking them up and attempting to transfer", async() => { + describe("Buy tokens using on-chain whitelist and test locking them up and attempting to transfer", async () => { - it("Should Buy the tokens", async() => { + it("Should Buy the tokens", async () => { // Add the Investor in to the whitelist let tx = await I_GeneralTransferManager.modifyWhitelist( @@ -184,7 +184,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should Buy some more tokens", async() => { + it("Should Buy some more tokens", async () => { // Add the Investor in to the whitelist let tx = await I_GeneralTransferManager.modifyWhitelist( @@ -211,18 +211,18 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should unsuccessfully attach the VolumeRestrictionTransferManager factory with the security token -- failed because Token is not paid", async () => { await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); await catchRevert( - I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) + I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) ) }); it("Should successfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManagerFactory doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), + .replace(/\u0000/g, ''), "LockupVolumeRestrictionTM", "VolumeRestrictionTransferManagerFactory module was not added" ); @@ -235,14 +235,14 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), + .replace(/\u0000/g, ''), "LockupVolumeRestrictionTM", "VolumeRestrictionTransferManager module was not added" ); I_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[2].args._module); }); - it("Add a new token holder", async() => { + it("Add a new token holder", async () => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor3, @@ -266,11 +266,11 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should pause the tranfers at transferManager level", async() => { - let tx = await I_VolumeRestrictionTransferManager.pause({from: token_owner}); + it("Should pause the tranfers at transferManager level", async () => { + let tx = await I_VolumeRestrictionTransferManager.pause({ from: token_owner }); }); - it("Should still be able to transfer between existing token holders up to limit", async() => { + it("Should still be able to transfer between existing token holders up to limit", async () => { // Add the Investor in to the whitelist // Mint some tokens await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); @@ -281,11 +281,11 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should unpause the tranfers at transferManager level", async() => { - await I_VolumeRestrictionTransferManager.unpause({from: token_owner}); + it("Should unpause the tranfers at transferManager level", async () => { + await I_VolumeRestrictionTransferManager.unpause({ from: token_owner }); }); - it("Should prevent the creation of a lockup with bad parameters where the totalAmount is zero", async() => { + it("Should prevent the creation of a lockup with bad parameters where the totalAmount is zero", async () => { // create a lockup // this will generate an exception because the totalAmount is zero await catchRevert( @@ -293,7 +293,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ) }); - it("Should prevent the creation of a lockup with bad parameters where the releaseFrequencySeconds is zero", async() => { + it("Should prevent the creation of a lockup with bad parameters where the releaseFrequencySeconds is zero", async () => { // create a lockup // this will generate an exception because the releaseFrequencySeconds is zero await catchRevert( @@ -301,7 +301,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is zero", async() => { + it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is zero", async () => { // create a lockup // this will generate an exception because the lockUpPeriodSeconds is zero await catchRevert( @@ -310,7 +310,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); - it("Should prevent the creation of a lockup with bad parameters where the total amount to be released is more granular than allowed by the token", async() => { + it("Should prevent the creation of a lockup with bad parameters where the total amount to be released is more granular than allowed by the token", async () => { // create a lockup // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens await catchRevert( @@ -318,7 +318,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is not evenly divisible by releaseFrequencySeconds", async() => { + it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is not evenly divisible by releaseFrequencySeconds", async () => { // balance should be 9000000000000000000 here (9 eth) let balance = await I_SecurityToken.balanceOf(account_investor2) @@ -332,7 +332,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should prevent the creation of a lockup with bad parameters where the total amount being locked up isn't evenly divisible by the number of total periods", async() => { + it("Should prevent the creation of a lockup with bad parameters where the total amount being locked up isn't evenly divisible by the number of total periods", async () => { // create a lockup for a balance of 1 eth // over 16e18 seconds total, with 4e18 periods of 4 seconds each. @@ -342,7 +342,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should prevent the creation of a lockup with bad parameters where the amount to be released per period is too granular for the token", async() => { + it("Should prevent the creation of a lockup with bad parameters where the amount to be released per period is too granular for the token", async () => { // balance should be 9000000000000000000 here (9 eth) let balance = await I_SecurityToken.balanceOf(account_investor2) @@ -356,7 +356,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); - it("Should prevent the transfer of tokens in a lockup", async() => { + it("Should prevent the transfer of tokens in a lockup", async () => { let balance = await I_SecurityToken.balanceOf(account_investor2) console.log("balance", balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); @@ -374,7 +374,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { + it("Should allow the transfer of tokens in a lockup if a period has passed", async () => { // wait 4 seconds await increaseTime(duration.seconds(4)); @@ -382,14 +382,14 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); }); - it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { + it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async () => { await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }) ); }); - it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { + it("Should allow the transfer of more tokens in a lockup if another period has passed", async () => { // wait 4 more seconds await increaseTime(4000); @@ -397,7 +397,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); }); - it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async() => { + it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async () => { let balance = await I_SecurityToken.balanceOf(account_investor2) @@ -407,7 +407,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); }); - it("Should prevent the transfer of tokens in an edited lockup", async() => { + it("Should prevent the transfer of tokens in an edited lockup", async () => { // balance here should be 12000000000000000000 (12e18 or 12 eth) @@ -453,7 +453,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); - it("Should succesfully modify the lockup - fail because array index out of bound", async() => { + it("Should successfully modify the lockup - fail because array index out of bound", async () => { // balance here should be 12000000000000000000 (12e18 or 12 eth) let balance = await I_SecurityToken.balanceOf(account_investor1); await catchRevert( @@ -461,13 +461,13 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }) - it("Should succesfully get the lockup - fail because array index out of bound", async() => { + it("Should successfully get the lockup - fail because array index out of bound", async () => { await catchRevert( I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 9) ); }) - it("Should be possible to remove a lockup -- couldn't transfer because of lock up", async() => { + it("Should be possible to remove a lockup -- couldn't transfer because of lock up", async () => { let acct1Balance = await I_SecurityToken.balanceOf(account_investor1) @@ -482,7 +482,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // remove the lockup await I_VolumeRestrictionTransferManager.removeLockUp(account_investor1, 0, { from: token_owner }); - lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); + lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); assert.equal(lockUpCount, 0) let acct2BalanceBefore = await I_SecurityToken.balanceOf(account_investor2) @@ -492,13 +492,13 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { assert.equal(acct2BalanceAfter.sub(acct2BalanceBefore).toString(), acct1Balance.toString()) }); - it("Should try to remove the lockup --failed because of index is out of bounds", async() => { + it("Should try to remove the lockup --failed because of index is out of bounds", async () => { await catchRevert( I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 7, { from: token_owner }) ); }) - it("Should be possible to create multiple lockups at once", async() => { + it("Should be possible to create multiple lockups at once", async () => { let balancesBefore = {} @@ -571,22 +571,22 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); - it("Should revert if the parameters are bad when creating multiple lockups", async() => { + it("Should revert if the parameters are bad when creating multiple lockups", async () => { await catchRevert( // pass in the wrong number of params. txn should revert - I_VolumeRestrictionTransferManager.addLockUpMulti( - [account_investor2, account_investor3], - [16, 8], - [2], // this array should have 2 elements but it has 1, which should cause a revert - [0, 0], - [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], - { from: token_owner } - ) + I_VolumeRestrictionTransferManager.addLockUpMulti( + [account_investor2, account_investor3], + [16, 8], + [2], // this array should have 2 elements but it has 1, which should cause a revert + [0, 0], + [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], + { from: token_owner } + ) ); }); - it("Should be possible to create a lockup with a specific start time in the future", async() => { + it("Should be possible to create a lockup with a specific start time in the future", async () => { // remove all lockups for account 2 let lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); @@ -613,7 +613,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); - it("Should be possible to edit a lockup with a specific start time in the future", async() => { + it("Should be possible to edit a lockup with a specific start time in the future", async () => { // edit the lockup let now = latestTime(); @@ -697,7 +697,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); }); - it("Should be possible to stack lockups", async() => { + it("Should be possible to stack lockups", async () => { // should be 17000000000000000000 let balance = await I_SecurityToken.balanceOf(account_investor1) @@ -763,13 +763,13 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); - it("Should get configuration function signature", async() => { + it("Should get configuration function signature", async () => { let sig = await I_VolumeRestrictionTransferManager.getInitFunction.call(); assert.equal(web3.utils.hexToNumber(sig), 0); }); - it("Should get the permission", async() => { + it("Should get the permission", async () => { let perm = await I_VolumeRestrictionTransferManager.getPermissions.call(); assert.equal(perm.length, 1); // console.log(web3.utils.toAscii(perm[0]).replace(/\u0000/g, '')) @@ -778,28 +778,28 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); - describe("VolumeRestriction Transfer Manager Factory test cases", async() => { + describe("VolumeRestriction Transfer Manager Factory test cases", async () => { - it("Should get the exact details of the factory", async() => { - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getSetupCost.call(),0); - assert.equal((await I_VolumeRestrictionTransferManagerFactory.getTypes.call())[0],2); + it("Should get the exact details of the factory", async () => { + assert.equal(await I_VolumeRestrictionTransferManagerFactory.getSetupCost.call(), 0); + assert.equal((await I_VolumeRestrictionTransferManagerFactory.getTypes.call())[0], 2); assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTransferManagerFactory.getName.call()) - .replace(/\u0000/g, ''), - "LockupVolumeRestrictionTM", - "Wrong Module added"); + .replace(/\u0000/g, ''), + "LockupVolumeRestrictionTM", + "Wrong Module added"); assert.equal(await I_VolumeRestrictionTransferManagerFactory.description.call(), - "Manage transfers using lock ups over time", - "Wrong Module added"); + "Manage transfers using lock ups over time", + "Wrong Module added"); assert.equal(await I_VolumeRestrictionTransferManagerFactory.title.call(), - "Lockup Volume Restriction Transfer Manager", - "Wrong Module added"); + "Lockup Volume Restriction Transfer Manager", + "Wrong Module added"); assert.equal(await I_VolumeRestrictionTransferManagerFactory.getInstructions.call(), - "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", - "Wrong Module added"); + "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", + "Wrong Module added"); assert.equal(await I_VolumeRestrictionTransferManagerFactory.version.call(), "1.0.0"); }); - it("Should get the tags of the factory", async() => { + it("Should get the tags of the factory", async () => { let tags = await I_VolumeRestrictionTransferManagerFactory.getTags.call(); assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Volume"); }); diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 1075a64e4..217d89919 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -1,6 +1,6 @@ import latestTime from './helpers/latestTime'; -import {signData} from './helpers/signData'; -import { pk } from './helpers/testprivateKey'; +import { signData } from './helpers/signData'; +import { pk } from './helpers/testprivateKey'; import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; import { catchRevert } from "./helpers/exceptions"; @@ -83,7 +83,7 @@ contract('VolumeRestrictionTransferManager', accounts => { Days Covered: ${data[2].toNumber()} Latest timestamp daily: ${data[3].toNumber()} Individual Total Trade on latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[0])) - .dividedBy(new BigNumber(10).pow(18)).toNumber()} + .dividedBy(new BigNumber(10).pow(18)).toNumber()} Individual Total Trade on daily latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[3])) .dividedBy(new BigNumber(10).pow(18)).toNumber()} `) @@ -100,7 +100,7 @@ contract('VolumeRestrictionTransferManager', accounts => { return sum; } - before(async() => { + before(async () => { // Accounts setup account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -186,9 +186,9 @@ contract('VolumeRestrictionTransferManager', accounts => { }); }); - describe("Attach the VRTM", async() => { - it("Deploy the VRTM and attach with the ST", async()=> { - let tx = await I_SecurityToken.addModule(I_VolumeRestrictionTMFactory.address, 0, 0, 0, {from: token_owner }); + describe("Attach the VRTM", async () => { + it("Deploy the VRTM and attach with the ST", async () => { + let tx = await I_SecurityToken.addModule(I_VolumeRestrictionTMFactory.address, 0, 0, 0, { from: token_owner }); assert.equal(tx.logs[2].args._moduleFactory, I_VolumeRestrictionTMFactory.address); assert.equal( web3.utils.toUtf8(tx.logs[2].args._name), @@ -197,24 +197,24 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM = VolumeRestrictionTM.at(tx.logs[2].args._module); }); - it("Transfer some tokens to different account", async() => { + it("Transfer some tokens to different account", async () => { // Add tokens in to the whitelist await I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor1, account_investor2, account_investor3], - [latestTime(), latestTime(), latestTime()], - [latestTime(), latestTime(), latestTime()], - [latestTime() + duration.days(60), latestTime() + duration.days(60), latestTime() + duration.days(60)], - [true, true, true], - { - from: token_owner - } + [account_investor1, account_investor2, account_investor3], + [latestTime(), latestTime(), latestTime()], + [latestTime(), latestTime(), latestTime()], + [latestTime() + duration.days(60), latestTime() + duration.days(60), latestTime() + duration.days(60)], + [true, true, true], + { + from: token_owner + } ); // Mint some tokens and transferred to whitelisted addresses - await I_SecurityToken.mint(account_investor1, web3.utils.toWei("40", "ether"), {from: token_owner}); - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("30", "ether"), {from: token_owner}); - await I_SecurityToken.mint(account_investor3, web3.utils.toWei("30", "ether"), {from: token_owner}); - + await I_SecurityToken.mint(account_investor1, web3.utils.toWei("40", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor2, web3.utils.toWei("30", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor3, web3.utils.toWei("30", "ether"), { from: token_owner }); + // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); let bal2 = await I_SecurityToken.balanceOf.call(account_investor2); @@ -224,17 +224,17 @@ contract('VolumeRestrictionTransferManager', accounts => { }); - it("Should transfer the tokens freely without any restriction", async() => { + it("Should transfer the tokens freely without any restriction", async () => { await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('5', 'ether'), { from: account_investor1 }); let bal1 = await I_SecurityToken.balanceOf.call(account_investor3); - // Verifying the balances + // Verifying the balances assert.equal(web3.utils.fromWei((bal1.toNumber()).toString()), 35); }); }) - describe("Test for the addIndividualRestriction", async() => { + describe("Test for the addIndividualRestriction", async () => { - it("Should add the restriction -- failed because of bad owner", async() => { + it("Should add the restriction -- failed because of bad owner", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -250,7 +250,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should add the restriction -- failed because of bad parameters i.e invalid restriction type", async() => { + it("Should add the restriction -- failed because of bad parameters i.e invalid restriction type", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -266,7 +266,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should add the restriction -- failed because of bad parameters i.e Invalid value of allowed tokens", async() => { + it("Should add the restriction -- failed because of bad parameters i.e Invalid value of allowed tokens", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -282,7 +282,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should add the restriction -- failed because of bad parameters i.e Percentage of tokens not within (0,100]", async() => { + it("Should add the restriction -- failed because of bad parameters i.e Percentage of tokens not within (0,100]", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -298,7 +298,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should add the restriction -- failed because of bad parameters i.e Percentage of tokens not within (0,100]", async() => { + it("Should add the restriction -- failed because of bad parameters i.e Percentage of tokens not within (0,100]", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -314,7 +314,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should add the restriction -- failed because of bad parameters i.e invalid dates", async() => { + it("Should add the restriction -- failed because of bad parameters i.e invalid dates", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -330,7 +330,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should add the restriction -- failed because of bad parameters i.e invalid dates", async() => { + it("Should add the restriction -- failed because of bad parameters i.e invalid dates", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -346,7 +346,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async() => { + it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -362,7 +362,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async() => { + it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -378,7 +378,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async() => { + it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, @@ -394,32 +394,32 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should add the restriction succesfully", async() => { + it("Should add the restriction successfully", async () => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( - account_investor1, - web3.utils.toWei("12"), - latestTime() + duration.seconds(2), - 3, - latestTime() + duration.days(5), - 0, - { - from: token_owner - } - ); - + account_investor1, + web3.utils.toWei("12"), + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(5), + 0, + { + from: token_owner + } + ); + assert.equal(tx.logs[0].args._holder, account_investor1); assert.equal(tx.logs[0].args._typeOfRestriction, 0); }); - it("Should add the restriction for multiple investor -- failed because of bad owner", async() => { + it("Should add the restriction for multiple investor -- failed because of bad owner", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], - [3,4,5], + [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], - [0,0,0], + [0, 0, 0], { from: account_polymath } @@ -427,15 +427,15 @@ contract('VolumeRestrictionTransferManager', accounts => { ) }); - it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], - [3,4,5], + [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], - [0,0,0], + [0, 0, 0], { from: token_owner } @@ -443,15 +443,15 @@ contract('VolumeRestrictionTransferManager', accounts => { ) }); - it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10")], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], - [3,4,5], + [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], - [0,0,0], + [0, 0, 0], { from: account_polymath } @@ -459,15 +459,15 @@ contract('VolumeRestrictionTransferManager', accounts => { ) }); - it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], - [3,4,5], + [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], - [0,0,0], + [0, 0, 0], { from: token_owner } @@ -475,7 +475,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ) }); - it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], @@ -483,7 +483,7 @@ contract('VolumeRestrictionTransferManager', accounts => { [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], - [0,0,0], + [0, 0, 0], { from: token_owner } @@ -491,7 +491,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ) }); - it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], @@ -499,7 +499,7 @@ contract('VolumeRestrictionTransferManager', accounts => { [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], [3, 4, 5], [latestTime() + duration.days(5)], - [0,0,0], + [0, 0, 0], { from: token_owner } @@ -507,7 +507,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ) }); - it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async() => { + it("Should add the restriction for multiple investor -- failed because of bad parameters i.e length mismatch", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], @@ -523,24 +523,24 @@ contract('VolumeRestrictionTransferManager', accounts => { ) }); - it("Should add the restriction for multiple investor successfully", async() => { + it("Should add the restriction for multiple investor successfully", async () => { await I_VolumeRestrictionTM.addIndividualRestrictionMulti( - [account_investor2, account_delegate3, account_investor4], - [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], - [3, 4, 5], - [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], - [0,0,0], - { - from: token_owner - } + [account_investor2, account_delegate3, account_investor4], + [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], + [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [3, 4, 5], + [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], + [0, 0, 0], + { + from: token_owner + } ); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[2].toNumber(), 3); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3))[2].toNumber(), 4); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor4))[2].toNumber(), 5); }); - it("Should remove the restriction multi -- failed because of address is 0", async() => { + it("Should remove the restriction multi -- failed because of address is 0", async () => { await catchRevert( I_VolumeRestrictionTM.removeIndividualRestrictionMulti( [0, account_delegate3, account_investor4], @@ -551,18 +551,18 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should successfully remove the restriction", async() => { - await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, {from: token_owner}); + it("Should successfully remove the restriction", async () => { + await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, { from: token_owner }); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 0); }); - it("Should remove the restriction -- failed because restriction not present anymore", async() => { + it("Should remove the restriction -- failed because restriction not present anymore", async () => { await catchRevert( - I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, {from: token_owner}) + I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, { from: token_owner }) ); }); - it("Should remove the restriction multi", async() => { + it("Should remove the restriction multi", async () => { await I_VolumeRestrictionTM.removeIndividualRestrictionMulti( [account_delegate3, account_investor4], { @@ -571,7 +571,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ) }); - it("Should add the restriction succesfully after the expiry of previous one for investor 1", async() => { + it("Should add the restriction successfully after the expiry of previous one for investor 1", async () => { await increaseTime(duration.days(5.1)); console.log( @@ -590,37 +590,37 @@ contract('VolumeRestrictionTransferManager', accounts => { `); let tx = await I_VolumeRestrictionTM.addIndividualRestriction( - account_investor1, - web3.utils.toWei("12"), - latestTime() + duration.seconds(2), - 3, - latestTime() + duration.days(6), - 0, - { - from: token_owner - } - ); - + account_investor1, + web3.utils.toWei("12"), + latestTime() + duration.seconds(2), + 3, + latestTime() + duration.days(6), + 0, + { + from: token_owner + } + ); + assert.equal(tx.logs[1].args._holder, account_investor1); assert.equal(tx.logs[1].args._typeOfRestriction, 0); }); - it("Should not successfully transact the tokens -- failed because volume is above the limit", async() => { + it("Should not successfully transact the tokens -- failed because volume is above the limit", async () => { await increaseTime(duration.seconds(10)); await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei("13"), { from: account_investor1}) + I_SecurityToken.transfer(account_investor3, web3.utils.toWei("13"), { from: account_investor1 }) ); }); - it("Should succesfully transact the tokens by investor 1 just after the startTime", async() => { + it("Should successfully transact the tokens by investor 1 just after the startTime", async () => { // Check the transfer will be valid or not by calling the verifyTransfer() directly by using _isTransfer = false let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor1, account_investor3, web3.utils.toWei('.3'), "0x0", false); assert.equal(result.toNumber(), 1); // Perform the transaction console.log(` - Gas estimation (Individual): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei('.3'), {from: account_investor1})}` + Gas estimation (Individual): ${await I_SecurityToken.transfer.estimateGas(account_investor3, web3.utils.toWei('.3'), { from: account_investor1 })}` ); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('.3'), {from: account_investor1}); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei('.3'), { from: account_investor1 }); // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances @@ -628,10 +628,10 @@ contract('VolumeRestrictionTransferManager', accounts => { let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor1); await print(data, account_investor1); - + assert.equal( (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor1, data[0])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), + .dividedBy(new BigNumber(10).pow(18)).toNumber(), 0.3 ); assert.equal( @@ -642,7 +642,7 @@ contract('VolumeRestrictionTransferManager', accounts => { tempArray.push(0.3); }); - it("Should fail to add the individual daily restriction -- Bad msg.sender", async() => { + it("Should fail to add the individual daily restriction -- Bad msg.sender", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor3, @@ -657,7 +657,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should fail to add the individual daily restriction -- Bad params value", async() => { + it("Should fail to add the individual daily restriction -- Bad params value", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor3, @@ -672,7 +672,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should fail to add the individual daily restriction -- Bad params value", async() => { + it("Should fail to add the individual daily restriction -- Bad params value", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor3, @@ -687,7 +687,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should fail to add the individual daily restriction -- Bad params value", async() => { + it("Should fail to add the individual daily restriction -- Bad params value", async () => { await catchRevert( I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor3, @@ -702,17 +702,17 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should add the individual daily restriction for investor 3", async() => { + it("Should add the individual daily restriction for investor 3", async () => { let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( - account_investor3, - web3.utils.toWei("6"), - latestTime() + duration.seconds(1), - latestTime() + duration.days(4), - 0, - { - from: token_owner - } - ); + account_investor3, + web3.utils.toWei("6"), + latestTime() + duration.seconds(1), + latestTime() + duration.days(4), + 0, + { + from: token_owner + } + ); assert.equal(tx.logs[0].args._holder, account_investor3); assert.equal(tx.logs[0].args._typeOfRestriction, 0); @@ -728,57 +728,57 @@ contract('VolumeRestrictionTransferManager', accounts => { `); }); - it("Should transfer the tokens within the individual daily restriction limits", async() => { + it("Should transfer the tokens within the individual daily restriction limits", async () => { // transfer 2 tokens as per the limit await increaseTime(5); // increase 5 seconds to layoff the time gap let startTime = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); console.log(` - Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), {from: account_investor3})} + Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), { from: account_investor3 })} `) - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), { from: account_investor3 }); let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + await increaseTime(duration.minutes(15)); console.log(` - Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("4"), {from: account_investor3})} + Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("4"), { from: account_investor3 })} `) // transfer the 4 tokens which is under the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), { from: account_investor3 }); let newData = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(newData, account_investor3); assert.equal(newData[3].toNumber(), data[3].toNumber()); assert.equal(data[3].toNumber(), startTime); assert.equal((await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[3])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), 6); + .dividedBy(new BigNumber(10).pow(18)).toNumber(), 6); }); - it("Should fail to transfer more tokens --because of the above limit", async() => { + it("Should fail to transfer more tokens --because of the above limit", async () => { await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei(".1"), {from: account_investor3}) - ); + I_SecurityToken.transfer(account_investor2, web3.utils.toWei(".1"), { from: account_investor3 }) + ); }); - it("Should try to send after the one day completion", async() => { + it("Should try to send after the one day completion", async () => { // increase the EVM time by one day await increaseTime(duration.days(1)); let startTime = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); console.log(` - Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), {from: account_investor3})} + Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), { from: account_investor3 })} `) - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), { from: account_investor3 }); let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); assert.equal(data[3].toNumber(), startTime + duration.days(1)); assert.equal((await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[3])) - .dividedBy(new BigNumber(10).pow(18)).toNumber(), 2); + .dividedBy(new BigNumber(10).pow(18)).toNumber(), 2); }); - it("Should add the daily restriction on the investor 1", async() => { + it("Should add the daily restriction on the investor 1", async () => { let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor1, new BigNumber(5).times(new BigNumber(10).pow(16)), @@ -804,15 +804,15 @@ contract('VolumeRestrictionTransferManager', accounts => { `); }); - it("Should transfer tokens on the 2nd day by investor1 (Individual + Individual daily)", async() => { + it("Should transfer tokens on the 2nd day by investor1 (Individual + Individual daily)", async () => { let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); console.log(` - Gas estimation (Individual + Individual daily): ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), {from: account_investor1})}` + Gas estimation (Individual + Individual daily): ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), { from: account_investor1 })}` ); - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor1}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), { from: account_investor1 }); // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); // Verifying the balances @@ -824,25 +824,25 @@ contract('VolumeRestrictionTransferManager', accounts => { // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor1, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, tempArray)); assert.equal(data[2].toNumber(), 1); assert.equal(data[3].toNumber(), - (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor1))[1].toNumber()); + (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor1))[1].toNumber()); assert.equal(amt, 2); }); - it("Should fail to transfer by investor 1 -- because voilating the individual daily", async() => { + it("Should fail to transfer by investor 1 -- because voilating the individual daily", async () => { // transfer 4 tokens -- voilate the daily restriction await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_investor1}) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), { from: account_investor1 }) ); }); - it("Should add the individual restriction to investor 3", async() => { + it("Should add the individual restriction to investor 3", async () => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor3, new BigNumber(15.36).times(new BigNumber(10).pow(16)), // 15.36 tokens as totalsupply is 1000 @@ -854,23 +854,23 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ); - + assert.equal(tx.logs[0].args._holder, account_investor3); assert.equal(tx.logs[0].args._typeOfRestriction, 1); }); - it("Should transfer the token by the investor 3 with in the (Individual + Individual daily limit)", async() => { + it("Should transfer the token by the investor 3 with in the (Individual + Individual daily limit)", async () => { await increaseTime(4); // Allowed 4 tokens to transfer let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); let startTimeDaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); console.log(` - Gas estimation (Individual + Individual daily): ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("4"), {from: account_investor3})}` + Gas estimation (Individual + Individual daily): ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("4"), { from: account_investor3 })}` ); // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor3); - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), { from: account_investor3 }); tempArray3.push(4); // Check the balance of the investors let bal2 = await I_SecurityToken.balanceOf.call(account_investor3); @@ -882,7 +882,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -893,35 +893,35 @@ contract('VolumeRestrictionTransferManager', accounts => { }); - it("Should fail during transferring more tokens by investor3 -- Voilating the daily Limit", async() => { + it("Should fail during transferring more tokens by investor3 -- Voilating the daily Limit", async () => { await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1"), {from: account_investor3}) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1"), { from: account_investor3 }) ); }); - it("Should remove the daily individual limit and transfer more tokens on a same day -- failed because of bad owner", async() => { + it("Should remove the daily individual limit and transfer more tokens on a same day -- failed because of bad owner", async () => { // remove the Individual daily restriction await catchRevert( - I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, {from: account_investor4}) + I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, { from: account_investor4 }) ); }) - it("Should remove the daily individual limit and transfer more tokens on a same day", async() => { + it("Should remove the daily individual limit and transfer more tokens on a same day", async () => { // remove the Individual daily restriction - let tx = await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, {from: token_owner}); + let tx = await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, { from: token_owner }); assert.equal(tx.logs[0].args._holder, account_investor3); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); // transfer more tokens on the same day - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_investor3}); - tempArray3[tempArray3.length -1] += 4; + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), { from: account_investor3 }); + tempArray3[tempArray3.length - 1] += 4; let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -931,7 +931,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, 8); }); - it("Should add the new Individual daily restriction and transact the tokens", async() => { + it("Should add the new Individual daily restriction and transact the tokens", async () => { // add new restriction let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor3, @@ -963,7 +963,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await increaseTime(duration.days(1.1)); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), { from: account_investor3 }); tempArray3.push(2); let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); @@ -971,7 +971,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -982,11 +982,11 @@ contract('VolumeRestrictionTransferManager', accounts => { // Fail to sell more tokens than the limit await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), { from: account_investor3 }) ); }); - it("Should fail to modify the individual daily restriction -- bad owner", async() => { + it("Should fail to modify the individual daily restriction -- bad owner", async () => { await catchRevert( I_VolumeRestrictionTM.modifyIndividualDailyRestriction( account_investor3, @@ -1000,17 +1000,17 @@ contract('VolumeRestrictionTransferManager', accounts => { ) ); }); - - it("Should modify the individual daily restriction", async() => { + + it("Should modify the individual daily restriction", async () => { await I_VolumeRestrictionTM.modifyIndividualDailyRestriction( - account_investor3, - web3.utils.toWei('3'), - 0, - latestTime() + duration.days(5), - 0, - { - from: token_owner - } + account_investor3, + web3.utils.toWei('3'), + 0, + latestTime() + duration.days(5), + 0, + { + from: token_owner + } ); let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3); @@ -1024,20 +1024,20 @@ contract('VolumeRestrictionTransferManager', accounts => { `); }); - it("Should allow to sell to transfer more tokens by investor3", async() => { + it("Should allow to sell to transfer more tokens by investor3", async () => { let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), {from: account_investor3}); - tempArray3[tempArray3.length -1] += 3; + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), { from: account_investor3 }); + tempArray3[tempArray3.length - 1] += 3; let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1047,14 +1047,14 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, 5); }); - it("Should allow to transact the tokens on the other day", async() => { + it("Should allow to transact the tokens on the other day", async () => { let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); await increaseTime(duration.days(1)); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2.36"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2.36"), { from: account_investor3 }); tempArray3.push(2.36); let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); @@ -1062,7 +1062,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1072,29 +1072,29 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, 2.36); }); - it("Should fail to transfer the tokens after completion of the total amount", async() => { + it("Should fail to transfer the tokens after completion of the total amount", async () => { await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei("0.3"), {from: account_investor3}) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("0.3"), { from: account_investor3 }) ); }) - it("Should sell more tokens on the same day after changing the total supply", async() => { - await I_SecurityToken.mint(account_investor3, web3.utils.toWei("10"), {from: token_owner}); + it("Should sell more tokens on the same day after changing the total supply", async () => { + await I_SecurityToken.mint(account_investor3, web3.utils.toWei("10"), { from: token_owner }); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei(".50"), {from: account_investor3}); - tempArray3[tempArray3.length -1] += .50; + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei(".50"), { from: account_investor3 }); + tempArray3[tempArray3.length - 1] += .50; let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1104,8 +1104,8 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, 2.86); }); - it("Should fail to transact tokens more than the allowed in the second rolling period", async() => { - await increaseTime(duration.days(4)); + it("Should fail to transact tokens more than the allowed in the second rolling period", async () => { + await increaseTime(duration.days(4)); let i for (i = 0; i < 3; i++) { tempArray3.push(0); @@ -1113,11 +1113,11 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log(`Diff Days: ${(latestTime() - ((await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3))[0]).toNumber()) / 86400}`); let allowedAmount = (tempArray3[0] + 1.1); await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei(allowedAmount.toString()), {from: account_investor3}) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei(allowedAmount.toString()), { from: account_investor3 }) ); }) - it("Should successfully to transact tokens in the second rolling period", async() => { + it("Should successfully to transact tokens in the second rolling period", async () => { // Should transact freely tokens daily limit is also ended let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); @@ -1125,15 +1125,15 @@ contract('VolumeRestrictionTransferManager', accounts => { let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); let allowedAmount = (tempArray3[0] + 1); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei(allowedAmount.toString()), {from: account_investor3}); - + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei(allowedAmount.toString()), { from: account_investor3 }); + tempArray3.push(allowedAmount); let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1143,7 +1143,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, allowedAmount); }); - it("Should sell more tokens on the net day of rolling period", async() => { + it("Should sell more tokens on the net day of rolling period", async () => { await increaseTime(duration.days(3)); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); @@ -1154,15 +1154,15 @@ contract('VolumeRestrictionTransferManager', accounts => { tempArray3.push(0); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("7"), {from: account_investor3}); - + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("7"), { from: account_investor3 }); + tempArray3.push(7) let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1172,10 +1172,10 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, 7); }) - it("Should transfer after the 5 days", async() => { + it("Should transfer after the 5 days", async () => { await increaseTime(duration.days(4.5)); - for (let i = 0; i <3; i++) { + for (let i = 0; i < 3; i++) { tempArray3.push(0); } @@ -1183,17 +1183,17 @@ contract('VolumeRestrictionTransferManager', accounts => { let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("25"), {from: account_investor2}); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("25"), { from: account_investor2 }); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("8"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("8"), { from: account_investor3 }); tempArray3.push(8); let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1203,16 +1203,16 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, 8); }); - it("Should freely transfer the tokens after one day (completion of individual restriction)", async() => { + it("Should freely transfer the tokens after one day (completion of individual restriction)", async () => { // increase one time await increaseTime(duration.days(2)); - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("17"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("17"), { from: account_investor3 }); }); }); - describe("Test cases for the Default restrictions", async() => { - - it("Should add the investor 4 in the whitelist", async() => { + describe("Test cases for the Default restrictions", async () => { + + it("Should add the investor 4 in the whitelist", async () => { await I_GeneralTransferManager.modifyWhitelist( account_investor4, latestTime(), @@ -1225,11 +1225,11 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should mint some tokens to investor 4", async() => { - await I_SecurityToken.mint(account_investor4, web3.utils.toWei("20"), {from: token_owner}); + it("Should mint some tokens to investor 4", async () => { + await I_SecurityToken.mint(account_investor4, web3.utils.toWei("20"), { from: token_owner }); }); - it("Should add the default daily restriction successfully", async() => { + it("Should add the default daily restriction successfully", async () => { await I_VolumeRestrictionTM.addDefaultDailyRestriction( new BigNumber(2.75).times(new BigNumber(10).pow(16)), 0, @@ -1251,23 +1251,23 @@ contract('VolumeRestrictionTransferManager', accounts => { `); }); - it("Should fail to transfer above the daily limit", async() => { + it("Should fail to transfer above the daily limit", async () => { await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei("5"), {from: account_investor4}) + I_SecurityToken.transfer(account_investor3, web3.utils.toWei("5"), { from: account_investor4 }) ) }) - it("Should transfer the token by investor 4", async() => { + it("Should transfer the token by investor 4", async () => { let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3.57"), {from: account_investor4}); - + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3.57"), { from: account_investor4 }); + let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor4); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor4, data[3].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), 0); @@ -1277,16 +1277,16 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, 3.57); }); - it("Should transfer the tokens freely after ending the default daily restriction", async() => { + it("Should transfer the tokens freely after ending the default daily restriction", async () => { await increaseTime(duration.days(3) + 10); //sell tokens upto the limit - let tx = await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), {from: account_investor4}); + let tx = await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), { from: account_investor4 }); assert.equal((tx.logs[0].args.value).toNumber(), web3.utils.toWei("5")); // Transfer the tokens again to investor 3 - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("40"), {from: account_investor2}); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("40"), { from: account_investor2 }); }) - it("Should successfully add the default restriction", async() => { + it("Should successfully add the default restriction", async () => { await I_VolumeRestrictionTM.addDefaultRestriction( web3.utils.toWei("10"), 0, @@ -1312,22 +1312,22 @@ contract('VolumeRestrictionTransferManager', accounts => { `); }); - it("Should transfer tokens on by investor 3 (comes under the Default restriction)", async() => { + it("Should transfer tokens on by investor 3 (comes under the Default restriction)", async () => { await increaseTime(10); tempArray3.length = 0; let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), { from: account_investor3 }); tempArray3.push(5); let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1339,7 +1339,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // Transfer tokens on another day await increaseTime(duration.days(1)); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), { from: account_investor3 }); tempArray3.push(3); data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); @@ -1347,7 +1347,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // get the trade amount using the timestamp amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1357,13 +1357,13 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amt, 3); }); - it("Should fail to transfer more tokens than the available default limit", async() => { + it("Should fail to transfer more tokens than the available default limit", async () => { await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), {from: account_investor3}) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), { from: account_investor3 }) ); }); - it("Should able to transfer tokens in the next rolling period", async() => { + it("Should able to transfer tokens in the next rolling period", async () => { await increaseTime(duration.days(4.1)); console.log(`*** Diff days: ${(latestTime() - ((await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3))[0]).toNumber()) / 86400}`) for (let i = 0; i < 3; i++) { @@ -1375,15 +1375,15 @@ contract('VolumeRestrictionTransferManager', accounts => { let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("7"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("7"), { from: account_investor3 }); tempArray3.push(7); let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1394,11 +1394,11 @@ contract('VolumeRestrictionTransferManager', accounts => { // Try to transact more on the same day but fail await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1"), {from: account_investor3}) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1"), { from: account_investor3 }) ); }); - it("Should add the daily default restriction again", async() => { + it("Should add the daily default restriction again", async () => { await I_VolumeRestrictionTM.addDefaultDailyRestriction( web3.utils.toWei("2"), 0, @@ -1420,27 +1420,27 @@ contract('VolumeRestrictionTransferManager', accounts => { `); }); - it("Should not able to transfer tokens more than the default daily restriction", async() => { + it("Should not able to transfer tokens more than the default daily restriction", async () => { await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), {from: account_investor3}) + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), { from: account_investor3 }) ); }); - it("Should able to transfer tokens within the limit of (daily default + default) restriction", async() => { + it("Should able to transfer tokens within the limit of (daily default + default) restriction", async () => { await increaseTime(duration.days(1)); let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), {from: account_investor3}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("2"), { from: account_investor3 }); tempArray3.push(2); let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3); await print(data, account_investor3); - + // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toNumber())) - .dividedBy(new BigNumber(10).pow(18)).toNumber(); + .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); @@ -1451,34 +1451,34 @@ contract('VolumeRestrictionTransferManager', accounts => { }); }) - describe("Test for the exemptlist", async() => { + describe("Test for the exemptlist", async () => { - it("Should add the token holder in the exemption list -- failed because of bad owner", async() => { + it("Should add the token holder in the exemption list -- failed because of bad owner", async () => { await catchRevert( - I_VolumeRestrictionTM.changeExemptWalletList(account_investor4, true, {from: account_polymath}) + I_VolumeRestrictionTM.changeExemptWalletList(account_investor4, true, { from: account_polymath }) ); }); - it("Should add the token holder in the exemption list", async() => { - await I_VolumeRestrictionTM.changeExemptWalletList(account_investor4, true, {from: token_owner}); + it("Should add the token holder in the exemption list", async () => { + await I_VolumeRestrictionTM.changeExemptWalletList(account_investor4, true, { from: token_owner }); let beforeBal = await I_SecurityToken.balanceOf.call(account_investor4); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("3"), {from: account_investor4}); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("3"), { from: account_investor4 }); let afterBal = await I_SecurityToken.balanceOf.call(account_investor4); let diff = beforeBal.minus(afterBal); assert.equal(web3.utils.fromWei((diff.toNumber()).toString()), 3); }); }); - describe("Test for modify functions", async() => { + describe("Test for modify functions", async () => { - it("Should add the individual restriction for multiple investor", async() => { + it("Should add the individual restriction for multiple investor", async () => { await I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor3, account_delegate3], [web3.utils.toWei("15"), new BigNumber(12.78).times(new BigNumber(10).pow(16))], [latestTime() + duration.days(1), latestTime() + duration.days(2)], [15, 20], [latestTime() + duration.days(40), latestTime() + duration.days(60)], - [0,1], + [0, 1], { from: token_owner } @@ -1497,14 +1497,14 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(indi2[4].toNumber(), 1); }); - it("Should modify the details before the starttime passed", async() => { + it("Should modify the details before the starttime passed", async () => { await I_VolumeRestrictionTM.modifyIndividualRestrictionMulti( [account_investor3, account_delegate3], [new BigNumber(12.78).times(new BigNumber(10).pow(16)), web3.utils.toWei("15")], [latestTime() + duration.days(1), latestTime() + duration.days(2)], [20, 15], [latestTime() + duration.days(40), latestTime() + duration.days(60)], - [1,0], + [1, 0], { from: token_owner } @@ -1525,32 +1525,32 @@ contract('VolumeRestrictionTransferManager', accounts => { }); - describe("VolumeRestriction Transfer Manager Factory test cases", async() => { + describe("VolumeRestriction Transfer Manager Factory test cases", async () => { - it("Should get the exact details of the factory", async() => { - assert.equal(await I_VolumeRestrictionTMFactory.getSetupCost.call(),0); - assert.equal((await I_VolumeRestrictionTMFactory.getTypes.call())[0],2); + it("Should get the exact details of the factory", async () => { + assert.equal(await I_VolumeRestrictionTMFactory.getSetupCost.call(), 0); + assert.equal((await I_VolumeRestrictionTMFactory.getTypes.call())[0], 2); assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTMFactory.getName.call()) - .replace(/\u0000/g, ''), - "VolumeRestrictionTM", - "Wrong Module added"); + .replace(/\u0000/g, ''), + "VolumeRestrictionTM", + "Wrong Module added"); assert.equal(await I_VolumeRestrictionTMFactory.description.call(), - "Manage transfers based on the volume of tokens that needs to be transact", - "Wrong Module added"); + "Manage transfers based on the volume of tokens that needs to be transact", + "Wrong Module added"); assert.equal(await I_VolumeRestrictionTMFactory.title.call(), - "Volume Restriction Transfer Manager", - "Wrong Module added"); + "Volume Restriction Transfer Manager", + "Wrong Module added"); assert.equal(await I_VolumeRestrictionTMFactory.getInstructions.call(), - "Module used to restrict the volume of tokens traded by the token holders", - "Wrong Module added"); + "Module used to restrict the volume of tokens traded by the token holders", + "Wrong Module added"); assert.equal(await I_VolumeRestrictionTMFactory.version.call(), "1.0.0"); }); - it("Should get the tags of the factory", async() => { + it("Should get the tags of the factory", async () => { let tags = await I_VolumeRestrictionTMFactory.getTags.call(); assert.equal(tags.length, 5); assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Maximum Volume"); }); }); - + }); \ No newline at end of file From e8c0cd6471141e29bc0982837ee6b606f7d143a5 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 8 Jan 2019 17:49:23 -0300 Subject: [PATCH 501/582] 'whould' typo --- CLI/commands/token_manager.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index e46019abb..87de6889e 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -467,7 +467,7 @@ async function listModuleOptions() { // Modules a actions async function addModule() { let options = ['Permission Manager', 'Transfer Manager', 'Security Token Offering', 'Dividends', 'Burn']; - let index = readlineSync.keyInSelect(options, 'What type of module whould you like to add?', { cancel: 'Return' }); + let index = readlineSync.keyInSelect(options, 'What type of module would you like to add?', { cancel: 'Return' }); switch (options[index]) { case 'Permission Manager': console.log(chalk.red(` @@ -498,7 +498,7 @@ async function addModule() { async function pauseModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); - let index = readlineSync.keyInSelect(options, 'Which module whould you like to pause?'); + let index = readlineSync.keyInSelect(options, 'Which module would you like to pause?'); if (index != -1) { console.log("\nSelected:", options[index]); let moduleABI; @@ -519,7 +519,7 @@ async function pauseModule(modules) { async function unpauseModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); - let index = readlineSync.keyInSelect(options, 'Which module whould you like to pause?'); + let index = readlineSync.keyInSelect(options, 'Which module would you like to pause?'); if (index != -1) { console.log("\nSelected: ", options[index]); let moduleABI; @@ -551,7 +551,7 @@ async function archiveModule(modules) { async function unarchiveModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); - let index = readlineSync.keyInSelect(options, 'Which module whould you like to unarchive?'); + let index = readlineSync.keyInSelect(options, 'Which module would you like to unarchive?'); if (index != -1) { console.log("\nSelected: ", options[index]); let unarchiveModuleAction = securityToken.methods.unarchiveModule(modules[index].address); @@ -562,7 +562,7 @@ async function unarchiveModule(modules) { async function removeModule(modules) { let options = modules.map(m => `${m.name} (${m.address})`); - let index = readlineSync.keyInSelect(options, 'Which module whould you like to remove?'); + let index = readlineSync.keyInSelect(options, 'Which module would you like to remove?'); if (index != -1) { console.log("\nSelected: ", options[index]); let removeModuleAction = securityToken.methods.removeModule(modules[index].address); @@ -573,7 +573,7 @@ async function removeModule(modules) { async function changeBudget() { let options = modules.map(m => `${m.name} (${m.address})`); - let index = readlineSync.keyInSelect(options, 'Which module whould you like to remove?'); + let index = readlineSync.keyInSelect(options, 'Which module would you like to remove?'); if (index != -1) { console.log("\nSelected: ", options[index]); let increase = 0 == readlineSync.keyInSelect(['Increase', 'Decrease'], `Do you want to increase or decrease budget?`, { cancel: false }); From 73f0377ceec5ec382734408c592fcbe18099c9a2 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 8 Jan 2019 17:56:28 -0300 Subject: [PATCH 502/582] To pause/unpause TM modules fix --- CLI/commands/token_manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 87de6889e..17d8fa2c0 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -504,7 +504,7 @@ async function pauseModule(modules) { let moduleABI; if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { moduleABI = abis.ISTO(); - } else if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { + } else if (modules[index].type == gbl.constants.MODULES_TYPES.TRANSFER) { moduleABI = abis.ITransferManager(); } else { console.log(chalk.red(`Only STO and TM modules can be paused/unpaused`)); @@ -525,7 +525,7 @@ async function unpauseModule(modules) { let moduleABI; if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { moduleABI = abis.ISTO(); - } else if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { + } else if (modules[index].type == gbl.constants.MODULES_TYPES.TRANSFER) { moduleABI = abis.ITransferManager(); } else { console.log(chalk.red(`Only STO and TM modules can be paused/unpaused`)); From 11f6b50fcefb1569089e9a6b2d6a9943e479da4c Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 8 Jan 2019 18:02:04 -0300 Subject: [PATCH 503/582] Change module budget error --- CLI/commands/token_manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 17d8fa2c0..4b667b54c 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -571,9 +571,9 @@ async function removeModule(modules) { } } -async function changeBudget() { +async function changeBudget(modules) { let options = modules.map(m => `${m.name} (${m.address})`); - let index = readlineSync.keyInSelect(options, 'Which module would you like to remove?'); + let index = readlineSync.keyInSelect(options, 'Which module would you like to change budget for?'); if (index != -1) { console.log("\nSelected: ", options[index]); let increase = 0 == readlineSync.keyInSelect(['Increase', 'Decrease'], `Do you want to increase or decrease budget?`, { cancel: false }); From 7429d130eff21f81192c94936ae68a5f3b1aa5c3 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 9 Jan 2019 14:58:32 +0530 Subject: [PATCH 504/582] modified the getRestrictedAddress() function --- .../TransferManager/VolumeRestrictionTM.sol | 66 ++++++++++++++-- test/y_volume_restriction_tm.js | 79 +++++++++++-------- 2 files changed, 109 insertions(+), 36 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index e19f937ad..3a212df4f 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -136,7 +136,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _change Boolean value used to add (i.e true) or remove (i.e false) from the list */ function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { - require(_wallet != address(0), "Invalid address"); + require(_wallet != address(0)); exemptList[_wallet] = _change; emit ChangedExemptWalletList(_wallet, _change); } @@ -446,7 +446,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /// @notice Internal function to facilitate the removal of individual restriction function _removeIndividualRestriction(address _holder) internal { require(_holder != address(0), "Invalid address"); - require(individualRestriction[_holder].endTime != 0, "Not present"); + require(individualRestriction[_holder].endTime != 0); individualRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); _deleteHolderFromList(_holder, uint8(TypeOfPeriod.OneDay)); userToBucket[_holder].lastTradedDayTime = 0; @@ -497,7 +497,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /// @notice Internal function to facilitate the removal of individual daily restriction function _removeIndividualDailyRestriction(address _holder) internal { require(_holder != address(0), "Invalid address"); - require(individualDailyRestriction[_holder].endTime != 0, "Not present"); + require(individualDailyRestriction[_holder].endTime != 0); individualDailyRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); _deleteHolderFromList(_holder, uint8(TypeOfPeriod.MultipleDays)); userToBucket[_holder].dailyLastTradedDayTime = 0; @@ -1088,7 +1088,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } else { require( _allowedTokens > 0 && _allowedTokens <= 100 * 10 ** 16, - "Percentage is not within (0,100]" + "Invalid value" ); } require(_endTime > _startTime, "Invalid times"); @@ -1186,7 +1186,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256[] List of daysCovered, first group for individuals, second group for default * @return uint256[] List of dailyLastTradedDayTime, first group for individuals, second group for default */ - function getRestrictedAddresses() external view returns( + /*function getRestrictedAddresses() external view returns( address[] memory allAddresses, uint8[] memory typeOfPeriodRestriction, uint256[] memory lastTradedDayTime, @@ -1207,6 +1207,62 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { (lastTradedDayTime[i + restrictedAddresses.length], sumOfLastPeriod[i + restrictedAddresses.length], daysCovered[i + restrictedAddresses.length], dailyLastTradedDayTime[i + restrictedAddresses.length]) = getDefaultBucketDetailsToUser(restrictedAddresses[i]); } + }*/ + + function getRestrictedAddresses() external view returns( + address[] memory allAddresses, + uint256[] memory allowedTokens, + uint256[] memory startTime, + uint256[] memory rollingPeriodInDays, + uint256[] memory endTime, + uint8[] memory typeOfRestriction + ) { + uint256 counter = 0; + uint256 i = 0; + for (i = 0; i < restrictedAddresses.length; i++) { + counter = counter + (restrictedHolders[restrictedAddresses[i]].typeOfPeriod == uint8(2) ? 2 : 1); + } + allAddresses = new address[](counter); + allowedTokens = new uint256[](counter); + startTime = new uint256[](counter); + rollingPeriodInDays = new uint256[](counter); + endTime = new uint256[](counter); + typeOfRestriction = new uint8[](counter); + counter = 0; + for (i = 0; i < restrictedAddresses.length; i++) { + allAddresses[counter] = restrictedAddresses[i]; + if (restrictedHolders[restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.MultipleDays)) { + _setValues(individualRestriction[restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + } + else if (restrictedHolders[restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.OneDay)) { + _setValues(individualDailyRestriction[restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + } + else if (restrictedHolders[restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.Both)) { + _setValues(individualRestriction[restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + counter = counter + 1; + allAddresses[counter] = restrictedAddresses[i]; + _setValues(individualDailyRestriction[restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + } + counter ++; + } + } + + function _setValues( + VolumeRestriction memory restriction, + uint256[] memory allowedTokens, + uint256[] memory startTime, + uint256[] memory rollingPeriodInDays, + uint256[] memory endTime, + uint8[] memory typeOfRestriction, + uint256 index + ) + internal + { + allowedTokens[index] = restriction.allowedTokens; + startTime[index] = restriction.startTime; + rollingPeriodInDays[index] = restriction.rollingPeriodInDays; + endTime[index] = restriction.endTime; + typeOfRestriction[index] = uint8(restriction.typeOfRestriction); } /** diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index c57ce68f5..90345b6ae 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -89,13 +89,28 @@ contract('VolumeRestrictionTransferManager', accounts => { `) } - async function printAll(data) { + // async function printAll(data) { + // let investors = data[0]; + // for (let i = 0; i < investors.length; i++) { + // console.log("Individual Restrictions: "); + // await print([data[2][i], data[3][i], data[4][i], data[5][i]], investors[i]); + // console.log("Daily Restrictions: "); + // await print([data[2][i + investors.length], data[3][i + investors.length], data[4][i + investors.length], data[5][i + investors.length]], investors[i]); + // } + // } + + async function printRestrictedData(data) { let investors = data[0]; - for (let i = 0; i < investors.length; i++) { - console.log("Individual Restrictions: "); - await print([data[2][i], data[3][i], data[4][i], data[5][i]], investors[i]); - console.log("Daily Restrictions: "); - await print([data[2][i + investors.length], data[3][i + investors.length], data[4][i + investors.length], data[5][i + investors.length]], investors[i]); + for (let i = 0 ; i < investors.length; i++) { + console.log(` + Token holder: ${data[0][i]} + Start Time: ${data[2][i].toNumber()} + Rolling Period In Days: ${data[3][i].toNumber()} + End Time : ${data[4][i].toNumber()} + Allowed Tokens: ${web3.utils.fromWei(data[1][i].toString())} + Type of Restriction: ${data[5][i].toNumber()} + `) + console.log("\n"); } } @@ -419,10 +434,8 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor1); assert.equal(tx.logs[0].args._typeOfRestriction, 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - await printAll(data); + await printRestrictedData(data); assert.equal(data[0][0], account_investor1); - assert.equal(data[1][0].toNumber(), 0); - }); it("Should add the restriction for multiple investor -- failed because of bad owner", async() => { @@ -554,7 +567,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor4))[2].toNumber(), 5); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - await printAll(data); + await printRestrictedData(data); assert.equal(data[0].length, 4); }); @@ -573,11 +586,11 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, {from: token_owner}); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - await printAll(data); + await printRestrictedData(data); + //await printAll(data); assert.equal(data[0].length, 3); for (let i = 0; i < data[0].length; i++) { assert.notEqual(data[0][i], account_investor2); - assert.equal(data[1][i], 0); } }); @@ -595,7 +608,8 @@ contract('VolumeRestrictionTransferManager', accounts => { } ) let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - await printAll(data); + await printRestrictedData(data); + //await printAll(data); assert.equal(data[0].length, 1); }); @@ -632,7 +646,8 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[1].args._holder, account_investor1); assert.equal(tx.logs[1].args._typeOfRestriction, 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - await printAll(data); + await printRestrictedData(data); + //await printAll(data); assert.equal(data[0].length, 1); assert.equal(data[0][0], account_investor1); }); @@ -750,10 +765,11 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._typeOfRestriction, 0); assert.equal((tx.logs[0].args._allowedTokens).toNumber(), web3.utils.toWei("6")); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - await printAll(data); + await printRestrictedData(data); + //await printAll(data); assert.equal(data[0].length, 2); assert.equal(data[0][1], account_investor3); - assert.equal(data[1][1], 1); + //assert.equal(data[1][1], 1); let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3); console.log(` *** Individual Daily restriction data *** @@ -831,12 +847,13 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((tx.logs[0].args._typeOfRestriction).toNumber(), 1); assert.equal((tx.logs[0].args._allowedTokens).dividedBy(new BigNumber(10).pow(16)).toNumber(), 5); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - await printAll(data); - assert.equal(data[0].length, 2); - assert.equal(data[0][1], account_investor3); + await printRestrictedData(data); + //await printAll(data); + assert.equal(data[0].length, 3); + assert.equal(data[0][2], account_investor3); assert.equal(data[0][0], account_investor1); - assert.equal(data[1][1].toNumber(), 1); - assert.equal(data[1][0].toNumber(), 2); + // // assert.equal(data[1][1].toNumber(), 1); + // // assert.equal(data[1][0].toNumber(), 2); let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor1); console.log(` *** Individual Daily restriction data *** @@ -903,12 +920,13 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._typeOfRestriction, 1); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - await printAll(data); - assert.equal(data[0].length, 2); - assert.equal(data[0][1], account_investor3); + await printRestrictedData(data); + //await printAll(data); + assert.equal(data[0].length, 4); + assert.equal(data[0][2], account_investor3); assert.equal(data[0][0], account_investor1); - assert.equal(data[1][1].toNumber(), 2); - assert.equal(data[1][0].toNumber(), 2); + // assert.equal(data[1][1].toNumber(), 2); + // assert.equal(data[1][0].toNumber(), 2); }); it("Should transfer the token by the investor 3 with in the (Individual + Individual daily limit)", async() => { @@ -963,12 +981,11 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, {from: token_owner}); assert.equal(tx.logs[0].args._holder, account_investor3); let dataAdd = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); - await printAll(dataAdd); - assert.equal(dataAdd[0].length, 2); + await printRestrictedData(dataAdd); + // //await printAll(dataAdd); + assert.equal(dataAdd[0].length, 3); assert.equal(dataAdd[0][0], account_investor1); - assert.equal(dataAdd[1][0].toNumber(), 2); - assert.equal(dataAdd[0][1], account_investor3); - assert.equal(dataAdd[1][1].toNumber(), 0); + assert.equal(dataAdd[0][2], account_investor3); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); From 72c1eb7b46dc1772dfed37a79f0020c3add667d0 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 9 Jan 2019 18:11:26 +0530 Subject: [PATCH 505/582] code cleanup --- .../TransferManager/VolumeRestrictionTM.sol | 50 ++++--------------- test/y_volume_restriction_tm.js | 23 --------- 2 files changed, 11 insertions(+), 62 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 3a212df4f..93b8bc6df 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -785,15 +785,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (_startTime == 0) { startTime = now; } + // If old startTime is already passed then new startTime should be greater than or equal to the + // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, (defaultDailyRestriction.startTime <= now ? defaultDailyRestriction.startTime : now) ); - // If old startTime is already passed then new startTime should be greater than or equal to the - // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. - /* if (defaultDailyRestriction.startTime <= now) - require(startTime >= defaultDailyRestriction.startTime, "Invalid StartTime"); - else - require(startTime >= now); */ defaultDailyRestriction = VolumeRestriction( _allowedTokens, startTime, @@ -1174,41 +1170,17 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { else return _callFrom; } - + /** - * @notice use to get the list of token holders who are restricted by the VRTM - * @return address[] List of addresses that are restricted by the VRTM - * @return uint8[] Array of the Type of period restriction on the addresses. 0 - address - * has only individual restriction, 1 - address has only individual daily restriction & 2 - * it means address has both type of restriction where rolling period is 24 hrs & multiple days as well - * @return uint256[] List of lastTradedDayTime, first group for individuals, second group for default - * @return uint256[] List of sumOfLastPeriod, first group for individuals, second group for default - * @return uint256[] List of daysCovered, first group for individuals, second group for default - * @return uint256[] List of dailyLastTradedDayTime, first group for individuals, second group for default + * @notice Provide the restriction details of all the restricted addresses + * @return address List of the restricted addresses + * @return uint256 List of the tokens allowed to the restricted addresses corresponds to restricted address + * @return uint256 List of the start time of the restriction corresponds to restricted address + * @return uint256 List of the rolling period in days for a restriction corresponds to restricted address. + * @return uint256 List of the end time of the restriction corresponds to restricted address. + * @return uint8 List of the type of restriction to validate the value of the `allowedTokens` + * of the restriction corresponds to restricted address */ - /*function getRestrictedAddresses() external view returns( - address[] memory allAddresses, - uint8[] memory typeOfPeriodRestriction, - uint256[] memory lastTradedDayTime, - uint256[] memory sumOfLastPeriod, - uint256[] memory daysCovered, - uint256[] memory dailyLastTradedDayTime - ) { - allAddresses = restrictedAddresses; - typeOfPeriodRestriction = new uint8[](restrictedAddresses.length); - lastTradedDayTime = new uint256[](2 * restrictedAddresses.length); - sumOfLastPeriod = new uint256[](2 * restrictedAddresses.length); - daysCovered = new uint256[](2 * restrictedAddresses.length); - dailyLastTradedDayTime = new uint256[](2 * restrictedAddresses.length); - for (uint256 i = 0; i < restrictedAddresses.length; i++) { - typeOfPeriodRestriction[i] = restrictedHolders[restrictedAddresses[i]].typeOfPeriod; - (lastTradedDayTime[i], sumOfLastPeriod[i], daysCovered[i], dailyLastTradedDayTime[i]) = - getIndividualBucketDetailsToUser(restrictedAddresses[i]); - (lastTradedDayTime[i + restrictedAddresses.length], sumOfLastPeriod[i + restrictedAddresses.length], daysCovered[i + restrictedAddresses.length], dailyLastTradedDayTime[i + restrictedAddresses.length]) = - getDefaultBucketDetailsToUser(restrictedAddresses[i]); - } - }*/ - function getRestrictedAddresses() external view returns( address[] memory allAddresses, uint256[] memory allowedTokens, diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 90345b6ae..93606f745 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -89,16 +89,6 @@ contract('VolumeRestrictionTransferManager', accounts => { `) } - // async function printAll(data) { - // let investors = data[0]; - // for (let i = 0; i < investors.length; i++) { - // console.log("Individual Restrictions: "); - // await print([data[2][i], data[3][i], data[4][i], data[5][i]], investors[i]); - // console.log("Daily Restrictions: "); - // await print([data[2][i + investors.length], data[3][i + investors.length], data[4][i + investors.length], data[5][i + investors.length]], investors[i]); - // } - // } - async function printRestrictedData(data) { let investors = data[0]; for (let i = 0 ; i < investors.length; i++) { @@ -110,7 +100,6 @@ contract('VolumeRestrictionTransferManager', accounts => { Allowed Tokens: ${web3.utils.fromWei(data[1][i].toString())} Type of Restriction: ${data[5][i].toNumber()} `) - console.log("\n"); } } @@ -587,7 +576,6 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); await printRestrictedData(data); - //await printAll(data); assert.equal(data[0].length, 3); for (let i = 0; i < data[0].length; i++) { assert.notEqual(data[0][i], account_investor2); @@ -609,7 +597,6 @@ contract('VolumeRestrictionTransferManager', accounts => { ) let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); await printRestrictedData(data); - //await printAll(data); assert.equal(data[0].length, 1); }); @@ -647,7 +634,6 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[1].args._typeOfRestriction, 0); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); await printRestrictedData(data); - //await printAll(data); assert.equal(data[0].length, 1); assert.equal(data[0][0], account_investor1); }); @@ -766,10 +752,8 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((tx.logs[0].args._allowedTokens).toNumber(), web3.utils.toWei("6")); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); await printRestrictedData(data); - //await printAll(data); assert.equal(data[0].length, 2); assert.equal(data[0][1], account_investor3); - //assert.equal(data[1][1], 1); let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3); console.log(` *** Individual Daily restriction data *** @@ -848,12 +832,9 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((tx.logs[0].args._allowedTokens).dividedBy(new BigNumber(10).pow(16)).toNumber(), 5); let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); await printRestrictedData(data); - //await printAll(data); assert.equal(data[0].length, 3); assert.equal(data[0][2], account_investor3); assert.equal(data[0][0], account_investor1); - // // assert.equal(data[1][1].toNumber(), 1); - // // assert.equal(data[1][0].toNumber(), 2); let dataRestriction = await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor1); console.log(` *** Individual Daily restriction data *** @@ -921,12 +902,9 @@ contract('VolumeRestrictionTransferManager', accounts => { let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); await printRestrictedData(data); - //await printAll(data); assert.equal(data[0].length, 4); assert.equal(data[0][2], account_investor3); assert.equal(data[0][0], account_investor1); - // assert.equal(data[1][1].toNumber(), 2); - // assert.equal(data[1][0].toNumber(), 2); }); it("Should transfer the token by the investor 3 with in the (Individual + Individual daily limit)", async() => { @@ -982,7 +960,6 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor3); let dataAdd = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); await printRestrictedData(dataAdd); - // //await printAll(dataAdd); assert.equal(dataAdd[0].length, 3); assert.equal(dataAdd[0][0], account_investor1); assert.equal(dataAdd[0][2], account_investor3); From f400049fe258ec8a66ed31af0724298619c0e4d6 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 9 Jan 2019 09:49:30 -0300 Subject: [PATCH 506/582] CLI - Show restrictions table --- CLI/commands/common/common_functions.js | 4 +-- CLI/commands/transfer_manager.js | 44 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index 7a9195891..40665d514 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -158,8 +158,8 @@ module.exports = { }, splitIntoBatches: function (data, batchSize) { let allBatches = []; - for (let index = 0; index < data.length; index += batchSize) { - allBatches.push(data.slice(index, index + batchSize)); + for (let index = 0; index < data.length; index += parseInt(batchSize)) { + allBatches.push(data.slice(index, index + parseInt(batchSize))); } return allBatches; }, diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 2b76a8f80..aea833d6c 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1472,6 +1472,23 @@ async function addInvestorsToBlacklistsInBatch() { } } +function makeBatchRequest(calls) { + let batch = new web3.BatchRequest(); + + let promises = calls.map(call => { + return new Promise((res, rej) => { + let req = call.request({ from: Issuer.address }, (err, data) => { + if (err) rej(err); + else res(data) + }); + batch.add(req) + }) + }) + batch.execute() + + return Promise.all(promises) +} + async function removeInvestorsFromBlacklistsInBatch() { let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REMOVE_INVESTOR_BLACKLIST_DATA_CSV}): `, { defaultInput: REMOVE_INVESTOR_BLACKLIST_DATA_CSV @@ -1529,6 +1546,7 @@ async function volumeRestrictionTM() { } let options = [ + 'Show restrictios', 'Change exempt wallet', 'Change default restrictions', 'Change individual restrictions', @@ -1540,6 +1558,17 @@ async function volumeRestrictionTM() { let optionSelected = index !== -1 ? options[index] : 'RETURN'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { + case 'Show restrictios': + let addressesAndRestrictions = await currentTransferManager.methods.getRestrictedAddresses().call(); + showRestrictionTable( + addressesAndRestrictions[0], + addressesAndRestrictions[1], + addressesAndRestrictions[5], + addressesAndRestrictions[3], + addressesAndRestrictions[2], + addressesAndRestrictions[4], + ); + break; case 'Change exempt wallet': await changeExemptWallet(); break; @@ -1562,6 +1591,21 @@ async function volumeRestrictionTM() { await volumeRestrictionTM(); } +function showRestrictionTable(investorArray, amountArray, typeArray, rollingPeriodArray, startTimeArray, endTimeTimeArray) { + let dataTable = [['Investor', 'Maximum transfer (# or %)', 'Rolling period (days)', 'Start date', 'End date']]; + for (let i = 0; i < investorArray.length; i++) { + dataTable.push([ + investorArray[i], + typeArray[i] === "0" ? `${web3.utils.fromWei(amountArray[i])} ${tokenSymbol}` : `${fromWeiPercentage(amountArray[i])}%`, + rollingPeriodArray[i], + moment.unix(startTimeArray[i]).format('MM/DD/YYYY HH:mm'), + moment.unix(endTimeTimeArray[i]).format('MM/DD/YYYY HH:mm') + ]); + } + console.log(); + console.log(table(dataTable)); +} + async function changeExemptWallet() { let options = [ 'Add exempt wallet', From 3638c60dad85c104103ce6d1bbecbc4b59b43b53 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 9 Jan 2019 18:40:55 +0530 Subject: [PATCH 507/582] minor fix --- .../TransferManager/VolumeRestrictionTM.sol | 3 ++- test/y_volume_restriction_tm.js | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 93b8bc6df..2bfa4edc2 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -1181,7 +1181,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint8 List of the type of restriction to validate the value of the `allowedTokens` * of the restriction corresponds to restricted address */ - function getRestrictedAddresses() external view returns( + function getRestrictedData() external view returns( address[] memory allAddresses, uint256[] memory allowedTokens, uint256[] memory startTime, @@ -1229,6 +1229,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 index ) internal + pure { allowedTokens[index] = restriction.allowedTokens; startTime[index] = restriction.startTime; diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 93606f745..3610c13a3 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -422,7 +422,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); assert.equal(tx.logs[0].args._holder, account_investor1); assert.equal(tx.logs[0].args._typeOfRestriction, 0); - let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + let data = await I_VolumeRestrictionTM.getRestrictedData.call(); await printRestrictedData(data); assert.equal(data[0][0], account_investor1); }); @@ -555,7 +555,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_delegate3))[2].toNumber(), 4); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor4))[2].toNumber(), 5); - let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + let data = await I_VolumeRestrictionTM.getRestrictedData.call(); await printRestrictedData(data); assert.equal(data[0].length, 4); }); @@ -574,7 +574,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should successfully remove the restriction", async() => { await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor2, {from: token_owner}); assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_investor2))[3].toNumber(), 0); - let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + let data = await I_VolumeRestrictionTM.getRestrictedData.call(); await printRestrictedData(data); assert.equal(data[0].length, 3); for (let i = 0; i < data[0].length; i++) { @@ -595,7 +595,7 @@ contract('VolumeRestrictionTransferManager', accounts => { from: token_owner } ) - let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + let data = await I_VolumeRestrictionTM.getRestrictedData.call(); await printRestrictedData(data); assert.equal(data[0].length, 1); }); @@ -632,7 +632,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[1].args._holder, account_investor1); assert.equal(tx.logs[1].args._typeOfRestriction, 0); - let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + let data = await I_VolumeRestrictionTM.getRestrictedData.call(); await printRestrictedData(data); assert.equal(data[0].length, 1); assert.equal(data[0][0], account_investor1); @@ -750,7 +750,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor3); assert.equal(tx.logs[0].args._typeOfRestriction, 0); assert.equal((tx.logs[0].args._allowedTokens).toNumber(), web3.utils.toWei("6")); - let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + let data = await I_VolumeRestrictionTM.getRestrictedData.call(); await printRestrictedData(data); assert.equal(data[0].length, 2); assert.equal(data[0][1], account_investor3); @@ -830,7 +830,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor1); assert.equal((tx.logs[0].args._typeOfRestriction).toNumber(), 1); assert.equal((tx.logs[0].args._allowedTokens).dividedBy(new BigNumber(10).pow(16)).toNumber(), 5); - let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + let data = await I_VolumeRestrictionTM.getRestrictedData.call(); await printRestrictedData(data); assert.equal(data[0].length, 3); assert.equal(data[0][2], account_investor3); @@ -900,7 +900,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[0].args._holder, account_investor3); assert.equal(tx.logs[0].args._typeOfRestriction, 1); - let data = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + let data = await I_VolumeRestrictionTM.getRestrictedData.call(); await printRestrictedData(data); assert.equal(data[0].length, 4); assert.equal(data[0][2], account_investor3); @@ -958,7 +958,7 @@ contract('VolumeRestrictionTransferManager', accounts => { // remove the Individual daily restriction let tx = await I_VolumeRestrictionTM.removeIndividualDailyRestriction(account_investor3, {from: token_owner}); assert.equal(tx.logs[0].args._holder, account_investor3); - let dataAdd = await I_VolumeRestrictionTM.getRestrictedAddresses.call(); + let dataAdd = await I_VolumeRestrictionTM.getRestrictedData.call(); await printRestrictedData(dataAdd); assert.equal(dataAdd[0].length, 3); assert.equal(dataAdd[0][0], account_investor1); From bb4c1feeaadf0a0f5bf45b5a71ba54448ad15c2c Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 9 Jan 2019 10:20:43 -0300 Subject: [PATCH 508/582] CLI - Update method name, updated csv dates --- CLI/commands/transfer_manager.js | 31 +++++++++++-------- .../VRTM/add_daily_restriction_data.csv | 16 +++++----- .../Transfer/VRTM/add_restriction_data.csv | 16 +++++----- .../VRTM/modify_daily_restriction_data.csv | 10 +++--- .../Transfer/VRTM/modify_restriction_data.csv | 10 +++--- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index aea833d6c..929d43017 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1536,7 +1536,7 @@ async function volumeRestrictionTM() { console.log(` Rolling period: ${defaultDailyRestriction.rollingPeriodInDays} days`); console.log(` End time: ${moment.unix(defaultDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - console.log(`- Default restriction: ${hasDefaultRestriction ? '' : 'None'} `); + console.log(`- Default restriction: ${hasDefaultRestriction ? '' : 'None'}`); if (hasDefaultRestriction) { console.log(` Type: ${RESTRICTION_TYPES[defaultRestriction.typeOfRestriction]}`); console.log(` Allowed tokens: ${defaultRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(defaultRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(defaultRestriction.allowedTokens)}%`}`); @@ -1545,28 +1545,33 @@ async function volumeRestrictionTM() { console.log(` End time: ${moment.unix(defaultRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - let options = [ - 'Show restrictios', + let addressesAndRestrictions = await currentTransferManager.methods.getRestrictedData().call(); + console.log(`- Individual restrictions: ${addressesAndRestrictions.allAddresses.length}`); + + let options = []; + if (addressesAndRestrictions[0].length > 0) { + options.push('Show restrictios'); + } + options.push( 'Change exempt wallet', 'Change default restrictions', 'Change individual restrictions', 'Explore account', 'Operate with multiple restrictions' - ]; + ); let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); let optionSelected = index !== -1 ? options[index] : 'RETURN'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Show restrictios': - let addressesAndRestrictions = await currentTransferManager.methods.getRestrictedAddresses().call(); showRestrictionTable( - addressesAndRestrictions[0], - addressesAndRestrictions[1], - addressesAndRestrictions[5], - addressesAndRestrictions[3], - addressesAndRestrictions[2], - addressesAndRestrictions[4], + addressesAndRestrictions.allAddresses, + addressesAndRestrictions.allowedTokens, + addressesAndRestrictions.typeOfRestriction, + addressesAndRestrictions.rollingPeriodInDays, + addressesAndRestrictions.startTime, + addressesAndRestrictions.endTime, ); break; case 'Change exempt wallet': @@ -1745,7 +1750,7 @@ async function changeIndividualRestrictions() { console.log(` Rolling period: ${currentDailyRestriction.rollingPeriodInDays} days`); console.log(` End time: ${moment.unix(currentDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - console.log(`- Other restriction: ${hasRestriction ? '' : 'None'} `); + console.log(`- Other restriction: ${hasRestriction ? '' : 'None'} `); if (hasRestriction) { console.log(` Type: ${RESTRICTION_TYPES[currentRestriction.typeOfRestriction]}`); console.log(` Allowed tokens: ${currentRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(currentRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(currentRestriction.allowedTokens)}%`}`); @@ -2164,7 +2169,7 @@ function inputRestrictionData(isDaily) { } restriction.startTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) at which restriction get into effect (now = 0): `, { defaultInput: 0 }); let oneMonthFromNow = Math.floor(Date.now() / 1000) + gbl.constants.DURATION.days(30); - restriction.endTime = readlineSync.question(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (1 week from now = ${oneMonthFromNow}): `, { + restriction.endTime = readlineSync.question(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (1 month from now = ${oneMonthFromNow}): `, { limit: function (input) { return input > restriction.startTime + gbl.constants.DURATION.days(restriction.rollingPeriodInDays); }, diff --git a/CLI/data/Transfer/VRTM/add_daily_restriction_data.csv b/CLI/data/Transfer/VRTM/add_daily_restriction_data.csv index 782c1107d..1486579b7 100644 --- a/CLI/data/Transfer/VRTM/add_daily_restriction_data.csv +++ b/CLI/data/Transfer/VRTM/add_daily_restriction_data.csv @@ -1,8 +1,8 @@ -0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,1000,1/8/2019,10/10/2019,"Fixed" -0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,1/8/2019,10/10/2019,"Fixed" -0xac297053173b02b02a737d47f7b4a718e5b170ef,500,1/8/2019,10/10/2019,"Fixed" -0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,1/8/2019,10/10/2019,"Percentage" -0x10223927009b8add0960359dd90d1449415b7ca9,0.25,1/8/2019,10/10/2019,"Percentage" -0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,0.1,1/8/2019,10/10/2019,"Percentage" -0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,1234,1/8/2019,10/10/2019,"Fixed" -0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,5678,1/8/2019,10/10/2019,"Fixed" \ No newline at end of file +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,1000,8/1/2019,10/10/2019,"Fixed" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,8/2/2019,10/12/2019,"Fixed" +0xac297053173b02b02a737d47f7b4a718e5b170ef,500,8/1/2019,10/10/2019,"Fixed" +0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,8/3/2019,10/1/2019,"Percentage" +0x10223927009b8add0960359dd90d1449415b7ca9,0.25,8/1/2019,10/10/2019,"Percentage" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,0.1,8/1/2019,10/5/2019,"Percentage" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,1234,8/12/2019,10/10/2019,"Fixed" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,5678,8/1/2019,10/10/2019,"Fixed" \ No newline at end of file diff --git a/CLI/data/Transfer/VRTM/add_restriction_data.csv b/CLI/data/Transfer/VRTM/add_restriction_data.csv index 072151a64..1807e90e6 100644 --- a/CLI/data/Transfer/VRTM/add_restriction_data.csv +++ b/CLI/data/Transfer/VRTM/add_restriction_data.csv @@ -1,8 +1,8 @@ -0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,1000,1/8/2019,90,10/10/2019,"Fixed" -0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,1/8/2019,30,10/10/2019,"Fixed" -0xac297053173b02b02a737d47f7b4a718e5b170ef,500,1/8/2019,15,10/10/2019,"Fixed" -0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,1/8/2019,90,10/10/2019,"Percentage" -0x10223927009b8add0960359dd90d1449415b7ca9,0.25,1/8/2019,30,10/10/2019,"Percentage" -0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,0.1,1/8/2019,15,10/10/2019,"Percentage" -0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,1234,1/8/2019,10,10/10/2019,"Fixed" -0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,5678,1/8/2019,2,10/10/2019,"Fixed" \ No newline at end of file +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,1000,8/1/2019,90,10/10/2019,"Fixed" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,8/2/2019,30,10/12/2019,"Fixed" +0xac297053173b02b02a737d47f7b4a718e5b170ef,500,8/1/2019,15,10/1/2019,"Fixed" +0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,8/5/2019,90,10/10/2019,"Percentage" +0x10223927009b8add0960359dd90d1449415b7ca9,0.25,8/3/2019,30,10/15/2019,"Percentage" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,0.1,8/10/2019,15,10/10/2019,"Percentage" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,1234,8/20/2019,10,10/22/2019,"Fixed" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,5678,8/1/2019,2,10/10/2019,"Fixed" \ No newline at end of file diff --git a/CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv b/CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv index 194e9b1d5..908c164e9 100644 --- a/CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv +++ b/CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv @@ -1,5 +1,5 @@ -0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,2000,1/8/2019,10/10/2019,"Fixed" -0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,2/8/2019,10/10/2019,"Fixed" -0xac297053173b02b02a737d47f7b4a718e5b170ef,500,1/8/2019,10/10/2019,"Fixed" -0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,1/8/2019,20/10/2019,"Percentage" -0x10223927009b8add0960359dd90d1449415b7ca9,25,1/8/2019,10/10/2019,"Fixed" +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,2000,8/1/2019,10/10/2019,"Fixed" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,8/1/2019,10/10/2019,"Fixed" +0xac297053173b02b02a737d47f7b4a718e5b170ef,500,8/1/2019,10/10/2019,"Fixed" +0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,8/1/2019,20/10/2019,"Percentage" +0x10223927009b8add0960359dd90d1449415b7ca9,25,8/1/2019,10/10/2019,"Fixed" diff --git a/CLI/data/Transfer/VRTM/modify_restriction_data.csv b/CLI/data/Transfer/VRTM/modify_restriction_data.csv index 588e39211..b69f43361 100644 --- a/CLI/data/Transfer/VRTM/modify_restriction_data.csv +++ b/CLI/data/Transfer/VRTM/modify_restriction_data.csv @@ -1,5 +1,5 @@ -0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,2000,1/8/2019,90,10/10/2019,"Fixed" -0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,2/8/2019,30,10/10/2019,"Fixed" -0xac297053173b02b02a737d47f7b4a718e5b170ef,500,1/8/2019,20,10/10/2019,"Fixed" -0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,1/8/2019,90,20/10/2019,"Percentage" -0x10223927009b8add0960359dd90d1449415b7ca9,25,1/8/2019,30,10/10/2019,"Fixed" \ No newline at end of file +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,2000,8/1/2019,90,10/10/2019,"Fixed" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,2000,8/2/2019,30,10/10/2019,"Fixed" +0xac297053173b02b02a737d47f7b4a718e5b170ef,500,8/1/2019,20,10/10/2019,"Fixed" +0x49fc0b78238dab644698a90fa351b4c749e123d2,0.15,8/1/2019,90,20/10/2019,"Percentage" +0x10223927009b8add0960359dd90d1449415b7ca9,25,8/1/2019,30,10/10/2019,"Fixed" \ No newline at end of file From 887860e3e5115e470aa9d4a0d429bc8b4cf3f91b Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 9 Jan 2019 10:54:11 -0300 Subject: [PATCH 509/582] Trigger TravisCI From ceb6acf54c92c97ba4dfb0998db4e0bc26b98b7a Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 9 Jan 2019 14:17:12 -0300 Subject: [PATCH 510/582] CLI - Changed names of restrictions --- CLI/commands/transfer_manager.js | 387 +++++++++--------- ...ta.csv => add_custom_restriction_data.csv} | 0 ...csv => modify_custom_restriction_data.csv} | 0 ...csv => remove_custom_restriction_data.csv} | 0 4 files changed, 194 insertions(+), 193 deletions(-) rename CLI/data/Transfer/VRTM/{add_restriction_data.csv => add_custom_restriction_data.csv} (100%) rename CLI/data/Transfer/VRTM/{modify_restriction_data.csv => modify_custom_restriction_data.csv} (100%) rename CLI/data/Transfer/VRTM/{remove_restriction_data.csv => remove_custom_restriction_data.csv} (100%) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 929d43017..8b84e74f8 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -23,9 +23,9 @@ const REVOKE_MANUAL_APPROVAL_DATA_CSV = `${__dirname}/../data/Transfer/MATM/revo const ADD_DAILY_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/add_daily_restriction_data.csv`; const MODIFY_DAILY_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/modify_daily_restriction_data.csv`; const REMOVE_DAILY_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/remove_daily_restriction_data.csv`; -const ADD_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/add_restriction_data.csv`; -const MODIFY_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/modify_restriction_data.csv`; -const REMOVE_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/remove_restriction_data.csv`; +const ADD_CUSTOM_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/add_custom_restriction_data.csv`; +const MODIFY_CUSTOM_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/modify_custom_restriction_data.csv`; +const REMOVE_CUSTOM_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/remove_custom_restriction_data.csv`; const RESTRICTION_TYPES = ['Fixed', 'Percentage']; @@ -75,6 +75,8 @@ async function executeApp() { console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Verify transfer': + let verifyTotalSupply = web3.utils.fromWei(await securityToken.methods.totalSupply().call()); + await logTotalInvestors(); let verifyTransferFrom = readlineSync.question(`Enter the sender account (${Issuer.address}): `, { limit: function (input) { return web3.utils.isAddress(input); @@ -82,16 +84,14 @@ async function executeApp() { limitMessage: "Must be a valid address", defaultInput: Issuer.address }); - let verifyFromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferFrom).call()); - console.log(chalk.yellow(`Balance of ${verifyTransferFrom}: ${verifyFromBalance} ${tokenSymbol}`)); + await logBalance(verifyTransferFrom, verifyTotalSupply); let verifyTransferTo = readlineSync.question('Enter the receiver account: ', { limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address", }); - let verifyToBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(verifyTransferTo).call()); - console.log(chalk.yellow(`Balance of ${verifyTransferTo}: ${verifyToBalance} ${tokenSymbol}`)); + await logBalance(verifyTransferTo, verifyTotalSupply); let verifyTransferAmount = readlineSync.question('Enter amount of tokens to verify: '); let isVerified = await securityToken.methods.verifyTransfer(verifyTransferFrom, verifyTransferTo, web3.utils.toWei(verifyTransferAmount), web3.utils.fromAscii("")).call(); if (isVerified) { @@ -101,16 +101,16 @@ async function executeApp() { } break; case 'Transfer': - let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call()); - console.log(chalk.yellow(`Balance of ${Issuer.address}: ${fromBalance} ${tokenSymbol}`)); + let totalSupply = web3.utils.fromWei(await securityToken.methods.totalSupply().call()); + await logTotalInvestors(); + await logBalance(Issuer.address, totalSupply); let transferTo = readlineSync.question('Enter beneficiary of tranfer: ', { limit: function (input) { return web3.utils.isAddress(input); }, limitMessage: "Must be a valid address" }); - let toBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call()); - console.log(chalk.yellow(`Balance of ${transferTo}: ${toBalance} ${tokenSymbol}`)); + await logBalance(transferTo, totalSupply); let transferAmount = readlineSync.question('Enter amount of tokens to transfer: '); let isTranferVerified = await securityToken.methods.verifyTransfer(Issuer.address, transferTo, web3.utils.toWei(transferAmount), web3.utils.fromAscii("")).call(); if (isTranferVerified) { @@ -118,8 +118,9 @@ async function executeApp() { let receipt = await common.sendTransaction(transferAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'Transfer'); console.log(chalk.green(`${event.from} transferred ${web3.utils.fromWei(event.value)} ${tokenSymbol} to ${event.to} successfully!`)); - console.log(`Balance of ${Issuer.address} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(Issuer.address).call())} ${tokenSymbol}`); - console.log(`Balance of ${transferTo} after transfer: ${web3.utils.fromWei(await securityToken.methods.balanceOf(transferTo).call())} ${tokenSymbol}`); + await logTotalInvestors(); + await logBalance(Issuer.address, totalSupply); + await logBalance(transferTo, totalSupply); } else { console.log(chalk.red(`Transfer failed at verification. Please review the transfer restrictions.`)); } @@ -1523,26 +1524,26 @@ async function removeInvestorsFromBlacklistsInBatch() { async function volumeRestrictionTM() { console.log('\n', chalk.blue(`Volume Restriction Transfer Manager at ${currentTransferManager.options.address}`, '\n')); - let defaultDailyRestriction = await currentTransferManager.methods.defaultDailyRestriction().call(); - let hasDefaultDailyRestriction = parseInt(defaultDailyRestriction.startTime) !== 0; - let defaultRestriction = await currentTransferManager.methods.defaultRestriction().call(); - let hasDefaultRestriction = parseInt(defaultRestriction.startTime) !== 0; + let globalDailyRestriction = await currentTransferManager.methods.defaultDailyRestriction().call(); + let hasGlobalDailyRestriction = parseInt(globalDailyRestriction.startTime) !== 0; + let globalCustomRestriction = await currentTransferManager.methods.defaultRestriction().call(); + let hasGlobalCustomRestriction = parseInt(globalCustomRestriction.startTime) !== 0; - console.log(`- Default daily restriction: ${hasDefaultDailyRestriction ? '' : 'None'}`); - if (hasDefaultDailyRestriction) { - console.log(` Type: ${RESTRICTION_TYPES[defaultDailyRestriction.typeOfRestriction]}`); - console.log(` Allowed tokens: ${defaultDailyRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(defaultDailyRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(defaultDailyRestriction.allowedTokens)}%`}`); - console.log(` Start time: ${moment.unix(defaultDailyRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(` Rolling period: ${defaultDailyRestriction.rollingPeriodInDays} days`); - console.log(` End time: ${moment.unix(defaultDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + console.log(`- Default daily restriction: ${hasGlobalDailyRestriction ? '' : 'None'}`); + if (hasGlobalDailyRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[globalDailyRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${globalDailyRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(globalDailyRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(globalDailyRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(globalDailyRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${globalDailyRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(globalDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - console.log(`- Default restriction: ${hasDefaultRestriction ? '' : 'None'}`); - if (hasDefaultRestriction) { - console.log(` Type: ${RESTRICTION_TYPES[defaultRestriction.typeOfRestriction]}`); - console.log(` Allowed tokens: ${defaultRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(defaultRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(defaultRestriction.allowedTokens)}%`}`); - console.log(` Start time: ${moment.unix(defaultRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(` Rolling period: ${defaultRestriction.rollingPeriodInDays} days`); - console.log(` End time: ${moment.unix(defaultRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + console.log(`- Default custom restriction: ${hasGlobalCustomRestriction ? '' : 'None'}`); + if (hasGlobalCustomRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[globalCustomRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${globalCustomRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(globalCustomRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(globalCustomRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(globalCustomRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${globalCustomRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(globalCustomRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } let addressesAndRestrictions = await currentTransferManager.methods.getRestrictedData().call(); @@ -1550,7 +1551,7 @@ async function volumeRestrictionTM() { let options = []; if (addressesAndRestrictions[0].length > 0) { - options.push('Show restrictios'); + options.push('Show restrictions'); } options.push( 'Change exempt wallet', @@ -1578,7 +1579,7 @@ async function volumeRestrictionTM() { await changeExemptWallet(); break; case 'Change default restrictions': - await changeDefaultRestrictions(hasDefaultDailyRestriction, hasDefaultRestriction); + await changeDefaultRestrictions(hasGlobalDailyRestriction, hasGlobalCustomRestriction); break; case 'Change individual restrictions': await changeIndividualRestrictions(); @@ -1644,85 +1645,85 @@ async function changeExemptWallet() { console.log(chalk.green(`${changeExemptWalletEvent._wallet} has been ${changeExemptWalletEvent._change ? `added to` : `removed from`} exempt wallets successfully!`)); } -async function changeDefaultRestrictions(hasDefaultDailyRestriction, hasDefaultRestriction) { +async function changeDefaultRestrictions(hasGlobalDailyRestriction, hasGlobalCustomRestriction) { let options = []; - if (!hasDefaultDailyRestriction) { - options.push('Add default daily restriction'); + if (!hasGlobalDailyRestriction) { + options.push('Add global daily restriction'); } else { - options.push('Modify default daily restriction', 'Remove default daily restriction'); + options.push('Modify global daily restriction', 'Remove global daily restriction'); } - if (!hasDefaultRestriction) { - options.push('Add default restriction'); + if (!hasGlobalCustomRestriction) { + options.push('Add global custom restriction'); } else { - options.push('Modify default restriction', 'Remove default restriction'); + options.push('Modify global custom restriction', 'Remove global custom restriction'); } let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); let optionSelected = index !== -1 ? options[index] : 'RETURN'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { - case 'Add default daily restriction': - let defaultDailyRestrictoToAdd = inputRestrictionData(true); - let addDefaultDailyRestrictionAction = currentTransferManager.methods.addDefaultDailyRestriction( - defaultDailyRestrictoToAdd.allowedTokens, - defaultDailyRestrictoToAdd.startTime, - defaultDailyRestrictoToAdd.endTime, - defaultDailyRestrictoToAdd.restrictionType + case 'Add global daily restriction': + let globalDailyRestrictoToAdd = inputRestrictionData(true); + let addGlobalDailyRestrictionAction = currentTransferManager.methods.addDefaultDailyRestriction( + globalDailyRestrictoToAdd.allowedTokens, + globalDailyRestrictoToAdd.startTime, + globalDailyRestrictoToAdd.endTime, + globalDailyRestrictoToAdd.restrictionType ); - let addDefaultDailyRestrictionReceipt = await common.sendTransaction(addDefaultDailyRestrictionAction); - let addDefaultDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addDefaultDailyRestrictionReceipt.logs, 'AddDefaultDailyRestriction'); - console.log(chalk.green(`Daily default restriction has been added successfully!`)); - break; - case 'Modify default daily restriction': - let defaultDailyRestrictoToModify = inputRestrictionData(true); - let modifyDefaultDailyRestrictionAction = currentTransferManager.methods.modifyDefaultDailyRestriction( - defaultDailyRestrictoToModify.allowedTokens, - defaultDailyRestrictoToModify.startTime, - defaultDailyRestrictoToModify.endTime, - defaultDailyRestrictoToModify.restrictionType + let addGlobalDailyRestrictionReceipt = await common.sendTransaction(addGlobalDailyRestrictionAction); + let addGlobalDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addGlobalDailyRestrictionReceipt.logs, 'AddDefaultDailyRestriction'); + console.log(chalk.green(`Global daily restriction has been added successfully!`)); + break; + case 'Modify global daily restriction': + let globalDailyRestrictoToModify = inputRestrictionData(true); + let modifyGlobalDailyRestrictionAction = currentTransferManager.methods.modifyDefaultDailyRestriction( + globalDailyRestrictoToModify.allowedTokens, + globalDailyRestrictoToModify.startTime, + globalDailyRestrictoToModify.endTime, + globalDailyRestrictoToModify.restrictionType ); - let modifyDefaultDailyRestrictionReceipt = await common.sendTransaction(modifyDefaultDailyRestrictionAction); - let modifyDefaultDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyDefaultDailyRestrictionReceipt.logs, 'ModifyDefaultDailyRestriction'); - console.log(chalk.green(`Daily default restriction has been modified successfully!`)); - break; - case 'Remove default daily restriction': - let removeDefaultDailyRestrictionAction = currentTransferManager.methods.removeDefaultDailyRestriction(); - let removeDefaultDailyRestrictionReceipt = await common.sendTransaction(removeDefaultDailyRestrictionAction); - let removeDefaultDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeDefaultDailyRestrictionReceipt.logs, 'DefaultDailyRestrictionRemoved'); - console.log(chalk.green(`Daily default restriction has been removed successfully!`)); - break; - case 'Add default restriction': - let defaultRestrictoToAdd = inputRestrictionData(false); - let addDefaultRestrictionAction = currentTransferManager.methods.addDefaultRestriction( - defaultRestrictoToAdd.allowedTokens, - defaultRestrictoToAdd.startTime, - defaultRestrictoToAdd.rollingPeriodInDays, - defaultRestrictoToAdd.endTime, - defaultRestrictoToAdd.restrictionType + let modifyGlobalDailyRestrictionReceipt = await common.sendTransaction(modifyGlobalDailyRestrictionAction); + let modifyGlobalDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyGlobalDailyRestrictionReceipt.logs, 'ModifyDefaultDailyRestriction'); + console.log(chalk.green(`Global daily restriction has been modified successfully!`)); + break; + case 'Remove global daily restriction': + let removeGlobalDailyRestrictionAction = currentTransferManager.methods.removeDefaultDailyRestriction(); + let removeGlobalDailyRestrictionReceipt = await common.sendTransaction(removeGlobalDailyRestrictionAction); + let removeGlobalDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeGlobalDailyRestrictionReceipt.logs, 'DefaultDailyRestrictionRemoved'); + console.log(chalk.green(`Global daily restriction has been removed successfully!`)); + break; + case 'Add global custom restriction': + let globalCustomRestrictoToAdd = inputRestrictionData(false); + let globalCustomRestrictionAction = currentTransferManager.methods.addDefaultRestriction( + globalCustomRestrictoToAdd.allowedTokens, + globalCustomRestrictoToAdd.startTime, + globalCustomRestrictoToAdd.rollingPeriodInDays, + globalCustomRestrictoToAdd.endTime, + globalCustomRestrictoToAdd.restrictionType ); - let addDefaultRestrictionReceipt = await common.sendTransaction(addDefaultRestrictionAction); - let addDefaultRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addDefaultRestrictionReceipt.logs, 'AddDefaultRestriction'); - console.log(chalk.green(`Default restriction has been added successfully!`)); - break; - case 'Modify default restriction': - let defaultRestrictoToModify = inputRestrictionData(false); - let modifyDefaultRestrictionAction = currentTransferManager.methods.modifyDefaultRestriction( - defaultRestrictoToModify.allowedTokens, - defaultRestrictoToModify.startTime, - defaultRestrictoToModify.rollingPeriodInDays, - defaultRestrictoToModify.endTime, - defaultRestrictoToModify.restrictionType + let globalCustomRestrictionReceipt = await common.sendTransaction(globalCustomRestrictionAction); + let globalCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, globalCustomRestrictionReceipt.logs, 'AddDefaultRestriction'); + console.log(chalk.green(`Global custom restriction has been added successfully!`)); + break; + case 'Modify global custom restriction': + let globalCustomRestrictoToModify = inputRestrictionData(false); + let globalCustomRestrictionAction = currentTransferManager.methods.modifyDefaultRestriction( + globalCustomRestrictoToModify.allowedTokens, + globalCustomRestrictoToModify.startTime, + globalCustomRestrictoToModify.rollingPeriodInDays, + globalCustomRestrictoToModify.endTime, + globalCustomRestrictoToModify.restrictionType ); - let modifyDefaultRestrictionReceipt = await common.sendTransaction(modifyDefaultRestrictionAction); - let modifyDefaultRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyDefaultRestrictionReceipt.logs, 'ModifyDefaultRestriction'); - console.log(chalk.green(`Default restriction has been modified successfully!`)); + let globalCustomRestrictionReceipt = await common.sendTransaction(globalCustomRestrictionAction); + let globalCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, globalCustomRestrictionReceipt.logs, 'ModifyDefaultRestriction'); + console.log(chalk.green(`Global custom restriction has been modified successfully!`)); break; - case 'Remove default restriction': - let removeDefaultRestrictionAction = currentTransferManager.methods.removeDefaultRestriction(); - let removeDefaultRestrictionReceipt = await common.sendTransaction(removeDefaultRestrictionAction); - let removeDefaultRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeDefaultRestrictionReceipt.logs, 'DefaultRestrictionRemoved'); - console.log(chalk.green(`Default restriction has been removed successfully!`)); + case 'Remove global custom restriction': + let removeGlobalCustomRestrictionAction = currentTransferManager.methods.removeDefaultRestriction(); + let removeGlobalCustomRestrictionReceipt = await common.sendTransaction(removeGlobalCustomRestrictionAction); + let removeGlobalCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeGlobalCustomRestrictionReceipt.logs, 'DefaultRestrictionRemoved'); + console.log(chalk.green(`Global custom restriction has been removed successfully!`)); break; } } @@ -1737,8 +1738,8 @@ async function changeIndividualRestrictions() { let currentDailyRestriction = await currentTransferManager.methods.individualDailyRestriction(holder).call(); let hasDailyRestriction = parseInt(currentDailyRestriction.startTime) !== 0; - let currentRestriction = await currentTransferManager.methods.individualRestriction(holder).call(); - let hasRestriction = parseInt(currentRestriction.startTime) !== 0; + let currentCustomRestriction = await currentTransferManager.methods.individualRestriction(holder).call(); + let hasCustomRestriction = parseInt(currentCustomRestriction.startTime) !== 0; console.log(`*** Current individual restrictions for ${holder} ***`, '\n'); @@ -1750,13 +1751,13 @@ async function changeIndividualRestrictions() { console.log(` Rolling period: ${currentDailyRestriction.rollingPeriodInDays} days`); console.log(` End time: ${moment.unix(currentDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - console.log(`- Other restriction: ${hasRestriction ? '' : 'None'} `); - if (hasRestriction) { - console.log(` Type: ${RESTRICTION_TYPES[currentRestriction.typeOfRestriction]}`); - console.log(` Allowed tokens: ${currentRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(currentRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(currentRestriction.allowedTokens)}%`}`); - console.log(` Start time: ${moment.unix(currentRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(` Rolling period: ${currentRestriction.rollingPeriodInDays} days`); - console.log(` End time: ${moment.unix(currentRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + console.log(`- Other restriction: ${hasCustomRestriction ? '' : 'None'} `); + if (hasCustomRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[currentCustomRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${currentCustomRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(currentCustomRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(currentCustomRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(currentCustomRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${currentCustomRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(currentCustomRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } let options = []; @@ -1766,10 +1767,10 @@ async function changeIndividualRestrictions() { options.push('Modify individual daily restriction', 'Remove individual daily restriction'); } - if (!hasRestriction) { - options.push('Add individual restriction'); + if (!hasCustomRestriction) { + options.push('Add individual custom restriction'); } else { - options.push('Modify individual restriction', 'Remove individual restriction'); + options.push('Modify individual custom restriction', 'Remove individual custom restriction'); } let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); @@ -1777,26 +1778,26 @@ async function changeIndividualRestrictions() { console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Add individual daily restriction': - let dailyRestrictoToAdd = inputRestrictionData(true); + let dailyRestrictonToAdd = inputRestrictionData(true); let addDailyRestrictionAction = currentTransferManager.methods.addIndividualDailyRestriction( holder, - dailyRestrictoToAdd.allowedTokens, - dailyRestrictoToAdd.startTime, - dailyRestrictoToAdd.endTime, - dailyRestrictoToAdd.restrictionType + dailyRestrictonToAdd.allowedTokens, + dailyRestrictonToAdd.startTime, + dailyRestrictonToAdd.endTime, + dailyRestrictonToAdd.restrictionType ); let addDailyRestrictionReceipt = await common.sendTransaction(addDailyRestrictionAction); let addDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addDailyRestrictionReceipt.logs, 'AddIndividualDailyRestriction'); console.log(chalk.green(`Daily restriction for ${addDailyRestrictionEvent._holder} has been added successfully!`)); break; case 'Modify individual daily restriction': - let dailyRestrictoToModify = inputRestrictionData(true); + let dailyRestrictonToModify = inputRestrictionData(true); let modifyDailyRestrictionAction = currentTransferManager.methods.modifyIndividualDailyRestriction( holder, - dailyRestrictoToModify.allowedTokens, - dailyRestrictoToModify.startTime, - dailyRestrictoToModify.endTime, - dailyRestrictoToModify.restrictionType + dailyRestrictonToModify.allowedTokens, + dailyRestrictonToModify.startTime, + dailyRestrictonToModify.endTime, + dailyRestrictonToModify.restrictionType ); let modifyDailyRestrictionReceipt = await common.sendTransaction(modifyDailyRestrictionAction); let modifyDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyDailyRestrictionReceipt.logs, 'ModifyIndividualDailyRestriction'); @@ -1808,39 +1809,39 @@ async function changeIndividualRestrictions() { let removeDailyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeDailyRestrictionReceipt.logs, 'IndividualDailyRestrictionRemoved'); console.log(chalk.green(`Daily restriction for ${removeDailyRestrictionEvent._holder} has been removed successfully!`)); break; - case 'Add individual restriction': - let restrictoToAdd = inputRestrictionData(false); - let addRestrictionAction = currentTransferManager.methods.addIndividualRestriction( + case 'Add individual custom restriction': + let restrictonToAdd = inputRestrictionData(false); + let addCustomRestrictionAction = currentTransferManager.methods.addIndividualRestriction( holder, - restrictoToAdd.allowedTokens, - restrictoToAdd.startTime, - restrictoToAdd.rollingPeriodInDays, - restrictoToAdd.endTime, - restrictoToAdd.restrictionType + restrictonToAdd.allowedTokens, + restrictonToAdd.startTime, + restrictonToAdd.rollingPeriodInDays, + restrictonToAdd.endTime, + restrictonToAdd.restrictionType ); - let addRestrictionReceipt = await common.sendTransaction(addRestrictionAction); - let addRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addRestrictionReceipt.logs, 'AddIndividualRestriction'); - console.log(chalk.green(`Restriction for ${addRestrictionEvent._holder} has been added successfully!`)); + let addCustomRestrictionReceipt = await common.sendTransaction(addCustomRestrictionAction); + let addCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addCustomRestrictionReceipt.logs, 'AddIndividualRestriction'); + console.log(chalk.green(`Custom restriction for ${addCustomRestrictionEvent._holder} has been added successfully!`)); break; - case 'Modify individual restriction': - let restrictoToModify = inputRestrictionData(false); - let modifyRestrictionAction = currentTransferManager.methods.modifyIndividualRestriction( + case 'Modify individual custom restriction': + let restrictonToModify = inputRestrictionData(false); + let modifyCustomRestrictionAction = currentTransferManager.methods.modifyIndividualRestriction( holder, - restrictoToModify.allowedTokens, - restrictoToModify.startTime, - restrictoToModify.rollingPeriodInDays, - restrictoToModify.endTime, - restrictoToModify.restrictionType + restrictonToModify.allowedTokens, + restrictonToModify.startTime, + restrictonToModify.rollingPeriodInDays, + restrictonToModify.endTime, + restrictonToModify.restrictionType ); - let modifyRestrictionReceipt = await common.sendTransaction(modifyRestrictionAction); - let modifyRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyRestrictionReceipt.logs, 'ModifyIndividualRestriction'); - console.log(chalk.green(`Restriction for ${modifyRestrictionEvent._holder} has been modified successfully!`)); + let modifyCustomRestrictionReceipt = await common.sendTransaction(modifyCustomRestrictionAction); + let modifyCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyCustomRestrictionReceipt.logs, 'ModifyIndividualRestriction'); + console.log(chalk.green(`Custom restriction for ${modifyCustomRestrictionEvent._holder} has been modified successfully!`)); break; - case 'Remove individual restriction': - let removeRestrictionAction = currentTransferManager.methods.removeIndividualRestriction(holder); - let removeRestrictionReceipt = await common.sendTransaction(removeRestrictionAction); - let removeRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeRestrictionReceipt.logs, 'IndividualRestrictionRemoved'); - console.log(chalk.green(`Restriction for ${removeRestrictionEvent._holder} has been removed successfully!`)); + case 'Remove individual custom restriction': + let removeCustomRestrictionAction = currentTransferManager.methods.removeIndividualRestriction(holder); + let removeCustomRestrictionReceipt = await common.sendTransaction(removeCustomRestrictionAction); + let removeCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeCustomRestrictionReceipt.logs, 'IndividualRestrictionRemoved'); + console.log(chalk.green(`Custom restriction for ${removeCustomRestrictionEvent._holder} has been removed successfully!`)); break; case 'RETURN': return; @@ -1855,54 +1856,54 @@ async function exploreAccount() { limitMessage: "Must be a valid address" }); - let appliyngdDailyRestriction = null; - let applyingOtherRestriction = null; + let appliyngDailyRestriction = null; + let applyingCustomRestriction = null; let hasIndividualRestrictions = false; let isExempted = await currentTransferManager.methods.exemptList(account).call(); if (!isExempted) { - let indiviaulDailyRestriction = await currentTransferManager.methods.individualDailyRestriction(account).call(); - if (parseInt(indiviaulDailyRestriction.endTime) !== 0) { - appliyngdDailyRestriction = indiviaulDailyRestriction; + let individuallDailyRestriction = await currentTransferManager.methods.individualDailyRestriction(account).call(); + if (parseInt(individuallDailyRestriction.endTime) !== 0) { + appliyngDailyRestriction = individuallDailyRestriction; } - let otherRestriction = await currentTransferManager.methods.individualRestriction(account).call(); - if (parseInt(otherRestriction.endTime) !== 0) { - applyingOtherRestriction = otherRestriction; + let customRestriction = await currentTransferManager.methods.individualRestriction(account).call(); + if (parseInt(customRestriction.endTime) !== 0) { + applyingCustomRestriction = customRestriction; } - hasIndividualRestrictions = applyingOtherRestriction || appliyngdDailyRestriction; + hasIndividualRestrictions = applyingCustomRestriction || appliyngDailyRestriction; if (!hasIndividualRestrictions) { - let defaultDailyRestriction = await currentTransferManager.methods.defaultDailyRestriction().call(); - if (parseInt(defaultDailyRestriction.endTime) !== 0) { - appliyngdDailyRestriction = defaultDailyRestriction; + let globalDailyRestriction = await currentTransferManager.methods.defaultDailyRestriction().call(); + if (parseInt(globalDailyRestriction.endTime) !== 0) { + appliyngDailyRestriction = globalDailyRestriction; } - let defaultOtherRestriction = await currentTransferManager.methods.defaultRestriction().call(); - if (parseInt(defaultOtherRestriction.endTime) === 0) { - applyingOtherRestriction = defaultOtherRestriction; + let globalCustomRestriction = await currentTransferManager.methods.defaultRestriction().call(); + if (parseInt(globalCustomRestriction.endTime) === 0) { + applyingCustomRestriction = globalCustomRestriction; } } } console.log(`*** Applying restrictions for ${account} ***`, '\n'); - console.log(`- Daily restriction: ${appliyngdDailyRestriction ? (!hasIndividualRestrictions ? 'default' : '') : 'None'}`); - if (appliyngdDailyRestriction) { - console.log(` Type: ${RESTRICTION_TYPES[appliyngdDailyRestriction.typeOfRestriction]}`); - console.log(` Allowed tokens: ${appliyngdDailyRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(appliyngdDailyRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(appliyngdDailyRestriction.allowedTokens)}%`}`); - console.log(` Start time: ${moment.unix(appliyngdDailyRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(` Rolling period: ${appliyngdDailyRestriction.rollingPeriodInDays} days`); - console.log(` End time: ${moment.unix(appliyngdDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + console.log(`- Daily restriction: ${appliyngDailyRestriction ? (!hasIndividualRestrictions ? 'global' : '') : 'None'}`); + if (appliyngDailyRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[appliyngDailyRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${appliyngDailyRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(appliyngDailyRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(appliyngDailyRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(appliyngDailyRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${appliyngDailyRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(appliyngDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - console.log(`- Other restriction: ${applyingOtherRestriction ? (!hasIndividualRestrictions ? 'default' : '') : 'None'} `); - if (applyingOtherRestriction) { - console.log(` Type: ${RESTRICTION_TYPES[applyingOtherRestriction.typeOfRestriction]}`); - console.log(` Allowed tokens: ${applyingOtherRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(applyingOtherRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(applyingOtherRestriction.allowedTokens)}%`}`); - console.log(` Start time: ${moment.unix(applyingOtherRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(` Rolling period: ${applyingOtherRestriction.rollingPeriodInDays} days`); - console.log(` End time: ${moment.unix(applyingOtherRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); + console.log(`- Other restriction: ${applyingCustomRestriction ? (!hasIndividualRestrictions ? 'global' : '') : 'None'} `); + if (applyingCustomRestriction) { + console.log(` Type: ${RESTRICTION_TYPES[applyingCustomRestriction.typeOfRestriction]}`); + console.log(` Allowed tokens: ${applyingCustomRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(applyingCustomRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(applyingCustomRestriction.allowedTokens)}%`}`); + console.log(` Start time: ${moment.unix(applyingCustomRestriction.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(` Rolling period: ${applyingCustomRestriction.rollingPeriodInDays} days`); + console.log(` End time: ${moment.unix(applyingCustomRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - if (applyingOtherRestriction || appliyngdDailyRestriction) { + if (applyingCustomRestriction || appliyngDailyRestriction) { let bucketDetails; if (hasIndividualRestrictions) { bucketDetails = await currentTransferManager.methods.getIndividualBucketDetailsToUser(account).call(); @@ -1945,13 +1946,13 @@ async function operateWithMultipleRestrictions() { await removeDailyRestrictionsInBatch(); break; case 'Add multiple individual restrictions': - await addRestrictionsInBatch(); + await addCustomRestrictionsInBatch(); break; case 'Modify multiple individual restrictions': - await modifyRestrictionsInBatch(); + await modifyCustomRestrictionsInBatch(); break; case 'Remove multiple individual restrictions': - await removeRestrictionsInBatch(); + await removeCustomRestrictionsInBatch(); break; } } @@ -2054,9 +2055,9 @@ async function removeDailyRestrictionsInBatch() { } } -async function addRestrictionsInBatch() { - let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_RESTRICTIONS_DATA_CSV}): `, { - defaultInput: ADD_RESTRICTIONS_DATA_CSV +async function addCustomRestrictionsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_CUSTOM_RESTRICTIONS_DATA_CSV}): `, { + defaultInput: ADD_CUSTOM_RESTRICTIONS_DATA_CSV }); let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { limit: function (input) { @@ -2080,19 +2081,19 @@ async function addRestrictionsInBatch() { let batches = common.splitIntoBatches(validData, batchSize); let [holderArray, allowanceArray, startTimeArray, rollingPeriodArray, endTimeArray, restrictionTypeArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { - console.log(`Batch ${batch + 1} - Attempting to add restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); + console.log(`Batch ${batch + 1} - Attempting to add custom restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); allowanceArray[batch] = allowanceArray[batch].map(n => web3.utils.toWei(n.toString())); restrictionTypeArray[batch] = restrictionTypeArray[batch].map(n => RESTRICTION_TYPES.indexOf(n)); let action = currentTransferManager.methods.addIndividualRestrictionMulti(holderArray[batch], allowanceArray[batch], startTimeArray[batch], rollingPeriodArray[batch], endTimeArray[batch], restrictionTypeArray[batch]); let receipt = await common.sendTransaction(action); - console.log(chalk.green('Add multiple restrictions transaction was successful.')); + console.log(chalk.green('Add multiple custom restrictions transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } } -async function modifyRestrictionsInBatch() { - let csvFilePath = readlineSync.question(`Enter the path for csv data file (${MODIFY_RESTRICTIONS_DATA_CSV}): `, { - defaultInput: MODIFY_RESTRICTIONS_DATA_CSV +async function modifyCustomRestrictionsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${MODIFY_CUSTOM_RESTRICTIONS_DATA_CSV}): `, { + defaultInput: MODIFY_CUSTOM_RESTRICTIONS_DATA_CSV }); let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { limit: function (input) { @@ -2116,19 +2117,19 @@ async function modifyRestrictionsInBatch() { let batches = common.splitIntoBatches(validData, batchSize); let [holderArray, allowanceArray, startTimeArray, rollingPeriodArray, endTimeArray, restrictionTypeArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { - console.log(`Batch ${batch + 1} - Attempting to modify restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); + console.log(`Batch ${batch + 1} - Attempting to modify custom restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); allowanceArray[batch] = allowanceArray[batch].map(n => web3.utils.toWei(n.toString())); restrictionTypeArray[batch] = restrictionTypeArray[batch].map(n => RESTRICTION_TYPES.indexOf(n)); let action = currentTransferManager.methods.modifyIndividualRestrictionMulti(holderArray[batch], allowanceArray[batch], startTimeArray[batch], rollingPeriodArray[batch], endTimeArray[batch], restrictionTypeArray[batch]); let receipt = await common.sendTransaction(action); - console.log(chalk.green('Modify multiple restrictions transaction was successful.')); + console.log(chalk.green('Modify multiple custom restrictions transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } } -async function removeRestrictionsInBatch() { - let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REMOVE_RESTRICTIONS_DATA_CSV}): `, { - defaultInput: REMOVE_RESTRICTIONS_DATA_CSV +async function removeCustomRestrictionsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REMOVE_CUSTOM_RESTRICTIONS_DATA_CSV}): `, { + defaultInput: REMOVE_CUSTOM_RESTRICTIONS_DATA_CSV }); let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { limit: function (input) { @@ -2146,10 +2147,10 @@ async function removeRestrictionsInBatch() { let batches = common.splitIntoBatches(validData, batchSize); let [holderArray] = common.transposeBatches(batches); for (let batch = 0; batch < batches.length; batch++) { - console.log(`Batch ${batch + 1} - Attempting to remove restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); + console.log(`Batch ${batch + 1} - Attempting to remove custom restrictions to the following accounts: \n\n`, holderArray[batch], '\n'); let action = currentTransferManager.methods.removeIndividualRestrictionMulti(holderArray[batch]); let receipt = await common.sendTransaction(action); - console.log(chalk.green('Remove multiple restrictions transaction was successful.')); + console.log(chalk.green('Remove multiple custom restrictions transaction was successful.')); console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); } } diff --git a/CLI/data/Transfer/VRTM/add_restriction_data.csv b/CLI/data/Transfer/VRTM/add_custom_restriction_data.csv similarity index 100% rename from CLI/data/Transfer/VRTM/add_restriction_data.csv rename to CLI/data/Transfer/VRTM/add_custom_restriction_data.csv diff --git a/CLI/data/Transfer/VRTM/modify_restriction_data.csv b/CLI/data/Transfer/VRTM/modify_custom_restriction_data.csv similarity index 100% rename from CLI/data/Transfer/VRTM/modify_restriction_data.csv rename to CLI/data/Transfer/VRTM/modify_custom_restriction_data.csv diff --git a/CLI/data/Transfer/VRTM/remove_restriction_data.csv b/CLI/data/Transfer/VRTM/remove_custom_restriction_data.csv similarity index 100% rename from CLI/data/Transfer/VRTM/remove_restriction_data.csv rename to CLI/data/Transfer/VRTM/remove_custom_restriction_data.csv From d2636c0a8172a71a711a054f10b3b90cd59d158d Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 9 Jan 2019 14:17:56 -0300 Subject: [PATCH 511/582] Minor fix --- CLI/commands/transfer_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 8b84e74f8..bfc47ff3d 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -2296,7 +2296,7 @@ async function selectToken() { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); break; - case 'Exit': + case 'EXIT': process.exit(); break; default: From 60efa3f6cf8116fe67e0d5adbdf20c86ba0a1a53 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 9 Jan 2019 15:03:11 -0300 Subject: [PATCH 512/582] CLI - Percentage with decimals fix --- CLI/commands/transfer_manager.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index bfc47ff3d..e8fce26c8 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1537,7 +1537,7 @@ async function volumeRestrictionTM() { console.log(` Rolling period: ${globalDailyRestriction.rollingPeriodInDays} days`); console.log(` End time: ${moment.unix(globalDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - console.log(`- Default custom restriction: ${hasGlobalCustomRestriction ? '' : 'None'}`); + console.log(`- Default custom restriction: ${hasGlobalCustomRestriction ? '' : 'None'}`); if (hasGlobalCustomRestriction) { console.log(` Type: ${RESTRICTION_TYPES[globalCustomRestriction.typeOfRestriction]}`); console.log(` Allowed tokens: ${globalCustomRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(globalCustomRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(globalCustomRestriction.allowedTokens)}%`}`); @@ -1565,7 +1565,7 @@ async function volumeRestrictionTM() { let optionSelected = index !== -1 ? options[index] : 'RETURN'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { - case 'Show restrictios': + case 'Show restrictions': showRestrictionTable( addressesAndRestrictions.allAddresses, addressesAndRestrictions.allowedTokens, @@ -1695,28 +1695,28 @@ async function changeDefaultRestrictions(hasGlobalDailyRestriction, hasGlobalCus break; case 'Add global custom restriction': let globalCustomRestrictoToAdd = inputRestrictionData(false); - let globalCustomRestrictionAction = currentTransferManager.methods.addDefaultRestriction( + let addGlobalCustomRestrictionAction = currentTransferManager.methods.addDefaultRestriction( globalCustomRestrictoToAdd.allowedTokens, globalCustomRestrictoToAdd.startTime, globalCustomRestrictoToAdd.rollingPeriodInDays, globalCustomRestrictoToAdd.endTime, globalCustomRestrictoToAdd.restrictionType ); - let globalCustomRestrictionReceipt = await common.sendTransaction(globalCustomRestrictionAction); - let globalCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, globalCustomRestrictionReceipt.logs, 'AddDefaultRestriction'); + let addGlobalCustomRestrictionReceipt = await common.sendTransaction(addGlobalCustomRestrictionAction); + let addGlobalCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addGlobalCustomRestrictionReceipt.logs, 'AddDefaultRestriction'); console.log(chalk.green(`Global custom restriction has been added successfully!`)); break; case 'Modify global custom restriction': let globalCustomRestrictoToModify = inputRestrictionData(false); - let globalCustomRestrictionAction = currentTransferManager.methods.modifyDefaultRestriction( + let modifiyGlobalCustomRestrictionAction = currentTransferManager.methods.modifyDefaultRestriction( globalCustomRestrictoToModify.allowedTokens, globalCustomRestrictoToModify.startTime, globalCustomRestrictoToModify.rollingPeriodInDays, globalCustomRestrictoToModify.endTime, globalCustomRestrictoToModify.restrictionType ); - let globalCustomRestrictionReceipt = await common.sendTransaction(globalCustomRestrictionAction); - let globalCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, globalCustomRestrictionReceipt.logs, 'ModifyDefaultRestriction'); + let modifyGlobalCustomRestrictionReceipt = await common.sendTransaction(modifiyGlobalCustomRestrictionAction); + let modifyGlobalCustomRestrictionEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyGlobalCustomRestrictionReceipt.logs, 'ModifyDefaultRestriction'); console.log(chalk.green(`Global custom restriction has been modified successfully!`)); break; case 'Remove global custom restriction': @@ -1743,7 +1743,7 @@ async function changeIndividualRestrictions() { console.log(`*** Current individual restrictions for ${holder} ***`, '\n'); - console.log(`- Daily restriction: ${hasDailyRestriction ? '' : 'None'}`); + console.log(`- Daily restriction: ${hasDailyRestriction ? '' : 'None'}`); if (hasDailyRestriction) { console.log(` Type: ${RESTRICTION_TYPES[currentDailyRestriction.typeOfRestriction]}`); console.log(` Allowed tokens: ${currentDailyRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(currentDailyRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(currentDailyRestriction.allowedTokens)}%`}`); @@ -1751,7 +1751,7 @@ async function changeIndividualRestrictions() { console.log(` Rolling period: ${currentDailyRestriction.rollingPeriodInDays} days`); console.log(` End time: ${moment.unix(currentDailyRestriction.endTime).format('MMMM Do YYYY, HH:mm:ss')} `); } - console.log(`- Other restriction: ${hasCustomRestriction ? '' : 'None'} `); + console.log(`- Custom restriction: ${hasCustomRestriction ? '' : 'None'} `); if (hasCustomRestriction) { console.log(` Type: ${RESTRICTION_TYPES[currentCustomRestriction.typeOfRestriction]}`); console.log(` Allowed tokens: ${currentCustomRestriction.typeOfRestriction === "0" ? `${web3.utils.fromWei(currentCustomRestriction.allowedTokens)} ${tokenSymbol}` : `${fromWeiPercentage(currentCustomRestriction.allowedTokens)}%`}`); @@ -2159,9 +2159,9 @@ function inputRestrictionData(isDaily) { let restriction = {}; restriction.restrictionType = readlineSync.keyInSelect(RESTRICTION_TYPES, 'How do you want to set the allowance? ', { cancel: false }); if (restriction.restrictionType == RESTRICTION_TYPES.indexOf('Fixed')) { - restriction.allowedTokens = web3.utils.toWei(readlineSync.questionInt(`Enter the maximum amount of tokens allowed to be traded every ${isDaily ? 'day' : 'rolling period'}: `).toString()); + restriction.allowedTokens = web3.utils.toWei(readlineSync.question(`Enter the maximum amount of tokens allowed to be traded every ${isDaily ? 'day' : 'rolling period'}: `).toString()); } else { - restriction.allowedTokens = toWeiPercentage(readlineSync.questionInt(`Enter the maximum percentage of total supply allowed to be traded every ${isDaily ? 'day' : 'rolling period'}: `).toString()); + restriction.allowedTokens = toWeiPercentage(readlineSync.question(`Enter the maximum percentage of total supply allowed to be traded every ${isDaily ? 'day' : 'rolling period'}: `).toString()); } if (isDaily) { restriction.rollingPeriodInDays = 1; @@ -2197,11 +2197,11 @@ function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, rest */ function toWeiPercentage(number) { - return new web3.utils.BN(web3.utils.toWei(number)).divn(100); + return web3.utils.toWei((parseFloat(number) / 100).toString()); } function fromWeiPercentage(number) { - return web3.utils.fromWei(new web3.utils.BN(number).muln(100)); + return web3.utils.fromWei(new web3.utils.BN(number).muln(100)).toString(); } async function getAllModulesByType(type) { From 5c2771114cb77f8a37aac0552e545dbac80e7a2e Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 9 Jan 2019 14:17:12 -0300 Subject: [PATCH 513/582] CLI - Changed names of restrictions --- CLI/commands/helpers/contract_abis.js | 7 +- CLI/commands/transfer_manager.js | 425 +++++++- .../Transfer/LockupTM/add_lockup_data.csv | 4 + .../LockupTM/add_lockup_investor_data.csv | 12 + .../Transfer/LockupTM/delete_lockup_data.csv | 2 + .../Transfer/LockupTM/modify_lockup_data.csv | 4 + .../LockupTM/remove_lockup_investor_data.csv | 12 + .../LockupVolumeRestrictionTM.sol | 411 -------- .../TransferManager/LockUpTransferManager.sol | 636 +++++++++++ .../LockUpTransferManagerFactory.sol} | 20 +- migrations/2_deploy_contracts.js | 21 +- test/helpers/createInstances.js | 6 +- test/w_lockup_transfer_manager.js | 995 ++++++++++++++++++ ...kup_volume_restriction_transfer_manager.js | 808 -------------- .../z_fuzz_test_adding_removing_modules_ST.js | 2 +- test/z_general_permission_manager_fuzzer.js | 1 - 16 files changed, 2117 insertions(+), 1249 deletions(-) create mode 100644 CLI/data/Transfer/LockupTM/add_lockup_data.csv create mode 100644 CLI/data/Transfer/LockupTM/add_lockup_investor_data.csv create mode 100644 CLI/data/Transfer/LockupTM/delete_lockup_data.csv create mode 100644 CLI/data/Transfer/LockupTM/modify_lockup_data.csv create mode 100644 CLI/data/Transfer/LockupTM/remove_lockup_investor_data.csv delete mode 100644 contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol create mode 100644 contracts/modules/TransferManager/LockUpTransferManager.sol rename contracts/modules/{Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol => TransferManager/LockUpTransferManagerFactory.sol} (74%) create mode 100644 test/w_lockup_transfer_manager.js delete mode 100644 test/w_lockup_volume_restriction_transfer_manager.js diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index f33e8bc28..67dc43244 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -11,6 +11,7 @@ let manualApprovalTransferManagerABI; let blacklistTransferManagerABI; let countTransferManagerABI; let percentageTransferManagerABI; +let lockUpTransferManagerABI; let volumeRestrictionTMABI; let generalPermissionManagerABI; let polyTokenABI; @@ -38,8 +39,9 @@ try { manualApprovalTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ManualApprovalTransferManager.json`).toString()).abi; countTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/CountTransferManager.json`).toString()).abi; percentageTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PercentageTransferManager.json`).toString()).abi; - blacklistTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/BlacklistTransferManager.json`).toString()).abi; + blacklistTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/BlacklistTransferManager.json`).toString()).abi; volumeRestrictionTMABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/VolumeRestrictionTM.json`).toString()).abi; + lockUpTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/LockUpTransferManager.json`).toString()).abi; generalPermissionManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/GeneralPermissionManager.json`).toString()).abi; polyTokenABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/PolyTokenFaucet.json`).toString()).abi; cappedSTOFactoryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/CappedSTOFactory.json`).toString()).abi; @@ -97,6 +99,9 @@ module.exports = { percentageTransferManager: function () { return percentageTransferManagerABI; }, + lockUpTransferManager: function () { + return lockUpTransferManagerABI; + }, volumeRestrictionTM: function () { return volumeRestrictionTMABI; }, diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index e8fce26c8..1ea70fa2b 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -6,7 +6,7 @@ const contracts = require('./helpers/contract_addresses'); const abis = require('./helpers/contract_abis'); const gbl = require('./common/global'); const csvParse = require('./helpers/csv'); -const { table } = require('table') +const { table } = require('table'); /////////////////// // Constants @@ -26,6 +26,11 @@ const REMOVE_DAILY_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/r const ADD_CUSTOM_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/add_custom_restriction_data.csv`; const MODIFY_CUSTOM_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/modify_custom_restriction_data.csv`; const REMOVE_CUSTOM_RESTRICTIONS_DATA_CSV = `${__dirname}/../data/Transfer/VRTM/remove_custom_restriction_data.csv`; +const ADD_LOCKUP_DATA_CSV = `${__dirname}/../data/Transfer/LockupTM/add_lockup_data.csv`; +const MODIFY_LOCKUP_DATA_CSV = `${__dirname}/../data/Transfer/LockupTM/modify_lockup_data.csv`; +const DELETE_LOCKUP_DATA_CSV = `${__dirname}/../data/Transfer/LockupTM/delete_lockup_data.csv`; +const ADD_LOCKUP_INVESTOR_DATA_CSV = `${__dirname}/../data/Transfer/LockupTM/add_lockup_investor_data.csv`; +const REMOVE_LOCKUP_INVESTOR_DATA_CSV = `${__dirname}/../data/Transfer/LockupTM/remove_lockup_investor_data.csv`; const RESTRICTION_TYPES = ['Fixed', 'Percentage']; @@ -71,7 +76,7 @@ async function executeApp() { options.push('Add new Transfer Manager module'); let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'EXIT' }); - let optionSelected = index !== -1 ? options[index] : 'EXIT'; + let optionSelected = index != -1 ? options[index] : 'EXIT'; console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'Verify transfer': @@ -241,6 +246,11 @@ async function configExistingModules(tmModules) { currentTransferManager.setProvider(web3.currentProvider); await percentageTransferManager(); break; + case 'LockUpTransferManager': + currentTransferManager = new web3.eth.Contract(abis.lockUpTransferManager(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await lockUpTransferManager(); + break; case 'BlacklistTransferManager': currentTransferManager = new web3.eth.Contract(abis.blacklistTransferManager(), tmModules[index].address); currentTransferManager.setProvider(web3.currentProvider); @@ -292,7 +302,7 @@ async function addTransferManagerModule() { } async function generalTransferManager() { - console.log(chalk.blue(`General Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + console.log('\n', chalk.blue(`General Transfer Manager at ${currentTransferManager.options.address}`), '\n'); // Show current data let displayIssuanceAddress = await currentTransferManager.methods.issuanceAddress().call(); @@ -553,7 +563,7 @@ async function modifyWhitelistInBatch(_csvFilePath, _batchSize) { } async function manualApprovalTransferManager() { - console.log(chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address} `), '\n'); + console.log('\n', chalk.blue(`Manual Approval Transfer Manager at ${currentTransferManager.options.address} `), '\n'); let totalApprovals = await currentTransferManager.methods.getTotalApprovalsLength().call(); console.log(`- Current active approvals: ${totalApprovals}`); @@ -942,7 +952,7 @@ function getBinarySize(string) { } async function countTransferManager() { - console.log(chalk.blue(`Count Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + console.log('\n', chalk.blue(`Count Transfer Manager at ${currentTransferManager.options.address}`), '\n'); // Show current data let displayMaxHolderCount = await currentTransferManager.methods.maxHolderCount().call(); @@ -969,7 +979,7 @@ async function countTransferManager() { } async function percentageTransferManager() { - console.log(chalk.blue(`Percentage Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + console.log('\n', chalk.blue(`Percentage Transfer Manager at ${currentTransferManager.options.address}`), '\n'); // Show current data let displayMaxHolderPercentage = await currentTransferManager.methods.maxHolderPercentage().call(); @@ -1069,15 +1079,13 @@ async function percentageTransferManager() { console.log(chalk.green(`Transactions which are part of the primary issuance will NOT be ignored!`)); } break; - case 'RETURN': - return; } await percentageTransferManager(); } async function blacklistTransferManager() { - console.log(chalk.blue(`Blacklist Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + console.log('\n', chalk.blue(`Blacklist Transfer Manager at ${currentTransferManager.options.address}`), '\n'); let currentBlacklists = await currentTransferManager.methods.getAllBlacklists().call(); console.log(`- Blacklists: ${currentBlacklists.length}`); @@ -2180,6 +2188,401 @@ function inputRestrictionData(isDaily) { return restriction; } +async function lockUpTransferManager() { + console.log('\n', chalk.blue(`Lockup Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + + let currentLockups = await currentTransferManager.methods.getAllLockups().call(); + console.log(`- Lockups: ${currentLockups.length}`); + + let options = ['Add new lockup']; + if (currentLockups.length > 0) { + options.push('Manage existing lockups', 'Explore investor'); + } + options.push('Operate with multiple lockups'); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add new lockup': + let name = readlineSync.question(`Enter the name of the lockup type: `, { + limit: function (input) { + return input !== ""; + }, + limitMessage: `Invalid lockup name` + }); + let lockupAmount = readlineSync.questionInt(`Enter the amount of tokens that will be locked: `); + let minuteFromNow = Math.floor(Date.now() / 1000) + 60; + let startTime = readlineSync.questionInt(`Enter the start time (Unix Epoch time) of the lockup type (a minute from now = ${minuteFromNow}): `, { defaultInput: minuteFromNow }); + let lockUpPeriodSeconds = readlineSync.questionInt(`Enter the total period (seconds) of the lockup type (ten minutes = 600): `, { defaultInput: 600 }); + let releaseFrequencySeconds = readlineSync.questionInt(`Enter how often to release a tranche of tokens in seconds (one minute = 60): `, { defaultInput: 60 }); + if (readlineSync.keyInYNStrict(`Do you want to add an investor to this lockup type? `)) { + let investor = readlineSync.question(`Enter the address of the investor: `, { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: `Must be a valid address` + }); + let addNewLockUpToUserAction = currentTransferManager.methods.addNewLockUpToUser( + investor, + web3.utils.toWei(lockupAmount.toString()), + startTime, + lockUpPeriodSeconds, + releaseFrequencySeconds, + web3.utils.toHex(name) + ); + let addNewLockUpToUserReceipt = await common.sendTransaction(addNewLockUpToUserAction); + let addNewLockUpToUserEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addNewLockUpToUserReceipt.logs, 'AddNewLockUpType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(addNewLockUpToUserEvent._lockupName)} lockup type has been added successfully!`)); + let addLockUpToUserEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addNewLockUpToUserReceipt.logs, 'AddLockUpToUser'); + console.log(chalk.green(`${addLockUpToUserEvent._userAddress} has been added to ${web3.utils.hexToUtf8(addLockUpToUserEvent._lockupName)} successfully!`)); + } else { + let addLockupTypeAction = currentTransferManager.methods.addNewLockUpType(web3.utils.toWei(lockupAmount.toString()), startTime, lockUpPeriodSeconds, releaseFrequencySeconds, web3.utils.toHex(name)); + let addLockupTypeReceipt = await common.sendTransaction(addLockupTypeAction); + let addLockupTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, addLockupTypeReceipt.logs, 'AddNewLockUpType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(addLockupTypeEvent._lockupName)} lockup type has been added successfully!`)); + } + break; + case 'Manage existing lockups': + let options = currentLockups.map(b => web3.utils.hexToUtf8(b)); + let index = readlineSync.keyInSelect(options, 'Which lockup type do you want to manage? ', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + if (index !== -1) { + await manageExistingLockups(currentLockups[index]); + } + break; + case 'Explore investor': + let investorToExplore = readlineSync.question('Enter the address you want to explore: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address" + }); + let lockupsToInvestor = await currentTransferManager.methods.getLockupsNamesToUser(investorToExplore).call(); + if (lockupsToInvestor.length > 0) { + let lockedTokenToInvestor = await currentTransferManager.methods.getLockedTokenToUser(investorToExplore).call(); + console.log(chalk.green(`The address ${investorToExplore} has ${web3.utils.fromWei(lockedTokenToInvestor)} ${tokenSymbol} locked across the following ${lockupsToInvestor.length} lockups: `)); + lockupsToInvestor.map(l => console.log(chalk.green(`- ${web3.utils.hexToUtf8(l)}`))); + } else { + console.log(chalk.yellow(`The address ${investorToExplore} has no lockups`)); + } + break; + case 'Operate with multiple lockups': + await operateWithMultipleLockups(currentLockups); + break; + case 'RETURN': + return; + } + + await lockUpTransferManager(); +} + +async function manageExistingLockups(lockupName) { + console.log('\n', chalk.blue(`Lockup ${web3.utils.hexToUtf8(lockupName)}`), '\n'); + + // Show current data + let currentLockup = await currentTransferManager.methods.getLockUp(lockupName).call(); + let investors = await currentTransferManager.methods.getListOfAddresses(lockupName).call(); + + console.log(`- Amount: ${web3.utils.fromWei(currentLockup.lockupAmount)} ${tokenSymbol}`); + console.log(`- Currently unlocked: ${web3.utils.fromWei(currentLockup.unlockedAmount)} ${tokenSymbol}`); + console.log(`- Start time: ${moment.unix(currentLockup.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- Lockup period: ${currentLockup.lockUpPeriodSeconds} seconds`); + console.log(`- End time: ${moment.unix(currentLockup.endTime).add(parseInt(currentLockup.lockUpPeriodSeconds)).format('MMMM Do YYYY, HH:mm:ss')}`); + console.log(`- Release frequency: ${currentLockup.releaseFrequencySeconds} senconds`); + console.log(`- Investors: ${investors.length}`); + // ------------------ + + let options = [ + 'Modify properties', + 'Show investors', + 'Add this lockup to investors', + 'Remove this lockup from investors', + 'Delete this lockup type' + ]; + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Modify properties': + let lockupAmount = readlineSync.questionInt(`Enter the amount of tokens that will be locked: `); + let minuteFromNow = Math.floor(Date.now() / 1000) + 60; + let startTime = readlineSync.questionInt(`Enter the start time (Unix Epoch time) of the lockup type (a minute from now = ${minuteFromNow}): `, { defaultInput: minuteFromNow }); + let lockUpPeriodSeconds = readlineSync.questionInt(`Enter the total period (seconds) of the lockup type (ten minutes = 600): `, { defaultInput: 600 }); + let releaseFrequencySeconds = readlineSync.questionInt(`Enter how often to release a tranche of tokens in seconds (one minute = 60): `, { defaultInput: 60 }); + let modifyLockUpTypeAction = currentTransferManager.methods.modifyLockUpType(lockupAmount, startTime, lockUpPeriodSeconds, releaseFrequencySeconds, lockupName); + let modifyLockUpTypeReceipt = await common.sendTransaction(modifyLockUpTypeAction); + let modifyLockUpTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyLockUpTypeReceipt.logs, 'ModifyLockUpType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(modifyLockUpTypeEvent._lockupName)} lockup type has been modified successfully!`)); + break; + case 'Show investors': + if (investors.length > 0) { + console.log("************ List of investors ************"); + investors.map(i => console.log(i)); + } else { + console.log(chalk.yellow("There are no investors yet")); + } + break; + case 'Add this lockup to investors': + let investorsToAdd = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e.addr1, addr2, addr3): `, { + limit: function (input) { + return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); + }, + limitMessage: `All addresses must be valid` + }).split(","); + let addInvestorToLockupAction; + if (investorsToAdd.length === 1) { + addInvestorToLockupAction = currentTransferManager.methods.addLockUpByName(investorsToAdd[0], lockupName); + } else { + addInvestorToLockupAction = currentTransferManager.methods.addLockUpByNameMulti(investorsToAdd, investorsToAdd.map(i => lockupName)); + } + let addInvestorToLockupReceipt = await common.sendTransaction(addInvestorToLockupAction); + let addInvestorToLockupEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, addInvestorToLockupReceipt.logs, 'AddLockUpToUser'); + addInvestorToLockupEvents.map(e => console.log(chalk.green(`${e._userAddress} has been added to ${web3.utils.hexToUtf8(e._lockupName)} successfully!`))); + break; + case 'Remove this lockup from investors': + let investorsToRemove = readlineSync.question(`Enter the addresses of the investors separated by comma (i.e.addr1, addr2, addr3): `, { + limit: function (input) { + return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); + }, + limitMessage: `All addresses must be valid` + }).split(","); + let removeLockupFromInvestorAction; + if (investorsToRemove.length === 1) { + removeLockupFromInvestorAction = currentTransferManager.methods.removeLockUpFromUser(investorsToRemove[0], lockupName); + } else { + removeLockupFromInvestorAction = currentTransferManager.methods.removeLockUpFromUserMulti(investorsToRemove, investorsToRemove.map(i => lockupName)); + } + let removeLockUpFromUserReceipt = await common.sendTransaction(removeLockupFromInvestorAction); + let removeLockUpFromUserEvents = common.getMultipleEventsFromLogs(currentTransferManager._jsonInterface, removeLockUpFromUserReceipt.logs, 'RemoveLockUpFromUser'); + removeLockUpFromUserEvents.map(e => console.log(chalk.green(`${e._userAddress} has been removed to ${web3.utils.hexToUtf8(e._lockupName)} successfully!`))); + break; + case 'Delete this lockup type': + let isEmpty = investors.length === 0; + if (!isEmpty) { + console.log(chalk.yellow(`This lockup have investors added to it. To delete it you must remove them first.`)); + if (readlineSync.keyInYNStrict(`Do you want to remove them? `)) { + let data = investors.map(i => [i, lockupName]) + let batches = common.splitIntoBatches(data, gbl.constants.DEFAULT_BATCH_SIZE); + let [investorArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to remove the following investors:\n\n`, investorArray[batch], '\n'); + let action = currentTransferManager.methods.removeLockUpFromUserMulti(investorArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Remove lockups from multiple investors transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } + isEmpty = true; + } + } + if (isEmpty) { + let removeLockupTypeAction = currentTransferManager.methods.removeLockupType(lockupName); + let removeLockupTypeReceipt = await common.sendTransaction(removeLockupTypeAction); + let removeLockupTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, removeLockupTypeReceipt.logs, 'RemoveLockUpType'); + console.log(chalk.green(`${web3.utils.hexToUtf8(removeLockupTypeEvent._lockupName)} lockup type has been deleted successfully!`)); + } + return; + case 'RETURN': + return; + } + + await manageExistingLockups(lockupName); +} + +async function operateWithMultipleLockups(currentLockups) { + let options = ['Add multiple lockups']; + if (currentLockups.length > 0) { + options.push('Modify multiple lockups'); + } + options.push( + 'Delete multiple lockups', + 'Add lockups to multiple investors', + 'Remove lockups from multiple investors' + ); + + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); + let optionSelected = index !== -1 ? options[index] : 'RETURN'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Add multiple lockups': + await addLockupsInBatch(); + break; + case 'Modify multiple lockups': + await modifyLockupsInBatch(); + break; + case 'Delete multiple lockups': + await deleteLockupsInBatch(); + break; + case 'Add lockups to multiple investors': + await addLockupsToInvestorsInBatch(); + break; + case 'Remove lockups from multiple investors': + await removeLockupsFromInvestorsInBatch(); + break; + } +} + +async function addLockupsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_LOCKUP_DATA_CSV}): `, { + defaultInput: ADD_LOCKUP_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => !isNaN(row[0]) && + moment.unix(row[1]).isValid() && + (!isNaN(row[2] && (parseFloat(row[2]) % 1 === 0))) && + (!isNaN(row[3] && (parseFloat(row[3]) % 1 === 0))) && + typeof row[4] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [amountArray, startTimeArray, lockUpPeriodArray, releaseFrequencyArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add the following lockups: \n\n`, lockupNameArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.addNewLockUpTypeMulti(amountArray[batch], startTimeArray[batch], lockUpPeriodArray[batch], releaseFrequencyArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add multiple lockups transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function modifyLockupsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${MODIFY_LOCKUP_DATA_CSV}): `, { + defaultInput: MODIFY_LOCKUP_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => !isNaN(row[0]) && + moment.unix(row[1]).isValid() && + (!isNaN(row[2] && (parseFloat(row[2]) % 1 === 0))) && + (!isNaN(row[3] && (parseFloat(row[3]) % 1 === 0))) && + typeof row[4] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [amountArray, startTimeArray, lockUpPeriodArray, releaseFrequencyArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to modify the following lockups: \n\n`, lockupNameArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.modifyLockUpTypeMulti(amountArray[batch], startTimeArray[batch], lockUpPeriodArray[batch], releaseFrequencyArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Modify multiple lockups transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function deleteLockupsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${DELETE_LOCKUP_DATA_CSV}): `, { + defaultInput: DELETE_LOCKUP_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter(row => typeof row[0] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to delete the following lockups: \n\n`, lockupNameArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.removeLockupTypeMulti(lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Delete multiple lockups transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function addLockupsToInvestorsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${ADD_LOCKUP_INVESTOR_DATA_CSV}): `, { + defaultInput: ADD_LOCKUP_INVESTOR_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + typeof row[1] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to add lockups to the following investors: \n\n`, investorArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.addLockUpByNameMulti(investorArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Add lockups to multiple investors transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + +async function removeLockupsFromInvestorsInBatch() { + let csvFilePath = readlineSync.question(`Enter the path for csv data file (${REMOVE_LOCKUP_INVESTOR_DATA_CSV}): `, { + defaultInput: REMOVE_LOCKUP_INVESTOR_DATA_CSV + }); + let batchSize = readlineSync.question(`Enter the max number of records per transaction or batch size (${gbl.constants.DEFAULT_BATCH_SIZE}): `, { + limit: function (input) { + return parseInt(input) > 0; + }, + limitMessage: 'Must be greater than 0', + defaultInput: gbl.constants.DEFAULT_BATCH_SIZE + }); + let parsedData = csvParse(csvFilePath); + let validData = parsedData.filter( + row => web3.utils.isAddress(row[0]) && + typeof row[1] === 'string'); + let invalidRows = parsedData.filter(row => !validData.includes(row)); + if (invalidRows.length > 0) { + console.log(chalk.red(`The following lines from csv file are not valid: ${invalidRows.map(r => parsedData.indexOf(r) + 1).join(',')} `)); + } + let batches = common.splitIntoBatches(validData, batchSize); + let [investorArray, lockupNameArray] = common.transposeBatches(batches); + for (let batch = 0; batch < batches.length; batch++) { + console.log(`Batch ${batch + 1} - Attempting to remove the following investors: \n\n`, investorArray[batch], '\n'); + lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + let action = currentTransferManager.methods.removeLockUpFromUserMulti(investorArray[batch], lockupNameArray[batch]); + let receipt = await common.sendTransaction(action); + console.log(chalk.green('Remove lockups from multiple investors transaction was successful.')); + console.log(`${receipt.gasUsed} gas used.Spent: ${web3.utils.fromWei((new web3.utils.BN(receipt.gasUsed)).mul(new web3.utils.BN(defaultGasPrice)))} ETH`); + } +} + /* // Copied from tests function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, pk) { @@ -2291,7 +2694,7 @@ async function selectToken() { options.push('Enter token symbol manually'); let index = readlineSync.keyInSelect(options, 'Select a token:', { cancel: 'EXIT' }); - let selected = index !== -1 ? options[index] : 'EXIT'; + let selected = index != -1 ? options[index] : 'EXIT'; switch (selected) { case 'Enter token symbol manually': result = readlineSync.question('Enter the token symbol: '); @@ -2315,7 +2718,7 @@ async function logTotalInvestors() { async function logBalance(from, totalSupply) { let fromBalance = web3.utils.fromWei(await securityToken.methods.balanceOf(from).call()); let percentage = totalSupply != '0' ? ` - ${parseFloat(fromBalance) / parseFloat(totalSupply) * 100}% of total supply` : ''; - console.log(chalk.yellow(`Balance of ${from}: ${fromBalance} ${tokenSymbol}${percentage}`)); + console.log(chalk.yellow(`Balance of ${from}: ${fromBalance} ${tokenSymbol} ${percentage} `)); } module.exports = { diff --git a/CLI/data/Transfer/LockupTM/add_lockup_data.csv b/CLI/data/Transfer/LockupTM/add_lockup_data.csv new file mode 100644 index 000000000..f3d27ab2d --- /dev/null +++ b/CLI/data/Transfer/LockupTM/add_lockup_data.csv @@ -0,0 +1,4 @@ +1000,1560178800,600,1,"TenMinutes" +1000,1560621600,3600,60,"OneHour" +2000,1567252800,7200,3600,"TwoHours" +3000,1567303200,14400,4800,"4Hours" diff --git a/CLI/data/Transfer/LockupTM/add_lockup_investor_data.csv b/CLI/data/Transfer/LockupTM/add_lockup_investor_data.csv new file mode 100644 index 000000000..68c08a7d7 --- /dev/null +++ b/CLI/data/Transfer/LockupTM/add_lockup_investor_data.csv @@ -0,0 +1,12 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,"TenMinutes" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,"TenMinutes" +0xac297053173b02b02a737d47f7b4a718e5b170ef,"TenMinutes" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"TenMinutes" +0x10223927009b8add0960359dd90d1449415b7ca9,"TenMinutes" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"OneHour" +0x10223927009b8add0960359dd90d1449415b7ca9,"OneHour" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,"OneHour" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,"OneHour" +0x10223927009b8add0960359dd90d1449415b7ca9,"OneHour" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,"OneHour" +0x56be93088141b16ebaa9416122fd1d928da25ecf,"OneHour" \ No newline at end of file diff --git a/CLI/data/Transfer/LockupTM/delete_lockup_data.csv b/CLI/data/Transfer/LockupTM/delete_lockup_data.csv new file mode 100644 index 000000000..0d9203ffe --- /dev/null +++ b/CLI/data/Transfer/LockupTM/delete_lockup_data.csv @@ -0,0 +1,2 @@ +"TwoHours" +"4Hours" \ No newline at end of file diff --git a/CLI/data/Transfer/LockupTM/modify_lockup_data.csv b/CLI/data/Transfer/LockupTM/modify_lockup_data.csv new file mode 100644 index 000000000..2b520c4ff --- /dev/null +++ b/CLI/data/Transfer/LockupTM/modify_lockup_data.csv @@ -0,0 +1,4 @@ +1000,1560178800,600,10,"TenMinutes" +1000,1560623200,3600,60,"OneHour" +2000,1567252800,7200,3600,"TwoHours" +6000,1567303200,14400,4800,"4Hours" diff --git a/CLI/data/Transfer/LockupTM/remove_lockup_investor_data.csv b/CLI/data/Transfer/LockupTM/remove_lockup_investor_data.csv new file mode 100644 index 000000000..68c08a7d7 --- /dev/null +++ b/CLI/data/Transfer/LockupTM/remove_lockup_investor_data.csv @@ -0,0 +1,12 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1,"TenMinutes" +0x2f0fd672bf222413cc69dc1f4f1d7e93ad1763a1,"TenMinutes" +0xac297053173b02b02a737d47f7b4a718e5b170ef,"TenMinutes" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"TenMinutes" +0x10223927009b8add0960359dd90d1449415b7ca9,"TenMinutes" +0x49fc0b78238dab644698a90fa351b4c749e123d2,"OneHour" +0x10223927009b8add0960359dd90d1449415b7ca9,"OneHour" +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399,"OneHour" +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98,"OneHour" +0x10223927009b8add0960359dd90d1449415b7ca9,"OneHour" +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3,"OneHour" +0x56be93088141b16ebaa9416122fd1d928da25ecf,"OneHour" \ No newline at end of file diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol deleted file mode 100644 index 80f44cdb6..000000000 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ /dev/null @@ -1,411 +0,0 @@ -pragma solidity ^0.4.24; - -import "./../../TransferManager/ITransferManager.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - - -contract LockupVolumeRestrictionTM is ITransferManager { - - using SafeMath for uint256; - - // permission definition - bytes32 public constant ADMIN = "ADMIN"; - - // a per-user lockup - struct LockUp { - uint lockUpPeriodSeconds; // total period of lockup (seconds) - uint releaseFrequencySeconds; // how often to release a tranche of tokens (seconds) - uint startTime; // when this lockup starts (seconds) - uint totalAmount; // total amount of locked up tokens - uint alreadyWithdrawn; // amount already withdrawn for this lockup - } - - // maps user addresses to an array of lockups for that user - mapping (address => LockUp[]) internal lockUps; - - event AddNewLockUp( - address indexed userAddress, - uint lockUpPeriodSeconds, - uint releaseFrequencySeconds, - uint startTime, - uint totalAmount, - uint indexed addedIndex - ); - - event RemoveLockUp( - address indexed userAddress, - uint lockUpPeriodSeconds, - uint releaseFrequencySeconds, - uint startTime, - uint totalAmount, - uint indexed removedIndex - ); - - event ModifyLockUp( - address indexed userAddress, - uint lockUpPeriodSeconds, - uint releaseFrequencySeconds, - uint startTime, - uint totalAmount, - uint indexed modifiedIndex - ); - - /** - * @notice Constructor - * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken - */ - constructor (address _securityToken, address _polyAddress) - public - Module(_securityToken, _polyAddress) - { - } - - - /** @notice Used to verify the transfer transaction and prevent locked up tokens from being transferred - * @param _from Address of the sender - * @param _amount The amount of tokens to transfer - * @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable - */ - function verifyTransfer(address _from, address /* _to*/, uint256 _amount, bytes /* _data */, bool _isTransfer) public returns(Result) { - // only attempt to verify the transfer if the token is unpaused, this isn't a mint txn, and there exists a lockup for this user - if (!paused && _from != address(0) && lockUps[_from].length != 0) { - // check if this transfer is valid - return _checkIfValidTransfer(_from, _amount, _isTransfer); - } - return Result.NA; - } - - /** - * @notice Lets the admin create a volume restriction lockup for a given address. - * @param _userAddress Address of the user whose tokens should be locked up - * @param _lockUpPeriodSeconds Total period of lockup (seconds) - * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) - * @param _startTime When this lockup starts (seconds) - * @param _totalAmount Total amount of locked up tokens - */ - function addLockUp( - address _userAddress, - uint _lockUpPeriodSeconds, - uint _releaseFrequencySeconds, - uint _startTime, - uint _totalAmount - ) public withPerm(ADMIN) { - uint256 startTime = _startTime; - _checkLockUpParams(_lockUpPeriodSeconds, _releaseFrequencySeconds, _totalAmount); - - // if a startTime of 0 is passed in, then start now. - if (startTime == 0) { - /*solium-disable-next-line security/no-block-members*/ - startTime = now; - } - - lockUps[_userAddress].push(LockUp(_lockUpPeriodSeconds, _releaseFrequencySeconds, startTime, _totalAmount, 0)); - - emit AddNewLockUp( - _userAddress, - _lockUpPeriodSeconds, - _releaseFrequencySeconds, - startTime, - _totalAmount, - lockUps[_userAddress].length - 1 - ); - } - - /** - * @notice Lets the admin create multiple volume restriction lockups for multiple given addresses. - * @param _userAddresses Array of address of the user whose tokens should be locked up - * @param _lockUpPeriodsSeconds Array of total periods of lockup (seconds) - * @param _releaseFrequenciesSeconds Array of how often to release a tranche of tokens (seconds) - * @param _startTimes Array of When this lockup starts (seconds) - * @param _totalAmounts Array of total amount of locked up tokens - */ - function addLockUpMulti( - address[] _userAddresses, - uint[] _lockUpPeriodsSeconds, - uint[] _releaseFrequenciesSeconds, - uint[] _startTimes, - uint[] _totalAmounts - ) external withPerm(ADMIN) { - require( - _userAddresses.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ - _userAddresses.length == _startTimes.length && - _userAddresses.length == _totalAmounts.length, - "Input array length mismatch" - ); - - for (uint i = 0; i < _userAddresses.length; i++) { - addLockUp(_userAddresses[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i], _startTimes[i], _totalAmounts[i]); - } - - } - - /** - * @notice Lets the admin remove a user's lock up - * @param _userAddress Address of the user whose tokens are locked up - * @param _lockUpIndex The index of the LockUp to remove for the given userAddress - */ - function removeLockUp(address _userAddress, uint _lockUpIndex) public withPerm(ADMIN) { - LockUp[] storage userLockUps = lockUps[_userAddress]; - require(_lockUpIndex < userLockUps.length, "Array out of bounds exception"); - - LockUp memory toRemove = userLockUps[_lockUpIndex]; - - emit RemoveLockUp( - _userAddress, - toRemove.lockUpPeriodSeconds, - toRemove.releaseFrequencySeconds, - toRemove.startTime, - toRemove.totalAmount, - _lockUpIndex - ); - - if (_lockUpIndex < userLockUps.length - 1) { - // move the last element in the array into the index that is desired to be removed. - userLockUps[_lockUpIndex] = userLockUps[userLockUps.length - 1]; - } - // delete the last element - userLockUps.length--; - } - - /** - * @notice Lets the admin modify a volume restriction lockup for a given address. - * @param _userAddress Address of the user whose tokens should be locked up - * @param _lockUpIndex The index of the LockUp to edit for the given userAddress - * @param _lockUpPeriodSeconds Total period of lockup (seconds) - * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) - * @param _startTime When this lockup starts (seconds) - * @param _totalAmount Total amount of locked up tokens - */ - function modifyLockUp( - address _userAddress, - uint _lockUpIndex, - uint _lockUpPeriodSeconds, - uint _releaseFrequencySeconds, - uint _startTime, - uint _totalAmount - ) public withPerm(ADMIN) { - require(_lockUpIndex < lockUps[_userAddress].length, "Array out of bounds exception"); - - uint256 startTime = _startTime; - // if a startTime of 0 is passed in, then start now. - if (startTime == 0) { - /*solium-disable-next-line security/no-block-members*/ - startTime = now; - } - - _checkLockUpParams(_lockUpPeriodSeconds, _releaseFrequencySeconds, _totalAmount); - - // Get the lockup from the master list and edit it - lockUps[_userAddress][_lockUpIndex] = LockUp( - _lockUpPeriodSeconds, - _releaseFrequencySeconds, - startTime, - _totalAmount, - lockUps[_userAddress][_lockUpIndex].alreadyWithdrawn - ); - - emit ModifyLockUp( - _userAddress, - _lockUpPeriodSeconds, - _releaseFrequencySeconds, - startTime, - _totalAmount, - _lockUpIndex - ); - } - - /** - * @notice Get the length of the lockups array for a specific user address - * @param _userAddress Address of the user whose tokens should be locked up - */ - function getLockUpsLength(address _userAddress) public view returns (uint) { - return lockUps[_userAddress].length; - } - - /** - * @notice Get a specific element in a user's lockups array given the user's address and the element index - * @param _userAddress Address of the user whose tokens should be locked up - * @param _lockUpIndex The index of the LockUp to edit for the given userAddress - */ - function getLockUp( - address _userAddress, - uint _lockUpIndex) - public view returns ( - uint lockUpPeriodSeconds, - uint releaseFrequencySeconds, - uint startTime, - uint totalAmount, - uint alreadyWithdrawn - ) { - require(_lockUpIndex < lockUps[_userAddress].length, "Array out of bounds exception"); - LockUp storage userLockUp = lockUps[_userAddress][_lockUpIndex]; - return ( - userLockUp.lockUpPeriodSeconds, - userLockUp.releaseFrequencySeconds, - userLockUp.startTime, - userLockUp.totalAmount, - userLockUp.alreadyWithdrawn - ); - } - - /** - * @notice Takes a userAddress as input, and returns a uint that represents the number of tokens allowed to be withdrawn right now - * @param userAddress Address of the user whose lock ups should be checked - */ - function _checkIfValidTransfer(address userAddress, uint amount, bool isTransfer) internal returns (Result) { - // get lock up array for this user - LockUp[] storage userLockUps = lockUps[userAddress]; - - // maps the index of userLockUps to the amount allowed in this transfer - uint[] memory allowedAmountPerLockup = new uint[](userLockUps.length); - - uint[3] memory tokenSums = [ - uint256(0), // allowed amount right now - uint256(0), // total locked up, ever - uint256(0) // already withdrawn, ever - ]; - - // loop over the user's lock ups - for (uint i = 0; i < userLockUps.length; i++) { - LockUp storage aLockUp = userLockUps[i]; - - uint allowedAmountForThisLockup = 0; - - // check if lockup has entirely passed - /*solium-disable-next-line security/no-block-members*/ - if (now >= aLockUp.startTime.add(aLockUp.lockUpPeriodSeconds)) { - // lockup has passed, or not started yet. allow all. - allowedAmountForThisLockup = aLockUp.totalAmount.sub(aLockUp.alreadyWithdrawn); - /*solium-disable-next-line security/no-block-members*/ - } else if (now >= aLockUp.startTime) { - // lockup is active. calculate how many to allow to be withdrawn right now - // calculate how many periods have elapsed already - /*solium-disable-next-line security/no-block-members*/ - uint elapsedPeriods = (now.sub(aLockUp.startTime)).div(aLockUp.releaseFrequencySeconds); - // calculate the total number of periods, overall - uint totalPeriods = aLockUp.lockUpPeriodSeconds.div(aLockUp.releaseFrequencySeconds); - // calculate how much should be released per period - uint amountPerPeriod = aLockUp.totalAmount.div(totalPeriods); - // calculate the number of tokens that should be released, - // multiplied by the number of periods that have elapsed already - // and add it to the total tokenSums[0] - allowedAmountForThisLockup = amountPerPeriod.mul(elapsedPeriods).sub(aLockUp.alreadyWithdrawn); - - } - // tokenSums[0] is allowed sum - tokenSums[0] = tokenSums[0].add(allowedAmountForThisLockup); - // tokenSums[1] is total locked up - tokenSums[1] = tokenSums[1].add(aLockUp.totalAmount); - // tokenSums[2] is total already withdrawn - tokenSums[2] = tokenSums[2].add(aLockUp.alreadyWithdrawn); - - allowedAmountPerLockup[i] = allowedAmountForThisLockup; - } - - // tokenSums[0] is allowed sum - if (amount <= tokenSums[0]) { - // transfer is valid and will succeed. - if (!isTransfer) { - // if this isn't a real transfer, don't subtract the withdrawn amounts from the lockups. it's a "read only" txn - return Result.VALID; - } - - // we are going to write the withdrawn balances back to the lockups, so make sure that the person calling this function is the securityToken itself, since its public - require(msg.sender == securityToken, "Sender is not securityToken"); - - // subtract amounts so they are now known to be withdrawen - for (i = 0; i < userLockUps.length; i++) { - aLockUp = userLockUps[i]; - - // tokenSums[0] is allowed sum - if (allowedAmountPerLockup[i] >= tokenSums[0]) { - aLockUp.alreadyWithdrawn = aLockUp.alreadyWithdrawn.add(tokenSums[0]); - // we withdrew the entire tokenSums[0] from the lockup. We are done. - break; - } else { - // we have to split the tokenSums[0] across mutiple lockUps - aLockUp.alreadyWithdrawn = aLockUp.alreadyWithdrawn.add(allowedAmountPerLockup[i]); - // subtract the amount withdrawn from this lockup - tokenSums[0] = tokenSums[0].sub(allowedAmountPerLockup[i]); - } - - } - return Result.VALID; - } - - return _checkIfUnlockedTokenTransferIsPossible(userAddress, amount, tokenSums[1], tokenSums[2]); - } - - function _checkIfUnlockedTokenTransferIsPossible( - address userAddress, - uint amount, - uint totalSum, - uint alreadyWithdrawnSum - ) internal view returns (Result) { - // the amount the user wants to withdraw is greater than their allowed amounts according to the lockups. however, if the user has like, 10 tokens, but only 4 are locked up, we should let the transfer go through for those 6 that aren't locked up - uint currentUserBalance = ISecurityToken(securityToken).balanceOf(userAddress); - uint stillLockedAmount = totalSum.sub(alreadyWithdrawnSum); - if (currentUserBalance >= stillLockedAmount && amount <= currentUserBalance.sub(stillLockedAmount)) { - // the user has more tokens in their balance than are actually locked up. they should be allowed to withdraw the difference - return Result.VALID; - } - return Result.INVALID; - } - - - /** - * @notice Parameter checking function for creating or editing a lockup. This function will cause an exception if any of the parameters are bad. - * @param lockUpPeriodSeconds Total period of lockup (seconds) - * @param releaseFrequencySeconds How often to release a tranche of tokens (seconds) - * @param totalAmount Total amount of locked up tokens - */ - function _checkLockUpParams(uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint totalAmount) internal view { - require(lockUpPeriodSeconds != 0, "lockUpPeriodSeconds cannot be zero"); - require(releaseFrequencySeconds != 0, "releaseFrequencySeconds cannot be zero"); - require(totalAmount != 0, "totalAmount cannot be zero"); - - // check that the total amount to be released isn't too granular - require( - totalAmount % ISecurityToken(securityToken).granularity() == 0, - "The total amount to be released is more granular than allowed by the token" - ); - - // check that releaseFrequencySeconds evenly divides lockUpPeriodSeconds - require( - lockUpPeriodSeconds % releaseFrequencySeconds == 0, - "lockUpPeriodSeconds must be evenly divisible by releaseFrequencySeconds" - ); - - // check that totalPeriods evenly divides totalAmount - uint totalPeriods = lockUpPeriodSeconds.div(releaseFrequencySeconds); - require( - totalAmount % totalPeriods == 0, - "The total amount being locked up must be evenly divisible by the number of total periods" - ); - - // make sure the amount to be released per period is not too granular for the token - uint amountPerPeriod = totalAmount.div(totalPeriods); - require( - amountPerPeriod % ISecurityToken(securityToken).granularity() == 0, - "The amount to be released per period is more granular than allowed by the token" - ); - } - - /** - * @notice This function returns the signature of configure function - */ - function getInitFunction() public pure returns (bytes4) { - return bytes4(0); - } - - /** - * @notice Returns the permissions flag that are associated with Percentage transfer Manager - */ - function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](1); - allPermissions[0] = ADMIN; - return allPermissions; - } -} diff --git a/contracts/modules/TransferManager/LockUpTransferManager.sol b/contracts/modules/TransferManager/LockUpTransferManager.sol new file mode 100644 index 000000000..993bbd5bb --- /dev/null +++ b/contracts/modules/TransferManager/LockUpTransferManager.sol @@ -0,0 +1,636 @@ +pragma solidity ^0.4.24; + +import "./ITransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +contract LockUpTransferManager is ITransferManager { + + using SafeMath for uint256; + + // permission definition + bytes32 public constant ADMIN = "ADMIN"; + + // a per-user lockup + struct LockUp { + uint256 lockupAmount; // Amount to be locked + uint256 startTime; // when this lockup starts (seconds) + uint256 lockUpPeriodSeconds; // total period of lockup (seconds) + uint256 releaseFrequencySeconds; // how often to release a tranche of tokens (seconds) + } + + // mapping use to store the lockup details corresponds to lockup name + mapping (bytes32 => LockUp) public lockups; + // mapping user addresses to an array of lockups name for that user + mapping (address => bytes32[]) internal userToLockups; + // get list of the addresses for a particular lockupName + mapping (bytes32 => address[]) internal lockupToUsers; + // holds lockup index corresponds to user address. userAddress => lockupName => lockupIndex + mapping (address => mapping(bytes32 => uint256)) internal userToLockupIndex; + // holds the user address index corresponds to the lockup. lockupName => userAddress => userIndex + mapping (bytes32 => mapping(address => uint256)) internal lockupToUserIndex; + + bytes32[] lockupArray; + + event AddLockUpToUser( + address indexed _userAddress, + bytes32 indexed _lockupName + ); + + event RemoveLockUpFromUser( + address indexed _userAddress, + bytes32 indexed _lockupName + ); + + event ModifyLockUpType( + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 indexed _lockupName + ); + + event AddNewLockUpType( + bytes32 indexed _lockupName, + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds + ); + + event RemoveLockUpType(bytes32 indexed _lockupName); + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { + } + + /** @notice Used to verify the transfer transaction and prevent locked up tokens from being transferred + * @param _from Address of the sender + * @param _amount The amount of tokens to transfer + */ + function verifyTransfer(address _from, address /* _to*/, uint256 _amount, bytes /* _data */, bool /*_isTransfer*/) public returns(Result) { + // only attempt to verify the transfer if the token is unpaused, this isn't a mint txn, and there exists a lockup for this user + if (!paused && _from != address(0) && userToLockups[_from].length != 0) { + // check if this transfer is valid + return _checkIfValidTransfer(_from, _amount); + } + return Result.NA; + } + + /** + * @notice Use to add the new lockup type + * @param _lockupAmount Amount of tokens that need to lock. + * @param _startTime When this lockup starts (seconds) + * @param _lockUpPeriodSeconds Total period of lockup (seconds) + * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) + * @param _lockupName Name of the lockup + */ + function addNewLockUpType( + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + public + withPerm(ADMIN) + { + _addNewLockUpType( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + } + + /** + * @notice Use to add the new lockup type + * @param _lockupAmounts Array of amount of tokens that need to lock. + * @param _startTimes Array of startTimes when this lockup starts (seconds) + * @param _lockUpPeriodsSeconds Array of total period of lockup (seconds) + * @param _releaseFrequenciesSeconds Array of how often to release a tranche of tokens (seconds) + * @param _lockupNames Array of names of the lockup + */ + function addNewLockUpTypeMulti( + uint256[] _lockupAmounts, + uint256[] _startTimes, + uint256[] _lockUpPeriodsSeconds, + uint256[] _releaseFrequenciesSeconds, + bytes32[] _lockupNames + ) + external + withPerm(ADMIN) + { + require( + _lockupNames.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _lockupAmounts.length, + "Input array length mismatch" + ); + for (uint256 i = 0; i < _lockupNames.length; i++) { + _addNewLockUpType( + _lockupAmounts[i], + _startTimes[i], + _lockUpPeriodsSeconds[i], + _releaseFrequenciesSeconds[i], + _lockupNames[i] + ); + } + } + + /** + * @notice Add the lockup to a user + * @param _userAddress Address of the user + * @param _lockupName Name of the lockup + */ + function addLockUpByName( + address _userAddress, + bytes32 _lockupName + ) + public + withPerm(ADMIN) + { + _addLockUpByName(_userAddress, _lockupName); + } + + /** + * @notice Add the lockup to a user + * @param _userAddresses Address of the user + * @param _lockupNames Name of the lockup + */ + function addLockUpByNameMulti( + address[] _userAddresses, + bytes32[] _lockupNames + ) + external + withPerm(ADMIN) + { + require(_userAddresses.length == _lockupNames.length, "Length mismatch"); + for (uint256 i = 0; i < _userAddresses.length; i++) { + _addLockUpByName(_userAddresses[i], _lockupNames[i]); + } + } + + /** + * @notice Lets the admin create a volume restriction lockup for a given address. + * @param _userAddress Address of the user whose tokens should be locked up + * @param _lockupAmount Amount of tokens that need to lock. + * @param _startTime When this lockup starts (seconds) + * @param _lockUpPeriodSeconds Total period of lockup (seconds) + * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) + * @param _lockupName Name of the lockup + */ + function addNewLockUpToUser( + address _userAddress, + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + external + withPerm(ADMIN) + { + _addNewLockUpToUser( + _userAddress, + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + } + + /** + * @notice Lets the admin create multiple volume restriction lockups for multiple given addresses. + * @param _userAddresses Array of address of the user whose tokens should be locked up + * @param _lockupAmounts Array of the amounts that need to be locked for the different addresses. + * @param _startTimes Array of When this lockup starts (seconds) + * @param _lockUpPeriodsSeconds Array of total periods of lockup (seconds) + * @param _releaseFrequenciesSeconds Array of how often to release a tranche of tokens (seconds) + * @param _lockupNames Array of names of the lockup + */ + function addNewLockUpToUserMulti( + address[] _userAddresses, + uint256[] _lockupAmounts, + uint256[] _startTimes, + uint256[] _lockUpPeriodsSeconds, + uint256[] _releaseFrequenciesSeconds, + bytes32[] _lockupNames + ) + public + withPerm(ADMIN) + { + require( + _userAddresses.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ + _userAddresses.length == _lockupAmounts.length && + _userAddresses.length == _lockupNames.length, + "Input array length mismatch" + ); + for (uint256 i = 0; i < _userAddresses.length; i++) { + _addNewLockUpToUser(_userAddresses[i], _lockupAmounts[i], _startTimes[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i], _lockupNames[i]); + } + } + + /** + * @notice Lets the admin remove a user's lock up + * @param _userAddress Address of the user whose tokens are locked up + * @param _lockupName Name of the lockup need to be removed. + */ + function removeLockUpFromUser(address _userAddress, bytes32 _lockupName) external withPerm(ADMIN) { + _removeLockUpFromUser(_userAddress, _lockupName); + } + + /** + * @notice Used to remove the lockup type + * @param _lockupName Name of the lockup + */ + function removeLockupType(bytes32 _lockupName) external withPerm(ADMIN) { + _removeLockupType(_lockupName); + } + + /** + * @notice Used to remove the multiple lockup type + * @param _lockupNames Array of the lockup names. + */ + function removeLockupTypeMulti(bytes32[] _lockupNames) external withPerm(ADMIN) { + for (uint256 i = 0; i < _lockupNames.length; i++) { + _removeLockupType(_lockupNames[i]); + } + } + + /** + * @notice Use to remove the lockup for multiple users + * @param _userAddresses Array of addresses of the user whose tokens are locked up + * @param _lockupNames Array of the names of the lockup that needs to be removed. + */ + function removeLockUpFromUserMulti(address[] _userAddresses, bytes32[] _lockupNames) external withPerm(ADMIN) { + require(_userAddresses.length == _lockupNames.length, "Array length mismatch"); + for (uint256 i = 0; i < _userAddresses.length; i++) { + _removeLockUpFromUser(_userAddresses[i], _lockupNames[i]); + } + } + + /** + * @notice Lets the admin modify a lockup. + * @param _lockupAmount Amount of tokens that needs to be locked + * @param _startTime When this lockup starts (seconds) + * @param _lockUpPeriodSeconds Total period of lockup (seconds) + * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) + * @param _lockupName name of the lockup that needs to be modified. + */ + function modifyLockUpType( + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + external + withPerm(ADMIN) + { + _modifyLockUpType( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + } + + /** + * @notice Lets the admin modify a volume restriction lockup for a multiple address. + * @param _lockupAmounts Array of the amount of tokens that needs to be locked for the respective addresses. + * @param _startTimes Array of the start time of the lockups (seconds) + * @param _lockUpPeriodsSeconds Array of unix timestamp for the list of lockups (seconds). + * @param _releaseFrequenciesSeconds How often to release a tranche of tokens (seconds) + * @param _lockupNames Array of the lockup names that needs to be modified + */ + function modifyLockUpTypeMulti( + uint256[] _lockupAmounts, + uint256[] _startTimes, + uint256[] _lockUpPeriodsSeconds, + uint256[] _releaseFrequenciesSeconds, + bytes32[] _lockupNames + ) + public + withPerm(ADMIN) + { + require( + _lockupNames.length == _lockUpPeriodsSeconds.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _releaseFrequenciesSeconds.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ + _lockupNames.length == _lockupAmounts.length, + "Input array length mismatch" + ); + for (uint256 i = 0; i < _lockupNames.length; i++) { + _modifyLockUpType( + _lockupAmounts[i], + _startTimes[i], + _lockUpPeriodsSeconds[i], + _releaseFrequenciesSeconds[i], + _lockupNames[i] + ); + } + } + + /** + * @notice Get a specific element in a user's lockups array given the user's address and the element index + * @param _lockupName The name of the lockup + */ + function getLockUp(bytes32 _lockupName) external view returns ( + uint256 lockupAmount, + uint256 startTime, + uint256 lockUpPeriodSeconds, + uint256 releaseFrequencySeconds, + uint256 unlockedAmount + ) { + if (lockups[_lockupName].lockupAmount != 0) { + return ( + lockups[_lockupName].lockupAmount, + lockups[_lockupName].startTime, + lockups[_lockupName].lockUpPeriodSeconds, + lockups[_lockupName].releaseFrequencySeconds, + _getUnlockedAmountForLockup(_lockupName) + ); + } + return (uint256(0), uint256(0), uint256(0), uint256(0), uint256(0)); + } + + /** + * @notice get the list of the users of a lockup type + * @param _lockupName Name of the lockup type + * @return address List of users associated with the blacklist + */ + function getListOfAddresses(bytes32 _lockupName) external view returns(address[]) { + require(lockups[_lockupName].startTime != 0, "Blacklist type doesn't exist"); + return lockupToUsers[_lockupName]; + } + + /** + * @notice get the list of lockups names + * @return bytes32 Array of lockups names + */ + function getAllLockups() external view returns(bytes32[]) { + return lockupArray; + } + + /** + * @notice get the list of the lockups for a given user + * @param _user Address of the user + * @return bytes32 List of lockups names associated with the given address + */ + function getLockupsNamesToUser(address _user) external view returns(bytes32[]) { + return userToLockups[_user]; + } + + /** + * @notice Use to get the total locked tokens for a given user + * @param _userAddress Address of the user + * @return uint256 Total locked tokens amount + */ + function getLockedTokenToUser(address _userAddress) public view returns(uint256) { + require(_userAddress != address(0), "Invalid address"); + bytes32[] memory userLockupNames = userToLockups[_userAddress]; + uint256 totalRemainingLockedAmount = 0; + + for (uint256 i = 0; i < userLockupNames.length; i++) { + // Find out the remaining locked amount for a given lockup + uint256 remainingLockedAmount = lockups[userLockupNames[i]].lockupAmount.sub(_getUnlockedAmountForLockup(userLockupNames[i])); + // aggregating all the remaining locked amount for all the lockups for a given address + totalRemainingLockedAmount = totalRemainingLockedAmount.add(remainingLockedAmount); + } + return totalRemainingLockedAmount; + } + + /** + * @notice Checks whether the transfer is allowed + * @param _userAddress Address of the user whose lock ups should be checked + * @param _amount Amount of tokens that need to transact + */ + function _checkIfValidTransfer(address _userAddress, uint256 _amount) internal view returns (Result) { + uint256 totalRemainingLockedAmount = getLockedTokenToUser(_userAddress); + // Present balance of the user + uint256 currentBalance = ISecurityToken(securityToken).balanceOf(_userAddress); + if ((currentBalance.sub(_amount)) >= totalRemainingLockedAmount) { + return Result.NA; + } + return Result.INVALID; + } + + /** + * @notice Provide the unlock amount for the given lockup for a particular user + */ + function _getUnlockedAmountForLockup(bytes32 _lockupName) internal view returns (uint256) { + /*solium-disable-next-line security/no-block-members*/ + if (lockups[_lockupName].startTime > now) { + return 0; + } else if (lockups[_lockupName].startTime.add(lockups[_lockupName].lockUpPeriodSeconds) <= now) { + return lockups[_lockupName].lockupAmount; + } else { + // Calculate the no. of periods for a lockup + uint256 noOfPeriods = (lockups[_lockupName].lockUpPeriodSeconds).div(lockups[_lockupName].releaseFrequencySeconds); + // Calculate the transaction time lies in which period + /*solium-disable-next-line security/no-block-members*/ + uint256 elapsedPeriod = (now.sub(lockups[_lockupName].startTime)).div(lockups[_lockupName].releaseFrequencySeconds); + // Find out the unlocked amount for a given lockup + uint256 unLockedAmount = (lockups[_lockupName].lockupAmount.mul(elapsedPeriod)).div(noOfPeriods); + return unLockedAmount; + } + } + + function _removeLockupType(bytes32 _lockupName) internal { + require(lockups[_lockupName].startTime != 0, "Lockup type doesn’t exist"); + require(lockupToUsers[_lockupName].length == 0, "Users are associated with the lockup"); + // delete lockup type + delete(lockups[_lockupName]); + uint256 i = 0; + for (i = 0; i < lockupArray.length; i++) { + if (lockupArray[i] == _lockupName) { + break; + } + } + if (i != lockupArray.length -1) { + lockupArray[i] = lockupArray[lockupArray.length -1]; + } + lockupArray.length--; + emit RemoveLockUpType(_lockupName); + } + + function _modifyLockUpType( + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + internal + { + /*solium-disable-next-line security/no-block-members*/ + uint256 startTime = _startTime; + + if (_startTime == 0) { + startTime = now; + } + require(startTime >= now, "Invalid start time"); + require(lockups[_lockupName].lockupAmount != 0, "Doesn't exist"); + + _checkLockUpParams( + _lockupAmount, + _lockUpPeriodSeconds, + _releaseFrequencySeconds + ); + + lockups[_lockupName] = LockUp( + _lockupAmount, + startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds + ); + + emit ModifyLockUpType( + _lockupAmount, + startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + } + + function _removeLockUpFromUser(address _userAddress, bytes32 _lockupName) internal { + require(_userAddress != address(0), "Invalid address"); + require(_lockupName != bytes32(0), "Invalid lockup name"); + require( + userToLockups[_userAddress][userToLockupIndex[_userAddress][_lockupName]] == _lockupName, + "User not assosicated with given lockup" + ); + + // delete the user from the lockup type + uint256 _lockupIndex = lockupToUserIndex[_lockupName][_userAddress]; + uint256 _len = lockupToUsers[_lockupName].length; + if ( _lockupIndex != _len) { + lockupToUsers[_lockupName][_lockupIndex] = lockupToUsers[_lockupName][_len - 1]; + lockupToUserIndex[_lockupName][lockupToUsers[_lockupName][_lockupIndex]] = _lockupIndex; + } + lockupToUsers[_lockupName].length--; + // delete the user index from the lockup + delete(lockupToUserIndex[_lockupName][_userAddress]); + // delete the lockup from the user + uint256 _userIndex = userToLockupIndex[_userAddress][_lockupName]; + _len = userToLockups[_userAddress].length; + if ( _userIndex != _len) { + userToLockups[_userAddress][_userIndex] = userToLockups[_userAddress][_len - 1]; + userToLockupIndex[_userAddress][userToLockups[_userAddress][_userIndex]] = _userIndex; + } + userToLockups[_userAddress].length--; + // delete the lockup index from the user + delete(userToLockupIndex[_userAddress][_lockupName]); + emit RemoveLockUpFromUser(_userAddress, _lockupName); + } + + function _addNewLockUpToUser( + address _userAddress, + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + internal + { + require(_userAddress != address(0), "Invalid address"); + _addNewLockUpType( + _lockupAmount, + _startTime, + _lockUpPeriodSeconds, + _releaseFrequencySeconds, + _lockupName + ); + _addLockUpByName(_userAddress, _lockupName); + } + + function _addLockUpByName( + address _userAddress, + bytes32 _lockupName + ) + internal + { + require(_userAddress != address(0), "Invalid address"); + require(lockups[_lockupName].startTime >= now, "Lockup expired"); + + userToLockupIndex[_userAddress][_lockupName] = userToLockups[_userAddress].length; + lockupToUserIndex[_lockupName][_userAddress] = lockupToUsers[_lockupName].length; + userToLockups[_userAddress].push(_lockupName); + lockupToUsers[_lockupName].push(_userAddress); + emit AddLockUpToUser(_userAddress, _lockupName); + } + + function _addNewLockUpType( + uint256 _lockupAmount, + uint256 _startTime, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds, + bytes32 _lockupName + ) + internal + { + uint256 startTime = _startTime; + require(_lockupName != bytes32(0), "Invalid name"); + require(lockups[_lockupName].lockupAmount == 0, "Already exist"); + /*solium-disable-next-line security/no-block-members*/ + if (_startTime == 0) { + startTime = now; + } + require(startTime >= now, "Invalid start time"); + _checkLockUpParams(_lockupAmount, _lockUpPeriodSeconds, _releaseFrequencySeconds); + lockups[_lockupName] = LockUp(_lockupAmount, startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds); + lockupArray.push(_lockupName); + emit AddNewLockUpType(_lockupName, _lockupAmount, startTime, _lockUpPeriodSeconds, _releaseFrequencySeconds); + } + + /** + * @notice Parameter checking function for creating or editing a lockup. + * This function will cause an exception if any of the parameters are bad. + * @param _lockupAmount Amount that needs to be locked + * @param _lockUpPeriodSeconds Total period of lockup (seconds) + * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds) + */ + function _checkLockUpParams( + uint256 _lockupAmount, + uint256 _lockUpPeriodSeconds, + uint256 _releaseFrequencySeconds + ) + internal + pure + { + require(_lockUpPeriodSeconds != 0, "lockUpPeriodSeconds cannot be zero"); + require(_releaseFrequencySeconds != 0, "releaseFrequencySeconds cannot be zero"); + require(_lockupAmount != 0, "lockupAmount cannot be zero"); + } + + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(0); + } + + /** + * @notice Returns the permissions flag that are associated with Percentage transfer Manager + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; + } +} diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol b/contracts/modules/TransferManager/LockUpTransferManagerFactory.sol similarity index 74% rename from contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol rename to contracts/modules/TransferManager/LockUpTransferManagerFactory.sol index 73bd753f1..3f5e7b31a 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol +++ b/contracts/modules/TransferManager/LockUpTransferManagerFactory.sol @@ -1,12 +1,12 @@ pragma solidity ^0.4.24; -import "./../../ModuleFactory.sol"; -import "./LockupVolumeRestrictionTM.sol"; +import "../ModuleFactory.sol"; +import "./LockUpTransferManager.sol"; /** - * @title Factory for deploying ManualApprovalTransferManager module + * @title Factory for deploying LockUpTransferManager module */ -contract LockupVolumeRestrictionTMFactory is ModuleFactory { +contract LockUpTransferManagerFactory is ModuleFactory { /** * @notice Constructor @@ -19,8 +19,8 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; - name = "LockupVolumeRestrictionTM"; - title = "Lockup Volume Restriction Transfer Manager"; + name = "LockUpTransferManager"; + title = "LockUp Transfer Manager"; description = "Manage transfers using lock ups over time"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); @@ -33,10 +33,10 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - LockupVolumeRestrictionTM lockupVolumeRestrictionTransferManager = new LockupVolumeRestrictionTM(msg.sender, address(polyToken)); + LockUpTransferManager lockUpTransferManager = new LockUpTransferManager(msg.sender, address(polyToken)); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(lockupVolumeRestrictionTransferManager), getName(), address(this), msg.sender, setupCost, now); - return address(lockupVolumeRestrictionTransferManager); + emit GenerateModuleFromFactory(address(lockUpTransferManager), getName(), address(this), msg.sender, setupCost, now); + return address(lockUpTransferManager); } /** @@ -61,7 +61,7 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { */ function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](2); - availableTags[0] = "Volume"; + availableTags[0] = "LockUp"; availableTags[1] = "Transfer Restriction"; return availableTags; } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index a89be3b90..e9cdee650 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -9,6 +9,7 @@ const EtherDividendCheckpointLogic = artifacts.require('./EtherDividendCheckpoin const ERC20DividendCheckpointLogic = artifacts.require('./ERC20DividendCheckpoint.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') +const LockUpTransferManagerFactory = artifacts.require('./LockUpTransferManagerFactory.sol') const BlacklistTransferManagerFactory = artifacts.require('./BlacklistTransferManagerFactory.sol') const VestingEscrowWalletFactory = artifacts.require('./VestingEscrowWalletFactory.sol'); const VestingEscrowWalletLogic = artifacts.require('./VestingEscrowWallet.sol'); @@ -186,6 +187,10 @@ module.exports = function (deployer, network, accounts) { // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this // manager attach with the securityToken contract at the time of deployment) return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, GeneralTransferManagerLogic.address, { from: PolymathAccount }); + }).then(() => { + // C) Deploy the LockUpTransferManagerFactory Contract (Factory used to generate the LockUpTransferManager contract and + // this manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(LockUpTransferManagerFactory, PolyToken, 0, 0, 0, { from: PolymathAccount }); }).then(() => { // C) Deploy the GeneralPermissionManagerFactory Contract (Factory used to generate the GeneralPermissionManager contract and // this manager attach with the securityToken contract at the time of deployment) @@ -197,7 +202,7 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // D) Deploy the BlacklistTransferManagerFactory Contract (Factory used to generate the BlacklistTransferManager contract use // to to automate blacklist and restrict transfers) - return deployer.deploy(BlacklistTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(BlacklistTransferManagerFactory, PolyToken, 0, 0, 0, { from: PolymathAccount }); }).then(() => { // D) Deploy the PercentageTransferManagerFactory Contract (Factory used to generate the PercentageTransferManager contract use // to track the percentage of investment the investors could do for a particular security token) @@ -241,6 +246,10 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // Update all addresses into the registry contract by calling the function updateFromregistry return moduleRegistry.updateFromRegistry({ from: PolymathAccount }); + }).then(() => { + // D) Register the LockUpTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the LockUpTransferManager contract. + return moduleRegistry.registerModule(LockUpTransferManagerFactory.address, { from: PolymathAccount }); }).then(() => { // D) Register the PercentageTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the PercentageTransferManager contract. @@ -260,7 +269,7 @@ module.exports = function (deployer, network, accounts) { }).then(() => { // D) Register the BlacklistTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the GeneralTransferManager contract. - return moduleRegistry.registerModule(BlacklistTransferManagerFactory.address, {from: PolymathAccount}); + return moduleRegistry.registerModule(BlacklistTransferManagerFactory.address, { from: PolymathAccount }); }).then(() => { // E) Register the GeneralPermissionManagerFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the GeneralPermissionManager contract. @@ -290,12 +299,17 @@ module.exports = function (deployer, network, accounts) { // G) Once the BlacklistTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(BlacklistTransferManagerFactory.address, true, {from: PolymathAccount}); + return moduleRegistry.verifyModule(BlacklistTransferManagerFactory.address, true, { from: PolymathAccount }); }).then(() => { // G) Once the CountTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(CountTransferManagerFactory.address, true, { from: PolymathAccount }); + }).then(() => { + // F) Once the LockUpTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(LockUpTransferManagerFactory.address, true, { from: PolymathAccount }); }).then(() => { // G) Once the PercentageTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. @@ -389,6 +403,7 @@ module.exports = function (deployer, network, accounts) { ERC20DividendCheckpointLogic: ${ERC20DividendCheckpointLogic.address} EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} + LockUpTransferManagerFactory: ${LockUpTransferManagerFactory.address} BlacklistTransferManagerFactory: ${BlacklistTransferManagerFactory.address} VolumeRestrictionTMFactory: ${VolumeRestrictionTMFactory.address} VolumeRestrictionTMLogic: ${VolumeRestrictionTMLogic.address} diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index d204f7237..4335e52b3 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -26,7 +26,7 @@ const GeneralTransferManager = artifacts.require("./GeneralTransferManager.sol") const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); -const VolumeRestrictionTransferManagerFactory = artifacts.require("./LockupVolumeRestrictionTMFactory"); +const LockUpTransferManagerFactory = artifacts.require("./LockUpTransferManagerFactory"); const PreSaleSTOFactory = artifacts.require("./PreSaleSTOFactory.sol"); const PolyToken = artifacts.require("./PolyToken.sol"); const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); @@ -301,11 +301,11 @@ export async function deployBlacklistTMAndVerified(accountPolymath, MRProxyInsta } export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + I_VolumeRestrictionTransferManagerFactory = await LockUpTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_VolumeRestrictionTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", - "VolumeRestrictionTransferManagerFactory contract was not deployed" + "LockUpTransferManagerFactory contract was not deployed" ); await registerAndVerifyByMR(I_VolumeRestrictionTransferManagerFactory.address, accountPolymath, MRProxyInstance); diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js new file mode 100644 index 000000000..27924eb20 --- /dev/null +++ b/test/w_lockup_transfer_manager.js @@ -0,0 +1,995 @@ +import latestTime from './helpers/latestTime'; +import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; +import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall } from './helpers/encodeCall'; +import { setUpPolymathNetwork, deployLockupVolumeRTMAndVerified } from "./helpers/createInstances"; +import { catchRevert } from "./helpers/exceptions"; + +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); +const LockUpTransferManager = artifacts.require('./LockUpTransferManager'); +const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract('LockUpTransferManager', accounts => { + + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let P_LockUpTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let P_LockUpTransferManager; + let I_GeneralTransferManagerFactory; + let I_LockUpTransferManagerFactory; + let I_GeneralPermissionManager; + let I_LockUpTransferManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_MRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + let I_SecurityToken_div; + let I_GeneralTransferManager_div; + let I_LockUpVolumeRestrictionTM_div; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + const name2 = "Core"; + const symbol2 = "Core"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + let temp; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + before(async() => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + + account_investor1 = accounts[7]; + account_investor2 = accounts[8]; + account_investor3 = accounts[9]; + + let instances = await setUpPolymathNetwork(account_polymath, token_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; + + // STEP 4(c): Deploy the LockUpVolumeRestrictionTMFactory + [I_LockUpTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 4(d): Deploy the LockUpVolumeRestrictionTMFactory + [P_LockUpTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${I_PolymathRegistry.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistry: ${I_ModuleRegistry.address} + ModuleRegistryProxy: ${I_ModuleRegistryProxy.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + STFactory: ${I_STFactory.address} + GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + + LockupVolumeRestrictionTransferManagerFactory: + ${I_LockUpTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async() => { + + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + + + it("Should register another ticker before the generation of new security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol2, contact, { from : token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol2.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails, true, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol2.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken_div = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken_div.ModuleAdded({from: _blockNo}), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal( + web3.utils.toAscii(log.args._name) + .replace(/\u0000/g, ''), + "GeneralTransferManager" + ); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken_div.getModulesByType(2))[0]; + I_GeneralTransferManager_div = GeneralTransferManager.at(moduleData); + }); + + + }); + + describe("Buy tokens using on-chain whitelist and test locking them up and attempting to transfer", async() => { + + it("Should Buy the tokens from non-divisible", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should Buy the tokens from the divisible token", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager_div.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken_div.mint(account_investor1, web3.utils.toWei('2', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken_div.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('2', 'ether') + ); + }); + + it("Should Buy some more tokens from non-divisible tokens", async() => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('10', 'ether') + ); + }); + + it("Should unsuccessfully attach the LockUpTransferManager factory with the security token -- failed because Token is not paid", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await catchRevert( + I_SecurityToken.addModule(P_LockUpTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) + ) + }); + + it("Should successfully attach the LockUpTransferManager factory with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_LockUpTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name) + .replace(/\u0000/g, ''), + "LockUpTransferManager", + "LockUpTransferManager module was not added" + ); + P_LockUpTransferManager = LockUpTransferManager.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + + it("Should successfully attach the LockUpVolumeRestrictionTMFactory with the non-divisible security token", async () => { + const tx = await I_SecurityToken.addModule(I_LockUpTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "LockUpTransferManager", + "LockUpTransferManager module was not added" + ); + I_LockUpTransferManager = LockUpTransferManager.at(tx.logs[2].args._module); + }); + + it("Should successfully attach the LockUpVolumeRestrictionTMFactory with the divisible security token", async () => { + const tx = await I_SecurityToken_div.addModule(I_LockUpTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "LockUpTransferManager", + "LockUpTransferManager module was not added" + ); + I_LockUpVolumeRestrictionTM_div = LockUpTransferManager.at(tx.logs[2].args._module); + }); + + it("Add a new token holder", async() => { + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer + }); + + assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); + + // Add the Investor in to the whitelist + // Mint some tokens + await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('10', 'ether') + ); + }); + + it("Should pause the tranfers at transferManager level", async() => { + let tx = await I_LockUpTransferManager.pause({from: token_owner}); + }); + + it("Should still be able to transfer between existing token holders up to limit", async() => { + // Transfer Some tokens between the investor + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), + web3.utils.toWei('3', 'ether') + ); + }); + + it("Should unpause the tranfers at transferManager level", async() => { + await I_LockUpTransferManager.unpause({from: token_owner}); + }); + + it("Should prevent the creation of a lockup with bad parameters where the lockupAmount is zero", async() => { + // create a lockup + // this will generate an exception because the lockupAmount is zero + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUser( + account_investor2, + 0, + latestTime() + + duration.seconds(1), + duration.seconds(400000), + duration.seconds(100000), + "a_lockup", + { + from: token_owner + } + ) + ) + }); + + it("Should prevent the creation of a lockup with bad parameters where the releaseFrequencySeconds is zero", async() => { + // create a lockup + // this will generate an exception because the releaseFrequencySeconds is zero + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUser( + account_investor2, + web3.utils.toWei('1', 'ether'), + latestTime() + duration.seconds(1), + duration.seconds(400000), + 0, + "a_lockup", + { + from: token_owner + } + ) + ); + }); + + it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is zero", async() => { + // create a lockup + // this will generate an exception because the lockUpPeriodSeconds is zero + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUser( + account_investor2, + web3.utils.toWei('1', 'ether'), + latestTime() + duration.seconds(1), + 0, + duration.seconds(100000), + "a_lockup", + { + from: token_owner + } + ) + ); + }); + + it("Should add the lockup type -- fail because of bad owner", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpType( + web3.utils.toWei('12', 'ether'), + latestTime() + duration.days(1), + 60, + 20, + "a_lockup", + { + from: account_investor1 + } + ) + ); + }) + + it("Should add the new lockup type", async() => { + let tx = await I_LockUpTransferManager.addNewLockUpType( + web3.utils.toWei('12', 'ether'), + latestTime() + duration.days(1), + 60, + 20, + "a_lockup", + { + from: token_owner + } + ); + assert.equal((tx.logs[0].args._lockupAmount).toNumber(), web3.utils.toWei('12', 'ether')); + }); + + it("Should fail to add the creation of the lockup where lockupName is already exists", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUser( + account_investor1, + web3.utils.toWei('5', 'ether'), + latestTime() + duration.seconds(1), + duration.seconds(400000), + duration.seconds(100000), + "a_lockup", + { + from: token_owner + } + ) + ); + }) + + it("Should allow the creation of a lockup where the lockup amount is divisible" , async() => { + // create a lockup + let tx = await I_LockUpVolumeRestrictionTM_div.addNewLockUpToUser( + account_investor1, + web3.utils.toWei('0.5', 'ether'), + latestTime() + duration.seconds(1), + duration.seconds(400000), + duration.seconds(100000), + "a_lockup", + { + from: token_owner + } + ); + assert.equal(tx.logs[1].args._userAddress, account_investor1); + assert.equal((tx.logs[0].args._lockupAmount).toNumber(), web3.utils.toWei('0.5', 'ether')); + }); + + it("Should allow the creation of a lockup where the lockup amount is prime no", async() => { + // create a lockup + let tx = await I_LockUpVolumeRestrictionTM_div.addNewLockUpToUser( + account_investor1, + web3.utils.toWei('64951', 'ether'), + latestTime() + duration.seconds(1), + duration.seconds(400000), + duration.seconds(100000), + "b_lockup", + { + from: token_owner + } + ); + assert.equal(tx.logs[1].args._userAddress, account_investor1); + assert.equal((tx.logs[0].args._lockupAmount).toNumber(), web3.utils.toWei('64951', 'ether')); + }); + + it("Should prevent the transfer of tokens in a lockup", async() => { + + let balance = await I_SecurityToken.balanceOf(account_investor2) + console.log("balance", balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); + // create a lockup for their entire balance + // over 12 seconds total, with 3 periods of 20 seconds each. + await I_LockUpTransferManager.addNewLockUpToUser( + account_investor2, + balance, + latestTime() + duration.seconds(1), + 60, + 20, + "b_lockup", + { + from: token_owner + } + ); + await increaseTime(2); + let tx = await I_LockUpTransferManager.getLockUp.call("b_lockup"); + console.log("Amount get unlocked:", (tx[4].toNumber())); + await catchRevert( + I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) + ); + }); + + it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { + // wait 20 seconds + await increaseTime(duration.seconds(20)); + let tx = await I_LockUpTransferManager.getLockUp.call("b_lockup"); + console.log("Amount get unlocked:", (tx[4].toNumber())); + await catchRevert( + I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }) + ); + }); + + it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { + let tx = await I_LockUpTransferManager.getLockUp.call("b_lockup"); + console.log("Amount get unlocked:", (tx[4].toNumber())); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + }); + + it("Should again transfer of tokens in a lockup if a period has passed", async() => { + let tx = await I_LockUpTransferManager.getLockUp.call("b_lockup"); + console.log("Amount get unlocked:", (tx[4].toNumber())); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); + }); + + it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { + + // wait 20 more seconds + 1 to get rid of same block time + await increaseTime(duration.seconds(21)); + let tx = await I_LockUpTransferManager.getLockUp.call( "b_lockup"); + console.log("Amount get unlocked:", (tx[4].toNumber())); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); + }); + + it("Buy more tokens from secondary market to investor2", async() => { + // Mint some tokens + await I_SecurityToken.mint(account_investor2, web3.utils.toWei('5', 'ether'), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('10', 'ether') + ); + }) + + it("Should allow transfer for the tokens that comes from secondary market + unlocked tokens", async() => { + + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('6', 'ether') + ); + }); + + it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async() => { + + let balance = await I_SecurityToken.balanceOf(account_investor2) + + // wait 20 more seconds + 1 to get rid of same block time + await increaseTime(duration.seconds(21)); + console.log((await I_LockUpTransferManager.getLockedTokenToUser.call(account_investor2)).toNumber()); + await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), + web3.utils.toWei('0', 'ether') + ); + }); + + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUserMulti( + [account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45], + [20, 15], + ["c_lockup", "d_lockup"], + { + from: token_owner + } + ) + ); + }) + + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUserMulti( + [account_investor3, account_investor3], + [], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45], + [20, 15], + ["c_lockup", "d_lockup"], + { + from: token_owner + } + ) + ); + }) + + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUserMulti( + [account_investor3, account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45, 50], + [20, 15], + ["c_lockup", "d_lockup"], + { + from: token_owner + } + ) + ); + }) + + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUserMulti( + [account_investor3, account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45, 50], + [20, 15, 10], + ["c_lockup", "d_lockup"], + { + from: token_owner + } + ) + ); + }) + + it("Should fail to add the multiple lockups -- because array length mismatch", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpToUserMulti( + [account_investor3, account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45], + [20, 15], + ["c_lockup"], + { + from: token_owner + } + ) + ); + }); + + it("Should add the multiple lockup to a address", async() => { + await I_LockUpTransferManager.addNewLockUpToUserMulti( + [account_investor3, account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [latestTime() + duration.seconds(1), latestTime() + duration.seconds(21)], + [60, 45], + [20, 15], + ["c_lockup", "d_lockup"], + { + from: token_owner + } + ); + + await increaseTime(1); + let tx = await I_LockUpTransferManager.getLockUp.call("c_lockup"); + let tx2 = await I_LockUpTransferManager.getLockUp.call("d_lockup"); + console.log("Total Amount get unlocked:", (tx[4].toNumber()) + (tx2[4].toNumber())); + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor3 }) + ); + + }); + + it("Should transfer the tokens after period get passed", async() => { + // increase 20 sec that makes 1 period passed + // 2 from a period and 1 is already unlocked + await increaseTime(21); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) + }) + + it("Should transfer the tokens after passing another period of the lockup", async() => { + // increase the 15 sec that makes first period of another lockup get passed + // allow 1 token to transfer + await increaseTime(15); + // first fail because 3 tokens are not in unlocked state + await catchRevert( + I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) + ) + // second txn will pass because 1 token is in unlocked state + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1'), { from: account_investor3 }) + }); + + it("Should transfer the tokens from both the lockup simultaneously", async() => { + // Increase the 20 sec (+ 1 to mitigate the block time) that unlocked another 2 tokens from the lockup 1 and simultaneously unlocked 1 + // more token from the lockup 2 + await increaseTime(21); + + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) + assert.equal( + (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), + web3.utils.toWei('3', 'ether') + ); + }); + + it("Should remove multiple lockup --failed because of bad owner", async() => { + await catchRevert( + I_LockUpTransferManager.removeLockUpFromUserMulti( + [account_investor3, account_investor3], + ["c_lockup", "d_lockup"], + { + from: account_polymath + } + ) + ); + }); + + it("Should remove the multiple lockup -- failed because of invalid lockupname", async() => { + await catchRevert( + I_LockUpTransferManager.removeLockUpFromUserMulti( + [account_investor3, account_investor3], + ["c_lockup", "e_lockup"], + { + from: account_polymath + } + ) + ); + }) + + it("Should remove the multiple lockup", async() => { + await I_LockUpTransferManager.removeLockUpFromUserMulti( + [account_investor3, account_investor3], + ["d_lockup", "c_lockup"], + { + from: token_owner + } + ) + // do the free transaction now + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) + }); + + it("Should fail to modify the lockup -- because of bad owner", async() => { + await I_SecurityToken.mint(account_investor3, web3.utils.toWei("9"), {from: token_owner}); + + let tx = await I_LockUpTransferManager.addNewLockUpToUser( + account_investor3, + web3.utils.toWei("9"), + latestTime() + duration.minutes(5), + 60, + 20, + "z_lockup", + { + from: token_owner + } + ); + + await catchRevert( + // edit the lockup + I_LockUpTransferManager.modifyLockUpType( + web3.utils.toWei("9"), + latestTime() + duration.seconds(1), + 60, + 20, + "z_lockup", + { + from: account_polymath + } + ) + ) + }) + + it("Modify the lockup when startTime is in past -- failed because startTime is in the past", async() => { + await catchRevert( + // edit the lockup + I_LockUpTransferManager.modifyLockUpType( + web3.utils.toWei("9"), + latestTime() - duration.seconds(50), + 60, + 20, + "z_lockup", + { + from: token_owner + } + ) + ) + }) + + it("Modify the lockup when startTime is in past -- failed because of invalid index", async() => { + await catchRevert( + // edit the lockup + I_LockUpTransferManager.modifyLockUpType( + web3.utils.toWei("9"), + latestTime() + duration.seconds(50), + 60, + 20, + "m_lockup", + { + from: token_owner + } + ) + ) + }) + + it("should successfully modify the lockup", async() => { + // edit the lockup + await I_LockUpTransferManager.modifyLockUpType( + web3.utils.toWei("9"), + latestTime() + duration.seconds(50), + 60, + 20, + "z_lockup", + { + from: token_owner + } + ); + }) + + it("Should prevent the transfer of tokens in an edited lockup", async() => { + + // balance here should be 12000000000000000000 (12e18 or 12 eth) + let balance = await I_SecurityToken.balanceOf(account_investor1) + + console.log("balance", balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); + + // create a lockup for their entire balance + // over 16 seconds total, with 4 periods of 4 seconds each. + await I_LockUpTransferManager.addNewLockUpToUser( + account_investor1, + balance, + latestTime() + duration.minutes(5), + 60, + 20, + "f_lockup", + { + from: token_owner + } + ); + + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) + ); + + let lockUp = await I_LockUpTransferManager.getLockUp("f_lockup"); + console.log(lockUp); + // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount + assert.equal( + lockUp[0].dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber(), + balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber() + ); + assert.equal(lockUp[2].toNumber(), 60); + assert.equal(lockUp[3].toNumber(), 20); + assert.equal(lockUp[4].toNumber(), 0); + + // edit the lockup + temp = latestTime() + duration.seconds(1); + await I_LockUpTransferManager.modifyLockUpType( + balance, + temp, + 60, + 20, + "f_lockup", + { + from: token_owner + } + ); + + // attempt a transfer + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }) + ); + + // wait 20 seconds + await increaseTime(21); + + // transfer should succeed + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); + + }); + + it("Modify the lockup during the lockup periods", async() => { + let balance = await I_SecurityToken.balanceOf(account_investor1) + let lockUp = await I_LockUpTransferManager.getLockUp("f_lockup"); + console.log(lockUp[4].dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); + // edit the lockup + await I_LockUpTransferManager.modifyLockUpType( + balance, + latestTime() + duration.days(10), + 90, + 30, + "f_lockup", + { + from: token_owner + } + ); + }); + + it("Should remove the lockup multi", async() => { + await I_LockUpTransferManager.addNewLockUpTypeMulti( + [web3.utils.toWei("10"), web3.utils.toWei("16")], + [latestTime() + duration.days(1), latestTime() + duration.days(1)], + [50000, 50000], + [10000, 10000], + ["k_lockup", "l_lockup"], + { + from: token_owner + } + ); + + // removing the lockup type + let tx = await I_LockUpTransferManager.removeLockupType("k_lockup", {from: token_owner}); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._lockupName), "k_lockup"); + + // attaching the lockup to a user + + await I_LockUpTransferManager.addLockUpByName(account_investor2, "l_lockup", {from: token_owner}); + + // try to delete the lockup but fail + + await catchRevert( + I_LockUpTransferManager.removeLockupType("l_lockup", {from: token_owner}) + ); + }) + + it("Should succesfully get the non existed lockup value, it will give everything 0", async() => { + let data = await I_LockUpTransferManager.getLockUp(9); + assert.equal(data[0], 0); + }) + + it("Should get configuration function signature", async() => { + let sig = await I_LockUpTransferManager.getInitFunction.call(); + assert.equal(web3.utils.hexToNumber(sig), 0); + }); + + it("Should get the all lockups added by the issuer till now", async() => { + let tx = await I_LockUpTransferManager.getAllLockups.call(); + for (let i = 0; i < tx.length; i++) { + console.log(web3.utils.toUtf8(tx[i])); + } + }) + + it("Should get the permission", async() => { + let perm = await I_LockUpTransferManager.getPermissions.call(); + assert.equal(perm.length, 1); + assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "ADMIN") + }); + + }); + + describe("LockUpTransferManager Transfer Manager Factory test cases", async() => { + + it("Should get the exact details of the factory", async() => { + assert.equal(await I_LockUpTransferManagerFactory.getSetupCost.call(),0); + assert.equal((await I_LockUpTransferManagerFactory.getTypes.call())[0],2); + assert.equal(web3.utils.toAscii(await I_LockUpTransferManagerFactory.getName.call()) + .replace(/\u0000/g, ''), + "LockUpTransferManager", + "Wrong Module added"); + assert.equal(await I_LockUpTransferManagerFactory.description.call(), + "Manage transfers using lock ups over time", + "Wrong Module added"); + assert.equal(await I_LockUpTransferManagerFactory.title.call(), + "LockUp Transfer Manager", + "Wrong Module added"); + assert.equal(await I_LockUpTransferManagerFactory.getInstructions.call(), + "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", + "Wrong Module added"); + assert.equal(await I_LockUpTransferManagerFactory.version.call(), "1.0.0"); + }); + + it("Should get the tags of the factory", async() => { + let tags = await I_LockUpTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "LockUp"); + }); + }); + +}); diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js deleted file mode 100644 index 358e5b702..000000000 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ /dev/null @@ -1,808 +0,0 @@ -import latestTime from './helpers/latestTime'; -import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; -import { setUpPolymathNetwork, deployLockupVolumeRTMAndVerified } from "./helpers/createInstances"; -import { catchRevert } from "./helpers/exceptions"; - -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); - -const Web3 = require('web3'); -const BigNumber = require('bignumber.js'); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port - -contract('LockupVolumeRestrictionTransferManager', accounts => { - - // Accounts Variable declaration - let account_polymath; - let account_issuer; - let token_owner; - let account_investor1; - let account_investor2; - let account_investor3; - let account_investor4; - - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - - let message = "Transaction Should Fail!"; - - // Contract Instance Declaration - let P_VolumeRestrictionTransferManagerFactory; - let I_SecurityTokenRegistryProxy; - let P_VolumeRestrictionTransferManager; - let I_GeneralTransferManagerFactory; - let I_VolumeRestrictionTransferManagerFactory; - let I_GeneralPermissionManager; - let I_VolumeRestrictionTransferManager; - let I_GeneralTransferManager; - let I_ModuleRegistryProxy; - let I_ModuleRegistry; - let I_FeatureRegistry; - let I_SecurityTokenRegistry; - let I_STRProxied; - let I_MRProxied; - let I_STFactory; - let I_SecurityToken; - let I_PolyToken; - let I_PolymathRegistry; - - // SecurityToken Details - const name = "Team"; - const symbol = "sap"; - const tokenDetails = "This is equity type of issuance"; - const decimals = 18; - const contact = "team@polymath.network"; - - // Module key - const delegateManagerKey = 1; - const transferManagerKey = 2; - const stoKey = 3; - - // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); - - before(async() => { - // Accounts setup - account_polymath = accounts[0]; - account_issuer = accounts[1]; - - token_owner = account_issuer; - - account_investor1 = accounts[7]; - account_investor2 = accounts[8]; - account_investor3 = accounts[9]; - - let instances = await setUpPolymathNetwork(account_polymath, token_owner); - - [ - I_PolymathRegistry, - I_PolyToken, - I_FeatureRegistry, - I_ModuleRegistry, - I_ModuleRegistryProxy, - I_MRProxied, - I_GeneralTransferManagerFactory, - I_STFactory, - I_SecurityTokenRegistry, - I_SecurityTokenRegistryProxy, - I_STRProxied - ] = instances; - - // STEP 4(c): Deploy the VolumeRestrictionTransferManager - [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); - // STEP 4(d): Deploy the VolumeRestrictionTransferManager - [P_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); - - // Printing all the contract addresses - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${I_PolymathRegistry.address} - SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} - ModuleRegistry: ${I_ModuleRegistry.address} - ModuleRegistryProxy: ${I_ModuleRegistryProxy.address} - FeatureRegistry: ${I_FeatureRegistry.address} - - STFactory: ${I_STFactory.address} - GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} - - LockupVolumeRestrictionTransferManagerFactory: - ${I_VolumeRestrictionTransferManagerFactory.address} - ----------------------------------------------------------------------------- - `); - }); - - describe("Generate the SecurityToken", async() => { - - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); - }); - - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); - - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); - - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); - - }); - - describe("Buy tokens using on-chain whitelist and test locking them up and attempting to transfer", async() => { - - it("Should Buy the tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Jump time - await increaseTime(5000); - - // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('2', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('2', 'ether') - ); - }); - - it("Should Buy some more tokens", async() => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor2.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('10', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('10', 'ether') - ); - }); - - it("Should unsuccessfully attach the VolumeRestrictionTransferManager factory with the security token -- failed because Token is not paid", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - await catchRevert( - I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) - ) - }); - - it("Should successfully attach the VolumeRestrictionTransferManager factory with the security token", async () => { - let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); - const tx = await I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, 0, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManagerFactory doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name) - .replace(/\u0000/g, ''), - "LockupVolumeRestrictionTM", - "VolumeRestrictionTransferManagerFactory module was not added" - ); - P_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[3].args._module); - await revertToSnapshot(snapId); - }); - - it("Should successfully attach the VolumeRestrictionTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_VolumeRestrictionTransferManagerFactory.address, 0, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "VolumeRestrictionTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "LockupVolumeRestrictionTM", - "VolumeRestrictionTransferManager module was not added" - ); - I_VolumeRestrictionTransferManager = VolumeRestrictionTransferManager.at(tx.logs[2].args._module); - }); - - it("Add a new token holder", async() => { - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), - true, - { - from: account_issuer - }); - - assert.equal(tx.logs[0].args._investor.toLowerCase(), account_investor3.toLowerCase(), "Failed in adding the investor in whitelist"); - - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('10', 'ether') - ); - }); - - it("Should pause the tranfers at transferManager level", async() => { - let tx = await I_VolumeRestrictionTransferManager.pause({from: token_owner}); - }); - - it("Should still be able to transfer between existing token holders up to limit", async() => { - // Add the Investor in to the whitelist - // Mint some tokens - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('3', 'ether') - ); - }); - - it("Should unpause the tranfers at transferManager level", async() => { - await I_VolumeRestrictionTransferManager.unpause({from: token_owner}); - }); - - it("Should prevent the creation of a lockup with bad parameters where the totalAmount is zero", async() => { - // create a lockup - // this will generate an exception because the totalAmount is zero - await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, 0, { from: token_owner }) - ) - }); - - it("Should prevent the creation of a lockup with bad parameters where the releaseFrequencySeconds is zero", async() => { - // create a lockup - // this will generate an exception because the releaseFrequencySeconds is zero - await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 0, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }) - ); - }); - - it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is zero", async() => { - // create a lockup - // this will generate an exception because the lockUpPeriodSeconds is zero - await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 0, 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }) - ); - }); - - - it("Should prevent the creation of a lockup with bad parameters where the total amount to be released is more granular than allowed by the token", async() => { - // create a lockup - // this will generate an exception because we're locking up 5e17 tokens but the granularity is 5e18 tokens - await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, web3.utils.toWei('0.5', 'ether'), { from: token_owner }) - ); - }); - - it("Should prevent the creation of a lockup with bad parameters where the lockUpPeriodSeconds is not evenly divisible by releaseFrequencySeconds", async() => { - - // balance should be 9000000000000000000 here (9 eth) - let balance = await I_SecurityToken.balanceOf(account_investor2) - - - // create a lockup - // over 17 seconds total, with 4 periods. - // this will generate an exception because 17 is not evenly divisble by 4. - await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 17, 4, 0, balance, { from: token_owner }) - ); - }); - - it("Should prevent the creation of a lockup with bad parameters where the total amount being locked up isn't evenly divisible by the number of total periods", async() => { - - // create a lockup for a balance of 1 eth - // over 16e18 seconds total, with 4e18 periods of 4 seconds each. - // this will generate an exception because 16e18 / 4e18 = 4e18 but the token granularity is 1e18 and 1e18 % 4e18 != 0 - await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, web3.utils.toWei('16', 'ether'), 4, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }) - ); - }); - - it("Should prevent the creation of a lockup with bad parameters where the amount to be released per period is too granular for the token", async() => { - - // balance should be 9000000000000000000 here (9 eth) - let balance = await I_SecurityToken.balanceOf(account_investor2) - - // create a lockup for their entire balance - // over 16 seconds total, with 4 periods of 4 seconds each. - // this will generate an exception because 9000000000000000000 / 4 = 2250000000000000000 but the token granularity is 1000000000000000000 - await catchRevert( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, balance, { from: token_owner }) - ); - - }); - - it("Should prevent the transfer of tokens in a lockup", async() => { - - let balance = await I_SecurityToken.balanceOf(account_investor2) - console.log("balance", balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); - // create a lockup for their entire balance - // over 12 seconds total, with 3 periods of 4 seconds each. - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from: token_owner }); - - // read only - check if transfer will pass. it should return INVALID - let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('1', 'ether'), 0, false) - // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 - assert.equal(result.toString(), '0') - - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); - }); - - it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { - - // wait 4 seconds - await increaseTime(duration.seconds(4)); - - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); - }); - - it("Should prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async() => { - - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('4', 'ether'), { from: account_investor2 }) - ); - }); - - it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { - - // wait 4 more seconds - await increaseTime(4000); - - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); - }); - - it("Should allow the transfer of all tokens in a lockup if the entire lockup has passed", async() => { - - let balance = await I_SecurityToken.balanceOf(account_investor2) - - // wait 4 more seconds - await increaseTime(4000); - - await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); - }); - - it("Should prevent the transfer of tokens in an edited lockup", async() => { - - - // balance here should be 12000000000000000000 (12e18 or 12 eth) - let balance = await I_SecurityToken.balanceOf(account_investor1) - - // create a lockup for their entire balance - // over 16 seconds total, with 4 periods of 4 seconds each. - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, balance, { from: token_owner }); - - // let blockNumber = await web3.eth.getBlockNumber(); - // console.log('blockNumber',blockNumber) - let now = (await web3.eth.getBlock('latest')).timestamp - - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) - ); - - // check and get the lockup - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 1) - - let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 0); - // console.log(lockUp); - // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount - assert.equal(lockUp[0].toString(), '16'); - assert.equal(lockUp[1].toString(), '4'); - assert.equal(lockUp[2].toNumber(), now); - assert.equal(lockUp[3].toString(), balance.toString()); - - // edit the lockup - await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 0, 8, 4, 0, balance, { from: token_owner }); - - // attempt a transfer - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }) - ); - - // wait 4 seconds - await new Promise(resolve => setTimeout(resolve, 4000)); - - // transfer should succeed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }); - - }); - - it("Should succesfully modify the lockup - fail because array index out of bound", async() => { - // balance here should be 12000000000000000000 (12e18 or 12 eth) - let balance = await I_SecurityToken.balanceOf(account_investor1); - await catchRevert( - I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 8, 8, 4, 0, balance, { from: token_owner }) - ); - }) - - it("Should succesfully get the lockup - fail because array index out of bound", async() => { - await catchRevert( - I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 9) - ); - }) - - it("Should be possible to remove a lockup -- couldn't transfer because of lock up", async() => { - - let acct1Balance = await I_SecurityToken.balanceOf(account_investor1) - - await catchRevert( - I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }) - ); - - // check and get the lockup - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 1) - - // remove the lockup - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor1, 0, { from: token_owner }); - - lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount, 0) - - let acct2BalanceBefore = await I_SecurityToken.balanceOf(account_investor2) - await I_SecurityToken.transfer(account_investor2, acct1Balance, { from: account_investor1 }); - let acct2BalanceAfter = await I_SecurityToken.balanceOf(account_investor2) - - assert.equal(acct2BalanceAfter.sub(acct2BalanceBefore).toString(), acct1Balance.toString()) - }); - - it("Should try to remove the lockup --failed because of index is out of bounds", async() => { - await catchRevert( - I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 7, { from: token_owner }) - ); - }) - - it("Should be possible to create multiple lockups at once", async() => { - - let balancesBefore = {} - - // should be 12000000000000000000 - balancesBefore[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - - - // should be 10000000000000000000 - balancesBefore[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - - - let lockUpCountsBefore = {} - - // get lockups for acct 2 - lockUpCountsBefore[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCountsBefore[account_investor2], 1) // there's one old, expired lockup on acct already - - // get lockups for acct 3 - lockUpCountsBefore[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); - assert.equal(lockUpCountsBefore[account_investor3], 0) - - // create lockups for their entire balances - await I_VolumeRestrictionTransferManager.addLockUpMulti( - [account_investor2, account_investor3], - [24, 8], - [4, 4], - [0, 0], - [balancesBefore[account_investor2], balancesBefore[account_investor3]], - { from: token_owner } - ); - - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }) - ); - - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }) - ); - - let balancesAfter = {} - balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - assert.equal(balancesBefore[account_investor2].toString(), balancesAfter[account_investor2].toString()) - - balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - assert.equal(balancesBefore[account_investor3].toString(), balancesAfter[account_investor3].toString()) - - let lockUpCountsAfter = {} - - // get lockups for acct 2 - lockUpCountsAfter[account_investor2] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCountsAfter[account_investor2], 2); - - // get lockups for acct 3 - lockUpCountsAfter[account_investor3] = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor3); - assert.equal(lockUpCountsAfter[account_investor3], 1); - - // wait 4 seconds - await increaseTime(4000); - - // try transfers again - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }); - - - balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2) - assert.equal(balancesBefore[account_investor2].sub(web3.utils.toWei('2', 'ether')).toString(), balancesAfter[account_investor2].toString()) - - balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - assert.equal(balancesBefore[account_investor3].sub(web3.utils.toWei('5', 'ether')).toString(), balancesAfter[account_investor3].toString()) - - }); - - it("Should revert if the parameters are bad when creating multiple lockups", async() => { - - await catchRevert( - // pass in the wrong number of params. txn should revert - I_VolumeRestrictionTransferManager.addLockUpMulti( - [account_investor2, account_investor3], - [16, 8], - [2], // this array should have 2 elements but it has 1, which should cause a revert - [0, 0], - [web3.utils.toWei('1', 'ether'), web3.utils.toWei('1', 'ether')], - { from: token_owner } - ) - ); - }); - - it("Should be possible to create a lockup with a specific start time in the future", async() => { - - // remove all lockups for account 2 - let lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpsLength, 2); - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); - lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpsLength, 0); - - let now = latestTime(); - - // balance here should be 10000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor2) - - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 100, 10, now + duration.seconds(4), balance, { from: token_owner }); - - // wait 4 seconds for the lockup to begin - await increaseTime(duration.seconds(4)); - - // try another transfer. it should also fail because the lockup has just begun - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); - - }); - - it("Should be possible to edit a lockup with a specific start time in the future", async() => { - - // edit the lockup - let now = latestTime(); - - // should be 10000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor2) - - // check and get the lockup - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCount, 1) - - let lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - - // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount - assert.equal(lockUp[0].toString(), '100'); - assert.equal(lockUp[1].toString(), '10'); - assert.isAtMost(lockUp[2].toNumber(), now); - assert.equal(lockUp[3].toString(), balance.toString()); - - // edit the lockup - await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor2, 0, 8, 4, now + duration.seconds(4), balance, { from: token_owner }); - - // check and get the lockup again - lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpCount, 1) - - lockUp = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - - // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount - assert.equal(lockUp[0].toString(), '8'); - assert.equal(lockUp[1].toString(), '4'); - assert.isAtMost(lockUp[2].toNumber(), now + 4); - assert.equal(lockUp[3].toString(), balance.toString()); - - // try a transfer. it should fail because again, the lockup hasn't started yet. - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); - - // wait 4 seconds for the lockup to begin - await increaseTime(duration.seconds(4)); - - // try another transfer. it should fail because the lockup has just begun - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); - - // wait 4 seconds for the lockup's first period to elapse - await increaseTime(duration.seconds(4)); - - // try another transfer. it should pass - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); - - - // try another transfer without waiting for another period to pass. it should fail - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }) - ); - - // wait 4 seconds for the lockup's first period to elapse - await increaseTime(duration.seconds(4)); - - let lockUpBeforeVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - // check if transfer will pass in read-only operation - let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call(account_investor2, account_investor1, web3.utils.toWei('5', 'ether'), 0, false) - // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 - assert.equal(result.toString(), '2') - let lockUpAfterVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - - assert.equal(lockUpBeforeVerify[4].toString(), lockUpAfterVerify[4].toString()) - - // try another transfer. it should pass - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); - - // wait 4 seconds for the lockup's first period to elapse. but, we are all out of periods. - await increaseTime(duration.seconds(4)); - - // try one final transfer. this should fail because the user has already withdrawn their entire balance - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); - }); - - it("Should be possible to stack lockups", async() => { - // should be 17000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor1) - - // check and make sure that acct1 has no lockups so far - let lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor1); - assert.equal(lockUpCount.toString(), 0) - - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 12, 4, 0, web3.utils.toWei('6', 'ether'), { from: token_owner }); - - // try to transfer 11 tokens that aren't locked up yet be locked up. should succeed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('11', 'ether'), { from: account_investor1 }); - - // try a transfer. it should fail because it's locked up from the first lockups - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) - ); - // wait 4 seconds for the lockup's first period to elapse. - await increaseTime(duration.seconds(4)); - - // should succeed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); - - // send 8 back to investor1 so that we can lock them up - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('8', 'ether'), { from: account_investor2 }); - - // let's add another lockup to stack them - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, 0, web3.utils.toWei('8', 'ether'), { from: token_owner }); - - // try a transfer. it should fail because it's locked up from both lockups - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) - ); - - // wait 4 seconds for the 1st lockup's second period to elapse, and the 2nd lockup's first period to elapse - await increaseTime(duration.seconds(4)); - - // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - - // try aother transfer. it should fail because it's locked up from both lockups again - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) - ); - - // wait 4 seconds for the 1st lockup's final period to elapse, and the 2nd lockup's second period to elapse - await increaseTime(duration.seconds(4)); - // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - - // wait 8 seconds for 2nd lockup's third and fourth periods to elapse - await increaseTime(duration.seconds(8)); - // should now be able to transfer 4, because there are 2 allowed per period in the 2nd lockup, and 2 periods have elapsed - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); - - // send the 3 back from acct2 that we sent over in the beginning of this test - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); - - // try another transfer. it should pass because both lockups have been entirely used - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }); - - balance = await I_SecurityToken.balanceOf(account_investor1) - assert.equal(balance.toString(), web3.utils.toWei('2', 'ether')) - }); - - - it("Should get configuration function signature", async() => { - let sig = await I_VolumeRestrictionTransferManager.getInitFunction.call(); - assert.equal(web3.utils.hexToNumber(sig), 0); - }); - - - it("Should get the permission", async() => { - let perm = await I_VolumeRestrictionTransferManager.getPermissions.call(); - assert.equal(perm.length, 1); - // console.log(web3.utils.toAscii(perm[0]).replace(/\u0000/g, '')) - assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "ADMIN") - }); - - }); - - describe("VolumeRestriction Transfer Manager Factory test cases", async() => { - - it("Should get the exact details of the factory", async() => { - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getSetupCost.call(),0); - assert.equal((await I_VolumeRestrictionTransferManagerFactory.getTypes.call())[0],2); - assert.equal(web3.utils.toAscii(await I_VolumeRestrictionTransferManagerFactory.getName.call()) - .replace(/\u0000/g, ''), - "LockupVolumeRestrictionTM", - "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.description.call(), - "Manage transfers using lock ups over time", - "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.title.call(), - "Lockup Volume Restriction Transfer Manager", - "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.getInstructions.call(), - "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", - "Wrong Module added"); - assert.equal(await I_VolumeRestrictionTransferManagerFactory.version.call(), "1.0.0"); - }); - - it("Should get the tags of the factory", async() => { - let tags = await I_VolumeRestrictionTransferManagerFactory.getTags.call(); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Volume"); - }); - }); - -}); diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index 32d28c6ab..5b6c8b57d 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -20,7 +20,7 @@ const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager') // modules for test const CountTransferManager = artifacts.require("./CountTransferManager"); const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); -const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); +const VolumeRestrictionTransferManager = artifacts.require('./LockUpTransferManager'); const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index 83e98fa78..d80b36094 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -17,7 +17,6 @@ const SecurityToken = artifacts.require('./SecurityToken.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); const CountTransferManager = artifacts.require("./CountTransferManager"); -const VolumeRestrictionTransferManager = artifacts.require('./LockupVolumeRestrictionTM'); const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); From 3689174411295677029e73811e91d408340e9ffa Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 10 Jan 2019 01:42:20 +0530 Subject: [PATCH 514/582] add exempt list getter --- contracts/libraries/VolumeRestrictionLib.sol | 87 +++++++++++++ .../TransferManager/VolumeRestrictionTM.sol | 123 ++++++------------ .../VolumeRestrictionTMStorage.sol | 18 +-- migrations/2_deploy_contracts.js | 5 + test/y_volume_restriction_tm.js | 1 + 5 files changed, 141 insertions(+), 93 deletions(-) create mode 100644 contracts/libraries/VolumeRestrictionLib.sol diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol new file mode 100644 index 000000000..fe3186369 --- /dev/null +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -0,0 +1,87 @@ +pragma solidity ^0.4.24; + +import "./BokkyPooBahsDateTimeLibrary.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../interfaces/ISecurityToken.sol"; + +library VolumeRestrictionLib { + + using SafeMath for uint256; + + enum TypeOfPeriod { MultipleDays, OneDay, Both } + + struct RestrictedHolder { + // 1 represent true & 0 for false + uint8 seen; + // Type of period will be enum index of TypeOfPeriod enum + uint8 typeOfPeriod; + // Index of the array where the holder address lives + uint128 index; + } + + struct RestrictedData { + mapping(address => RestrictedHolder) restrictedHolders; + address[] restrictedAddresses; + } + + function _checkLengthOfArray( + address[] _holders, + uint256[] _allowedTokens, + uint256[] _startTimes, + uint256[] _rollingPeriodInDays, + uint256[] _endTimes, + uint256[] _restrictionTypes + ) + internal + pure + { + require( + _holders.length == _allowedTokens.length && + _allowedTokens.length == _startTimes.length && + _startTimes.length == _rollingPeriodInDays.length && + _rollingPeriodInDays.length == _endTimes.length && + _endTimes.length == _restrictionTypes.length, + "Length mismatch" + ); + } + + function _deleteHolderFromList(RestrictedData storage data, address _holder, uint8 _typeOfPeriod) public { + // Deleting the holder if holder's type of Period is `Both` type otherwise + // it will assign the given type `_typeOfPeriod` to the _holder typeOfPeriod + // `_typeOfPeriod` it always be contrary to the removing restriction + // if removing restriction is individual then typeOfPeriod is TypeOfPeriod.OneDay + // in uint8 its value is 1. if removing restriction is daily individual then typeOfPeriod + // is TypeOfPeriod.MultipleDays in uint8 its value is 0. + if (data.restrictedHolders[_holder].typeOfPeriod != uint8(TypeOfPeriod.Both)) { + uint128 index = data.restrictedHolders[_holder].index; + uint256 _len = data.restrictedAddresses.length; + if (index != _len) { + data.restrictedHolders[data.restrictedAddresses[_len - 1]].index = index; + data.restrictedAddresses[index - 1] = data.restrictedAddresses[_len - 1]; + } + delete data.restrictedHolders[_holder]; + data.restrictedAddresses.length--; + } else { + data.restrictedHolders[_holder].typeOfPeriod = _typeOfPeriod; + } + } + + function _addRestrictionData(RestrictedData storage data, address _holder, uint8 _callFrom, uint256 _endTime) public { + uint128 index = data.restrictedHolders[_holder].index; + if (data.restrictedHolders[_holder].seen == 0) { + data.restrictedAddresses.push(_holder); + index = uint128(data.restrictedAddresses.length); + } + uint8 _type = _getTypeOfPeriod(data.restrictedHolders[_holder].typeOfPeriod, _callFrom, _endTime); + data.restrictedHolders[_holder] = RestrictedHolder(uint8(1), _type, index); + } + + function _getTypeOfPeriod(uint8 _currentTypeOfPeriod, uint8 _callFrom, uint256 _endTime) internal view returns(uint8) { + if (_currentTypeOfPeriod != _callFrom && _endTime != uint256(0)) + return uint8(TypeOfPeriod.Both); + else + return _callFrom; + } + + +} \ No newline at end of file diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 2bfa4edc2..c742e0b4a 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -137,7 +137,17 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { */ function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { require(_wallet != address(0)); - exemptList[_wallet] = _change; + require(exemptList[_wallet] != _change); + if (_change) { + exemptAddresses.push(_wallet); + exemptIndex[_wallet] = exemptAddresses.length; + exemptList[_wallet] = true; + } else { + exemptAddresses[exemptIndex[_wallet]] = exemptAddresses[exemptAddresses.length -1]; + exemptIndex[exemptAddresses[exemptIndex[_wallet]]] = exemptIndex[_wallet]; + delete exemptList[_wallet]; + exemptAddresses.length --; + } emit ChangedExemptWalletList(_wallet, _change); } @@ -203,7 +213,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _endTime, RestrictionType(_restrictionType) ); - _addRestrictionData(_holder, uint8(TypeOfPeriod.MultipleDays)); + VolumeRestrictionLib._addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.MultipleDays), individualRestriction[_holder].endTime); emit AddIndividualRestriction( _holder, _allowedTokens, @@ -214,16 +224,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ); } - function _addRestrictionData(address _holder, uint8 _callFrom) internal { - uint128 index = restrictedHolders[_holder].index; - if (restrictedHolders[_holder].seen == 0) { - restrictedAddresses.push(_holder); - index = uint128(restrictedAddresses.length); - } - uint8 _type = _getTypeOfPeriod(restrictedHolders[_holder].typeOfPeriod, _callFrom, _holder); - restrictedHolders[_holder] = RestrictedHolder(uint8(1), _type, index); - } - /** * @notice Use to add the new individual daily restriction for all token holder * @param _holder Address of the token holder, whom restriction will be implied @@ -276,7 +276,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _endTime, RestrictionType(_restrictionType) ); - _addRestrictionData(_holder, uint8(TypeOfPeriod.OneDay)); + VolumeRestrictionLib._addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.OneDay), individualRestriction[_holder].endTime); emit AddIndividualDailyRestriction( _holder, _allowedTokens, @@ -306,7 +306,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { withPerm(ADMIN) { //NB - we duplicate _startTimes below to allow function reuse - _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); + VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); for (uint256 i = 0; i < _holders.length; i++) { _addIndividualDailyRestriction( _holders[i], @@ -338,7 +338,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { public withPerm(ADMIN) { - _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); for (uint256 i = 0; i < _holders.length; i++) { _addIndividualRestriction( _holders[i], @@ -445,37 +445,16 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /// @notice Internal function to facilitate the removal of individual restriction function _removeIndividualRestriction(address _holder) internal { - require(_holder != address(0), "Invalid address"); + require(_holder != address(0)); require(individualRestriction[_holder].endTime != 0); individualRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - _deleteHolderFromList(_holder, uint8(TypeOfPeriod.OneDay)); + VolumeRestrictionLib._deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.OneDay)); userToBucket[_holder].lastTradedDayTime = 0; userToBucket[_holder].sumOfLastPeriod = 0; userToBucket[_holder].daysCovered = 0; emit IndividualRestrictionRemoved(_holder); } - function _deleteHolderFromList(address _holder, uint8 _typeOfPeriod) internal { - // Deleting the holder if holder's type of Period is `Both` type otherwise - // it will assign the given type `_typeOfPeriod` to the _holder typeOfPeriod - // `_typeOfPeriod` it always be contrary to the removing restriction - // if removing restriction is individual then typeOfPeriod is TypeOfPeriod.OneDay - // in uint8 its value is 1. if removing restriction is daily individual then typeOfPeriod - // is TypeOfPeriod.MultipleDays in uint8 its value is 0. - if (restrictedHolders[_holder].typeOfPeriod != uint8(TypeOfPeriod.Both)) { - uint128 index = restrictedHolders[_holder].index; - uint256 _len = restrictedAddresses.length; - if (index != _len) { - restrictedHolders[restrictedAddresses[_len - 1]].index = index; - restrictedAddresses[index - 1] = restrictedAddresses[_len - 1]; - } - delete restrictedHolders[_holder]; - restrictedAddresses.length--; - } else { - restrictedHolders[_holder].typeOfPeriod = _typeOfPeriod; - } - } - /** * @notice use to remove the individual restriction for a given address * @param _holders Array of address of the user @@ -496,10 +475,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /// @notice Internal function to facilitate the removal of individual daily restriction function _removeIndividualDailyRestriction(address _holder) internal { - require(_holder != address(0), "Invalid address"); + require(_holder != address(0)); require(individualDailyRestriction[_holder].endTime != 0); individualDailyRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - _deleteHolderFromList(_holder, uint8(TypeOfPeriod.MultipleDays)); + VolumeRestrictionLib._deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.MultipleDays)); userToBucket[_holder].dailyLastTradedDayTime = 0; emit IndividualDailyRestrictionRemoved(_holder); } @@ -677,7 +656,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { withPerm(ADMIN) { //NB - we duplicate _startTimes below to allow function reuse - _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); + VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); for (uint256 i = 0; i < _holders.length; i++) { _modifyIndividualDailyRestriction( _holders[i], @@ -709,7 +688,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { public withPerm(ADMIN) { - _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); for (uint256 i = 0; i < _holders.length; i++) { _modifyIndividualRestriction( _holders[i], @@ -745,7 +724,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (_startTime == 0) { startTime = now; } - /* require(startTime >= now, "Invalid startTime"); */ _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); defaultRestriction = VolumeRestriction( _allowedTokens, @@ -812,7 +790,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { */ function _defaultRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { // using the variable to avoid stack too deep error - BucketDetails memory bucketDetails = defaultUserToBucket[_from]; + BucketDetails storage bucketDetails = defaultUserToBucket[_from]; uint256 daysCovered = defaultRestriction.rollingPeriodInDays; uint256 fromTimestamp = 0; uint256 sumOfLastPeriod = 0; @@ -1087,30 +1065,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { "Invalid value" ); } - require(_endTime > _startTime, "Invalid times"); // Maximum limit for the rollingPeriod is 365 days require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365, "Invalid rollingperiod"); - require(BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays, "Invalid times"); - } - - function _checkLengthOfArray( - address[] _holders, - uint256[] _allowedTokens, - uint256[] _startTimes, - uint256[] _rollingPeriodInDays, - uint256[] _endTimes, - uint256[] _restrictionTypes - ) - internal - pure - { require( - _holders.length == _allowedTokens.length && - _allowedTokens.length == _startTimes.length && - _startTimes.length == _rollingPeriodInDays.length && - _rollingPeriodInDays.length == _endTimes.length && - _endTimes.length == _restrictionTypes.length, - "Length mismatch" + BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays && _endTime > _startTime, + "Invalid times" ); } @@ -1164,11 +1123,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { return bytes4(0); } - function _getTypeOfPeriod(uint8 _currentTypeOfPeriod, uint8 _callFrom, address _holder) internal view returns(uint8) { - if (_currentTypeOfPeriod != _callFrom && individualRestriction[_holder].endTime != uint256(0)) - return uint8(TypeOfPeriod.Both); - else - return _callFrom; + /** + * @notice Use to return the list of exempted addresses + */ + function getExemptAddress() external view returns(address[]) { + return exemptAddresses; } /** @@ -1191,8 +1150,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) { uint256 counter = 0; uint256 i = 0; - for (i = 0; i < restrictedAddresses.length; i++) { - counter = counter + (restrictedHolders[restrictedAddresses[i]].typeOfPeriod == uint8(2) ? 2 : 1); + for (i = 0; i < holderData.restrictedAddresses.length; i++) { + counter = counter + (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == uint8(2) ? 2 : 1); } allAddresses = new address[](counter); allowedTokens = new uint256[](counter); @@ -1201,19 +1160,19 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { endTime = new uint256[](counter); typeOfRestriction = new uint8[](counter); counter = 0; - for (i = 0; i < restrictedAddresses.length; i++) { - allAddresses[counter] = restrictedAddresses[i]; - if (restrictedHolders[restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.MultipleDays)) { - _setValues(individualRestriction[restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + for (i = 0; i < holderData.restrictedAddresses.length; i++) { + allAddresses[counter] = holderData.restrictedAddresses[i]; + if (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.MultipleDays)) { + _setValues(individualRestriction[holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); } - else if (restrictedHolders[restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.OneDay)) { - _setValues(individualDailyRestriction[restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + else if (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.OneDay)) { + _setValues(individualDailyRestriction[holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); } - else if (restrictedHolders[restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.Both)) { - _setValues(individualRestriction[restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + else if (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.Both)) { + _setValues(individualRestriction[holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); counter = counter + 1; - allAddresses[counter] = restrictedAddresses[i]; - _setValues(individualDailyRestriction[restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + allAddresses[counter] = holderData.restrictedAddresses[i]; + _setValues(individualDailyRestriction[holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); } counter ++; } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol index ddc2b8e21..629f21be7 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol @@ -1,5 +1,7 @@ pragma solidity ^0.4.24; +import "../../libraries/VolumeRestrictionLib.sol"; + /** * @title Storage layout for VolumeRestrictionTM */ @@ -27,15 +29,6 @@ contract VolumeRestrictionTMStorage { uint256 dailyLastTradedDayTime; } - struct RestrictedHolder { - // 1 represent true & 0 for false - uint8 seen; - // Type of period will be enum index of TypeOfPeriod enum - uint8 typeOfPeriod; - // Index of the array where the holder address lives - uint128 index; - } - // Global restriction that applies to all token holders VolumeRestriction public defaultRestriction; // Daily global restriction that applies to all token holders (Total ST traded daily is restricted) @@ -52,7 +45,10 @@ contract VolumeRestrictionTMStorage { mapping(address => BucketDetails) internal defaultUserToBucket; // List of wallets that are exempted from all the restrictions applied by the this contract mapping(address => bool) public exemptList; - mapping(address => RestrictedHolder) internal restrictedHolders; - address[] public restrictedAddresses; + // Restricted data (refernce from the VolumeRestrictionLib library ) + VolumeRestrictionLib.RestrictedData holderData; + // Holde exempt index + mapping(address => uint256) exemptIndex; + address[] public exemptAddresses; } \ No newline at end of file diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index a89be3b90..9f0af4066 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -26,6 +26,7 @@ const STFactory = artifacts.require('./tokens/STFactory.sol') const DevPolyToken = artifacts.require('./helpers/PolyTokenFaucet.sol') const MockOracle = artifacts.require('./MockOracle.sol') const TokenLib = artifacts.require('./TokenLib.sol'); +const VolumeRestrictionLib = artifacts.require('./VolumeRestrictionLib.sol'); const SecurityToken = artifacts.require('./tokens/SecurityToken.sol') let BigNumber = require('bignumber.js'); @@ -140,7 +141,11 @@ module.exports = function (deployer, network, accounts) { // Deploy libraries return deployer.deploy(TokenLib, { from: PolymathAccount }); }).then(() => { + return deployer.deploy(VolumeRestrictionLib, { from: PolymathAccount }); + }).then(() => { + // Link libraries + deployer.link(VolumeRestrictionLib, VolumeRestrictionTMLogic); deployer.link(TokenLib, SecurityToken); deployer.link(TokenLib, STFactory); // A) Deploy the ModuleRegistry Contract (It contains the list of verified ModuleFactory) diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 3610c13a3..db1a179b8 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -1514,6 +1514,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should add the token holder in the exemption list", async() => { await I_VolumeRestrictionTM.changeExemptWalletList(account_investor4, true, {from: token_owner}); + console.log(await I_VolumeRestrictionTM.getExemptAddress.call()); let beforeBal = await I_SecurityToken.balanceOf.call(account_investor4); await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("3"), {from: account_investor4}); let afterBal = await I_SecurityToken.balanceOf.call(account_investor4); From c0700ea78a9ce75b25af982ae2400ca1a3bec9a0 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 10 Jan 2019 12:00:41 +0530 Subject: [PATCH 515/582] minor fix --- contracts/libraries/VolumeRestrictionLib.sol | 2 +- .../TransferManager/VolumeRestrictionTM.sol | 4 +- test/y_volume_restriction_tm.js | 50 +++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol index fe3186369..e1e94a50b 100644 --- a/contracts/libraries/VolumeRestrictionLib.sol +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -76,7 +76,7 @@ library VolumeRestrictionLib { data.restrictedHolders[_holder] = RestrictedHolder(uint8(1), _type, index); } - function _getTypeOfPeriod(uint8 _currentTypeOfPeriod, uint8 _callFrom, uint256 _endTime) internal view returns(uint8) { + function _getTypeOfPeriod(uint8 _currentTypeOfPeriod, uint8 _callFrom, uint256 _endTime) internal pure returns(uint8) { if (_currentTypeOfPeriod != _callFrom && _endTime != uint256(0)) return uint8(TypeOfPeriod.Both); else diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index c742e0b4a..efeeff0d1 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -143,8 +143,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { exemptIndex[_wallet] = exemptAddresses.length; exemptList[_wallet] = true; } else { - exemptAddresses[exemptIndex[_wallet]] = exemptAddresses[exemptAddresses.length -1]; - exemptIndex[exemptAddresses[exemptIndex[_wallet]]] = exemptIndex[_wallet]; + exemptAddresses[exemptIndex[_wallet] - 1] = exemptAddresses[exemptAddresses.length -1]; + exemptIndex[exemptAddresses[exemptIndex[_wallet] -1 ]] = exemptIndex[_wallet]; delete exemptList[_wallet]; exemptAddresses.length --; } diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index db1a179b8..335e76d1d 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -1521,6 +1521,56 @@ contract('VolumeRestrictionTransferManager', accounts => { let diff = beforeBal.minus(afterBal); assert.equal(web3.utils.fromWei((diff.toNumber()).toString()), 3); }); + + it("Should add multiple token holders to exemption list and check the getter value", async() => { + let holders = [account_investor1, account_investor3, account_investor2, account_delegate2]; + let change = [true, true, true, true]; + for (let i = 0; i < holders.length; i++) { + await I_VolumeRestrictionTM.changeExemptWalletList(holders[i], change[i], {from: token_owner}); + } + let data = await I_VolumeRestrictionTM.getExemptAddress.call(); + assert.equal(data.length, 5); + assert.equal(data[0], account_investor4); + assert.equal(data[1], account_investor1); + assert.equal(data[2], account_investor3); + assert.equal(data[3], account_investor2); + assert.equal(data[4], account_delegate2); + }); + + it("Should unexempt a particular address", async() => { + await I_VolumeRestrictionTM.changeExemptWalletList(account_investor1, false, {from: token_owner}); + let data = await I_VolumeRestrictionTM.getExemptAddress.call(); + assert.equal(data.length, 4); + assert.equal(data[0], account_investor4); + assert.equal(data[1], account_delegate2); + assert.equal(data[2], account_investor3); + assert.equal(data[3], account_investor2); + }); + + it("Should fail to unexempt the same address again", async() => { + await catchRevert( + I_VolumeRestrictionTM.changeExemptWalletList(account_investor1, false, {from: token_owner}) + ); + }); + + it("Should delete the last element of the exemption list", async() => { + await I_VolumeRestrictionTM.changeExemptWalletList(account_investor2, false, {from: token_owner}); + let data = await I_VolumeRestrictionTM.getExemptAddress.call(); + assert.equal(data.length, 3); + assert.equal(data[0], account_investor4); + assert.equal(data[1], account_delegate2); + assert.equal(data[2], account_investor3); + }); + + it("Should delete multiple investor from the exemption list", async() => { + let holders = [account_delegate2, account_investor4, account_investor3]; + let change = [false, false, false]; + for (let i = 0; i < holders.length; i++) { + await I_VolumeRestrictionTM.changeExemptWalletList(holders[i], change[i], {from: token_owner}); + } + let data = await I_VolumeRestrictionTM.getExemptAddress.call(); + assert.equal(data.length, 0); + }); }); describe("Test for modify functions", async() => { From a2692fcedc9d2b16ff2dfb0b8e4344b7139b0638 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 10 Jan 2019 09:09:56 -0300 Subject: [PATCH 516/582] CLI - Added 'show exempted addresses' --- CLI/commands/transfer_manager.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 1ea70fa2b..39af92b78 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1556,11 +1556,16 @@ async function volumeRestrictionTM() { let addressesAndRestrictions = await currentTransferManager.methods.getRestrictedData().call(); console.log(`- Individual restrictions: ${addressesAndRestrictions.allAddresses.length}`); + let exemptedAddresses = await currentTransferManager.methods.getExemptAddress().call(); + console.log(`- Exempted addresses: ${exemptedAddresses.length}`); let options = []; - if (addressesAndRestrictions[0].length > 0) { + if (addressesAndRestrictions.allAddresses.length > 0) { options.push('Show restrictions'); } + if (exemptedAddresses.length > 0) { + options.push('Show exempted addresses'); + } options.push( 'Change exempt wallet', 'Change default restrictions', @@ -1583,6 +1588,9 @@ async function volumeRestrictionTM() { addressesAndRestrictions.endTime, ); break; + case 'Show exempted addresses': + showExemptedAddresses(exemptedAddresses); + break; case 'Change exempt wallet': await changeExemptWallet(); break; @@ -1620,6 +1628,11 @@ function showRestrictionTable(investorArray, amountArray, typeArray, rollingPeri console.log(table(dataTable)); } +function showExemptedAddresses(addresses) { + console.log("*********** Exepmpted addresses ***********"); + addresses.map(i => console.log(i)); +} + async function changeExemptWallet() { let options = [ 'Add exempt wallet', From 1b126c201a049d48006d170dcac5dbee01bacdd2 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Thu, 10 Jan 2019 09:10:02 -0400 Subject: [PATCH 517/582] Small optimisation --- .../TransferManager/VolumeRestrictionTM.sol | 19 +++++++++---------- .../VolumeRestrictionTMStorage.sol | 10 +++++----- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index efeeff0d1..5cf1e4ac6 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -112,7 +112,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { */ function verifyTransfer(address _from, address /*_to */, uint256 _amount, bytes /*_data*/, bool _isTransfer) public returns (Result) { // If `_from` is present in the exemptionList or it is `0x0` address then it will not follow the vol restriction - if (!paused && _from != address(0) && !exemptList[_from]) { + if (!paused && _from != address(0) && exemptIndex[_from] == 0) { // Function must only be called by the associated security token if _isTransfer == true require(msg.sender == securityToken || !_isTransfer); // Checking the individual restriction if the `_from` comes in the individual category @@ -137,15 +137,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { */ function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { require(_wallet != address(0)); - require(exemptList[_wallet] != _change); + require((exemptIndex[_wallet] == 0) == _change); if (_change) { exemptAddresses.push(_wallet); exemptIndex[_wallet] = exemptAddresses.length; - exemptList[_wallet] = true; } else { - exemptAddresses[exemptIndex[_wallet] - 1] = exemptAddresses[exemptAddresses.length -1]; - exemptIndex[exemptAddresses[exemptIndex[_wallet] -1 ]] = exemptIndex[_wallet]; - delete exemptList[_wallet]; + exemptAddresses[exemptIndex[_wallet] - 1] = exemptAddresses[exemptAddresses.length - 1]; + exemptIndex[exemptAddresses[exemptIndex[_wallet] - 1]] = exemptIndex[_wallet]; + delete exemptIndex[_wallet]; exemptAddresses.length --; } emit ChangedExemptWalletList(_wallet, _change); @@ -200,7 +199,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { individualRestriction[_holder].endTime < now, "Not Allowed" ); - require(_holder != address(0) && !exemptList[_holder], "Invalid address"); + require(_holder != address(0) && exemptIndex[_holder] == 0, "Invalid address"); _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); if (individualRestriction[_holder].endTime != 0) { @@ -1129,7 +1128,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { function getExemptAddress() external view returns(address[]) { return exemptAddresses; } - + /** * @notice Provide the restriction details of all the restricted addresses * @return address List of the restricted addresses @@ -1137,7 +1136,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 List of the start time of the restriction corresponds to restricted address * @return uint256 List of the rolling period in days for a restriction corresponds to restricted address. * @return uint256 List of the end time of the restriction corresponds to restricted address. - * @return uint8 List of the type of restriction to validate the value of the `allowedTokens` + * @return uint8 List of the type of restriction to validate the value of the `allowedTokens` * of the restriction corresponds to restricted address */ function getRestrictedData() external view returns( @@ -1186,7 +1185,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] memory endTime, uint8[] memory typeOfRestriction, uint256 index - ) + ) internal pure { diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol index 629f21be7..9eb776ff0 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol @@ -13,7 +13,7 @@ contract VolumeRestrictionTMStorage { struct VolumeRestriction { // If typeOfRestriction is `Percentage` then allowedTokens will be in - // the % (w.r.t to totalSupply) with a multiplier of 10**16 . else it + // the % (w.r.t to totalSupply) with a multiplier of 10**16 . else it // will be fixed amount of tokens uint256 allowedTokens; uint256 startTime; @@ -24,7 +24,7 @@ contract VolumeRestrictionTMStorage { struct BucketDetails { uint256 lastTradedDayTime; - uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays + uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays uint256 daysCovered; // No of days covered till (from the startTime of VolumeRestriction) uint256 dailyLastTradedDayTime; } @@ -44,11 +44,11 @@ contract VolumeRestrictionTMStorage { // Storing the information related to default restriction mapping(address => BucketDetails) internal defaultUserToBucket; // List of wallets that are exempted from all the restrictions applied by the this contract - mapping(address => bool) public exemptList; + /* mapping(address => bool) public exemptList; */ // Restricted data (refernce from the VolumeRestrictionLib library ) VolumeRestrictionLib.RestrictedData holderData; // Holde exempt index mapping(address => uint256) exemptIndex; address[] public exemptAddresses; - -} \ No newline at end of file + +} From c843a9981cde41eb0a51bd3cf3f5d5cf52f959d5 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 10 Jan 2019 12:31:54 -0300 Subject: [PATCH 518/582] Typo --- CLI/commands/transfer_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 2b76a8f80..c48bb3483 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -369,7 +369,7 @@ async function generalTransferManager() { break; case 'Change the default times used when they are zero': let fromTimeDefault = readlineSync.questionInt(`Enter the default time (Unix Epoch time) used when fromTime is zero: `); - let toTimeDefault = readlineSync.questionInt(`Enter the default time (Unix Epoch time) used when fromTime is zero: `); + let toTimeDefault = readlineSync.questionInt(`Enter the default time (Unix Epoch time) used when toTime is zero: `); let changeDefaultsAction = currentTransferManager.methods.changeDefaults(fromTimeDefault, toTimeDefault); let changeDefaultsReceipt = await common.sendTransaction(changeDefaultsAction); let changeDefaultsEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, changeDefaultsReceipt.logs, 'ChangeDefaults'); From 14a96509cb3c33c32e1763f3687ebec89b9fb371 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 10 Jan 2019 12:33:06 -0300 Subject: [PATCH 519/582] Text improvements --- CLI/commands/transfer_manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index c48bb3483..47008eca8 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -193,8 +193,8 @@ async function forcedTransfers() { }, limitMessage: `Amount must be less or equal than ${fromBalance} ${tokenSymbol}`, }); - let data = readlineSync.question('Enter the data to indicate validation: '); - let log = readlineSync.question('Enter the data attached to the transfer by controller to emit in event: '); + let data = '';//readlineSync.question('Enter the data to indicate validation: '); + let log = readlineSync.question('Enter a message to attach to the transfer (i.e. "Private key lost"): '); let forceTransferAction = securityToken.methods.forceTransfer(from, to, web3.utils.toWei(amount), web3.utils.asciiToHex(data), web3.utils.asciiToHex(log)); let forceTransferReceipt = await common.sendTransaction(forceTransferAction, { factor: 1.5 }); let forceTransferEvent = common.getEventFromLogs(securityToken._jsonInterface, forceTransferReceipt.logs, 'ForceTransfer'); From b2551b43214aa9c366be6efc3cf2db2c06cefa6c Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 10 Jan 2019 12:35:36 -0300 Subject: [PATCH 520/582] KYC expiry date modified to one year from now --- CLI/commands/transfer_manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 47008eca8..37e00d788 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -385,8 +385,8 @@ async function generalTransferManager() { let now = Math.floor(Date.now() / 1000); let fromTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens (now = ${now}): `, { defaultInput: now }); let toTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (now = ${now}): `, { defaultInput: now }); - let oneHourFromNow = Math.floor(Date.now() / 1000 + 3600); - let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated (after that investor need to do re - KYC) (1 hour from now = ${oneHourFromNow}): `, { defaultInput: oneHourFromNow }); + let oneYearFromNow = Math.floor(Date.now() / 1000 + (60 * 60 * 24 * 365)); + let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated (after that investor need to do re - KYC) (1 year from now = ${oneYearFromNow}): `, { defaultInput: oneYearFromNow }); let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); From c1b5c7e988bb4dac36c4cc7c59a033b79e83e5c5 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 10 Jan 2019 15:42:26 -0300 Subject: [PATCH 521/582] Fix for CappedSTO --- CLI/commands/investor_portal.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 0cb02f681..0bf12342a 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -152,8 +152,6 @@ async function showTokenInfo() { // Show info async function showUserInfo(_user) { - let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); - console.log(` ******************* User Information ******************** - Address: ${_user}`); @@ -164,6 +162,7 @@ async function showUserInfo(_user) { console.log(` - ETH balance:\t ${web3.utils.fromWei(await web3.eth.getBalance(_user))}`); } if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.STABLE).call()) { + let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); let stableSymbolsAndBalance = await processAddressWithBalance(listOfStableCoins); stableSymbolsAndBalance.forEach(stable => { console.log(` - ${stable.symbol} balance:\t ${web3.utils.fromWei(stable.balance)}`); From 124311bf5ff8010ff1cd8e95f77bde181c1fe561 Mon Sep 17 00:00:00 2001 From: Satyam Agrawal Date: Mon, 14 Jan 2019 18:15:46 +0530 Subject: [PATCH 522/582] Move contracts to the respective folders (#510) * move storage contracts to storage folder and migrate vesting to experimental * BTM migrate to experimental * move Lockup to experimental * Small re-shuffling * remove _ prefix from public functions --- contracts/libraries/VolumeRestrictionLib.sol | 31 +++++-------------- .../BlacklistTransferManager.sol | 2 +- .../BlacklistTransferManagerFactory.sol | 4 +-- .../TransferManager/LockUpTransferManager.sol | 2 +- .../LockUpTransferManagerFactory.sol | 2 +- .../{ => Experimental}/Wallet/IWallet.sol | 4 +-- .../Wallet/VestingEscrowWallet.sol | 2 +- .../Wallet/VestingEscrowWalletFactory.sol | 8 ++--- contracts/modules/STO/USDTieredSTO.sol | 2 +- .../GeneralTransferManager.sol | 2 +- .../TransferManager/VolumeRestrictionTM.sol | 10 +++--- .../proxy/GeneralTransferManagerProxy.sol | 2 +- contracts/proxy/USDTieredSTOProxy.sol | 2 +- contracts/proxy/VestingEscrowWalletProxy.sol | 2 +- contracts/proxy/VolumeRestrictionTMProxy.sol | 2 +- .../GeneralTransferManagerStorage.sol | 0 .../STO => storage}/USDTieredSTOStorage.sol | 2 +- .../VestingEscrowWalletStorage.sol | 0 .../VolumeRestrictionTMStorage.sol | 22 +++++++++---- test/y_volume_restriction_tm.js | 2 +- 20 files changed, 49 insertions(+), 54 deletions(-) rename contracts/modules/{ => Experimental}/TransferManager/BlacklistTransferManager.sol (99%) rename contracts/modules/{ => Experimental}/TransferManager/BlacklistTransferManagerFactory.sol (97%) rename contracts/modules/{ => Experimental}/TransferManager/LockUpTransferManager.sol (99%) rename contracts/modules/{ => Experimental}/TransferManager/LockUpTransferManagerFactory.sol (98%) rename contracts/modules/{ => Experimental}/Wallet/IWallet.sol (83%) rename contracts/modules/{ => Experimental}/Wallet/VestingEscrowWallet.sol (99%) rename contracts/modules/{ => Experimental}/Wallet/VestingEscrowWalletFactory.sol (94%) rename contracts/{modules/TransferManager => storage}/GeneralTransferManagerStorage.sol (100%) rename contracts/{modules/STO => storage}/USDTieredSTOStorage.sol (98%) rename contracts/{modules/Wallet => storage}/VestingEscrowWalletStorage.sol (100%) rename contracts/{modules/TransferManager => storage}/VolumeRestrictionTMStorage.sol (81%) diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol index e1e94a50b..9f71d3fed 100644 --- a/contracts/libraries/VolumeRestrictionLib.sol +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -3,27 +3,12 @@ pragma solidity ^0.4.24; import "./BokkyPooBahsDateTimeLibrary.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../interfaces/ISecurityToken.sol"; +import "../storage/VolumeRestrictionTMStorage.sol"; library VolumeRestrictionLib { using SafeMath for uint256; - enum TypeOfPeriod { MultipleDays, OneDay, Both } - - struct RestrictedHolder { - // 1 represent true & 0 for false - uint8 seen; - // Type of period will be enum index of TypeOfPeriod enum - uint8 typeOfPeriod; - // Index of the array where the holder address lives - uint128 index; - } - - struct RestrictedData { - mapping(address => RestrictedHolder) restrictedHolders; - address[] restrictedAddresses; - } - function _checkLengthOfArray( address[] _holders, uint256[] _allowedTokens, @@ -45,14 +30,14 @@ library VolumeRestrictionLib { ); } - function _deleteHolderFromList(RestrictedData storage data, address _holder, uint8 _typeOfPeriod) public { + function deleteHolderFromList(VolumeRestrictionTMStorage.RestrictedData storage data, address _holder, uint8 _typeOfPeriod) public { // Deleting the holder if holder's type of Period is `Both` type otherwise // it will assign the given type `_typeOfPeriod` to the _holder typeOfPeriod // `_typeOfPeriod` it always be contrary to the removing restriction // if removing restriction is individual then typeOfPeriod is TypeOfPeriod.OneDay // in uint8 its value is 1. if removing restriction is daily individual then typeOfPeriod // is TypeOfPeriod.MultipleDays in uint8 its value is 0. - if (data.restrictedHolders[_holder].typeOfPeriod != uint8(TypeOfPeriod.Both)) { + if (data.restrictedHolders[_holder].typeOfPeriod != uint8(VolumeRestrictionTMStorage.TypeOfPeriod.Both)) { uint128 index = data.restrictedHolders[_holder].index; uint256 _len = data.restrictedAddresses.length; if (index != _len) { @@ -66,22 +51,22 @@ library VolumeRestrictionLib { } } - function _addRestrictionData(RestrictedData storage data, address _holder, uint8 _callFrom, uint256 _endTime) public { + function addRestrictionData(VolumeRestrictionTMStorage.RestrictedData storage data, address _holder, uint8 _callFrom, uint256 _endTime) public { uint128 index = data.restrictedHolders[_holder].index; if (data.restrictedHolders[_holder].seen == 0) { data.restrictedAddresses.push(_holder); index = uint128(data.restrictedAddresses.length); } uint8 _type = _getTypeOfPeriod(data.restrictedHolders[_holder].typeOfPeriod, _callFrom, _endTime); - data.restrictedHolders[_holder] = RestrictedHolder(uint8(1), _type, index); + data.restrictedHolders[_holder] = VolumeRestrictionTMStorage.RestrictedHolder(uint8(1), _type, index); } function _getTypeOfPeriod(uint8 _currentTypeOfPeriod, uint8 _callFrom, uint256 _endTime) internal pure returns(uint8) { if (_currentTypeOfPeriod != _callFrom && _endTime != uint256(0)) - return uint8(TypeOfPeriod.Both); + return uint8(VolumeRestrictionTMStorage.TypeOfPeriod.Both); else return _callFrom; } - -} \ No newline at end of file + +} diff --git a/contracts/modules/TransferManager/BlacklistTransferManager.sol b/contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol similarity index 99% rename from contracts/modules/TransferManager/BlacklistTransferManager.sol rename to contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol index d88fea770..d1e653803 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; +import "../../TransferManager/ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** diff --git a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol similarity index 97% rename from contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol rename to contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol index cdb7c90eb..36dd4304f 100644 --- a/contracts/modules/TransferManager/BlacklistTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol @@ -1,8 +1,8 @@ pragma solidity ^0.4.24; import "./BlacklistTransferManager.sol"; -import "../ModuleFactory.sol"; -import "../../libraries/Util.sol"; +import "../../ModuleFactory.sol"; +import "../../../libraries/Util.sol"; /** * @title Factory for deploying BlacklistManager module diff --git a/contracts/modules/TransferManager/LockUpTransferManager.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol similarity index 99% rename from contracts/modules/TransferManager/LockUpTransferManager.sol rename to contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol index 993bbd5bb..85ae126fa 100644 --- a/contracts/modules/TransferManager/LockUpTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; +import "../../TransferManager/ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; contract LockUpTransferManager is ITransferManager { diff --git a/contracts/modules/TransferManager/LockUpTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol similarity index 98% rename from contracts/modules/TransferManager/LockUpTransferManagerFactory.sol rename to contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol index 3f5e7b31a..22581eba4 100644 --- a/contracts/modules/TransferManager/LockUpTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../ModuleFactory.sol"; +import "../../ModuleFactory.sol"; import "./LockUpTransferManager.sol"; /** diff --git a/contracts/modules/Wallet/IWallet.sol b/contracts/modules/Experimental/Wallet/IWallet.sol similarity index 83% rename from contracts/modules/Wallet/IWallet.sol rename to contracts/modules/Experimental/Wallet/IWallet.sol index ea5c918d8..96affd472 100644 --- a/contracts/modules/Wallet/IWallet.sol +++ b/contracts/modules/Experimental/Wallet/IWallet.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; -import "../../Pausable.sol"; -import "../Module.sol"; +import "../../../Pausable.sol"; +import "../../Module.sol"; /** * @title Interface to be implemented by all Wallet modules diff --git a/contracts/modules/Wallet/VestingEscrowWallet.sol b/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol similarity index 99% rename from contracts/modules/Wallet/VestingEscrowWallet.sol rename to contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol index 17f6dbb08..c53e1143f 100644 --- a/contracts/modules/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "./VestingEscrowWalletStorage.sol"; +import "../../../storage/VestingEscrowWalletStorage.sol"; import "./IWallet.sol"; /** diff --git a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol similarity index 94% rename from contracts/modules/Wallet/VestingEscrowWalletFactory.sol rename to contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol index 238d571ea..2e35453f0 100644 --- a/contracts/modules/Wallet/VestingEscrowWalletFactory.sol +++ b/contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol @@ -1,9 +1,9 @@ pragma solidity ^0.4.24; -import "../../proxy/VestingEscrowWalletProxy.sol"; -import "../../interfaces/IBoot.sol"; -import "../ModuleFactory.sol"; -import "../../libraries/Util.sol"; +import "../../../proxy/VestingEscrowWalletProxy.sol"; +import "../../../interfaces/IBoot.sol"; +import "../../ModuleFactory.sol"; +import "../../../libraries/Util.sol"; /** * @title Factory for deploying VestingEscrowWallet module diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index b3a248da5..97345ad51 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -7,7 +7,7 @@ import "../../RegistryUpdater.sol"; import "../../libraries/DecimalMath.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; -import "./USDTieredSTOStorage.sol"; +import "../../storage/USDTieredSTOStorage.sol"; /** * @title STO module for standard capped crowdsale diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index ef7d15e98..dc7eabd4b 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "./ITransferManager.sol"; -import "./GeneralTransferManagerStorage.sol"; +import "../../storage/GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 5cf1e4ac6..69b036aa4 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -1,9 +1,9 @@ pragma solidity ^0.4.24; import "./ITransferManager.sol"; -import "./VolumeRestrictionTMStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../../libraries/BokkyPooBahsDateTimeLibrary.sol"; +import "../../libraries/VolumeRestrictionLib.sol"; contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { @@ -212,7 +212,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _endTime, RestrictionType(_restrictionType) ); - VolumeRestrictionLib._addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.MultipleDays), individualRestriction[_holder].endTime); + VolumeRestrictionLib.addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.MultipleDays), individualRestriction[_holder].endTime); emit AddIndividualRestriction( _holder, _allowedTokens, @@ -275,7 +275,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _endTime, RestrictionType(_restrictionType) ); - VolumeRestrictionLib._addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.OneDay), individualRestriction[_holder].endTime); + VolumeRestrictionLib.addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.OneDay), individualRestriction[_holder].endTime); emit AddIndividualDailyRestriction( _holder, _allowedTokens, @@ -447,7 +447,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_holder != address(0)); require(individualRestriction[_holder].endTime != 0); individualRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - VolumeRestrictionLib._deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.OneDay)); + VolumeRestrictionLib.deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.OneDay)); userToBucket[_holder].lastTradedDayTime = 0; userToBucket[_holder].sumOfLastPeriod = 0; userToBucket[_holder].daysCovered = 0; @@ -477,7 +477,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_holder != address(0)); require(individualDailyRestriction[_holder].endTime != 0); individualDailyRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - VolumeRestrictionLib._deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.MultipleDays)); + VolumeRestrictionLib.deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.MultipleDays)); userToBucket[_holder].dailyLastTradedDayTime = 0; emit IndividualDailyRestrictionRemoved(_holder); } diff --git a/contracts/proxy/GeneralTransferManagerProxy.sol b/contracts/proxy/GeneralTransferManagerProxy.sol index cb9b69070..0fbaa7880 100644 --- a/contracts/proxy/GeneralTransferManagerProxy.sol +++ b/contracts/proxy/GeneralTransferManagerProxy.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../modules/TransferManager/GeneralTransferManagerStorage.sol"; +import "../storage/GeneralTransferManagerStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "../modules/ModuleStorage.sol"; diff --git a/contracts/proxy/USDTieredSTOProxy.sol b/contracts/proxy/USDTieredSTOProxy.sol index 12cf8fdb1..a412a8278 100644 --- a/contracts/proxy/USDTieredSTOProxy.sol +++ b/contracts/proxy/USDTieredSTOProxy.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../modules/STO/USDTieredSTOStorage.sol"; +import "../storage/USDTieredSTOStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; diff --git a/contracts/proxy/VestingEscrowWalletProxy.sol b/contracts/proxy/VestingEscrowWalletProxy.sol index 0138e0402..8f7be97ce 100644 --- a/contracts/proxy/VestingEscrowWalletProxy.sol +++ b/contracts/proxy/VestingEscrowWalletProxy.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../modules/Wallet/VestingEscrowWalletStorage.sol"; +import "../storage/VestingEscrowWalletStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "../modules/ModuleStorage.sol"; diff --git a/contracts/proxy/VolumeRestrictionTMProxy.sol b/contracts/proxy/VolumeRestrictionTMProxy.sol index e8c24e6be..0f5cc7f5a 100644 --- a/contracts/proxy/VolumeRestrictionTMProxy.sol +++ b/contracts/proxy/VolumeRestrictionTMProxy.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../modules/TransferManager/VolumeRestrictionTMStorage.sol"; +import "../storage/VolumeRestrictionTMStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "../modules/ModuleStorage.sol"; diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol similarity index 100% rename from contracts/modules/TransferManager/GeneralTransferManagerStorage.sol rename to contracts/storage/GeneralTransferManagerStorage.sol diff --git a/contracts/modules/STO/USDTieredSTOStorage.sol b/contracts/storage/USDTieredSTOStorage.sol similarity index 98% rename from contracts/modules/STO/USDTieredSTOStorage.sol rename to contracts/storage/USDTieredSTOStorage.sol index c9df0f24c..f801000e0 100644 --- a/contracts/modules/STO/USDTieredSTOStorage.sol +++ b/contracts/storage/USDTieredSTOStorage.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../../interfaces/IERC20.sol"; +import "../interfaces/IERC20.sol"; /** * @title Contract used to store layout for the USDTieredSTO storage diff --git a/contracts/modules/Wallet/VestingEscrowWalletStorage.sol b/contracts/storage/VestingEscrowWalletStorage.sol similarity index 100% rename from contracts/modules/Wallet/VestingEscrowWalletStorage.sol rename to contracts/storage/VestingEscrowWalletStorage.sol diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol b/contracts/storage/VolumeRestrictionTMStorage.sol similarity index 81% rename from contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol rename to contracts/storage/VolumeRestrictionTMStorage.sol index 9eb776ff0..9718c2c09 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMStorage.sol +++ b/contracts/storage/VolumeRestrictionTMStorage.sol @@ -1,7 +1,5 @@ pragma solidity ^0.4.24; -import "../../libraries/VolumeRestrictionLib.sol"; - /** * @title Storage layout for VolumeRestrictionTM */ @@ -11,6 +9,20 @@ contract VolumeRestrictionTMStorage { enum TypeOfPeriod { MultipleDays, OneDay, Both } + struct RestrictedHolder { + // 1 represent true & 0 for false + uint8 seen; + // Type of period will be enum index of TypeOfPeriod enum + uint8 typeOfPeriod; + // Index of the array where the holder address lives + uint128 index; + } + + struct RestrictedData { + mapping(address => RestrictedHolder) restrictedHolders; + address[] restrictedAddresses; + } + struct VolumeRestriction { // If typeOfRestriction is `Percentage` then allowedTokens will be in // the % (w.r.t to totalSupply) with a multiplier of 10**16 . else it @@ -43,11 +55,9 @@ contract VolumeRestrictionTMStorage { mapping(address => BucketDetails) internal userToBucket; // Storing the information related to default restriction mapping(address => BucketDetails) internal defaultUserToBucket; - // List of wallets that are exempted from all the restrictions applied by the this contract - /* mapping(address => bool) public exemptList; */ // Restricted data (refernce from the VolumeRestrictionLib library ) - VolumeRestrictionLib.RestrictedData holderData; - // Holde exempt index + RestrictedData holderData; + // Hold exempt index mapping(address => uint256) exemptIndex; address[] public exemptAddresses; diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 335e76d1d..0a9894032 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -543,7 +543,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [0, 0, 0], [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], [0,0,0], From 688f0a40f5f671d48fb94955a72e513e5c384b73 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 14 Jan 2019 09:34:56 -0400 Subject: [PATCH 523/582] Fix comments (#519) --- contracts/tokens/SecurityToken.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index e9782b2d1..d2aaa9b55 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -499,14 +499,14 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice Internal - adjusts totalSupply at checkpoint after minting or burning tokens + * @notice Internal - adjusts totalSupply at checkpoint before minting or burning tokens */ function _adjustTotalSupplyCheckpoints() internal { TokenLib.adjustCheckpoints(checkpointTotalSupply, totalSupply(), currentCheckpointId); } /** - * @notice Internal - adjusts token holder balance at checkpoint after a token transfer + * @notice Internal - adjusts token holder balance at checkpoint before a token transfer * @param _investor address of the token holder affected */ function _adjustBalanceCheckpoints(address _investor) internal { From 5448cb3e3cecce1a7609c92aa020a2a59e1d9d4e Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 15 Jan 2019 12:05:00 -0300 Subject: [PATCH 524/582] Removed default stable coin --- CLI/commands/sto_manager.js | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index f581b7339..4a96b1088 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -22,7 +22,6 @@ let tokenSymbol; let securityTokenRegistry; let moduleRegistry; let polyToken; -let usdToken; let securityToken; async function executeApp() { @@ -329,7 +328,7 @@ async function addressesConfigUSDTieredSTO(usdTokenRaise) { let listOfAddress; if (usdTokenRaise) { - addresses.usdToken = readlineSync.question('Enter the address (or multiple addresses separated by commas) of the USD stable coin(s) (' + usdToken.options.address + '): ', { + addresses.usdToken = readlineSync.question('Enter the address (or multiple addresses separated by commas) of the USD stable coin(s): ', { limit: function (input) { listOfAddress = input.split(','); return listOfAddress.every((addr) => { @@ -337,12 +336,7 @@ async function addressesConfigUSDTieredSTO(usdTokenRaise) { }) }, limitMessage: "Must be a valid address", - defaultInput: usdToken.options.address }); - if (addresses.usdToken == "") { - listOfAddress = [usdToken.options.address] - addresses.usdToken = [usdToken.options.address]; - } } else { listOfAddress = [] addresses.usdToken = []; @@ -978,8 +972,6 @@ async function getBalance(from, type) { return await web3.eth.getBalance(from); case gbl.constants.FUND_RAISE_TYPES.POLY: return await polyToken.methods.balanceOf(from).call(); - case gbl.constants.FUND_RAISE_TYPES.STABLE: - return await usdToken.methods.balanceOf(from).call(); } } @@ -1055,11 +1047,6 @@ async function setup() { let polytokenABI = abis.polyToken(); polyToken = new web3.eth.Contract(polytokenABI, polytokenAddress); polyToken.setProvider(web3.currentProvider); - - //TODO: Use proper DAI token here - let usdTokenAddress = await contracts.usdToken(); - usdToken = new web3.eth.Contract(polytokenABI, usdTokenAddress); - usdToken.setProvider(web3.currentProvider); } catch (err) { console.log(err) console.log('\x1b[31m%s\x1b[0m', "There was a problem getting the contracts. Make sure they are deployed to the selected network."); From 83f0afa32699b6945e66efd0d1b0bcbb51a009a8 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 16 Jan 2019 07:54:07 -0400 Subject: [PATCH 525/582] Dividend improvements (#526) * Working * Wallet change test case * Fix ether dividend tests * CLI - Update for wallet on dividends modules * Add estimated tax / amounts to getter * CLI - Update for dividends status data --- CLI/commands/dividends_manager.js | 74 +++++++++++---- .../modules/Checkpoint/DividendCheckpoint.sol | 47 +++++++-- .../Checkpoint/DividendCheckpointStorage.sol | 2 + .../Checkpoint/ERC20DividendCheckpoint.sol | 10 +- .../ERC20DividendCheckpointFactory.sol | 8 +- .../Checkpoint/EtherDividendCheckpoint.sol | 10 +- .../EtherDividendCheckpointFactory.sol | 8 +- contracts/modules/STO/USDTieredSTO.sol | 2 - contracts/modules/STO/USDTieredSTOFactory.sol | 4 +- test/e_erc20_dividends.js | 95 ++++++++++++++----- test/f_ether_dividends.js | 30 +++--- 11 files changed, 211 insertions(+), 79 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 15b624953..0b4dd8f39 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -123,14 +123,16 @@ async function configExistingModules(dividendModules) { async function dividendsManager() { console.log(chalk.blue(`Dividends module at ${currentDividendsModule.options.address}`), '\n'); + let wallet = await currentDividendsModule.methods.wallet().call(); let currentDividends = await getDividends(); let defaultExcluded = await currentDividendsModule.methods.getDefaultExcluded().call(); let currentCheckpointId = await securityToken.methods.currentCheckpointId().call(); + console.log(`- Wallet: ${wallet}`); console.log(`- Current dividends: ${currentDividends.length}`); console.log(`- Default exclusions: ${defaultExcluded.length}`); - let options = ['Create checkpoint']; + let options = ['Change wallet', 'Create checkpoint']; if (currentCheckpointId > 0) { options.push('Explore checkpoint'); } @@ -150,6 +152,9 @@ async function dividendsManager() { let selected = index != -1 ? options[index] : 'RETURN'; console.log('Selected:', selected, '\n'); switch (selected) { + case 'Change wallet': + await changeWallet(); + break; case 'Create checkpoint': await createCheckpointFromDividendModule(); break; @@ -180,6 +185,19 @@ async function dividendsManager() { await dividendsManager(); } +async function changeWallet() { + let newWallet = readlineSync.question('Enter the new account address to receive reclaimed dividends and tax: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + }); + let action = currentDividendsModule.methods.changeWallet(newWallet); + let receipt = await common.sendTransaction(action); + let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'SetWallet'); + console.log(chalk.green(`The wallet has been changed successfully!`)); +} + async function createCheckpointFromDividendModule() { let createCheckpointAction = securityToken.methods.createCheckpoint(); await common.sendTransaction(createCheckpointAction); @@ -230,8 +248,19 @@ async function manageExistingDividend(dividendIndex) { let claimedArray = progress[1]; let excludedArray = progress[2]; let withheldArray = progress[3]; - let balanceArray = progress[4]; - let amountArray = progress[5]; + let amountArray = progress[4]; + let balanceArray = progress[5]; + + // function for adding two numbers. Easy! + const add = (a, b) => { + const bnA = new web3.utils.BN(a); + const bnB = new web3.utils.BN(b); + return bnA.add(bnB).toString(); + }; + // use reduce to sum our array + let taxesToWithHeld = withheldArray.reduce(add, 0); + let claimedInvestors = claimedArray.filter(c => c).length; + let excludedInvestors = excludedArray.filter(e => e).length; console.log(`- Name: ${web3.utils.hexToUtf8(dividend.name)}`); console.log(`- Created: ${moment.unix(dividend.created).format('MMMM Do YYYY, HH:mm:ss')}`); @@ -240,11 +269,13 @@ async function manageExistingDividend(dividendIndex) { console.log(`- At checkpoint: ${dividend.checkpointId}`); console.log(`- Amount: ${web3.utils.fromWei(dividend.amount)} ${dividendTokenSymbol}`); console.log(`- Claimed amount: ${web3.utils.fromWei(dividend.claimedAmount)} ${dividendTokenSymbol}`); - console.log(`- Withheld: ${web3.utils.fromWei(dividend.totalWithheld)} ${dividendTokenSymbol}`); - console.log(`- Withheld claimed: ${web3.utils.fromWei(dividend.totalWithheldWithdrawn)} ${dividendTokenSymbol}`); + console.log(`- Taxes:`); + console.log(` To withhold: ${web3.utils.fromWei(taxesToWithHeld)} ${dividendTokenSymbol}`); + console.log(` Withheld to-date: ${web3.utils.fromWei(dividend.totalWithheld)} ${dividendTokenSymbol}`); + console.log(` Withdrawn to-date: ${web3.utils.fromWei(dividend.totalWithheldWithdrawn)} ${dividendTokenSymbol}`); console.log(`- Total investors: ${investorArray.length}`); - console.log(` Have already claimed: ${claimedArray.filter(c => c).length}`); - console.log(` Excluded: ${excludedArray.filter(e => e).length} `); + console.log(` Have already claimed: ${claimedInvestors} (${investorArray.length - excludedInvestors !== 0 ? claimedInvestors / (investorArray.length - excludedInvestors) * 100 : 0}%)`); + console.log(` Excluded: ${excludedInvestors} `); // ------------------ @@ -454,10 +485,10 @@ function showReport(_name, _tokenSymbol, _amount, _witthheld, _claimed, _investo let investor = _investorArray[i]; let excluded = _excludedArray[i]; let withdrawn = _claimedArray[i] ? 'YES' : 'NO'; - let amount = !excluded ? web3.utils.fromWei(_amountArray[i]) : 0; - let withheld = (!excluded && _claimedArray[i]) ? web3.utils.fromWei(_withheldArray[i]) : 'NA'; - let withheldPercentage = (!excluded && _claimedArray[i]) ? (withheld !== '0' ? parseFloat(withheld) / parseFloat(amount) * 100 : 0) : 'NA'; - let received = (!excluded && _claimedArray[i]) ? web3.utils.fromWei(web3.utils.toBN(_amountArray[i]).sub(web3.utils.toBN(_withheldArray[i]))) : 0; + let amount = !excluded ? web3.utils.fromWei(web3.utils.toBN(_amountArray[i]).add(web3.utils.toBN(_withheldArray[i]))) : 0; + let withheld = !excluded ? web3.utils.fromWei(_withheldArray[i]) : 'NA'; + let withheldPercentage = (!excluded) ? (withheld !== '0' ? parseFloat(withheld) / parseFloat(amount) * 100 : 0) : 'NA'; + let received = !excluded ? web3.utils.fromWei(_amountArray[i]) : 0; dataTable.push([ investor, amount, @@ -476,6 +507,8 @@ function showReport(_name, _tokenSymbol, _amount, _witthheld, _claimed, _investo console.log(`- Total amount of investors: ${_investorArray.length} `); console.log(); console.log(table(dataTable)); + console.log(); + console.log(chalk.yellow(`NOTE: If investor has not claimed the dividend yet, TAX and AMOUNT are calculated with the current values set and they might change.`)); console.log(chalk.yellow(`-----------------------------------------------------------------------------------------------------------------------------------------------------------`)); console.log(); } @@ -561,7 +594,14 @@ async function addDividendsModule() { let index = readlineSync.keyInSelect(options, 'Which dividends module do you want to add? ', { cancel: 'Return' }); if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module? `)) { - let bytes = web3.utils.fromAscii('', 16); + let wallet = readlineSync.question('Enter the account address to receive reclaimed dividends and tax: ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + }); + let configureFunction = abis.erc20DividendCheckpoint().find(o => o.name === 'configure' && o.type === 'function'); + let bytes = web3.eth.abi.encodeFunctionCall(configureFunction, [wallet]); let selectedDividendFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.DIVIDENDS, options[index]); let addModuleAction = securityToken.methods.addModule(selectedDividendFactoryAddress, bytes, 0, 0); @@ -655,11 +695,11 @@ async function selectDividend(dividends) { let result = null; let options = dividends.map(function (d) { return `${d.name} - Amount: ${ web3.utils.fromWei(d.amount)} ${dividendsType} - Status: ${ isExpiredDividend(d) ? 'Expired' : hasRemaining(d) ? 'In progress' : 'Completed'} - Token: ${ d.tokenSymbol} - Created: ${ moment.unix(d.created).format('MMMM Do YYYY, HH:mm:ss')} - Expiry: ${ moment.unix(d.expiry).format('MMMM Do YYYY, HH:mm:ss')} ` + Amount: ${web3.utils.fromWei(d.amount)} ${d.tokenSymbol} + Status: ${isExpiredDividend(d) ? 'Expired' : hasRemaining(d) ? 'In progress' : 'Completed'} + Token: ${d.tokenSymbol} + Created: ${moment.unix(d.created).format('MMMM Do YYYY, HH:mm:ss')} + Expiry: ${moment.unix(d.expiry).format('MMMM Do YYYY, HH:mm:ss')} ` }); let index = readlineSync.keyInSelect(options, 'Select a dividend:', { cancel: 'RETURN' }); diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 8f8c75e2d..30cf49c54 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -24,6 +24,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { event SetDefaultExcludedAddresses(address[] _excluded, uint256 _timestamp); event SetWithholding(address[] _investors, uint256[] _withholding, uint256 _timestamp); event SetWithholdingFixed(address[] _investors, uint256 _withholding, uint256 _timestamp); + event SetWallet(address indexed _oldWallet, address indexed _newWallet, uint256 _timestamp); modifier validDividendIndex(uint256 _dividendIndex) { require(_dividendIndex < dividends.length, "Invalid dividend"); @@ -35,12 +36,36 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { _; } + /** + * @notice Function used to intialize the contract variables + * @param _wallet Ethereum account address to receive reclaimed dividends and tax + */ + function configure( + address _wallet + ) public onlyFactory { + _setWallet(_wallet); + } + /** * @notice Init function i.e generalise function to maintain the structure of the module contract * @return bytes4 */ function getInitFunction() public pure returns (bytes4) { - return bytes4(0); + return this.configure.selector; + } + + /** + * @notice Function used to change wallet address + * @param _wallet Ethereum account address to receive reclaimed dividends and tax + */ + function changeWallet(address _wallet) external onlyOwner { + _setWallet(_wallet); + } + + function _setWallet(address _wallet) internal { + require(_wallet != address(0)); + emit SetWallet(wallet, _wallet, now); + wallet = _wallet; } /** @@ -286,17 +311,17 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @return address[] list of investors * @return bool[] whether investor has claimed * @return bool[] whether investor is excluded - * @return uint256[] amount of withheld tax + * @return uint256[] amount of withheld tax (estimate if not claimed) + * @return uint256[] amount of claim (estimate if not claimeed) * @return uint256[] investor balance - * @return uint256[] amount to be claimed including withheld tax */ function getDividendProgress(uint256 _dividendIndex) external view returns ( address[] memory investors, bool[] memory resultClaimed, bool[] memory resultExcluded, uint256[] memory resultWithheld, - uint256[] memory resultBalance, - uint256[] memory resultAmount) + uint256[] memory resultAmount, + uint256[] memory resultBalance) { require(_dividendIndex < dividends.length, "Invalid dividend"); //Get list of Investors @@ -306,15 +331,21 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { resultClaimed = new bool[](investors.length); resultExcluded = new bool[](investors.length); resultWithheld = new uint256[](investors.length); - resultBalance = new uint256[](investors.length); resultAmount = new uint256[](investors.length); + resultBalance = new uint256[](investors.length); for (uint256 i; i < investors.length; i++) { resultClaimed[i] = dividend.claimed[investors[i]]; resultExcluded[i] = dividend.dividendExcluded[investors[i]]; resultBalance[i] = ISecurityToken(securityToken).balanceOfAt(investors[i], dividend.checkpointId); if (!resultExcluded[i]) { - resultWithheld[i] = dividend.withheld[investors[i]]; - resultAmount[i] = resultBalance[i].mul(dividend.amount).div(dividend.totalSupply); + if (resultClaimed[i]) { + resultWithheld[i] = dividend.withheld[investors[i]]; + resultAmount[i] = resultBalance[i].mul(dividend.amount).div(dividend.totalSupply).sub(resultWithheld[i]); + } else { + (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, investors[i]); + resultWithheld[i] = withheld; + resultAmount[i] = claim.sub(withheld); + } } } } diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol index 85e7e789a..2ae0473ac 100644 --- a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -6,6 +6,8 @@ pragma solidity ^0.4.24; */ contract DividendCheckpointStorage { + // Address to which reclaimed dividends and withholding tax is sent + address public wallet; uint256 public EXCLUDED_ADDRESS_LIMIT = 150; bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; bytes32 public constant MANAGE = "MANAGE"; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 19be8a606..1d3c8b1bb 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -261,9 +261,8 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec dividends[_dividendIndex].reclaimed = true; Dividend storage dividend = dividends[_dividendIndex]; uint256 remainingAmount = dividend.amount.sub(dividend.claimedAmount); - address owner = IOwnable(securityToken).owner(); - require(IERC20(dividendTokens[_dividendIndex]).transfer(owner, remainingAmount), "transfer failed"); - emit ERC20DividendReclaimed(owner, _dividendIndex, dividendTokens[_dividendIndex], remainingAmount); + require(IERC20(dividendTokens[_dividendIndex]).transfer(wallet, remainingAmount), "transfer failed"); + emit ERC20DividendReclaimed(wallet, _dividendIndex, dividendTokens[_dividendIndex], remainingAmount); } /** @@ -275,9 +274,8 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec Dividend storage dividend = dividends[_dividendIndex]; uint256 remainingWithheld = dividend.totalWithheld.sub(dividend.totalWithheldWithdrawn); dividend.totalWithheldWithdrawn = dividend.totalWithheld; - address owner = IOwnable(securityToken).owner(); - require(IERC20(dividendTokens[_dividendIndex]).transfer(owner, remainingWithheld), "transfer failed"); - emit ERC20DividendWithholdingWithdrawn(owner, _dividendIndex, dividendTokens[_dividendIndex], remainingWithheld); + require(IERC20(dividendTokens[_dividendIndex]).transfer(wallet, remainingWithheld), "transfer failed"); + emit ERC20DividendWithholdingWithdrawn(wallet, _dividendIndex, dividendTokens[_dividendIndex], remainingWithheld); } } diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index bae9913b8..3935154cf 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -1,6 +1,8 @@ pragma solidity ^0.4.24; import "../../proxy/ERC20DividendCheckpointProxy.sol"; +import "../../libraries/Util.sol"; +import "../../interfaces/IBoot.sol"; import "../ModuleFactory.sol"; /** @@ -35,10 +37,14 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { * @notice Used to launch the Module with the help of factory * @return Address Contract address of the Module */ - function deploy(bytes /* _data */) external returns(address) { + function deploy(bytes _data) external returns(address) { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "insufficent allowance"); address erc20DividendCheckpoint = new ERC20DividendCheckpointProxy(msg.sender, address(polyToken), logicContract); + //Checks that _data is valid (not calling anything it shouldn't) + require(Util.getSig(_data) == IBoot(erc20DividendCheckpoint).getInitFunction(), "Invalid data"); + /*solium-disable-next-line security/no-low-level-calls*/ + require(erc20DividendCheckpoint.call(_data), "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return erc20DividendCheckpoint; diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index 81d94d3ce..2952fc955 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -200,9 +200,8 @@ contract EtherDividendCheckpoint is DividendCheckpoint { Dividend storage dividend = dividends[_dividendIndex]; dividend.reclaimed = true; uint256 remainingAmount = dividend.amount.sub(dividend.claimedAmount); - address owner = IOwnable(securityToken).owner(); - owner.transfer(remainingAmount); - emit EtherDividendReclaimed(owner, _dividendIndex, remainingAmount); + wallet.transfer(remainingAmount); + emit EtherDividendReclaimed(wallet, _dividendIndex, remainingAmount); } /** @@ -214,9 +213,8 @@ contract EtherDividendCheckpoint is DividendCheckpoint { Dividend storage dividend = dividends[_dividendIndex]; uint256 remainingWithheld = dividend.totalWithheld.sub(dividend.totalWithheldWithdrawn); dividend.totalWithheldWithdrawn = dividend.totalWithheld; - address owner = IOwnable(securityToken).owner(); - owner.transfer(remainingWithheld); - emit EtherDividendWithholdingWithdrawn(owner, _dividendIndex, remainingWithheld); + wallet.transfer(remainingWithheld); + emit EtherDividendWithholdingWithdrawn(wallet, _dividendIndex, remainingWithheld); } } diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 712292d0a..923af1c64 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -1,6 +1,8 @@ pragma solidity ^0.4.24; import "../../proxy/EtherDividendCheckpointProxy.sol"; +import "../../libraries/Util.sol"; +import "../../interfaces/IBoot.sol"; import "../ModuleFactory.sol"; /** @@ -35,10 +37,14 @@ contract EtherDividendCheckpointFactory is ModuleFactory { * @notice Used to launch the Module with the help of factory * @return address Contract address of the Module */ - function deploy(bytes /* _data */) external returns(address) { + function deploy(bytes _data) external returns(address) { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent allowance or balance"); address ethDividendCheckpoint = new EtherDividendCheckpointProxy(msg.sender, address(polyToken), logicContract); + //Checks that _data is valid (not calling anything it shouldn't) + require(Util.getSig(_data) == IBoot(ethDividendCheckpoint).getInitFunction(), "Invalid data"); + /*solium-disable-next-line security/no-low-level-calls*/ + require(ethDividendCheckpoint.call(_data), "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return ethDividendCheckpoint; diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 97345ad51..f1c959671 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -199,8 +199,6 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { address _reserveWallet, address[] _usdTokens ) external onlyOwner { - /*solium-disable-next-line security/no-block-members*/ - // require(now < startTime, "STO already started"); _modifyAddresses(_wallet, _reserveWallet, _usdTokens); } diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 3263a4fa7..1e44c7a7e 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -42,10 +42,10 @@ contract USDTieredSTOFactory is ModuleFactory { //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == IBoot(usdTieredSTO).getInitFunction(), "Invalid data"); /*solium-disable-next-line security/no-low-level-calls*/ - require(address(usdTieredSTO).call(_data), "Unsuccessfull call"); + require(usdTieredSTO.call(_data), "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(usdTieredSTO, getName(), address(this), msg.sender, setupCost, now); - return address(usdTieredSTO); + return usdTieredSTO; } /** diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index a13047fc0..1d3820991 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -3,6 +3,7 @@ import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; import { catchRevert } from "./helpers/exceptions"; import { setUpPolymathNetwork, deployERC20DividendAndVerifyed, deployGPMAndVerifyed } from "./helpers/createInstances"; +import { encodeModuleCall } from "./helpers/encodeCall"; const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); @@ -18,6 +19,7 @@ contract("ERC20DividendCheckpoint", accounts => { let account_polymath; let account_issuer; let token_owner; + let wallet; let account_investor1; let account_investor2; let account_investor3; @@ -76,6 +78,8 @@ contract("ERC20DividendCheckpoint", accounts => { const one_address = '0x0000000000000000000000000000000000000001'; + const DividendParameters = ["address"]; + before(async () => { // Accounts setup account_polymath = accounts[0]; @@ -89,6 +93,7 @@ contract("ERC20DividendCheckpoint", accounts => { account_investor4 = accounts[9]; account_temp = accounts[2]; account_manager = accounts[5]; + wallet = accounts[3]; // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -157,8 +162,9 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Should successfully attach the ERC20DividendCheckpoint with the security token - fail insufficient payment", async () => { + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); await catchRevert( - I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, bytesDividend, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) ); @@ -168,7 +174,8 @@ contract("ERC20DividendCheckpoint", accounts => { let snapId = await takeSnapshot(); await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); - const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); + const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, bytesDividend, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); @@ -182,7 +189,8 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); + const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, bytesDividend, 0, 0, { from: token_owner }); assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), @@ -844,32 +852,80 @@ contract("ERC20DividendCheckpoint", accounts => { it("Issuer reclaims withholding tax", async () => { let info = await I_ERC20DividendCheckpoint.getDividendProgress.call(3); - console.log(info); + + console.log("Address:"); + console.log(info[0][0]); + console.log(info[0][1]); + console.log(info[0][2]); + console.log(info[0][3]); + + console.log("Claimed:"); + console.log(info[1][0]); + console.log(info[1][1]); + console.log(info[1][2]); + console.log(info[1][3]); + + console.log("Excluded:"); + console.log(info[2][0]); + console.log(info[2][1]); + console.log(info[2][2]); + console.log(info[2][3]); + + console.log("Withheld:"); + console.log(info[3][0].toNumber()); + console.log(info[3][1].toNumber()); + console.log(info[3][2].toNumber()); + console.log(info[3][3].toNumber()); + + console.log("Claimed:"); + console.log(info[4][0].toNumber()); + console.log(info[4][1].toNumber()); + console.log(info[4][2].toNumber()); + console.log(info[4][3].toNumber()); + + console.log("Balance:"); + console.log(info[5][0].toNumber()); + console.log(info[5][1].toNumber()); + console.log(info[5][2].toNumber()); + console.log(info[5][3].toNumber()); + assert.equal(info[0][0], account_investor1, "account match"); assert.equal(info[0][1], account_investor2, "account match"); assert.equal(info[0][2], account_temp, "account match"); assert.equal(info[0][3], account_investor3, "account match"); + assert.equal(info[3][0].toNumber(), 0, "withheld match"); assert.equal(info[3][1].toNumber(), web3.utils.toWei("0.2", "ether"), "withheld match"); assert.equal(info[3][2].toNumber(), web3.utils.toWei("0.2", "ether"), "withheld match"); assert.equal(info[3][3].toNumber(), 0, "withheld match"); - assert.equal(info[4][0].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor1, 4)).toNumber(), "balance match"); - assert.equal(info[4][1].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor2, 4)).toNumber(), "balance match"); - assert.equal(info[4][2].toNumber(), (await I_SecurityToken.balanceOfAt(account_temp, 4)).toNumber(), "balance match"); - assert.equal(info[4][3].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor3, 4)).toNumber(), "balance match"); + assert.equal(info[4][0].toNumber(), 0, "excluded"); + assert.equal(info[4][1].toNumber(), web3.utils.toWei("1.8", "ether"), "claim match"); + assert.equal(info[4][2].toNumber(), web3.utils.toWei("0.8", "ether"), "claim match"); + assert.equal(info[4][3].toNumber(), web3.utils.toWei("7", "ether"), "claim match"); + + assert.equal(info[5][0].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor1, 4)).toNumber(), "balance match"); + assert.equal(info[5][1].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor2, 4)).toNumber(), "balance match"); + assert.equal(info[5][2].toNumber(), (await I_SecurityToken.balanceOfAt(account_temp, 4)).toNumber(), "balance match"); + assert.equal(info[5][3].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor3, 4)).toNumber(), "balance match"); - assert.equal(info[5][0].toNumber(), 0, "excluded"); - assert.equal(info[5][1].toNumber(), web3.utils.toWei("2", "ether"), "claim match"); - assert.equal(info[5][2].toNumber(), web3.utils.toWei("1", "ether"), "claim match"); - assert.equal(info[5][3].toNumber(), web3.utils.toWei("7", "ether"), "claim match"); - let issuerBalance = new BigNumber(await I_PolyToken.balanceOf(token_owner)); + let issuerBalance = new BigNumber(await I_PolyToken.balanceOf(wallet)); await I_ERC20DividendCheckpoint.withdrawWithholding(3, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BigNumber(await I_PolyToken.balanceOf(token_owner)); + let issuerBalanceAfter = new BigNumber(await I_PolyToken.balanceOf(wallet)); assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0.4", "ether")); }); + it("Issuer changes wallet address", async () => { + await catchRevert(I_ERC20DividendCheckpoint.changeWallet(token_owner, { from: wallet })); + await I_ERC20DividendCheckpoint.changeWallet(token_owner, {from: token_owner}); + let newWallet = await I_ERC20DividendCheckpoint.wallet.call(); + assert.equal(newWallet, token_owner, "Wallets match"); + await I_ERC20DividendCheckpoint.changeWallet(wallet, {from: token_owner}); + newWallet = await I_ERC20DividendCheckpoint.wallet.call(); + assert.equal(newWallet, wallet, "Wallets match"); + }); + it("Issuer unable to reclaim dividend (expiry not passed)", async () => { await catchRevert(I_ERC20DividendCheckpoint.reclaimDividend(3, { from: token_owner })); }); @@ -884,9 +940,9 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Issuer is able to reclaim dividend after expiry", async () => { - let tokenOwnerBalance = new BigNumber(await I_PolyToken.balanceOf(token_owner)); + let tokenOwnerBalance = new BigNumber(await I_PolyToken.balanceOf(wallet)); await I_ERC20DividendCheckpoint.reclaimDividend(3, { from: token_owner, gasPrice: 0 }); - let tokenOwnerAfter = new BigNumber(await I_PolyToken.balanceOf(token_owner)); + let tokenOwnerAfter = new BigNumber(await I_PolyToken.balanceOf(wallet)); assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei("7", "ether")); }); @@ -908,11 +964,6 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(index.length, 0); }); - it("Get the init data", async () => { - let tx = await I_ERC20DividendCheckpoint.getInitFunction.call(); - assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ""), 0); - }); - it("Should get the listed permissions", async () => { let tx = await I_ERC20DividendCheckpoint.getPermissions.call(); assert.equal(tx.length, 2); @@ -1098,7 +1149,7 @@ contract("ERC20DividendCheckpoint", accounts => { { from: account_manager } ); let info = await I_ERC20DividendCheckpoint.getCheckpointData.call(checkpointID); - + assert.equal(info[0][0], account_investor1, "account match"); assert.equal(info[0][1], account_investor2, "account match"); assert.equal(info[0][2], account_temp, "account match"); diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 98fd092cc..6849e9cbd 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -4,6 +4,7 @@ import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; import { setUpPolymathNetwork, deployEtherDividendAndVerifyed, deployGPMAndVerifyed } from "./helpers/createInstances"; +import { encodeModuleCall } from "./helpers/encodeCall"; const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); @@ -19,6 +20,7 @@ contract("EtherDividendCheckpoint", accounts => { let account_polymath; let account_issuer; let token_owner; + let wallet; let account_investor1; let account_investor2; let account_investor3; @@ -68,6 +70,7 @@ contract("EtherDividendCheckpoint", accounts => { const transferManagerKey = 2; const stoKey = 3; const checkpointKey = 4; + const DividendParameters = ["address"]; // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -85,6 +88,7 @@ contract("EtherDividendCheckpoint", accounts => { account_investor4 = accounts[9]; account_manager = accounts[5]; account_temp = accounts[2]; + wallet = accounts[3]; // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -156,8 +160,9 @@ contract("EtherDividendCheckpoint", accounts => { it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); await catchRevert( - I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, bytesDividend, web3.utils.toWei("500", "ether"), 0, { from: token_owner }) ); @@ -166,7 +171,8 @@ contract("EtherDividendCheckpoint", accounts => { it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); - const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); + const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, bytesDividend, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); @@ -180,7 +186,8 @@ contract("EtherDividendCheckpoint", accounts => { }); it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); + const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, bytesDividend, 0, 0, { from: token_owner }); assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), @@ -343,9 +350,9 @@ contract("EtherDividendCheckpoint", accounts => { }); it("Issuer reclaims withholding tax", async () => { - let issuerBalance = new BigNumber(await web3.eth.getBalance(token_owner)); + let issuerBalance = new BigNumber(await web3.eth.getBalance(wallet)); await I_EtherDividendCheckpoint.withdrawWithholding(0, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(token_owner)); + let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(wallet)); assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0.2", "ether")); }); @@ -491,9 +498,9 @@ contract("EtherDividendCheckpoint", accounts => { }); it("Issuer withdraws new withholding tax", async () => { - let issuerBalance = new BigNumber(await web3.eth.getBalance(token_owner)); + let issuerBalance = new BigNumber(await web3.eth.getBalance(wallet)); await I_EtherDividendCheckpoint.withdrawWithholding(2, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(token_owner)); + let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(wallet)); assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0.6", "ether")); }); @@ -699,9 +706,9 @@ contract("EtherDividendCheckpoint", accounts => { }); it("Issuer is able to reclaim dividend after expiry", async () => { - let tokenOwnerBalance = new BigNumber(await web3.eth.getBalance(token_owner)); + let tokenOwnerBalance = new BigNumber(await web3.eth.getBalance(wallet)); await I_EtherDividendCheckpoint.reclaimDividend(3, { from: token_owner, gasPrice: 0 }); - let tokenOwnerAfter = new BigNumber(await web3.eth.getBalance(token_owner)); + let tokenOwnerAfter = new BigNumber(await web3.eth.getBalance(wallet)); assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei("7", "ether")); }); @@ -781,11 +788,6 @@ contract("EtherDividendCheckpoint", accounts => { assert.equal(index.length, 0); }); - it("Get the init data", async () => { - let tx = await I_EtherDividendCheckpoint.getInitFunction.call(); - assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ""), 0); - }); - it("Should get the listed permissions", async () => { let tx = await I_EtherDividendCheckpoint.getPermissions.call(); assert.equal(tx.length, 2); From e0a60870845c4d6b58a7ef46aea35d18bbb5c4b4 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 17 Jan 2019 22:37:36 +0530 Subject: [PATCH 526/582] add the remove function during re-add of the restriction --- contracts/modules/TransferManager/VolumeRestrictionTM.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 69b036aa4..6547d1b61 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -268,6 +268,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { "Not Allowed" ); _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now); + if (individualDailyRestriction[_holder].endTime != 0) { + _removeIndividualDailyRestriction(_holder); + } individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, _startTime, From a7b1f42913c05cded01d5bf3999bb44240c5ad18 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 18 Jan 2019 12:21:30 +0530 Subject: [PATCH 527/582] add the 2.1.0 changes --- CHANGELOG.md | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cd726971..836b840d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,15 +21,21 @@ All notable changes to this project will be documented in this file. * Removed individual mappings for tier data removed in UDSTSTO. * Removed the old Proxy deployment method of USDTieredSTO and adopt the new inherited proxy deployment approach. * Bump the version to `2.1.0` -* Added `getAccreditedData` to return accredited & non-accredited investor data +* Added `getAccreditedData` to return accredited & non-accredited investor data. +* Event `TokenPurchase` has uint256 tier instead of uint8 tier. +* Event `SetAddresses` has non-indexed array of address of `_usdTokens` rather than single indexed address. +* Added `getUsdTokens()` function that returns array of accepted stable coin (usd token) addresses. +* Pass an array of `_usdToken` address in `configure` function instead of singleton address. This will require changes in bytes data generation when deploying a usdtsto through factory. ## GeneralTransferManager * `getInvestors`, `getAllInvestorsData`, `getInvestorsData` added to GTM to allow easy data queries. -* `modifyDefaults(uint64 _defaultFromTime, uint64 _defaultToTime)` added which sets a default timestamp used when `fromTime` or `toTime` are 0 +* `changeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime)` added which sets a default timestamp used when `fromTime` or `toTime` are 0. * Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`). -* General Transfer Manager: Fix for when `allowAllWhitelistIssuances` is FALSE -* General Transfer Manager: Make GTM a Proxy based implementation to reduce deployment gas costs +* Fix for when `allowAllWhitelistIssuances` is FALSE +* Make GTM a Proxy based implementation to reduce deployment gas costs * Changed the version of `GeneralTransferManagerFactory` from `1.0.0` to `2.1.0`. +* `_investor` and `_addedBy` is now indexed in the `ModifyWhitelist` event. +* Add public variable `defaults` to get the offset timing. ## Manual Approval TransferManager * Removed `0x0` check for the `_from` address to `ManualApprovalTransferManager`. This allows for the Issuer/Transfer Agent to approve a one-off mint of tokens that otherwise would not be possible. @@ -39,13 +45,35 @@ All notable changes to this project will be documented in this file. * Add `getApprovalDetails()` to get the details of the approval corresponds to `_from` and `_to` address. * Add feature to modify the details of the active approval using `modifyApproval()` & `modifyApprovalMulti()`. * Add `addManualApprovalMulti()` and `revokeManualApprovalMulti()` batch function for adding and revoking the manual approval respectively. +* Add `_description` parameter during the `addManualApproval()` function call. It will be a `bytes32` variable which depicts the cause of manual approval. +* Remove `addManualBlocking()` , `revokeManualBlocking()` functions. +* Add `getTotalApprovalsLength()` to get the number of active approvals. +* Add `getAllApprovals()` to get the details of all approvals. ## Dividends * Changed the version of `ERC20DividendCheckpointFactory` & `EtherDividendCheckpointFactory` from `1.0.0` to `2.1.0`. -* Applied proxy pattern to Dividends modules +* Applied proxy pattern to Dividends modules. +* During the launch of dividend module issuer need to pass the reclaimed wallet that receive the left over funds from the module. +i.e pass `_wallet` in `configure()` function of dividend module. It emits `SetWallet` event for the confirmation of the same. +* Add `changeWallet()` function to change the reclaimed wallet address (only be called by the owner). +* Add `getDividendsData()` getter to receive the details about all the dividend. +* Add `getDividendData()` getter to receive the details about the particular dividend by passing a corresponding dividend index. +* Add `getDividendProgress()` getter to retrieves the list of investors and their details corresponds to particular dividend. +* Add `getCheckpointData()` use to retrieves list of investors, their balances, and their current withholding tax percentage corresponds to checkpointId. +* `isExcluded()` a view function added to check whether an address is excluded from claming a dividend or not. +* `isClaimed()` a view function added to checks whether an address has claimed a dividend or not. +* DividendIndex is indexed in the events `ERC20DividendClaimed`, `ERC20DividendReclaimed`, `ERC20DividendWithholdingWithdrawn`. Similarly for the Ether dividend module `EtherDividendClaimed`, `EtherDividendReclaimed`, `EtherDividendClaimFailed`, `EtherDividendWithholdingWithdrawn`. +* `EXCLUDED_ADDRESS_LIMIT` changed from 50 to 150. ## Experimental modules * Remove the `SingleTradeVolumeRestrictionTMFactory.sol` and its corresponding module `SingleTradeVolumeRestrictionTM.sol`. +* Add the new TM called `BlacklistTransferManager.sol` and its corresponding factory `BlacklistTransferManagerFactory.sol`. +* Chnage the name of module from `LockupVolumeRestrictionTM.sol` to `LockUpTransferManager.sol`, similarly factory become `LockUpTransferManagerFactory.sol`. +* Add new module called `VestingEscrowWallet.sol` and its corresponding factory `VestingEscrowWalletFactory.sol`. + +## STR & MR +* `getArrayAddress(), getArrayBytes32(), getArrayUint()` are now public getters. +* `getUintValues(), getBoolValues(), getStringValues(), getAddressValues(), getBytes32Values(), getBytesValues()` rename to `getUintValue(), getBoolValue(), getStringValue(), getAddressValue(), getBytes32Value(), getBytesValue()`. #488 ## Added * Add new module called `VolumeRestrictionTM.sol` under the TransferManager modules list. It will be used to restrict the token From 47df79159cd73a2a7d6783530a44fd77efb68f6b Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 23 Jan 2019 09:42:20 -0500 Subject: [PATCH 528/582] Lockup typos and fixes --- CLI/commands/transfer_manager.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 5b621950b..bf05d1141 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -2302,16 +2302,15 @@ async function manageExistingLockups(lockupName) { console.log(`- Currently unlocked: ${web3.utils.fromWei(currentLockup.unlockedAmount)} ${tokenSymbol}`); console.log(`- Start time: ${moment.unix(currentLockup.startTime).format('MMMM Do YYYY, HH:mm:ss')}`); console.log(`- Lockup period: ${currentLockup.lockUpPeriodSeconds} seconds`); - console.log(`- End time: ${moment.unix(currentLockup.endTime).add(parseInt(currentLockup.lockUpPeriodSeconds)).format('MMMM Do YYYY, HH:mm:ss')}`); - console.log(`- Release frequency: ${currentLockup.releaseFrequencySeconds} senconds`); + console.log(`- End time: ${moment.unix(currentLockup.startTime).add(parseInt(currentLockup.lockUpPeriodSeconds), 'seconds').format('MMMM Do YYYY, HH:mm:ss')}`); console.log(`- Release frequency: ${currentLockup.releaseFrequencySeconds} seconds`); console.log(`- Investors: ${investors.length}`); // ------------------ let options = [ 'Modify properties', 'Show investors', - 'Add this lockup to investors', - 'Remove this lockup from investors', + 'Add investors to this lockup', + 'Remove investors from this lockup', 'Delete this lockup type' ]; @@ -2325,7 +2324,7 @@ async function manageExistingLockups(lockupName) { let startTime = readlineSync.questionInt(`Enter the start time (Unix Epoch time) of the lockup type (a minute from now = ${minuteFromNow}): `, { defaultInput: minuteFromNow }); let lockUpPeriodSeconds = readlineSync.questionInt(`Enter the total period (seconds) of the lockup type (ten minutes = 600): `, { defaultInput: 600 }); let releaseFrequencySeconds = readlineSync.questionInt(`Enter how often to release a tranche of tokens in seconds (one minute = 60): `, { defaultInput: 60 }); - let modifyLockUpTypeAction = currentTransferManager.methods.modifyLockUpType(lockupAmount, startTime, lockUpPeriodSeconds, releaseFrequencySeconds, lockupName); + let modifyLockUpTypeAction = currentTransferManager.methods.modifyLockUpType(web3.utils.toWei(lockupAmount.toString()), startTime, lockUpPeriodSeconds, releaseFrequencySeconds, lockupName); let modifyLockUpTypeReceipt = await common.sendTransaction(modifyLockUpTypeAction); let modifyLockUpTypeEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyLockUpTypeReceipt.logs, 'ModifyLockUpType'); console.log(chalk.green(`${web3.utils.hexToUtf8(modifyLockUpTypeEvent._lockupName)} lockup type has been modified successfully!`)); From ddd72ea61762f7897754085ebccade06d7626a29 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 1 Feb 2019 22:30:00 +0530 Subject: [PATCH 529/582] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d518d6f8e..ac5e5b0f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "polymath-core", - "version": "2.0.0", + "version": "2.1.0", "description": "Polymath Network Core Smart Contracts", "main": "truffle.js", "directories": { From 511f404f8bd5e5338bd010744bded5e68d82f0f7 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 4 Feb 2019 21:40:24 +0530 Subject: [PATCH 530/582] add getAllLockupData getter --- .../TransferManager/LockUpTransferManager.sol | 32 ++++++++++++++++++- test/w_lockup_transfer_manager.js | 4 +++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol index 85ae126fa..93f271420 100644 --- a/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol @@ -348,7 +348,7 @@ contract LockUpTransferManager is ITransferManager { * @notice Get a specific element in a user's lockups array given the user's address and the element index * @param _lockupName The name of the lockup */ - function getLockUp(bytes32 _lockupName) external view returns ( + function getLockUp(bytes32 _lockupName) public view returns ( uint256 lockupAmount, uint256 startTime, uint256 lockUpPeriodSeconds, @@ -385,6 +385,36 @@ contract LockUpTransferManager is ITransferManager { return lockupArray; } + /** + * @notice Return the data of the lockups + */ + function getAllLockupData() external view returns( + bytes32[] memory, + uint256[] memory, + uint256[] memory, + uint256[] memory, + uint256[] memory, + uint256[] memory + ) + { + uint256[] memory lockupAmounts = new uint256[](lockupArray.length); + uint256[] memory startTimes = new uint256[](lockupArray.length); + uint256[] memory lockUpPeriodSeconds = new uint256[](lockupArray.length); + uint256[] memory releaseFrequencySeconds = new uint256[](lockupArray.length); + uint256[] memory unlockedAmounts = new uint256[](lockupArray.length); + for (uint256 i = 0; i < lockupArray.length; i++) { + (lockupAmounts[i], startTimes[i], lockUpPeriodSeconds[i], releaseFrequencySeconds[i], unlockedAmounts[i]) = getLockUp(lockupArray[i]); + } + return ( + lockupArray, + lockupAmounts, + startTimes, + lockUpPeriodSeconds, + releaseFrequencySeconds, + unlockedAmounts + ); + } + /** * @notice get the list of the lockups for a given user * @param _user Address of the user diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js index 27924eb20..41f9ea61e 100644 --- a/test/w_lockup_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -940,6 +940,10 @@ contract('LockUpTransferManager', accounts => { ); }) + it("Should get the data of all lockups", async() => { + console.log(await I_LockUpTransferManager.getAllLockupData.call()); + }); + it("Should succesfully get the non existed lockup value, it will give everything 0", async() => { let data = await I_LockUpTransferManager.getLockUp(9); assert.equal(data[0], 0); From e36e38aae7916801a6ffbdb7181517a9546e384c Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 5 Feb 2019 09:11:09 -0300 Subject: [PATCH 531/582] CLI - Added support to new lockup getter --- CLI/commands/transfer_manager.js | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 39af92b78..a85613bdf 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -2209,7 +2209,7 @@ async function lockUpTransferManager() { let options = ['Add new lockup']; if (currentLockups.length > 0) { - options.push('Manage existing lockups', 'Explore investor'); + options.push('Show all existing lockups', 'Manage existing lockups', 'Explore investor'); } options.push('Operate with multiple lockups'); @@ -2256,6 +2256,16 @@ async function lockUpTransferManager() { console.log(chalk.green(`${web3.utils.hexToUtf8(addLockupTypeEvent._lockupName)} lockup type has been added successfully!`)); } break; + case 'Show all existing lockups': + let allLockups = await currentTransferManager.methods.getAllLockupData().call(); + let nameArray = allLockups[0]; + let amountArray = allLockups[1]; + let startTimeArray = allLockups[2]; + let periodSecondsArray = allLockups[3]; + let releaseFrequencySecondsArray = allLockups[4]; + let unlockedAmountsArray = allLockups[5]; + showLockupTable(nameArray, amountArray, startTimeArray, periodSecondsArray, releaseFrequencySecondsArray, unlockedAmountsArray); + break; case 'Manage existing lockups': let options = currentLockups.map(b => web3.utils.hexToUtf8(b)); let index = readlineSync.keyInSelect(options, 'Which lockup type do you want to manage? ', { cancel: 'RETURN' }); @@ -2291,6 +2301,22 @@ async function lockUpTransferManager() { await lockUpTransferManager(); } +function showLockupTable(nameArray, amountArray, startTimeArray, periodSecondsArray, releaseFrequencySecondsArray, unlockedAmountsArray) { + let dataTable = [['Lockup Name', `Amount (${tokenSymbol})`, 'Start time', 'Period (seconds)', 'Release frequency (seconds)', `Unlocked amount (${tokenSymbol})`]]; + for (let i = 0; i < nameArray.length; i++) { + dataTable.push([ + web3.utils.hexToUtf8(nameArray[i]), + web3.utils.fromWei(amountArray[i]), + moment.unix(startTimeArray[i]).format('MM/DD/YYYY HH:mm'), + periodSecondsArray[i], + releaseFrequencySecondsArray[i], + web3.utils.fromWei(unlockedAmountsArray[i]) + ]); + } + console.log(); + console.log(table(dataTable)); +} + async function manageExistingLockups(lockupName) { console.log('\n', chalk.blue(`Lockup ${web3.utils.hexToUtf8(lockupName)}`), '\n'); @@ -2464,6 +2490,7 @@ async function addLockupsInBatch() { for (let batch = 0; batch < batches.length; batch++) { console.log(`Batch ${batch + 1} - Attempting to add the following lockups: \n\n`, lockupNameArray[batch], '\n'); lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + amountArray[batch] = amountArray[batch].map(n => web3.utils.toWei(n.toString())); let action = currentTransferManager.methods.addNewLockUpTypeMulti(amountArray[batch], startTimeArray[batch], lockUpPeriodArray[batch], releaseFrequencyArray[batch], lockupNameArray[batch]); let receipt = await common.sendTransaction(action); console.log(chalk.green('Add multiple lockups transaction was successful.')); @@ -2498,6 +2525,7 @@ async function modifyLockupsInBatch() { for (let batch = 0; batch < batches.length; batch++) { console.log(`Batch ${batch + 1} - Attempting to modify the following lockups: \n\n`, lockupNameArray[batch], '\n'); lockupNameArray[batch] = lockupNameArray[batch].map(n => web3.utils.toHex(n)); + amountArray[batch] = amountArray[batch].map(n => web3.utils.toWei(n.toString())); let action = currentTransferManager.methods.modifyLockUpTypeMulti(amountArray[batch], startTimeArray[batch], lockUpPeriodArray[batch], releaseFrequencyArray[batch], lockupNameArray[batch]); let receipt = await common.sendTransaction(action); console.log(chalk.green('Modify multiple lockups transaction was successful.')); From 3bea43c4aefdab0de50c348dd753556e7263a710 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 5 Feb 2019 09:22:56 -0300 Subject: [PATCH 532/582] KYC date text improved --- CLI/commands/transfer_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index bf05d1141..d7538b01f 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -397,7 +397,7 @@ async function generalTransferManager() { let fromTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens (now = ${now}): `, { defaultInput: now }); let toTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (now = ${now}): `, { defaultInput: now }); let oneYearFromNow = Math.floor(Date.now() / 1000 + (60 * 60 * 24 * 365)); - let expiryTime = readlineSync.questionInt(`Enter the time till investors KYC will be validated (after that investor need to do re - KYC) (1 year from now = ${oneYearFromNow}): `, { defaultInput: oneYearFromNow }); + let expiryTime = readlineSync.questionInt(`Enter the time until the investors KYC will be valid (after this time expires, the investor must re-do KYC) (1 year from now = ${oneYearFromNow}): `, { defaultInput: oneYearFromNow }); let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); From 3ca197a1db716e565053f32173a61b78989df389 Mon Sep 17 00:00:00 2001 From: F O'Brien <42175565+F-OBrien@users.noreply.github.com> Date: Wed, 6 Feb 2019 10:33:05 -0300 Subject: [PATCH 533/582] Update CLI/commands/transfer_manager.js Co-Authored-By: VictorVicente --- CLI/commands/transfer_manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index d7538b01f..cc286fcdd 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -398,7 +398,7 @@ async function generalTransferManager() { let toTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (now = ${now}): `, { defaultInput: now }); let oneYearFromNow = Math.floor(Date.now() / 1000 + (60 * 60 * 24 * 365)); let expiryTime = readlineSync.questionInt(`Enter the time until the investors KYC will be valid (after this time expires, the investor must re-do KYC) (1 year from now = ${oneYearFromNow}): `, { defaultInput: oneYearFromNow }); - let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); + let canBuyFromSTO = readlineSync.keyInYNStrict('Can the investor buy from security token offerings?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); let modifyWhitelistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); @@ -2750,4 +2750,4 @@ module.exports = { currentTransferManager.setProvider(web3.currentProvider); return modifyWhitelistInBatch(_csvFilePath, _batchSize); } -} \ No newline at end of file +} From a742e6764d9dc5aab18805defc304f129d10bd74 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 6 Feb 2019 11:17:37 -0300 Subject: [PATCH 534/582] Allowance method fix --- CLI/commands/ST20Generator.js | 8 ++++---- CLI/commands/investor_portal.js | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 0863c727e..2b9311172 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -187,13 +187,13 @@ async function selectTicker() { async function approvePoly(spender, fee) { polyBalance = await polyToken.methods.balanceOf(Issuer.address).call(); - let requiredAmount = web3.utils.toWei(fee.toString(), "ether"); + let requiredAmount = web3.utils.toWei(fee.toString()); if (parseInt(polyBalance) >= parseInt(requiredAmount)) { - let allowance = await polyToken.methods.allowance(spender, Issuer.address).call(); - if (allowance == web3.utils.toWei(fee.toString(), "ether")) { + let allowance = await polyToken.methods.allowance(Issuer.address, spender).call(); + if (parseInt(allowance) >= parseInt(requiredAmount)) { return true; } else { - let approveAction = polyToken.methods.approve(spender, web3.utils.toWei(fee.toString(), "ether")); + let approveAction = polyToken.methods.approve(spender, requiredAmount); await common.sendTransaction(approveAction); } } else { diff --git a/CLI/commands/investor_portal.js b/CLI/commands/investor_portal.js index 0bf12342a..124d0d297 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -498,8 +498,8 @@ async function investCappedSTO(currency, amount) { if (raiseTypes[0] == 'POLY') { let userBalance = await polyBalance(User.address); if (parseInt(userBalance) >= parseInt(cost)) { - let allowance = await polyToken.methods.allowance(STOAddress, User.address).call(); - if (allowance < costWei) { + let allowance = await polyToken.methods.allowance(User.address, STOAddress).call(); + if (parseInt(allowance) < parseInt(costWei)) { let approveAction = polyToken.methods.approve(STOAddress, costWei); await common.sendTransaction(approveAction, { from: User }); } @@ -607,8 +607,8 @@ async function investUsdTieredSTO(currency, amount) { if (raiseType == POLY) { let userBalance = await polyBalance(User.address); if (parseInt(userBalance) >= parseInt(cost)) { - let allowance = await polyToken.methods.allowance(STOAddress, User.address).call(); - if (allowance < costWei) { + let allowance = await polyToken.methods.allowance(User.address, STOAddress).call(); + if (parseInt(allowance) < parseInt(costWei)) { let approveAction = polyToken.methods.approve(STOAddress, costWei); await common.sendTransaction(approveAction, { from: User }); } @@ -628,8 +628,8 @@ async function investUsdTieredSTO(currency, amount) { if (parseInt(stableInfo.balance) >= parseInt(cost)) { let stableCoin = common.connect(abis.erc20(), stableInfo.address); - let allowance = await stableCoin.methods.allowance(STOAddress, User.address).call(); - if (allowance < costWei) { + let allowance = await stableCoin.methods.allowance(User.address, STOAddress).call(); + if (parseInt(allowance) < parseInt(costWei)) { let approveAction = stableCoin.methods.approve(STOAddress, costWei); await common.sendTransaction(approveAction, { from: User }); } From 0973815dbf1283eb897282392aaf27a9964481aa Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 6 Feb 2019 11:30:42 -0300 Subject: [PATCH 535/582] Minor change --- CLI/commands/token_manager.js | 2 +- CLI/commands/transfer_manager.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 4b667b54c..8ceb3bb4f 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -297,7 +297,7 @@ async function mintTokens() { let fromTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the sale lockup period ends and the investor can freely sell his tokens: '); let toTime = readlineSync.questionInt('Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others: '); let expiryTime = readlineSync.questionInt('Enter the time till investors KYC will be validated (after that investor need to do re-KYC): '); - let canBuyFromSTO = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); + let canBuyFromSTO = readlineSync.keyInYNStrict('Can the investor buy from security token offerings?'); await modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); break; case 'Mint tokens to a single address': diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index e163bf0b5..5a5b148ca 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -398,7 +398,7 @@ async function generalTransferManager() { let toTime = readlineSync.questionInt(`Enter the time (Unix Epoch time) when the purchase lockup period ends and the investor can freely purchase tokens from others (now = ${now}): `, { defaultInput: now }); let oneYearFromNow = Math.floor(Date.now() / 1000 + (60 * 60 * 24 * 365)); let expiryTime = readlineSync.questionInt(`Enter the time until the investors KYC will be valid (after this time expires, the investor must re-do KYC) (1 year from now = ${oneYearFromNow}): `, { defaultInput: oneYearFromNow }); - let canBuyFromSTO = readlineSync.keyInYNStrict('Can the investor buy from security token offerings?'); + let canBuyFromSTO = readlineSync.keyInYNStrict('Can the investor buy from security token offerings?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); let modifyWhitelistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); @@ -421,7 +421,7 @@ async function generalTransferManager() { let vSigned = readlineSync.questionInt('Enter v: '); let rSigned = readlineSync.question('Enter r: '); let sSigned = readlineSync.question('Enter s: '); - let canBuyFromSTOSigned = readlineSync.keyInYNStrict('Is the investor a restricted investor?'); + let canBuyFromSTOSigned = readlineSync.keyInYNStrict('Can the investor buy from security token offerings?'); let modifyWhitelistSignedAction = currentTransferManager.methods.modifyWhitelistSigned(investorSigned, fromTimeSigned, toTimeSigned, expiryTimeSigned, canBuyFromSTOSigned); let modifyWhitelistSignedReceipt = await common.sendTransaction(Issuer, modifyWhitelistSignedAction, defaultGasPrice); let modifyWhitelistSignedEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistSignedReceipt.logs, 'ModifyWhitelist'); From 3c4531c44996acf319c9a9de0511dd0fb9c3923a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 7 Feb 2019 10:01:34 +0530 Subject: [PATCH 536/582] Initial auto deploy --- .circleci/config.yml | 29 +++++++++++++++++++++++++++++ truffle-ci.js | 7 +++++++ 2 files changed, 36 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 841b807b6..71a6bc1ba 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -57,6 +57,24 @@ jobs: - node_modules - store_artifacts: path: ./coverage/lcov.info + deploy_kovan: + docker: + - image: maxsam4/solidity-kit:0.4.24 + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package.json" }} + - run: yarn install + - run: node --version + - run: truffle version + - run: mv truffle-ci.js truffle-config.js + - run: + command: truffle deploy --network kovan + no_output_timeout: 1h + - save_cache: + key: dependency-cache-{{ checksum "package.json" }} + paths: + - node_modules docs: docker: - image: circleci/node:8 @@ -78,6 +96,7 @@ workflows: commit: jobs: - coverage + - deploy_kovan daily-builds: triggers: - schedule: @@ -98,3 +117,13 @@ workflows: branches: only: - master + deploy: + jobs: + - deploy_kovan: + filters: + branches: + only: + - master + - dev-2.1.0 + - dev-2.2.0 + - dev-3.0.0 diff --git a/truffle-ci.js b/truffle-ci.js index 049deb0c6..0a5157c33 100644 --- a/truffle-ci.js +++ b/truffle-ci.js @@ -9,6 +9,13 @@ module.exports = { network_id: '*', // Match any network id gas: 7900000, }, + kovan: { + provider: () => { + return new HDWalletProvider(process.env.PRIVATE_KEY, "https://kovan.mudit.blog/"); + }, + network_id: '42', + gasPrice: 2000000000 + }, coverage: { host: "localhost", network_id: "*", From e6fb8bfd3c59e45d8189916e3644aa2a71dca5ee Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 7 Feb 2019 10:08:33 +0530 Subject: [PATCH 537/582] HDWalletProvider --- package.json | 1 + truffle-ci.js | 2 ++ yarn.lock | 45 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index ac5e5b0f9..9641338b9 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "solidity-docgen": "^0.1.0", "solium": "^1.1.8", "truffle": "4.1.14", + "truffle-hdwallet-provider": "^1.0.3", "truffle-wallet-provider": "0.0.5" }, "greenkeeper": { diff --git a/truffle-ci.js b/truffle-ci.js index 0a5157c33..f6d2bf7ae 100644 --- a/truffle-ci.js +++ b/truffle-ci.js @@ -1,6 +1,8 @@ require('babel-register'); require('babel-polyfill'); +let HDWalletProvider = require("truffle-hdwallet-provider"); + module.exports = { networks: { development: { diff --git a/yarn.lock b/yarn.lock index 39e3b7bb3..99f339018 100644 --- a/yarn.lock +++ b/yarn.lock @@ -253,7 +253,7 @@ async-eventemitter@^0.2.2: dependencies: async "^2.4.0" -"async-eventemitter@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c": +async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c: version "0.2.3" resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c" dependencies: @@ -1024,13 +1024,13 @@ bignumber.js@^8.0.1: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.0.1.tgz#5d419191370fb558c64e3e5f70d68e5947138832" integrity sha512-zAySveTJXkgLYCBi0b14xzfnOs+f3G6x36I8w2a1+PFQpWk/dp0mI0F+ZZK2bu+3ELewDcSyP+Cfq++NcHX7sg== -"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": +"bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" - resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9" -"bignumber.js@git+https://github.com/debris/bignumber.js.git#master": +"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": version "2.0.7" - resolved "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9" + resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" "bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git": version "2.0.7" @@ -1046,6 +1046,13 @@ bindings@^1.2.1: resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.1.tgz#21fc7c6d67c18516ec5aaa2815b145ff77b26ea5" integrity sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew== +bindings@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.4.0.tgz#909efa49f2ebe07ecd3cb136778f665052040127" + integrity sha512-7znEVX22Djn+nYjxCWKDne0RRloa9XfYa84yk3s+HkE3LpDYZmhArYr9O9huBoHY3/oXispx5LorIX7Sl2CgSQ== + dependencies: + file-uri-to-path "1.0.0" + bip66@^1.1.3: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" @@ -3030,6 +3037,11 @@ file-type@^6.1.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -4810,7 +4822,7 @@ nan@2.10.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== -nan@^2.0.8, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: +nan@^2.0.8, nan@^2.11.0, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: version "2.12.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== @@ -6871,6 +6883,15 @@ truffle-hdwallet-provider-privkey@0.3.0: web3 "^0.20.6" web3-provider-engine "^13.8.0" +truffle-hdwallet-provider@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-1.0.3.tgz#4ae845f9b2de23f47c4f0fbc6ef2d4b13b494604" + integrity sha512-Lm4MrXHnWg8wHNUoumUBc8AhlCBg05x7wZA81JOFfO0j3QU53A/hhSfV7v8gANbRsvpF5Su0s3SNQGJjewtnYw== + dependencies: + any-promise "^1.3.0" + bindings "^1.3.1" + websocket "^1.0.28" + truffle-wallet-provider@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-wallet-provider/-/truffle-wallet-provider-0.0.5.tgz#db59ce6fa1c558766011137509a94dfca8d1408e" @@ -6943,7 +6964,7 @@ typechecker@~2.0.1: resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.0.8.tgz#e83da84bb64c584ccb345838576c40b0337db82e" integrity sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4= -typedarray-to-buffer@^3.1.2: +typedarray-to-buffer@^3.1.2, typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== @@ -7450,6 +7471,16 @@ web3@^0.20.6: xhr2-cookies "^1.1.0" xmlhttprequest "*" +websocket@^1.0.28: + version "1.0.28" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.28.tgz#9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3" + integrity sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA== + dependencies: + debug "^2.2.0" + nan "^2.11.0" + typedarray-to-buffer "^3.1.5" + yaeti "^0.0.6" + "websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": version "1.0.26" resolved "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" From ad72cc226ceedcd2b29cd424863a8ca1663e438f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 7 Feb 2019 10:14:22 +0530 Subject: [PATCH 538/582] Use local truffle --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 71a6bc1ba..ef877b4db 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,7 +69,7 @@ jobs: - run: truffle version - run: mv truffle-ci.js truffle-config.js - run: - command: truffle deploy --network kovan + command: node_modules/.bin/truffle deploy --network kovan no_output_timeout: 1h - save_cache: key: dependency-cache-{{ checksum "package.json" }} From 5c10dfbebf8b4506886ea71868803d2f8caddf5c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 7 Feb 2019 10:30:39 +0530 Subject: [PATCH 539/582] Deploy only on dev and master branches --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ef877b4db..2935ae4af 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -96,7 +96,6 @@ workflows: commit: jobs: - coverage - - deploy_kovan daily-builds: triggers: - schedule: From f775272bc507cd9367088414bf55880d53715b46 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Sat, 9 Feb 2019 12:06:36 +0530 Subject: [PATCH 540/582] Added deploy script --- scripts/deploy.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100755 scripts/deploy.sh diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100755 index 000000000..f961fb5fd --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +node_modules/.bin/truffle deploy --network kovan +address=$(grep build/contracts/PolymathRegistry.json -e "\"address\":" | grep -o "0[0-9a-z]*") +commitId=$(git rev-parse HEAD) +branchName=$(git rev-parse --abbrev-ref HEAD) +commitName=$(git log -1 --pretty=%B) +data='{"text":"Somebody merged a new pull request!\nBranch Name: '$branchName'\nCommit Name: '$commitName'\nCommit ID: '$commitId'\nPolymath Registry Address(Kovan): '$address'"}' +curl -X POST -H 'Content-type: application/json' --data "$data" ${SLACK_DEVNOTIFACTIONS_WH} \ No newline at end of file From 287fe50e4d64b1addcde3b29719c045f7ab67c7b Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Sat, 9 Feb 2019 12:10:44 +0530 Subject: [PATCH 541/582] Enabled deployment on commit --- .circleci/config.yml | 5 ++--- package.json | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2935ae4af..b3e81a7e7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -68,9 +68,7 @@ jobs: - run: node --version - run: truffle version - run: mv truffle-ci.js truffle-config.js - - run: - command: node_modules/.bin/truffle deploy --network kovan - no_output_timeout: 1h + - run: npm run deploy-kovan - save_cache: key: dependency-cache-{{ checksum "package.json" }} paths: @@ -96,6 +94,7 @@ workflows: commit: jobs: - coverage + - deploy_kovan daily-builds: triggers: - schedule: diff --git a/package.json b/package.json index 9641338b9..fbaf43ed0 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "scripts": { "test": "scripts/test.sh 2> /dev/null", + "deploy-kovan": "scripts/deploy.sh", "wintest": "scripts\\wintest.cmd", "wincov": "scripts\\wincov.cmd", "docs": "scripts/docs.sh", From 2967a6cb492f4c318bccc15e929c957630d5b285 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Sat, 9 Feb 2019 12:22:56 +0530 Subject: [PATCH 542/582] Deploy only on dev/master branches --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b3e81a7e7..da2111136 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -94,7 +94,6 @@ workflows: commit: jobs: - coverage - - deploy_kovan daily-builds: triggers: - schedule: From 577dd46139214ad0ffa4af1f3c439ab6136cbcf3 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 6 Mar 2019 12:20:11 -0300 Subject: [PATCH 543/582] Fix reading factory address from module registry for dividends modules --- CLI/commands/dividends_manager.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 0b4dd8f39..9f091d7dc 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -586,14 +586,18 @@ to account ${ event._claimer} ` async function addDividendsModule() { let availableModules = await moduleRegistry.methods.getModulesByTypeAndToken(gbl.constants.MODULES_TYPES.DIVIDENDS, securityToken.options.address).call(); - let options = await Promise.all(availableModules.map(async function (m) { + let moduleList = await Promise.all(availableModules.map(async function (m) { let moduleFactoryABI = abis.moduleFactory(); let moduleFactory = new web3.eth.Contract(moduleFactoryABI, m); - return web3.utils.hexToUtf8(await moduleFactory.methods.name().call()); + let moduleName = web3.utils.hexToUtf8(await moduleFactory.methods.name().call()); + let moduleVersion = await moduleFactory.methods.version().call(); + return { name: moduleName, version: moduleVersion, factoryAddress: m }; })); + let options = moduleList.map(m => `${m.name} - ${m.version} (${m.factoryAddress})`); + let index = readlineSync.keyInSelect(options, 'Which dividends module do you want to add? ', { cancel: 'Return' }); - if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]} module? `)) { + if (index != -1 && readlineSync.keyInYNStrict(`Are you sure you want to add ${options[index]}? `)) { let wallet = readlineSync.question('Enter the account address to receive reclaimed dividends and tax: ', { limit: function (input) { return web3.utils.isAddress(input); @@ -603,7 +607,7 @@ async function addDividendsModule() { let configureFunction = abis.erc20DividendCheckpoint().find(o => o.name === 'configure' && o.type === 'function'); let bytes = web3.eth.abi.encodeFunctionCall(configureFunction, [wallet]); - let selectedDividendFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.DIVIDENDS, options[index]); + let selectedDividendFactoryAddress = moduleList[index].factoryAddress; let addModuleAction = securityToken.methods.addModule(selectedDividendFactoryAddress, bytes, 0, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); From fb7bfd3d86278a792ba4e681dcafbf6504f5b113 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 6 Mar 2019 15:51:54 -0300 Subject: [PATCH 544/582] Alternative symbol() ABI for ERC20 tokens --- CLI/commands/dividends_manager.js | 31 ++++++++++++++++++++------- CLI/commands/helpers/contract_abis.js | 12 +++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 9f091d7dc..f4aca926e 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -240,8 +240,7 @@ async function manageExistingDividend(dividendIndex) { let dividendTokenSymbol = 'ETH'; if (dividendsType === 'ERC20') { dividendTokenAddress = await currentDividendsModule.methods.dividendTokens(dividendIndex).call(); - let erc20token = new web3.eth.Contract(abis.erc20(), dividendTokenAddress); - dividendTokenSymbol = await erc20token.methods.symbol().call(); + dividendTokenSymbol = await getERC20TokenSymbol(dividendTokenAddress); } let progress = await currentDividendsModule.methods.getDividendProgress(dividendIndex).call(); let investorArray = progress[0]; @@ -387,10 +386,11 @@ async function createDividends() { limitMessage: "Must be a valid ERC20 address", defaultInput: polyToken.options.address }); - token = new web3.eth.Contract(abis.erc20(), dividendToken); - try { - dividendSymbol = await token.methods.symbol().call(); - } catch (err) { + let erc20Symbol = await getERC20TokenSymbol(dividendToken); + if (erc20Symbol != null) { + token = new web3.eth.Contract(abis.erc20(), dividendToken); + dividendSymbol = erc20Symbol; + } else { console.log(chalk.red(`${dividendToken} is not a valid ERC20 token address!!`)); } } while (dividendSymbol === 'ETH'); @@ -738,8 +738,7 @@ async function getDividends() { let tokenSymbol = 'ETH'; if (dividendsType === 'ERC20') { let tokenAddress = await currentDividendsModule.methods.dividendTokens(i).call(); - let erc20token = new web3.eth.Contract(abis.erc20(), tokenAddress); - tokenSymbol = await erc20token.methods.symbol().call(); + tokenSymbol = await getERC20TokenSymbol(tokenAddress); } dividends.push( new DividendData( @@ -885,6 +884,22 @@ async function selectToken() { return result; } +async function getERC20TokenSymbol(tokenAddress) { + let tokenSymbol = null; + try { + let erc20token = new web3.eth.Contract(abis.erc20(), tokenAddress); + tokenSymbol = await erc20token.methods.symbol().call(); + } catch (err) { + try { + // Some ERC20 tokens use bytes32 for symbol instead of string + let erc20token = new web3.eth.Contract(abis.alternativeErc20(), tokenAddress); + tokenSymbol = web3.utils.hexToUtf8(await erc20token.methods.symbol().call()); + } catch (err) { + } + } + return tokenSymbol; +} + module.exports = { executeApp: async function (_tokenSymbol) { await initialize(_tokenSymbol); diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index 67dc43244..f5d8064a6 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -140,5 +140,17 @@ module.exports = { }, erc20: function () { return erc20ABI; + }, + alternativeErc20: function () { + let alternativeErc20 = [{ + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [{ "name": "", "type": "bytes32" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }]; + return alternativeErc20; } } \ No newline at end of file From fd51e7abaad3d01bbf4697349e0a827fa64e356e Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 7 Mar 2019 21:45:43 +0530 Subject: [PATCH 545/582] STO fixes (#583) * Minor STO changes * typo fix * Added STO interface * Typo fixed * Refund remaining amount in last cappedsto tx --- contracts/interfaces/ISTO.sol | 11 +++++ contracts/modules/STO/CappedSTO.sol | 47 ++++++------------- contracts/modules/STO/DummySTO.sol | 4 +- contracts/modules/STO/PreSaleSTO.sol | 4 +- contracts/modules/STO/{ISTO.sol => STO.sol} | 14 ++---- .../STO/{ISTOStorage.sol => STOStorage.sol} | 6 +-- contracts/modules/STO/USDTieredSTO.sol | 32 ++++++------- contracts/proxy/USDTieredSTOProxy.sol | 4 +- contracts/storage/USDTieredSTOStorage.sol | 3 -- test/p_usd_tiered_sto.js | 3 +- 10 files changed, 57 insertions(+), 71 deletions(-) create mode 100644 contracts/interfaces/ISTO.sol rename contracts/modules/STO/{ISTO.sol => STO.sol} (87%) rename contracts/modules/STO/{ISTOStorage.sol => STOStorage.sol} (88%) diff --git a/contracts/interfaces/ISTO.sol b/contracts/interfaces/ISTO.sol new file mode 100644 index 000000000..dd5ce3f16 --- /dev/null +++ b/contracts/interfaces/ISTO.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.24; + +/** + * @title Interface to be implemented by all STO modules + */ +interface ISTO { + /** + * @notice Returns the total no. of tokens sold + */ + function getTokensSold() external view returns (uint256); +} diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index af091dacf..3245aa3f5 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./ISTO.sol"; +import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -8,7 +8,7 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title STO module for standard capped crowdsale */ -contract CappedSTO is ISTO, ReentrancyGuard { +contract CappedSTO is STO, ReentrancyGuard { using SafeMath for uint256; // Determine whether users can invest on behalf of a beneficiary @@ -51,7 +51,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @param _startTime Unix timestamp at which offering get started * @param _endTime Unix timestamp at which offering get ended * @param _cap Maximum No. of token base units for sale - * @param _rate Token units a buyer gets multiplied by 10^18 per wei / base unit of POLY + * @param _rate Token units a buyer gets multiplied by 10^18 per wei / base unit of POLY * @param _fundRaiseTypes Type of currency used to collect the funds * @param _fundsReceiver Ethereum account address to hold the funds */ @@ -115,7 +115,6 @@ contract CappedSTO is ISTO, ReentrancyGuard { weiAmount = weiAmount.sub(refund); _forwardFunds(refund); - _postValidatePurchase(_beneficiary, weiAmount); } /** @@ -127,7 +126,6 @@ contract CappedSTO is ISTO, ReentrancyGuard { require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "Mode of investment is not POLY"); uint256 refund = _processTx(msg.sender, _investedPOLY); _forwardPoly(msg.sender, wallet, _investedPOLY.sub(refund)); - _postValidatePurchase(msg.sender, _investedPOLY.sub(refund)); } /** @@ -161,7 +159,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { * @return Token units a buyer gets(multiplied by 10^18) per wei / base unit of POLY * @return Amount of funds raised * @return Number of individual investors this STO have. - * @return Amount of tokens get sold. + * @return Amount of tokens get sold. * @return Boolean value to justify whether the fund raise type is POLY or not, i.e true for POLY. */ function getSTODetails() public view returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool) { @@ -203,8 +201,6 @@ contract CappedSTO is ISTO, ReentrancyGuard { _processPurchase(_beneficiary, tokens); emit TokenPurchase(msg.sender, _beneficiary, _investedAmount, tokens); - - _updatePurchasingState(_beneficiary, _investedAmount); } /** @@ -216,21 +212,10 @@ contract CappedSTO is ISTO, ReentrancyGuard { function _preValidatePurchase(address _beneficiary, uint256 _investedAmount) internal view { require(_beneficiary != address(0), "Beneficiary address should not be 0x"); require(_investedAmount != 0, "Amount invested should not be equal to 0"); - uint256 tokens; - (tokens, ) = _getTokenAmount(_investedAmount); - require(totalTokensSold.add(tokens) <= cap, "Investment more than cap is not allowed"); /*solium-disable-next-line security/no-block-members*/ require(now >= startTime && now <= endTime, "Offering is closed/Not yet started"); } - /** - * @notice Validation of an executed purchase. - Observe state and use revert statements to undo rollback when valid conditions are not met. - */ - function _postValidatePurchase(address /*_beneficiary*/, uint256 /*_investedAmount*/) internal pure { - // optional override - } - /** * @notice Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens. @@ -255,27 +240,23 @@ contract CappedSTO is ISTO, ReentrancyGuard { _deliverTokens(_beneficiary, _tokenAmount); } - /** - * @notice Overrides for extensions that require an internal state to check for validity - (current user contributions, etc.) - */ - function _updatePurchasingState(address /*_beneficiary*/, uint256 /*_investedAmount*/) internal pure { - // optional override - } - /** * @notice Overrides to extend the way in which ether is converted to tokens. * @param _investedAmount Value in wei to be converted into tokens * @return Number of tokens that can be purchased with the specified _investedAmount * @return Remaining amount that should be refunded to the investor */ - function _getTokenAmount(uint256 _investedAmount) internal view returns (uint256 _tokens, uint256 _refund) { - _tokens = _investedAmount.mul(rate); - _tokens = _tokens.div(uint256(10) ** 18); + function _getTokenAmount(uint256 _investedAmount) internal view returns (uint256 tokens, uint256 refund) { + tokens = _investedAmount.mul(rate); + tokens = tokens.div(uint256(10) ** 18); + if (totalTokensSold.add(tokens) > cap) { + tokens = cap.sub(totalTokensSold); + } uint256 granularity = ISecurityToken(securityToken).granularity(); - _tokens = _tokens.div(granularity); - _tokens = _tokens.mul(granularity); - _refund = _investedAmount.sub((_tokens.mul(uint256(10) ** 18)).div(rate)); + tokens = tokens.div(granularity); + tokens = tokens.mul(granularity); + require(tokens > 0, "Cap reached"); + refund = _investedAmount.sub((tokens.mul(uint256(10) ** 18)).div(rate)); } /** diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index 1b44d2e9b..fafc6c1c4 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -1,12 +1,12 @@ pragma solidity ^0.4.24; -import "./ISTO.sol"; +import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; /** * @title STO module for sample implementation of a different crowdsale module */ -contract DummySTO is ISTO { +contract DummySTO is STO { bytes32 public constant ADMIN = "ADMIN"; diff --git a/contracts/modules/STO/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index 7378fb06b..4dacaa2d7 100644 --- a/contracts/modules/STO/PreSaleSTO.sol +++ b/contracts/modules/STO/PreSaleSTO.sol @@ -1,13 +1,13 @@ pragma solidity ^0.4.24; -import "./ISTO.sol"; +import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title STO module for private presales */ -contract PreSaleSTO is ISTO { +contract PreSaleSTO is STO { using SafeMath for uint256; bytes32 public constant PRE_SALE_ADMIN = "PRE_SALE_ADMIN"; diff --git a/contracts/modules/STO/ISTO.sol b/contracts/modules/STO/STO.sol similarity index 87% rename from contracts/modules/STO/ISTO.sol rename to contracts/modules/STO/STO.sol index 6fb216566..5f9a6e9e3 100644 --- a/contracts/modules/STO/ISTO.sol +++ b/contracts/modules/STO/STO.sol @@ -3,17 +3,18 @@ pragma solidity ^0.4.24; import "../../Pausable.sol"; import "../Module.sol"; import "../../interfaces/IERC20.sol"; -import "./ISTOStorage.sol"; +import "../../interfaces/ISTO.sol"; +import "./STOStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Interface to be implemented by all STO modules */ -contract ISTO is ISTOStorage, Module, Pausable { +contract STO is ISTO, STOStorage, Module, Pausable { using SafeMath for uint256; enum FundRaiseType { ETH, POLY, SC } - + // Event event SetFundRaiseTypes(FundRaiseType[] _fundRaiseTypes); @@ -36,11 +37,6 @@ contract ISTO is ISTOStorage, Module, Pausable { return fundsRaised[uint8(_fundRaiseType)]; } - /** - * @notice Returns the total no. of tokens sold - */ - function getTokensSold() public view returns (uint256); - /** * @notice Pause (overridden function) */ @@ -59,7 +55,7 @@ contract ISTO is ISTOStorage, Module, Pausable { function _setFundRaiseType(FundRaiseType[] _fundRaiseTypes) internal { // FundRaiseType[] parameter type ensures only valid values for _fundRaiseTypes - require(_fundRaiseTypes.length > 0, "Raise type is not specified"); + require(_fundRaiseTypes.length > 0 && _fundRaiseTypes.length <= 3, "Raise type is not specified"); fundRaiseTypes[uint8(FundRaiseType.ETH)] = false; fundRaiseTypes[uint8(FundRaiseType.POLY)] = false; fundRaiseTypes[uint8(FundRaiseType.SC)] = false; diff --git a/contracts/modules/STO/ISTOStorage.sol b/contracts/modules/STO/STOStorage.sol similarity index 88% rename from contracts/modules/STO/ISTOStorage.sol rename to contracts/modules/STO/STOStorage.sol index b808c98b4..2e2401fb0 100644 --- a/contracts/modules/STO/ISTOStorage.sol +++ b/contracts/modules/STO/STOStorage.sol @@ -1,9 +1,9 @@ pragma solidity ^0.4.24; /** - * @title Storage layout for the ISTO contract + * @title Storage layout for the STO contract */ -contract ISTOStorage { +contract STOStorage { mapping (uint8 => bool) public fundRaiseTypes; mapping (uint8 => uint256) public fundsRaised; @@ -21,4 +21,4 @@ contract ISTOStorage { // Final amount of tokens sold uint256 public totalTokensSold; -} \ No newline at end of file +} diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index f1c959671..c29402355 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./ISTO.sol"; +import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; import "../../interfaces/IOracle.sol"; import "../../RegistryUpdater.sol"; @@ -12,7 +12,7 @@ import "../../storage/USDTieredSTOStorage.sol"; /** * @title STO module for standard capped crowdsale */ -contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { +contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { using SafeMath for uint256; string public constant POLY_ORACLE = "PolyUsdOracle"; @@ -262,7 +262,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { } usdTokens = _usdTokens; for(i = 0; i < _usdTokens.length; i++) { - require(_usdTokens[i] != address(0), "Invalid USD token"); + require(_usdTokens[i] != address(0) && _usdTokens[i] != address(polyToken), "Invalid USD token"); usdTokenEnabled[_usdTokens[i]] = true; } emit SetAddresses(wallet, reserveWallet, _usdTokens); @@ -276,7 +276,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @notice Finalizes the STO and mint remaining tokens to reserve address * @notice Reserve address must be whitelisted to successfully finalize */ - function finalize() public onlyOwner { + function finalize() external onlyOwner { require(!isFinalized, "STO is already finalized"); isFinalized = true; uint256 tempReturned; @@ -301,7 +301,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @param _investors Array of investor addresses to modify * @param _accredited Array of bools specifying accreditation status */ - function changeAccredited(address[] _investors, bool[] _accredited) public onlyOwner { + function changeAccredited(address[] _investors, bool[] _accredited) external onlyOwner { require(_investors.length == _accredited.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { if (_accredited[i]) { @@ -319,7 +319,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @param _investors Array of investor addresses to modify * @param _nonAccreditedLimit Array of uints specifying non-accredited limits */ - function changeNonAccreditedLimit(address[] _investors, uint256[] _nonAccreditedLimit) public onlyOwner { + function changeNonAccreditedLimit(address[] _investors, uint256[] _nonAccreditedLimit) external onlyOwner { //nonAccreditedLimitUSDOverride require(_investors.length == _nonAccreditedLimit.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { @@ -357,7 +357,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @notice Function to set allowBeneficialInvestments (allow beneficiary to be different to funder) * @param _allowBeneficialInvestments Boolean to allow or disallow beneficial investments */ - function changeAllowBeneficialInvestments(bool _allowBeneficialInvestments) public onlyOwner { + function changeAllowBeneficialInvestments(bool _allowBeneficialInvestments) external onlyOwner { require(_allowBeneficialInvestments != allowBeneficialInvestments, "Value unchanged"); allowBeneficialInvestments = _allowBeneficialInvestments; emit SetAllowBeneficialInvestments(allowBeneficialInvestments); @@ -508,7 +508,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { uint256 _investmentValue, FundRaiseType _fundRaiseType ) - public + external view returns(uint256 spentUSD, uint256 spentValue, uint256 tokensMinted) { @@ -732,7 +732,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @param _amount Value to convert to USD * @return uint256 Value in USD */ - function convertToUSD(FundRaiseType _fundRaiseType, uint256 _amount) public view returns(uint256) { + function convertToUSD(FundRaiseType _fundRaiseType, uint256 _amount) external view returns(uint256) { uint256 rate = getRate(_fundRaiseType); return DecimalMath.mul(_amount, rate); } @@ -743,7 +743,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @param _amount Value to convert from USD * @return uint256 Value in ETH or POLY */ - function convertFromUSD(FundRaiseType _fundRaiseType, uint256 _amount) public view returns(uint256) { + function convertFromUSD(FundRaiseType _fundRaiseType, uint256 _amount) external view returns(uint256) { uint256 rate = getRate(_fundRaiseType); return DecimalMath.div(_amount, rate); } @@ -776,7 +776,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * param _fundRaiseType The fund raising currency (e.g. ETH, POLY, SC) to calculate sold tokens for * @return uint256 Total number of tokens sold for ETH */ - function getTokensSoldFor(FundRaiseType _fundRaiseType) public view returns (uint256) { + function getTokensSoldFor(FundRaiseType _fundRaiseType) external view returns (uint256) { uint256 tokensSold; for (uint256 i = 0; i < tiers.length; i++) { tokensSold = tokensSold.add(tiers[i].minted[uint8(_fundRaiseType)]); @@ -789,7 +789,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * param _tier The tier to return minted tokens for * @return uint256[] array of minted tokens in each fund raise type */ - function getTokensMintedByTier(uint256 _tier) public view returns (uint256[]) { + function getTokensMintedByTier(uint256 _tier) external view returns (uint256[]) { require(_tier < tiers.length, "Invalid tier"); uint256[] memory tokensMinted = new uint256[](3); tokensMinted[0] = tiers[_tier].minted[uint8(FundRaiseType.ETH)]; @@ -803,7 +803,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * param _tier The tier to calculate sold tokens for * @return uint256 Total number of tokens sold in the tier */ - function getTokensSoldByTier(uint256 _tier) public view returns (uint256) { + function getTokensSoldByTier(uint256 _tier) external view returns (uint256) { require(_tier < tiers.length, "Incorrect tier"); uint256 tokensSold; tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.ETH)]); @@ -816,7 +816,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @notice Return the total no. of tiers * @return uint256 Total number of tiers */ - function getNumberOfTiers() public view returns (uint256) { + function getNumberOfTiers() external view returns (uint256) { return tiers.length; } @@ -824,7 +824,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @notice Return the usd tokens accepted by the STO * @return address[] usd tokens */ - function getUsdTokens() public view returns (address[]) { + function getUsdTokens() external view returns (address[]) { return usdTokens; } @@ -848,7 +848,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @return Amount of tokens sold. * @return Array of bools to show if funding is allowed in ETH, POLY, SC respectively */ - function getSTODetails() public view returns(uint256, uint256, uint256, uint256[], uint256[], uint256, uint256, uint256, bool[]) { + function getSTODetails() external view returns(uint256, uint256, uint256, uint256[], uint256[], uint256, uint256, uint256, bool[]) { uint256[] memory cap = new uint256[](tiers.length); uint256[] memory rate = new uint256[](tiers.length); for(uint256 i = 0; i < tiers.length; i++) { diff --git a/contracts/proxy/USDTieredSTOProxy.sol b/contracts/proxy/USDTieredSTOProxy.sol index a412a8278..050e14a21 100644 --- a/contracts/proxy/USDTieredSTOProxy.sol +++ b/contracts/proxy/USDTieredSTOProxy.sol @@ -4,13 +4,13 @@ import "../storage/USDTieredSTOStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; -import "../modules/STO/ISTOStorage.sol"; +import "../modules/STO/STOStorage.sol"; import "../modules/ModuleStorage.sol"; /** * @title USDTiered STO module Proxy */ -contract USDTieredSTOProxy is USDTieredSTOStorage, ISTOStorage, ModuleStorage, Pausable, ReentrancyGuard, OwnedProxy { +contract USDTieredSTOProxy is USDTieredSTOStorage, STOStorage, ModuleStorage, Pausable, ReentrancyGuard, OwnedProxy { /** * @notice Constructor diff --git a/contracts/storage/USDTieredSTOStorage.sol b/contracts/storage/USDTieredSTOStorage.sol index f801000e0..31e9d803d 100644 --- a/contracts/storage/USDTieredSTOStorage.sol +++ b/contracts/storage/USDTieredSTOStorage.sol @@ -51,9 +51,6 @@ contract USDTieredSTOStorage { // Whether or not the STO has been finalized bool public isFinalized; - // Address where ETH, POLY & Stable Coin funds are delivered - address public wallet; - // Address of issuer reserve wallet for unsold tokens address public reserveWallet; diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index ae1fbbbb0..fca953a18 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1246,7 +1246,8 @@ contract("USDTieredSTO", accounts => { await I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 }); // Change Stable coin address - await I_USDTieredSTO_Array[stoId].modifyAddresses(WALLET, RESERVEWALLET, [I_PolyToken.address], { from: ISSUER }); + let I_DaiToken2 = await PolyTokenFaucet.new({from: POLYMATH}); + await I_USDTieredSTO_Array[stoId].modifyAddresses(WALLET, RESERVEWALLET, [I_DaiToken2.address], { from: ISSUER }); // NONACCREDITED DAI await catchRevert(I_USDTieredSTO_Array[stoId].buyWithUSD(NONACCREDITED1, investment_DAI, I_DaiToken.address, { from: NONACCREDITED1 })); From 69b96d507a22d72a130e7e25d5ec0762e486cf0f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 8 Mar 2019 01:14:16 +0530 Subject: [PATCH 546/582] Finalize changed granularity edge case fixed (#588) --- contracts/modules/STO/USDTieredSTO.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index c29402355..fca1fe810 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -290,6 +290,9 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { tiers[i].mintedTotal = tiers[i].tokenTotal; } } + uint256 granularity = ISecurityToken(securityToken).granularity(); + tempReturned = tempReturned.div(granularity); + tempReturned = tempReturned.mul(granularity); require(ISecurityToken(securityToken).mint(reserveWallet, tempReturned), "Error in minting"); emit ReserveTokenMint(msg.sender, reserveWallet, tempReturned, currentTier); finalAmountReturned = tempReturned; From 3d45fb224f7636c1f71d93b18185bde048b2a7c5 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 14 Mar 2019 03:13:59 +0530 Subject: [PATCH 547/582] USDTieredSTO Granularity edge case fixed (#595) * sto granularity edge case fixed * Added test case --- contracts/modules/STO/USDTieredSTO.sol | 25 ++-- test/p_usd_tiered_sto.js | 151 +++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 12 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index fca1fe810..dcc3ada36 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -662,21 +662,22 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { view returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) { - uint256 maximumTokens = DecimalMath.div(_investedUSD, _tierPrice); + purchasedTokens = DecimalMath.div(_investedUSD, _tierPrice); uint256 granularity = ISecurityToken(securityToken).granularity(); - maximumTokens = maximumTokens.div(granularity); - maximumTokens = maximumTokens.mul(granularity); - if (maximumTokens > _tierRemaining) { - spentUSD = DecimalMath.mul(_tierRemaining, _tierPrice); - // In case of rounding issues, ensure that spentUSD is never more than investedUSD - if (spentUSD > _investedUSD) { - spentUSD = _investedUSD; - } - purchasedTokens = _tierRemaining; + + if (purchasedTokens > _tierRemaining) { + purchasedTokens = _tierRemaining.div(granularity); gotoNextTier = true; } else { - spentUSD = DecimalMath.mul(maximumTokens, _tierPrice); - purchasedTokens = maximumTokens; + purchasedTokens = purchasedTokens.div(granularity); + } + + purchasedTokens = purchasedTokens.mul(granularity); + spentUSD = DecimalMath.mul(purchasedTokens, _tierPrice); + + // In case of rounding issues, ensure that spentUSD is never more than investedUSD + if (spentUSD > _investedUSD) { + spentUSD = _investedUSD; } } diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index fca953a18..48cad94b8 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -678,6 +678,45 @@ contract("USDTieredSTO", accounts => { I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); }); + it("Should successfully attach the sixth STO module to the security token", async () => { + let stoId = 5; // Non-divisible tokens with bad granularity in tiers + + _startTime.push(latestTime() + duration.days(2)); + _endTime.push(_startTime[stoId] + duration.days(100)); + _ratePerTier.push([BigNumber(1 * 10 ** 18), BigNumber(1 * 10 ** 18)]); // [ 1 USD/Token, 1 USD/Token ] + _ratePerTierDiscountPoly.push([BigNumber(1 * 10 ** 18), BigNumber(1 * 10 ** 18)]); // [ 1 USD/Token, 1 USD/Token ] + _tokensPerTierTotal.push([BigNumber(1001 * 10 ** 17), BigNumber(50 * 10 ** 18)]); // [ 100.1 Token, 50 Token ] + _tokensPerTierDiscountPoly.push([BigNumber(0), BigNumber(0)]); // [ 0 Token, 0 Token ] + _nonAccreditedLimitUSD.push(BigNumber(25 * 10 ** 18)); // [ 25 USD ] + _minimumInvestmentUSD.push(BigNumber(5)); + _fundRaiseTypes.push([0, 1, 2]); + _wallet.push(WALLET); + _reserveWallet.push(RESERVEWALLET); + _usdToken.push([I_DaiToken.address]); + + let config = [ + _startTime[stoId], + _endTime[stoId], + _ratePerTier[stoId], + _ratePerTierDiscountPoly[stoId], + _tokensPerTierTotal[stoId], + _tokensPerTierDiscountPoly[stoId], + _nonAccreditedLimitUSD[stoId], + _minimumInvestmentUSD[stoId], + _fundRaiseTypes[stoId], + _wallet[stoId], + _reserveWallet[stoId], + _usdToken[stoId] + ]; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); + console.log(" Gas addModule: ".grey + tx.receipt.gasUsed.toString().grey); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(web3.utils.hexToString(tx.logs[2].args._name), "USDTieredSTO", "USDTieredSTOFactory module was not added"); + I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); + }); + it("Should fail because rates and tier array of different length", async () => { let stoId = 0; @@ -3948,6 +3987,118 @@ contract("USDTieredSTO", accounts => { await I_SecurityToken.changeGranularity(1, {from: ISSUER}); }); + it("should successfully buy a granular amount when buying indivisible token accross tiers with invalid tier limit", async () => { + let stoId = 5; + let tierId = 0; + await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); + let investment_Tokens = (new BigNumber(110)).mul(10 ** 18); + let investment_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", investment_Tokens); + + let refund_Tokens = new BigNumber(0); + let refund_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", refund_Tokens); + + await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); + await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: ACCREDITED1 }); + + let init_TokenSupply = await I_SecurityToken.totalSupply(); + let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let init_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let init_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let init_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let init_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + let tokensToMint = (await I_USDTieredSTO_Array[stoId].buyTokensView(ACCREDITED1, investment_POLY,POLY))[2]; + + // Buy With POLY + let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { + from: ACCREDITED1, + gasPrice: GAS_PRICE + }); + let gasCost2 = BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); + console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + + let final_TokenSupply = await I_SecurityToken.totalSupply(); + let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); + let final_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorPOLYBal = await I_PolyToken.balanceOf(ACCREDITED1); + let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); + let final_STOETHBal = BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOPOLYBal = await I_PolyToken.balanceOf(I_USDTieredSTO_Array[stoId].address); + let final_RaisedETH = await I_USDTieredSTO_Array[stoId].fundsRaised.call(ETH); + let final_RaisedPOLY = await I_USDTieredSTO_Array[stoId].fundsRaised.call(POLY); + let final_WalletETHBal = BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); + + assert.equal( + final_TokenSupply.toNumber(), + init_TokenSupply + .add(investment_Tokens) + .sub(refund_Tokens) + .toNumber(), + "Token Supply not changed as expected" + ); + assert.equal( + tokensToMint.toNumber(), + investment_Tokens.sub(refund_Tokens).toNumber(), + "View function returned incorrect data" + ); + assert.equal( + final_InvestorTokenBal.toNumber(), + init_InvestorTokenBal + .add(investment_Tokens) + .sub(refund_Tokens) + .toNumber(), + "Investor Token Balance not changed as expected" + ); + assert.equal( + final_InvestorETHBal.toNumber(), + init_InvestorETHBal.sub(gasCost2).toNumber(), + "Investor ETH Balance not changed as expected" + ); + assert.equal( + final_InvestorPOLYBal.toNumber(), + init_InvestorPOLYBal + .sub(investment_POLY) + .add(refund_POLY) + .toNumber(), + "Investor POLY Balance not changed as expected" + ); + assert.equal( + final_STOTokenSold.toNumber(), + init_STOTokenSold + .add(investment_Tokens) + .sub(refund_Tokens) + .toNumber(), + "STO Token Sold not changed as expected" + ); + assert.equal(final_STOETHBal.toNumber(), init_STOETHBal.toNumber(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toNumber(), init_STOPOLYBal.toNumber(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toNumber(), init_RaisedETH.toNumber(), "Raised ETH not changed as expected"); + assert.equal( + final_RaisedPOLY.toNumber(), + init_RaisedPOLY + .add(investment_POLY) + .sub(refund_POLY) + .toNumber(), + "Raised POLY not changed as expected" + ); + assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal( + final_WalletPOLYBal.toNumber(), + init_WalletPOLYBal + .add(investment_POLY) + .sub(refund_POLY) + .toNumber(), + "Wallet POLY Balance not changed as expected" + ); + await I_SecurityToken.changeGranularity(1, {from: ISSUER}); + }); + it("should successfully buy a granular amount and refund balance when buying indivisible token with ETH", async () => { await I_SecurityToken.changeGranularity(10**18, {from: ISSUER}); let stoId = 4; From 0008f283c1a6cd98555825faffb47979b79968d0 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 18 Mar 2019 05:55:32 +0530 Subject: [PATCH 548/582] gtm matm optimizations (#601) * MATM optimizations * Added code comments * Updated tests * Updated names * Added overflow check --- .../GeneralTransferManager.sol | 133 +++++++++------- .../ManualApprovalTransferManager.sol | 149 +++++++++--------- .../storage/GeneralTransferManagerStorage.sol | 10 +- test/j_manual_approval_transfer_manager.js | 12 +- 4 files changed, 161 insertions(+), 143 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index dc7eabd4b..0d2f96700 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -24,19 +24,19 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag // Emit when there is change in the flag variable called signingAddress event ChangeSigningAddress(address _signingAddress); // Emit when investor details get modified related to their whitelisting - event ChangeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime); + event ChangeDefaults(uint64 _defaultCanSendAfter, uint64 _defaultCanReceiveAfter); - // _fromTime is the time from which the _investor can send tokens - // _toTime is the time from which the _investor can receive tokens - // if allowAllWhitelistIssuances is TRUE, then _toTime is ignored when receiving tokens from the issuance address - // if allowAllWhitelistTransfers is TRUE, then _toTime and _fromTime is ignored when sending or receiving tokens + // _canSendAfter is the time from which the _investor can send tokens + // _canReceiveAfter is the time from which the _investor can receive tokens + // if allowAllWhitelistIssuances is TRUE, then _canReceiveAfter is ignored when receiving tokens from the issuance address + // if allowAllWhitelistTransfers is TRUE, then _canReceiveAfter and _canSendAfter is ignored when sending or receiving tokens // in any case, any investor sending or receiving tokens, must have a _expiryTime in the future event ModifyWhitelist( address indexed _investor, uint256 _dateAdded, address indexed _addedBy, - uint256 _fromTime, - uint256 _toTime, + uint256 _canSendAfter, + uint256 _canReceiveAfter, uint256 _expiryTime, bool _canBuyFromSTO ); @@ -60,14 +60,17 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag } /** - * @notice Used to change the default times used when fromTime / toTime are zero - * @param _defaultFromTime default for zero fromTime - * @param _defaultToTime default for zero toTime + * @notice Used to change the default times used when canSendAfter / canReceiveAfter are zero + * @param _defaultCanSendAfter default for zero canSendAfter + * @param _defaultCanReceiveAfter default for zero canReceiveAfter */ - function changeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime) public withPerm(FLAGS) { - defaults.fromTime = _defaultFromTime; - defaults.toTime = _defaultToTime; - emit ChangeDefaults(_defaultFromTime, _defaultToTime); + function changeDefaults(uint64 _defaultCanSendAfter, uint64 _defaultCanReceiveAfter) public withPerm(FLAGS) { + /* 0 values are also allowed as they represent that the Issuer + does not want a default value for these variables. + 0 is also the default value of these variables */ + defaults.canSendAfter = _defaultCanSendAfter; + defaults.canReceiveAfter = _defaultCanReceiveAfter; + emit ChangeDefaults(_defaultCanSendAfter, _defaultCanReceiveAfter); } /** @@ -75,6 +78,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag * @param _issuanceAddress new address for the issuance */ function changeIssuanceAddress(address _issuanceAddress) public withPerm(FLAGS) { + // address(0x0) is also a valid value and in most cases, the address that issues tokens is 0x0. issuanceAddress = _issuanceAddress; emit ChangeIssuanceAddress(_issuanceAddress); } @@ -84,6 +88,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag * @param _signingAddress new address for the signing */ function changeSigningAddress(address _signingAddress) public withPerm(FLAGS) { + /* address(0x0) is also a valid value as an Issuer might want to + give this permission to nobody (except their own address). + 0x0 is also the default value */ signingAddress = _signingAddress; emit ChangeSigningAddress(_signingAddress); } @@ -156,7 +163,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA; } - (uint64 adjustedFromTime, uint64 adjustedToTime) = _adjustTimes(whitelist[_from].fromTime, whitelist[_to].toTime); + (uint64 adjustedCanSendAfter, uint64 adjustedCanReceiveAfter) = _adjustTimes(whitelist[_from].canSendAfter, whitelist[_to].canReceiveAfter); if (_from == issuanceAddress) { // Possible STO transaction, but investor not allowed to purchased from STO if ((whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { @@ -166,14 +173,14 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag if (allowAllWhitelistIssuances) { return _onWhitelist(_to) ? Result.VALID : Result.NA; } else { - return (_onWhitelist(_to) && (adjustedToTime <= uint64(now))) ? Result.VALID : Result.NA; + return (_onWhitelist(_to) && (adjustedCanReceiveAfter <= uint64(now))) ? Result.VALID : Result.NA; } } //Anyone on the whitelist can transfer provided the blocknumber is large enough /*solium-disable-next-line security/no-block-members*/ - return ((_onWhitelist(_from) && (adjustedFromTime <= uint64(now))) && - (_onWhitelist(_to) && (adjustedToTime <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return ((_onWhitelist(_from) && (adjustedCanSendAfter <= uint64(now))) && + (_onWhitelist(_to) && (adjustedCanReceiveAfter <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -181,36 +188,36 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag /** * @notice Adds or removes addresses from the whitelist. * @param _investor is the address to whitelist - * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens - * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others + * @param _canSendAfter the moment when the sale lockup period ends and the investor can freely sell or transfer away their tokens + * @param _canReceiveAfter the moment when the purchase lockup period ends and the investor can freely purchase or receive from others * @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC * @param _canBuyFromSTO is used to know whether the investor is restricted investor or not. */ function modifyWhitelist( address _investor, - uint256 _fromTime, - uint256 _toTime, + uint256 _canSendAfter, + uint256 _canReceiveAfter, uint256 _expiryTime, bool _canBuyFromSTO ) public withPerm(WHITELIST) { - _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + _modifyWhitelist(_investor, _canSendAfter, _canReceiveAfter, _expiryTime, _canBuyFromSTO); } /** * @notice Adds or removes addresses from the whitelist. * @param _investor is the address to whitelist - * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens - * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others + * @param _canSendAfter is the moment when the sale lockup period ends and the investor can freely sell his tokens + * @param _canReceiveAfter is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others * @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC * @param _canBuyFromSTO is used to know whether the investor is restricted investor or not. */ function _modifyWhitelist( address _investor, - uint256 _fromTime, - uint256 _toTime, + uint256 _canSendAfter, + uint256 _canReceiveAfter, uint256 _expiryTime, bool _canBuyFromSTO ) @@ -224,39 +231,45 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag if (whitelist[_investor].added == uint8(0)) { investors.push(_investor); } - whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); - emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + require( + uint64(_canSendAfter) == _canSendAfter && + uint64(_canReceiveAfter) == _canReceiveAfter && + uint64(_expiryTime) == _expiryTime, + "uint64 overflow" + ); + whitelist[_investor] = TimeRestriction(uint64(_canSendAfter), uint64(_canReceiveAfter), uint64(_expiryTime), canBuyFromSTO, uint8(1)); + emit ModifyWhitelist(_investor, now, msg.sender, _canSendAfter, _canReceiveAfter, _expiryTime, _canBuyFromSTO); } /** * @notice Adds or removes addresses from the whitelist. * @param _investors List of the addresses to whitelist - * @param _fromTimes An array of the moment when the sale lockup period ends and the investor can freely sell his tokens - * @param _toTimes An array of the moment when the purchase lockup period ends and the investor can freely purchase tokens from others + * @param _canSendAfters An array of the moment when the sale lockup period ends and the investor can freely sell his tokens + * @param _canReceiveAfters An array of the moment when the purchase lockup period ends and the investor can freely purchase tokens from others * @param _expiryTimes An array of the moment till investors KYC will be validated. After that investor need to do re-KYC * @param _canBuyFromSTO An array of boolean values */ function modifyWhitelistMulti( address[] _investors, - uint256[] _fromTimes, - uint256[] _toTimes, + uint256[] _canSendAfters, + uint256[] _canReceiveAfters, uint256[] _expiryTimes, bool[] _canBuyFromSTO ) public withPerm(WHITELIST) { - require(_investors.length == _fromTimes.length, "Mismatched input lengths"); - require(_fromTimes.length == _toTimes.length, "Mismatched input lengths"); - require(_toTimes.length == _expiryTimes.length, "Mismatched input lengths"); - require(_canBuyFromSTO.length == _toTimes.length, "Mismatched input length"); + require(_investors.length == _canSendAfters.length, "Mismatched input lengths"); + require(_canSendAfters.length == _canReceiveAfters.length, "Mismatched input lengths"); + require(_canReceiveAfters.length == _expiryTimes.length, "Mismatched input lengths"); + require(_canBuyFromSTO.length == _canReceiveAfters.length, "Mismatched input length"); for (uint256 i = 0; i < _investors.length; i++) { - _modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i]); + _modifyWhitelist(_investors[i], _canSendAfters[i], _canReceiveAfters[i], _expiryTimes[i], _canBuyFromSTO[i]); } } /** * @notice Adds or removes addresses from the whitelist - can be called by anyone with a valid signature * @param _investor is the address to whitelist - * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens - * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others + * @param _canSendAfter is the moment when the sale lockup period ends and the investor can freely sell his tokens + * @param _canReceiveAfter is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others * @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC * @param _canBuyFromSTO is used to know whether the investor is restricted investor or not. * @param _validFrom is the time that this signature is valid from @@ -268,8 +281,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag */ function modifyWhitelistSigned( address _investor, - uint256 _fromTime, - uint256 _toTime, + uint256 _canSendAfter, + uint256 _canReceiveAfter, uint256 _expiryTime, bool _canBuyFromSTO, uint256 _validFrom, @@ -286,10 +299,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag require(!nonceMap[_investor][_nonce], "Already used signature"); nonceMap[_investor][_nonce] = true; bytes32 hash = keccak256( - abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) + abi.encodePacked(this, _investor, _canSendAfter, _canReceiveAfter, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) ); _checkSig(hash, _v, _r, _s); - _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + _modifyWhitelist(_investor, _canSendAfter, _canReceiveAfter, _expiryTime, _canBuyFromSTO); } /** @@ -297,7 +310,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag */ function _checkSig(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal view { //Check that the signature is valid - //sig should be signing - _investor, _fromTime, _toTime & _expiryTime and be signed by the issuer address + //sig should be signing - _investor, _canSendAfter, _canReceiveAfter & _expiryTime and be signed by the issuer address address signer = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)), _v, _r, _s); require(signer == Ownable(securityToken).owner() || signer == signingAddress, "Incorrect signer"); } @@ -322,16 +335,16 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag /** * @notice Internal function to adjust times using default values */ - function _adjustTimes(uint64 _fromTime, uint64 _toTime) internal view returns(uint64, uint64) { - uint64 adjustedFromTime = _fromTime; - uint64 adjustedToTime = _toTime; - if (_fromTime == 0) { - adjustedFromTime = defaults.fromTime; + function _adjustTimes(uint64 _canSendAfter, uint64 _canReceiveAfter) internal view returns(uint64, uint64) { + uint64 adjustedCanSendAfter = _canSendAfter; + uint64 adjustedCanReceiveAfter = _canReceiveAfter; + if (_canSendAfter == 0) { + adjustedCanSendAfter = defaults.canSendAfter; } - if (_toTime == 0) { - adjustedToTime = defaults.toTime; + if (_canReceiveAfter == 0) { + adjustedCanReceiveAfter = defaults.canReceiveAfter; } - return (adjustedFromTime, adjustedToTime); + return (adjustedCanSendAfter, adjustedCanReceiveAfter); } /** @@ -345,9 +358,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag * @dev Returns list of all investors data */ function getAllInvestorsData() external view returns(address[], uint256[], uint256[], uint256[], bool[]) { - (uint256[] memory fromTimes, uint256[] memory toTimes, uint256[] memory expiryTimes, bool[] memory canBuyFromSTOs) + (uint256[] memory canSendAfters, uint256[] memory canReceiveAfters, uint256[] memory expiryTimes, bool[] memory canBuyFromSTOs) = _investorsData(investors); - return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs); + return (investors, canSendAfters, canReceiveAfters, expiryTimes, canBuyFromSTOs); } @@ -359,13 +372,13 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag } function _investorsData(address[] _investors) internal view returns(uint256[], uint256[], uint256[], bool[]) { - uint256[] memory fromTimes = new uint256[](_investors.length); - uint256[] memory toTimes = new uint256[](_investors.length); + uint256[] memory canSendAfters = new uint256[](_investors.length); + uint256[] memory canReceiveAfters = new uint256[](_investors.length); uint256[] memory expiryTimes = new uint256[](_investors.length); bool[] memory canBuyFromSTOs = new bool[](_investors.length); for (uint256 i = 0; i < _investors.length; i++) { - fromTimes[i] = whitelist[_investors[i]].fromTime; - toTimes[i] = whitelist[_investors[i]].toTime; + canSendAfters[i] = whitelist[_investors[i]].canSendAfter; + canReceiveAfters[i] = whitelist[_investors[i]].canReceiveAfter; expiryTimes[i] = whitelist[_investors[i]].expiryTime; if (whitelist[_investors[i]].canBuyFromSTO == 0) { canBuyFromSTOs[i] = false; @@ -373,7 +386,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag canBuyFromSTOs[i] = true; } } - return (fromTimes, toTimes, expiryTimes, canBuyFromSTOs); + return (canSendAfters, canReceiveAfters, expiryTimes, canBuyFromSTOs); } /** diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index f660ac639..5e95f6513 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -9,12 +9,6 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; contract ManualApprovalTransferManager is ITransferManager { using SafeMath for uint256; - //Address from which issuances come - address public issuanceAddress = address(0); - - //Address which can sign whitelist changes - address public signingAddress = address(0); - bytes32 public constant TRANSFER_APPROVAL = "TRANSFER_APPROVAL"; //Manual approval is an allowance (that has been approved) with an expiry time @@ -27,7 +21,10 @@ contract ManualApprovalTransferManager is ITransferManager { } mapping (address => mapping (address => uint256)) public approvalIndex; - // An array to track all approvals + + // An array to track all approvals. It is an unbounded array but it's not a problem as + // it is never looped through in an onchain call. It is defined as an Array instead of mapping + // just to make it easier for users to fetch list of all approvals through constant functions. ManualApproval[] public approvals; event AddManualApproval( @@ -72,7 +69,7 @@ contract ManualApprovalTransferManager is ITransferManager { return bytes4(0); } - /** + /** * @notice Used to verify the transfer transaction and allow a manually approved transqaction to bypass other restrictions * @param _from Address of the sender * @param _to Address of the receiver @@ -82,13 +79,14 @@ contract ManualApprovalTransferManager is ITransferManager { function verifyTransfer(address _from, address _to, uint256 _amount, bytes /* _data */, bool _isTransfer) public returns(Result) { // function must only be called by the associated security token if _isTransfer == true require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); - - if (!paused && approvalIndex[_from][_to] != 0) { - uint256 index = approvalIndex[_from][_to] - 1; + uint256 index = approvalIndex[_from][_to]; + if (!paused && index != 0) { + index--; //Actual index is stored index - 1. ManualApproval storage approval = approvals[index]; - if ((approval.expiryTime >= now) && (approval.allowance >= _amount)) { + uint256 allowance = approval.allowance; + if ((approval.expiryTime >= now) && (allowance >= _amount)) { if (_isTransfer) { - approval.allowance = approval.allowance.sub(_amount); + approval.allowance = allowance - _amount; } return Result.VALID; } @@ -110,8 +108,8 @@ contract ManualApprovalTransferManager is ITransferManager { uint256 _allowance, uint256 _expiryTime, bytes32 _description - ) - external + ) + external withPerm(TRANSFER_APPROVAL) { _addManualApproval(_from, _to, _allowance, _expiryTime, _description); @@ -121,8 +119,9 @@ contract ManualApprovalTransferManager is ITransferManager { require(_to != address(0), "Invalid to address"); require(_expiryTime > now, "Invalid expiry time"); require(_allowance > 0, "Invalid allowance"); - if (approvalIndex[_from][_to] != 0) { - uint256 index = approvalIndex[_from][_to] - 1; + uint256 index = approvalIndex[_from][_to]; + if (index != 0) { + index--; //Actual index is stored index - 1. require(approvals[index].expiryTime < now || approvals[index].allowance == 0, "Approval already exists"); _revokeManualApproval(_from, _to); } @@ -135,7 +134,7 @@ contract ManualApprovalTransferManager is ITransferManager { * @notice Adds mutiple manual approvals in batch * @param _from is the address array from which transfers are approved * @param _to is the address array to which transfers are approved - * @param _allowances is the array of approved amounts + * @param _allowances is the array of approved amounts * @param _expiryTimes is the array of the times until which eath transfer is allowed * @param _descriptions is the description array for these manual approvals */ @@ -145,8 +144,8 @@ contract ManualApprovalTransferManager is ITransferManager { uint256[] _allowances, uint256[] _expiryTimes, bytes32[] _descriptions - ) - external + ) + external withPerm(TRANSFER_APPROVAL) { _checkInputLengthArray(_from, _to, _allowances, _expiryTimes, _descriptions); @@ -160,69 +159,70 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _from is the address from which transfers are approved * @param _to is the address to which transfers are approved * @param _expiryTime is the time until which the transfer is allowed - * @param _changedAllowance is the changed allowance + * @param _changeInAllowance is the change in allowance * @param _description Description about the manual approval - * @param _change uint values which tells whether the allowances will be increased (1) or decreased (0) + * @param _increase tells whether the allowances will be increased (true) or decreased (false). * or any value when there is no change in allowances */ function modifyManualApproval( address _from, address _to, uint256 _expiryTime, - uint256 _changedAllowance, + uint256 _changeInAllowance, bytes32 _description, - uint8 _change - ) + bool _increase + ) external withPerm(TRANSFER_APPROVAL) { - _modifyManualApproval(_from, _to, _expiryTime, _changedAllowance, _description, _change); + _modifyManualApproval(_from, _to, _expiryTime, _changeInAllowance, _description, _increase); } function _modifyManualApproval( address _from, address _to, uint256 _expiryTime, - uint256 _changedAllowance, + uint256 _changeInAllowance, bytes32 _description, - uint8 _change - ) - internal + bool _increase + ) + internal { require(_to != address(0), "Invalid to address"); /*solium-disable-next-line security/no-block-members*/ require(_expiryTime > now, "Invalid expiry time"); - require(approvalIndex[_from][_to] != 0, "Approval not present"); - uint256 index = approvalIndex[_from][_to] - 1; + uint256 index = approvalIndex[_from][_to]; + require(index != 0, "Approval not present"); + index--; //Index is stored in an incremented form. 0 represnts non existant. ManualApproval storage approval = approvals[index]; - require(approval.allowance != 0 && approval.expiryTime > now, "Not allowed"); - uint256 currentAllowance = approval.allowance; - uint256 newAllowance; - if (_change == 1) { - // Allowance get increased - newAllowance = currentAllowance.add(_changedAllowance); - approval.allowance = newAllowance; - } else if (_change == 0) { - // Allowance get decreased - if (_changedAllowance > currentAllowance) { - newAllowance = 0; - approval.allowance = newAllowance; + uint256 allowance = approval.allowance; + uint256 expiryTime = approval.expiryTime; + require(allowance != 0 && expiryTime > now, "Not allowed"); + + if (_changeInAllowance > 0) { + if (_increase) { + // Allowance get increased + allowance = allowance.add(_changeInAllowance); } else { - newAllowance = currentAllowance.sub(_changedAllowance); - approval.allowance = newAllowance; + // Allowance get decreased + if (_changeInAllowance >= allowance) { + allowance = 0; + } else { + allowance = allowance - _changeInAllowance; + } } - } else { - // No change in the Allowance - newAllowance = currentAllowance; + approval.allowance = allowance; } + // Greedy storage technique - if (approval.expiryTime != _expiryTime) { + if (expiryTime != _expiryTime) { approval.expiryTime = _expiryTime; } if (approval.description != _description) { approval.description = _description; } - emit ModifyManualApproval(_from, _to, _expiryTime, newAllowance, _description, msg.sender); + + emit ModifyManualApproval(_from, _to, _expiryTime, allowance, _description, msg.sender); } /** @@ -230,9 +230,9 @@ contract ManualApprovalTransferManager is ITransferManager { * @param _from is the address array from which transfers are approved * @param _to is the address array to which transfers are approved * @param _expiryTimes is the array of the times until which eath transfer is allowed - * @param _changedAllowances is the array of approved amounts + * @param _changedAllowances is the array of approved amounts * @param _descriptions is the description array for these manual approvals - * @param _changes Array of uint values which tells whether the allowances will be increased (1) or decreased (0) + * @param _increase Array of bool values which tells whether the allowances will be increased (true) or decreased (false) * or any value when there is no change in allowances */ function modifyManualApprovalMulti( @@ -241,15 +241,15 @@ contract ManualApprovalTransferManager is ITransferManager { uint256[] _expiryTimes, uint256[] _changedAllowances, bytes32[] _descriptions, - uint8[] _changes + bool[] _increase ) public withPerm(TRANSFER_APPROVAL) { _checkInputLengthArray(_from, _to, _changedAllowances, _expiryTimes, _descriptions); - require(_changes.length == _changedAllowances.length, "Input length array mismatch"); + require(_increase.length == _changedAllowances.length, "Input length array mismatch"); for (uint256 i = 0; i < _from.length; i++) { - _modifyManualApproval(_from[i], _to[i], _expiryTimes[i], _changedAllowances[i], _descriptions[i], _changes[i]); + _modifyManualApproval(_from[i], _to[i], _expiryTimes[i], _changedAllowances[i], _descriptions[i], _increase[i]); } } @@ -263,13 +263,14 @@ contract ManualApprovalTransferManager is ITransferManager { } function _revokeManualApproval(address _from, address _to) internal { - require(approvalIndex[_from][_to] != 0, "Approval not exist"); - + uint256 index = approvalIndex[_from][_to]; + require(index != 0, "Approval does not exist"); + index--; //Actual index is stored index - 1. + uint256 lastApprovalIndex = approvals.length - 1; // find the record in active approvals array & delete it - uint256 index = approvalIndex[_from][_to] - 1; - if (index != approvals.length -1) { - approvals[index] = approvals[approvals.length -1]; - approvalIndex[approvals[index].from][approvals[index].to] = index + 1; + if (index != lastApprovalIndex) { + approvals[index] = approvals[lastApprovalIndex]; + approvalIndex[approvals[index].from][approvals[index].to] = index + 1; } delete approvalIndex[_from][_to]; approvals.length--; @@ -294,9 +295,9 @@ contract ManualApprovalTransferManager is ITransferManager { uint256[] _expiryTimes, uint256[] _allowances, bytes32[] _descriptions - ) + ) internal - pure + pure { require(_from.length == _to.length && _to.length == _allowances.length && @@ -308,7 +309,7 @@ contract ManualApprovalTransferManager is ITransferManager { /** * @notice Returns the all active approvals corresponds to an address - * @param _user Address of the holder corresponds to whom list of manual approvals + * @param _user Address of the holder corresponds to whom list of manual approvals * need to return * @return address[] addresses from * @return address[] addresses to @@ -318,7 +319,8 @@ contract ManualApprovalTransferManager is ITransferManager { */ function getActiveApprovalsToUser(address _user) external view returns(address[], address[], uint256[], uint256[], bytes32[]) { uint256 counter = 0; - for (uint256 i = 0; i < approvals.length; i++) { + uint256 approvalsLength = approvals.length; + for (uint256 i = 0; i < approvalsLength; i++) { if ((approvals[i].from == _user || approvals[i].to == _user) && approvals[i].expiryTime >= now) counter ++; @@ -331,7 +333,7 @@ contract ManualApprovalTransferManager is ITransferManager { bytes32[] memory description = new bytes32[](counter); counter = 0; - for (i = 0; i < approvals.length; i++) { + for (i = 0; i < approvalsLength; i++) { if ((approvals[i].from == _user || approvals[i].to == _user) && approvals[i].expiryTime >= now) { @@ -341,7 +343,7 @@ contract ManualApprovalTransferManager is ITransferManager { expiryTime[counter]=approvals[i].expiryTime; description[counter]=approvals[i].description; counter ++; - } + } } return (from, to, allowance, expiryTime, description); } @@ -355,8 +357,9 @@ contract ManualApprovalTransferManager is ITransferManager { * @return uint256 Description provided to the approval */ function getApprovalDetails(address _from, address _to) external view returns(uint256, uint256, bytes32) { - if (approvalIndex[_from][_to] != 0) { - uint256 index = approvalIndex[_from][_to] - 1; + uint256 index = approvalIndex[_from][_to]; + if (index != 0) { + index--; if (index < approvals.length) { ManualApproval storage approval = approvals[index]; return( @@ -366,7 +369,6 @@ contract ManualApprovalTransferManager is ITransferManager { ); } } - return (uint256(0), uint256(0), bytes32(0)); } /** @@ -390,8 +392,9 @@ contract ManualApprovalTransferManager is ITransferManager { uint256[] memory allowance = new uint256[](approvals.length); uint256[] memory expiryTime = new uint256[](approvals.length); bytes32[] memory description = new bytes32[](approvals.length); + uint256 approvalsLength = approvals.length; - for (uint256 i = 0; i < approvals.length; i++) { + for (uint256 i = 0; i < approvalsLength; i++) { from[i]=approvals[i].from; to[i]=approvals[i].to; @@ -402,7 +405,7 @@ contract ManualApprovalTransferManager is ITransferManager { } return (from, to, allowance, expiryTime, description); - + } /** diff --git a/contracts/storage/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol index cca7b5dd1..87f886ae7 100644 --- a/contracts/storage/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -16,8 +16,10 @@ contract GeneralTransferManagerStorage { //from and to timestamps that an investor can send / receive tokens respectively struct TimeRestriction { - uint64 fromTime; - uint64 toTime; + //the moment when the sale lockup period ends and the investor can freely sell or transfer away their tokens + uint64 canSendAfter; + //the moment when the purchase lockup period ends and the investor can freely purchase or receive from others + uint64 canReceiveAfter; uint64 expiryTime; uint8 canBuyFromSTO; uint8 added; @@ -25,8 +27,8 @@ contract GeneralTransferManagerStorage { // Allows all TimeRestrictions to be offset struct Defaults { - uint64 fromTime; - uint64 toTime; + uint64 canSendAfter; + uint64 canReceiveAfter; } // Offset to be applied to all timings (except KYC expiry) diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 49a2f9645..985d471ca 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -459,7 +459,7 @@ contract("ManualApprovalTransferManager", accounts => { latestTime() + duration.days(2), web3.utils.toWei("5"), "New Description", - 0, + false, { from: token_owner } @@ -493,9 +493,9 @@ contract("ManualApprovalTransferManager", accounts => { account_investor1, account_investor4, expiryTimeMA, - web3.utils.toWei("5"), + 0, "New Description", - 45, + true, { from: token_owner } @@ -529,7 +529,7 @@ contract("ManualApprovalTransferManager", accounts => { expiryTimeMA, web3.utils.toWei("4"), "New Description", - 1, + true, { from: token_owner } @@ -557,7 +557,7 @@ contract("ManualApprovalTransferManager", accounts => { expiryTimeMA, web3.utils.toWei("1"), "New Description", - 0, + false, { from: token_owner } @@ -592,7 +592,7 @@ contract("ManualApprovalTransferManager", accounts => { expiryTimeMA, web3.utils.toWei("5"), "New Description", - 0, + false, { from: token_owner } From c3c7fd188f17ec8884913025fd39937066546696 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 18 Mar 2019 10:35:35 -0400 Subject: [PATCH 549/582] Fixes --- .../modules/Checkpoint/DividendCheckpoint.sol | 19 ++++++++++++++-- .../Checkpoint/ERC20DividendCheckpoint.sol | 10 ++++----- .../Checkpoint/EtherDividendCheckpoint.sol | 22 +++++++++---------- contracts/modules/Module.sol | 21 ++++++++++++++++++ contracts/modules/STO/STO.sol | 12 ---------- 5 files changed, 53 insertions(+), 31 deletions(-) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 30cf49c54..d40585e5c 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -10,6 +10,7 @@ pragma solidity ^0.4.24; import "./ICheckpoint.sol"; import "./DividendCheckpointStorage.sol"; import "../Module.sol"; +import "../../Pausable.sol"; import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/math/Math.sol"; @@ -18,7 +19,7 @@ import "openzeppelin-solidity/contracts/math/Math.sol"; * @title Checkpoint module for issuing ether dividends * @dev abstract contract */ -contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { +contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module, Pausable { using SafeMath for uint256; event SetDefaultExcludedAddresses(address[] _excluded, uint256 _timestamp); @@ -36,6 +37,20 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { _; } + /** + * @notice Pause (overridden function) + */ + function pause() public onlyOwner { + super._pause(); + } + + /** + * @notice Unpause (overridden function) + */ + function unpause() public onlyOwner { + super._unpause(); + } + /** * @notice Function used to intialize the contract variables * @param _wallet Ethereum account address to receive reclaimed dividends and tax @@ -182,7 +197,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @notice Investors can pull their own dividends * @param _dividendIndex Dividend to pull */ - function pullDividendPayment(uint256 _dividendIndex) public validDividendIndex(_dividendIndex) + function pullDividendPayment(uint256 _dividendIndex) public validDividendIndex(_dividendIndex) whenNotPaused { Dividend storage dividend = dividends[_dividendIndex]; require(!dividend.claimed[msg.sender], "Dividend already claimed"); diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 1d3c8b1bb..d9dc93579 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -241,12 +241,12 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec uint256 claimAfterWithheld = claim.sub(withheld); if (claimAfterWithheld > 0) { require(IERC20(dividendTokens[_dividendIndex]).transfer(_payee, claimAfterWithheld), "transfer failed"); - if (withheld > 0) { - _dividend.totalWithheld = _dividend.totalWithheld.add(withheld); - _dividend.withheld[_payee] = withheld; - } - emit ERC20DividendClaimed(_payee, _dividendIndex, dividendTokens[_dividendIndex], claim, withheld); } + if (withheld > 0) { + _dividend.totalWithheld = _dividend.totalWithheld.add(withheld); + _dividend.withheld[_payee] = withheld; + } + emit ERC20DividendClaimed(_payee, _dividendIndex, dividendTokens[_dividendIndex], claim, withheld); } /** diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index 2952fc955..699da0b57 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -172,19 +172,17 @@ contract EtherDividendCheckpoint is DividendCheckpoint { (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee); _dividend.claimed[_payee] = true; uint256 claimAfterWithheld = claim.sub(withheld); - if (claimAfterWithheld > 0) { - /*solium-disable-next-line security/no-send*/ - if (_payee.send(claimAfterWithheld)) { - _dividend.claimedAmount = _dividend.claimedAmount.add(claim); - if (withheld > 0) { - _dividend.totalWithheld = _dividend.totalWithheld.add(withheld); - _dividend.withheld[_payee] = withheld; - } - emit EtherDividendClaimed(_payee, _dividendIndex, claim, withheld); - } else { - _dividend.claimed[_payee] = false; - emit EtherDividendClaimFailed(_payee, _dividendIndex, claim, withheld); + /*solium-disable-next-line security/no-send*/ + if (_payee.send(claimAfterWithheld)) { + _dividend.claimedAmount = _dividend.claimedAmount.add(claim); + if (withheld > 0) { + _dividend.totalWithheld = _dividend.totalWithheld.add(withheld); + _dividend.withheld[_payee] = withheld; } + emit EtherDividendClaimed(_payee, _dividendIndex, claim, withheld); + } else { + _dividend.claimed[_payee] = false; + emit EtherDividendClaimFailed(_payee, _dividendIndex, claim, withheld); } } diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index 1566a3428..4edd39c8d 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -56,4 +56,25 @@ contract Module is IModule, ModuleStorage { require(polyToken.transferFrom(securityToken, Ownable(factory).owner(), _amount), "Unable to take fee"); return true; } + + /** + * @notice Reclaims ERC20Basic compatible tokens + * @dev We duplicate here due to the overriden owner & onlyOwner + * @param _tokenContract The address of the token contract + */ + function reclaimERC20(address _tokenContract) external onlyOwner { + require(_tokenContract != address(0), "Invalid address"); + IERC20 token = IERC20(_tokenContract); + uint256 balance = token.balanceOf(address(this)); + require(token.transfer(msg.sender, balance), "Transfer failed"); + } + + /** + * @notice Reclaims ETH + * @dev We duplicate here due to the overriden owner & onlyOwner + */ + function reclaimETH() external onlyOwner { + msg.sender.transfer(address(this).balance); + } + } diff --git a/contracts/modules/STO/STO.sol b/contracts/modules/STO/STO.sol index 5f9a6e9e3..4cb832eaf 100644 --- a/contracts/modules/STO/STO.sol +++ b/contracts/modules/STO/STO.sol @@ -18,18 +18,6 @@ contract STO is ISTO, STOStorage, Module, Pausable { // Event event SetFundRaiseTypes(FundRaiseType[] _fundRaiseTypes); - /** - * @notice Reclaims ERC20Basic compatible tokens - * @dev We duplicate here due to the overriden owner & onlyOwner - * @param _tokenContract The address of the token contract - */ - function reclaimERC20(address _tokenContract) external onlyOwner { - require(_tokenContract != address(0), "Invalid address"); - IERC20 token = IERC20(_tokenContract); - uint256 balance = token.balanceOf(address(this)); - require(token.transfer(msg.sender, balance), "Transfer failed"); - } - /** * @notice Returns funds raised by the STO */ From eba4a935c16df738a310c6b1e1cd2f96bb60c998 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 18 Mar 2019 10:55:20 -0400 Subject: [PATCH 550/582] Allow maturity / expiry dates to be updated --- .../modules/Checkpoint/DividendCheckpoint.sol | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index d40585e5c..2ded603de 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -26,6 +26,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module, P event SetWithholding(address[] _investors, uint256[] _withholding, uint256 _timestamp); event SetWithholdingFixed(address[] _investors, uint256 _withholding, uint256 _timestamp); event SetWallet(address indexed _oldWallet, address indexed _newWallet, uint256 _timestamp); + event UpdateDividendDates(uint256 indexed _dividendIndex, uint256 _maturity, uint256 _expiry); modifier validDividendIndex(uint256 _dividendIndex) { require(_dividendIndex < dividends.length, "Invalid dividend"); @@ -267,6 +268,21 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module, P */ function withdrawWithholding(uint256 _dividendIndex) external; + /** + * @notice Allows issuer to change maturity / expiry dates for dividends + * @param _dividendIndex Dividend to withdraw from + * @param _maturity updated maturity date + * @param _expiry updated expiry date + */ + function updateDividendDates(uint256 _dividendIndex, uint256 _maturity, uint256 _expiry) onlyOwner { + require(_dividendIndex < dividends.length, "Invalid dividend"); + require(_expiry > _maturity, "Expiry before maturity"); + Dividend storage dividend = dividends[_dividendIndex]; + dividend.expiry = _expiry; + dividend.maturity = _maturity; + emit UpdateDividendDates(_dividendIndex, _maturity, _expiry); + } + /** * @notice Get static dividend data * @return uint256[] timestamp of dividends creation From 548d7fdb168cc0d3e2aac30afb5d5cd832b85f97 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 18 Mar 2019 12:33:02 -0400 Subject: [PATCH 551/582] Add tests & fixes --- contracts/{modules/STO => mocks}/DummySTO.sol | 6 ++- .../STO => mocks}/DummySTOFactory.sol | 4 +- contracts/mocks/MockFactory.sol | 4 +- contracts/mocks/TestSTOFactory.sol | 2 +- .../modules/Checkpoint/DividendCheckpoint.sol | 28 ++++++++++++- contracts/modules/Module.sol | 20 ---------- contracts/modules/STO/STO.sol | 20 ++++++++++ contracts/modules/STO/USDTieredSTO.sol | 18 ++++----- test/e_erc20_dividends.js | 39 +++++++++++++------ test/f_ether_dividends.js | 19 +++++---- test/p_usd_tiered_sto.js | 4 +- 11 files changed, 107 insertions(+), 57 deletions(-) rename contracts/{modules/STO => mocks}/DummySTO.sol (97%) rename contracts/{modules/STO => mocks}/DummySTOFactory.sol (97%) diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/mocks/DummySTO.sol similarity index 97% rename from contracts/modules/STO/DummySTO.sol rename to contracts/mocks/DummySTO.sol index fafc6c1c4..f452a01eb 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/mocks/DummySTO.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; -import "./STO.sol"; -import "../../interfaces/ISecurityToken.sol"; +import "../modules/STO/STO.sol"; +import "../interfaces/ISecurityToken.sol"; /** * @title STO module for sample implementation of a different crowdsale module @@ -90,4 +90,6 @@ contract DummySTO is STO { return allPermissions; } + + } diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/mocks/DummySTOFactory.sol similarity index 97% rename from contracts/modules/STO/DummySTOFactory.sol rename to contracts/mocks/DummySTOFactory.sol index 04640ac58..03d5fb3a6 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/mocks/DummySTOFactory.sol @@ -1,8 +1,8 @@ pragma solidity ^0.4.24; import "./DummySTO.sol"; -import "../ModuleFactory.sol"; -import "../../libraries/Util.sol"; +import "../modules/ModuleFactory.sol"; +import "../libraries/Util.sol"; /** * @title Factory for deploying DummySTO module diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index 627efb71c..8be7754f7 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../modules/STO/DummySTOFactory.sol"; +import "./DummySTOFactory.sol"; /** * @title Mock Contract Not fit for production environment @@ -32,7 +32,7 @@ contract MockFactory is DummySTOFactory { res[1] = 1; return res; } - + } function changeTypes() external onlyOwner { diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index a8bcbbeb6..120f72bbf 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../modules/STO/DummySTOFactory.sol"; +import "./DummySTOFactory.sol"; contract TestSTOFactory is DummySTOFactory { diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 2ded603de..54e6394cf 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -29,13 +29,17 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module, P event UpdateDividendDates(uint256 indexed _dividendIndex, uint256 _maturity, uint256 _expiry); modifier validDividendIndex(uint256 _dividendIndex) { + _validDividendIndex(_dividendIndex); + _; + } + + function _validDividendIndex(uint256 _dividendIndex) internal view { require(_dividendIndex < dividends.length, "Invalid dividend"); require(!dividends[_dividendIndex].reclaimed, "Dividend reclaimed"); /*solium-disable-next-line security/no-block-members*/ require(now >= dividends[_dividendIndex].maturity, "Dividend maturity in future"); /*solium-disable-next-line security/no-block-members*/ require(now < dividends[_dividendIndex].expiry, "Dividend expiry in past"); - _; } /** @@ -52,6 +56,26 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module, P super._unpause(); } + /** + * @notice Reclaims ERC20Basic compatible tokens + * @dev We duplicate here due to the overriden owner & onlyOwner + * @param _tokenContract The address of the token contract + */ + function reclaimERC20(address _tokenContract) external onlyOwner { + require(_tokenContract != address(0), "Invalid address"); + IERC20 token = IERC20(_tokenContract); + uint256 balance = token.balanceOf(address(this)); + require(token.transfer(msg.sender, balance), "Transfer failed"); + } + + /** + * @notice Reclaims ETH + * @dev We duplicate here due to the overriden owner & onlyOwner + */ + function reclaimETH() external onlyOwner { + msg.sender.transfer(address(this).balance); + } + /** * @notice Function used to intialize the contract variables * @param _wallet Ethereum account address to receive reclaimed dividends and tax @@ -274,7 +298,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module, P * @param _maturity updated maturity date * @param _expiry updated expiry date */ - function updateDividendDates(uint256 _dividendIndex, uint256 _maturity, uint256 _expiry) onlyOwner { + function updateDividendDates(uint256 _dividendIndex, uint256 _maturity, uint256 _expiry) external onlyOwner { require(_dividendIndex < dividends.length, "Invalid dividend"); require(_expiry > _maturity, "Expiry before maturity"); Dividend storage dividend = dividends[_dividendIndex]; diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index 4edd39c8d..a3698f22f 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -57,24 +57,4 @@ contract Module is IModule, ModuleStorage { return true; } - /** - * @notice Reclaims ERC20Basic compatible tokens - * @dev We duplicate here due to the overriden owner & onlyOwner - * @param _tokenContract The address of the token contract - */ - function reclaimERC20(address _tokenContract) external onlyOwner { - require(_tokenContract != address(0), "Invalid address"); - IERC20 token = IERC20(_tokenContract); - uint256 balance = token.balanceOf(address(this)); - require(token.transfer(msg.sender, balance), "Transfer failed"); - } - - /** - * @notice Reclaims ETH - * @dev We duplicate here due to the overriden owner & onlyOwner - */ - function reclaimETH() external onlyOwner { - msg.sender.transfer(address(this).balance); - } - } diff --git a/contracts/modules/STO/STO.sol b/contracts/modules/STO/STO.sol index 4cb832eaf..d05de918e 100644 --- a/contracts/modules/STO/STO.sol +++ b/contracts/modules/STO/STO.sol @@ -53,4 +53,24 @@ contract STO is ISTO, STOStorage, Module, Pausable { emit SetFundRaiseTypes(_fundRaiseTypes); } + /** + * @notice Reclaims ERC20Basic compatible tokens + * @dev We duplicate here due to the overriden owner & onlyOwner + * @param _tokenContract The address of the token contract + */ + function reclaimERC20(address _tokenContract) external onlyOwner { + require(_tokenContract != address(0), "Invalid address"); + IERC20 token = IERC20(_tokenContract); + uint256 balance = token.balanceOf(address(this)); + require(token.transfer(msg.sender, balance), "Transfer failed"); + } + + /** + * @notice Reclaims ETH + * @dev We duplicate here due to the overriden owner & onlyOwner + */ + function reclaimETH() external onlyOwner { + msg.sender.transfer(address(this).balance); + } + } diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index dcc3ada36..e40e4c6b0 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -277,7 +277,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @notice Reserve address must be whitelisted to successfully finalize */ function finalize() external onlyOwner { - require(!isFinalized, "STO is already finalized"); + require(!isFinalized, "STO is finalized"); isFinalized = true; uint256 tempReturned; uint256 tempSold; @@ -305,7 +305,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @param _accredited Array of bools specifying accreditation status */ function changeAccredited(address[] _investors, bool[] _accredited) external onlyOwner { - require(_investors.length == _accredited.length, "Array length mismatch"); + require(_investors.length == _accredited.length, "Array mismatch"); for (uint256 i = 0; i < _investors.length; i++) { if (_accredited[i]) { investors[_investors[i]].accredited = uint8(1); @@ -324,7 +324,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { */ function changeNonAccreditedLimit(address[] _investors, uint256[] _nonAccreditedLimit) external onlyOwner { //nonAccreditedLimitUSDOverride - require(_investors.length == _nonAccreditedLimit.length, "Array length mismatch"); + require(_investors.length == _nonAccreditedLimit.length, "Array mismatch"); for (uint256 i = 0; i < _investors.length; i++) { investors[_investors[i]].nonAccreditedLimitUSDOverride = _nonAccreditedLimit[i]; _addToInvestorsList(_investors[i]); @@ -361,7 +361,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @param _allowBeneficialInvestments Boolean to allow or disallow beneficial investments */ function changeAllowBeneficialInvestments(bool _allowBeneficialInvestments) external onlyOwner { - require(_allowBeneficialInvestments != allowBeneficialInvestments, "Value unchanged"); + require(_allowBeneficialInvestments != allowBeneficialInvestments); allowBeneficialInvestments = _allowBeneficialInvestments; emit SetAllowBeneficialInvestments(allowBeneficialInvestments); } @@ -399,7 +399,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { uint256 rate = getRate(FundRaiseType.ETH); uint256 initialMinted = getTokensMinted(); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, msg.value, rate, FundRaiseType.ETH); - require(getTokensMinted().sub(initialMinted) >= _minTokens, "Insufficient tokens minted"); + require(getTokensMinted().sub(initialMinted) >= _minTokens, "Insufficient minted"); // Modify storage investorInvested[_beneficiary][uint8(FundRaiseType.ETH)] = investorInvested[_beneficiary][uint8(FundRaiseType.ETH)].add(spentValue); fundsRaised[uint8(FundRaiseType.ETH)] = fundsRaised[uint8(FundRaiseType.ETH)].add(spentValue); @@ -434,11 +434,11 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { } function _buyWithTokens(address _beneficiary, uint256 _tokenAmount, FundRaiseType _fundRaiseType, uint256 _minTokens, IERC20 _token) internal { - require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.SC, "Invalid raise type"); + require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.SC, "Invalid raise"); uint256 initialMinted = getTokensMinted(); uint256 rate = getRate(_fundRaiseType); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, _tokenAmount, rate, _fundRaiseType); - require(getTokensMinted().sub(initialMinted) >= _minTokens, "Insufficient tokens minted"); + require(getTokensMinted().sub(initialMinted) >= _minTokens, "Insufficient minted"); // Modify storage investorInvested[_beneficiary][uint8(_fundRaiseType)] = investorInvested[_beneficiary][uint8(_fundRaiseType)].add(spentValue); fundsRaised[uint8(_fundRaiseType)] = fundsRaised[uint8(_fundRaiseType)].add(spentValue); @@ -552,12 +552,12 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { require(_investmentValue > 0, "No funds were sent"); // Check for minimum investment - require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); + require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "investment < minimumInvestmentUSD"); netInvestedUSD = investedUSD; // Check for non-accredited cap if (investors[_beneficiary].accredited == uint8(0)) { uint256 investorLimitUSD = (investors[_beneficiary].nonAccreditedLimitUSDOverride == 0) ? nonAccreditedLimitUSD : investors[_beneficiary].nonAccreditedLimitUSDOverride; - require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Over Non-accredited investor limit"); + require(investorInvestedUSD[_beneficiary] < investorLimitUSD, "Over investor limit"); if (investedUSD.add(investorInvestedUSD[_beneficiary]) > investorLimitUSD) netInvestedUSD = investorLimitUSD.sub(investorInvestedUSD[_beneficiary]); } diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 1d3820991..af5620832 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -663,10 +663,10 @@ contract("ERC20DividendCheckpoint", accounts => { ); }); - it("Set withholding tax of 20% on account_temp and 10% on investor2", async () => { + it("Set withholding tax of 20% on account_temp and 100% on investor2", async () => { await I_ERC20DividendCheckpoint.setWithholding( [account_temp, account_investor2], - [BigNumber(20 * 10 ** 16), BigNumber(10 * 10 ** 16)], + [BigNumber(20 * 10 ** 16), BigNumber(100 * 10 ** 16)], { from: token_owner } ); }); @@ -800,7 +800,7 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); - assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.2", "ether")); + assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("2", "ether")); assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0.2", "ether")); }); @@ -810,15 +810,23 @@ contract("ERC20DividendCheckpoint", accounts => { let investor2Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); let investor3Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); let tempBalance = new BigNumber(await web3.eth.getBalance(account_temp)); - await I_ERC20DividendCheckpoint.pullDividendPayment(3, { from: account_investor2, gasPrice: 0 }); + let _blockNo = latestBlock(); + let tx = await I_ERC20DividendCheckpoint.pullDividendPayment(3, { from: account_investor2, gasPrice: 0 }); let investor1BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); let investor2BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); let investor3BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); let tempBalanceAfter1 = new BigNumber(await web3.eth.getBalance(account_temp)); assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); - assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei("1.8", "ether")); + // Full amount is in withheld tax + assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); + //Check tx contains event... + const log = await promisifyLogWatch(I_ERC20DividendCheckpoint.ERC20DividendClaimed({ from: _blockNo }), 1); + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._payee, account_investor2); + assert.equal(log.args._withheld.toNumber(), web3.utils.toWei("2", "ether")); + assert.equal(log.args._amount.toNumber(), web3.utils.toWei("2", "ether")); }); it("Should issuer pushes temp investor - investor1 excluded", async () => { @@ -895,12 +903,12 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(info[0][3], account_investor3, "account match"); assert.equal(info[3][0].toNumber(), 0, "withheld match"); - assert.equal(info[3][1].toNumber(), web3.utils.toWei("0.2", "ether"), "withheld match"); + assert.equal(info[3][1].toNumber(), web3.utils.toWei("2", "ether"), "withheld match"); assert.equal(info[3][2].toNumber(), web3.utils.toWei("0.2", "ether"), "withheld match"); assert.equal(info[3][3].toNumber(), 0, "withheld match"); assert.equal(info[4][0].toNumber(), 0, "excluded"); - assert.equal(info[4][1].toNumber(), web3.utils.toWei("1.8", "ether"), "claim match"); + assert.equal(info[4][1].toNumber(), web3.utils.toWei("0", "ether"), "claim match"); assert.equal(info[4][2].toNumber(), web3.utils.toWei("0.8", "ether"), "claim match"); assert.equal(info[4][3].toNumber(), web3.utils.toWei("7", "ether"), "claim match"); @@ -909,11 +917,20 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(info[5][2].toNumber(), (await I_SecurityToken.balanceOfAt(account_temp, 4)).toNumber(), "balance match"); assert.equal(info[5][3].toNumber(), (await I_SecurityToken.balanceOfAt(account_investor3, 4)).toNumber(), "balance match"); - + let dividend = await I_ERC20DividendCheckpoint.dividends.call(3); + console.log("totalWithheld: " + dividend[8].toNumber()); + console.log("totalWithheldWithdrawn: " + dividend[9].toNumber()); + assert.equal(dividend[8].toNumber(), web3.utils.toWei("2.2", "ether")); + assert.equal(dividend[9].toNumber(), 0); let issuerBalance = new BigNumber(await I_PolyToken.balanceOf(wallet)); await I_ERC20DividendCheckpoint.withdrawWithholding(3, { from: token_owner, gasPrice: 0 }); let issuerBalanceAfter = new BigNumber(await I_PolyToken.balanceOf(wallet)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0.4", "ether")); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("2.2", "ether")); + dividend = await I_ERC20DividendCheckpoint.dividends.call(3); + console.log("totalWithheld: " + dividend[8].toNumber()); + console.log("totalWithheldWithdrawn: " + dividend[9].toNumber()); + assert.equal(dividend[8].toNumber(), web3.utils.toWei("2.2", "ether")); + assert.equal(dividend[9].toNumber(), web3.utils.toWei("2.2", "ether")); }); it("Issuer changes wallet address", async () => { @@ -969,7 +986,7 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(tx.length, 2); }); - it("should registr a delegate", async () => { + it("should register a delegate", async () => { [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); @@ -1159,7 +1176,7 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(info[1][2].toNumber(), (await I_SecurityToken.balanceOfAt.call(account_temp, checkpointID)).toNumber(), "balance match"); assert.equal(info[1][3].toNumber(), (await I_SecurityToken.balanceOfAt.call(account_investor3, checkpointID)).toNumber(), "balance match"); assert.equal(info[2][0].toNumber(), 0, "withholding match"); - assert.equal(info[2][1].toNumber(), BigNumber(10 * 10 ** 16).toNumber(), "withholding match"); + assert.equal(info[2][1].toNumber(), BigNumber(100 * 10 ** 16).toNumber(), "withholding match"); assert.equal(info[2][2].toNumber(), BigNumber(20 * 10 ** 16).toNumber(), "withholding match"); assert.equal(info[2][3].toNumber(), 0, "withholding match"); assert.equal(tx.logs[0].args._checkpointId.toNumber(), checkpointID); diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 6849e9cbd..e079649ae 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -363,6 +363,10 @@ contract("EtherDividendCheckpoint", accounts => { assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0", "ether")); }); + it("Set withholding tax of 100% on investor 2", async () => { + await I_EtherDividendCheckpoint.setWithholdingFixed([account_investor2], BigNumber(100 * 10 ** 16), { from: token_owner }); + }); + it("Buy some tokens for account_temp (1 ETH)", async () => { // Add the Investor in to the whitelist @@ -486,12 +490,13 @@ contract("EtherDividendCheckpoint", accounts => { let investor1BalanceAfter1 = new BigNumber(await web3.eth.getBalance(account_investor1)); let investor2BalanceAfter1 = new BigNumber(await web3.eth.getBalance(account_investor2)); let investor3BalanceAfter1 = new BigNumber(await web3.eth.getBalance(account_investor3)); - await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, { from: token_owner }); let investor1BalanceAfter2 = new BigNumber(await web3.eth.getBalance(account_investor1)); let investor2BalanceAfter2 = new BigNumber(await web3.eth.getBalance(account_investor2)); let investor3BalanceAfter2 = new BigNumber(await web3.eth.getBalance(account_investor3)); assert.equal(investor1BalanceAfter2.sub(investor1BalanceAfter1).toNumber(), 0); - assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), web3.utils.toWei("2.4", "ether")); + assert.equal(investor2BalanceAfter2.sub(investor2BalanceAfter1).toNumber(), 0); assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); //Check fully claimed assert.equal((await I_EtherDividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei("11", "ether")); @@ -501,7 +506,7 @@ contract("EtherDividendCheckpoint", accounts => { let issuerBalance = new BigNumber(await web3.eth.getBalance(wallet)); await I_EtherDividendCheckpoint.withdrawWithholding(2, { from: token_owner, gasPrice: 0 }); let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(wallet)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0.6", "ether")); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("3", "ether")); }); it("Investor 2 transfers 1 ETH of his token balance to investor 1", async () => { @@ -531,7 +536,7 @@ contract("EtherDividendCheckpoint", accounts => { ); }); - it("Create another new dividend with bad expirty - fails", async () => { + it("Create another new dividend with bad expiry - fails", async () => { let maturity = latestTime() - duration.days(5); let expiry = latestTime() - duration.days(2); await catchRevert( @@ -648,7 +653,7 @@ contract("EtherDividendCheckpoint", accounts => { assert.equal(dividendAmount1[0].toNumber(), web3.utils.toWei("0", "ether")); assert.equal(dividendAmount1[1].toNumber(), web3.utils.toWei("0", "ether")); assert.equal(dividendAmount2[0].toNumber(), web3.utils.toWei("2", "ether")); - assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("0.4", "ether")); + assert.equal(dividendAmount2[1].toNumber(), web3.utils.toWei("2", "ether")); assert.equal(dividendAmount3[0].toNumber(), web3.utils.toWei("7", "ether")); assert.equal(dividendAmount3[1].toNumber(), web3.utils.toWei("0", "ether")); assert.equal(dividendAmount_temp[0].toNumber(), web3.utils.toWei("1", "ether")); @@ -666,7 +671,7 @@ contract("EtherDividendCheckpoint", accounts => { let investor3BalanceAfter1 = new BigNumber(await web3.eth.getBalance(account_investor3)); let tempBalanceAfter1 = new BigNumber(await web3.eth.getBalance(account_temp)); assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); - assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), web3.utils.toWei("1.6", "ether")); + assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); assert.equal(investor3BalanceAfter1.sub(investor3Balance).toNumber(), 0); assert.equal(tempBalanceAfter1.sub(tempBalance).toNumber(), 0); }); @@ -769,7 +774,7 @@ contract("EtherDividendCheckpoint", accounts => { let tokenBalanceAfter = new BigNumber(await web3.eth.getBalance(I_PolyToken.address)); assert.equal(investor1BalanceAfter.sub(investor1BalanceBefore).toNumber(), web3.utils.toWei("1", "ether")); - assert.equal(investor2BalanceAfter.sub(investor2BalanceBefore).toNumber(), web3.utils.toWei("1.6", "ether")); + assert.equal(investor2BalanceAfter.sub(investor2BalanceBefore).toNumber(), 0); assert.equal(investor3BalanceAfter.sub(investor3BalanceBefore).toNumber(), web3.utils.toWei("7", "ether")); assert.equal(tempBalanceAfter.sub(tempBalanceBefore).toNumber(), web3.utils.toWei("1", "ether")); assert.equal(tokenBalanceAfter.sub(tokenBalanceBefore).toNumber(), web3.utils.toWei("0", "ether")); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 48cad94b8..5d7de01a5 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -2197,7 +2197,7 @@ contract("USDTieredSTO", accounts => { let investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(NONACCREDITED1); console.log("Current limit: " + investorStatus[2].toNumber()); let totalStatus = await I_USDTieredSTO_Array[stoId].getAccreditedData.call(); - + assert.equal(totalStatus[0][0], NONACCREDITED1, "Account match"); assert.equal(totalStatus[0][1], ACCREDITED1, "Account match"); assert.equal(totalStatus[1][0], false, "Account match"); @@ -4665,6 +4665,8 @@ contract("USDTieredSTO", accounts => { await I_USDOracle.changePrice(USDETH, { from: POLYMATH }); await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); }); + + it("should allow issuer to retrieve funds", async () => { }); describe("Test getter functions", async () => { From 4463496b80cd617a8ce368f8da96b93fa4ca434a Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 18 Mar 2019 12:37:27 -0400 Subject: [PATCH 552/582] Typo --- test/p_usd_tiered_sto.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 5d7de01a5..ee5838d0a 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -4666,7 +4666,6 @@ contract("USDTieredSTO", accounts => { await I_POLYOracle.changePrice(USDPOLY, { from: POLYMATH }); }); - it("should allow issuer to retrieve funds", async () => { }); describe("Test getter functions", async () => { From 8577bd8d94ac30e2b1b4b5f43da51a1c9d50850d Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 18 Mar 2019 16:14:13 -0400 Subject: [PATCH 553/582] More tests --- contracts/mocks/DummySTO.sol | 4 ++- test/b_capped_sto.js | 58 ++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/contracts/mocks/DummySTO.sol b/contracts/mocks/DummySTO.sol index f452a01eb..a444df49c 100644 --- a/contracts/mocks/DummySTO.sol +++ b/contracts/mocks/DummySTO.sol @@ -90,6 +90,8 @@ contract DummySTO is STO { return allPermissions; } - + function () payable { + //Payable fallback function to allow us to test leaking ETH + } } diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 13dff7d85..6cbbbe51a 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -2,11 +2,12 @@ import latestTime from "./helpers/latestTime"; import { duration, ensureException, promisifyLogWatch, latestBlock } from "./helpers/utils"; import { takeSnapshot, increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeModuleCall } from "./helpers/encodeCall"; -import { setUpPolymathNetwork, deployGPMAndVerifyed } from "./helpers/createInstances"; +import { setUpPolymathNetwork, deployGPMAndVerifyed, deployDummySTOAndVerifyed } from "./helpers/createInstances"; import { catchRevert } from "./helpers/exceptions"; const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const CappedSTO = artifacts.require("./CappedSTO.sol"); +const DummySTO = artifacts.require("./DummySTO.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); @@ -54,6 +55,7 @@ contract("CappedSTO", accounts => { let I_SecurityToken_POLY; let I_CappedSTO_Array_ETH = []; let I_CappedSTO_Array_POLY = []; + let I_DummySTO; let I_PolyToken; let I_PolymathRegistry; let I_STRProxied; @@ -441,7 +443,7 @@ contract("CappedSTO", accounts => { }); it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async () => { - + // Fallback transaction await web3.eth.sendTransaction({ @@ -850,6 +852,56 @@ contract("CappedSTO", accounts => { }); }); + describe("Check that we can reclaim ETH and ERC20 tokens from an STO", async () => { + //xxx + it("should attach a dummy STO", async () => { + let I_DummySTOFactory; + [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + const DummySTOParameters = ["uint256", "uint256", "uint256", "string"]; + let startTime = latestTime() + duration.days(1); + let endTime = startTime + duration.days(30); + const cap = web3.utils.toWei("10000"); + const dummyBytesSig = encodeModuleCall(DummySTOParameters, [startTime, endTime, cap, "Hello"]); + const tx = await I_SecurityToken_ETH.addModule(I_DummySTOFactory.address, dummyBytesSig, maxCost, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0], stoKey, `Wrong module type added`); + assert.equal( + web3.utils.hexToString(tx.logs[2].args._name), + "DummySTO", + `Wrong STO module added` + ); + I_DummySTO = DummySTO.at(tx.logs[2].args._module); + }); + it("should send some funds and ERC20 to the DummySTO", async () => { + let tx = await web3.eth.sendTransaction({ + from: account_investor1, + to: I_DummySTO.address, + gas: 2100000, + value: web3.utils.toWei("1", "ether") + }); + let dummyETH = BigNumber(await web3.eth.getBalance(I_DummySTO.address)); + assert.equal(dummyETH.toNumber(), web3.utils.toWei("1", "ether")); + await I_PolyToken.getTokens(web3.utils.toWei("2", "ether"), I_DummySTO.address); + let dummyPOLY = BigNumber(await I_PolyToken.balanceOf(I_DummySTO.address)); + assert.equal(dummyPOLY.toNumber(), web3.utils.toWei("2", "ether")); + }); + + it("should reclaim ETH and ERC20 from STO", async () => { + let initialIssuerETH = BigNumber(await web3.eth.getBalance(token_owner)); + let initialIssuerPOLY = BigNumber(await I_PolyToken.balanceOf(token_owner)); + let tx = await I_DummySTO.reclaimERC20(I_PolyToken.address, {from: token_owner, gasPrice: 0}); + let tx2 = await I_DummySTO.reclaimETH({from: token_owner, gasPrice: 0}); + let finalIssuerETH = BigNumber(await web3.eth.getBalance(token_owner)); + let finalIssuerPOLY = BigNumber(await I_PolyToken.balanceOf(token_owner)); + assert.equal(finalIssuerETH.sub(initialIssuerETH).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal(finalIssuerPOLY.sub(initialIssuerPOLY).toNumber(), web3.utils.toWei("2", "ether")); + let dummyETH = BigNumber(await web3.eth.getBalance(I_DummySTO.address)); + assert.equal(dummyETH.toNumber(), 0); + let dummyPOLY = BigNumber(await I_PolyToken.balanceOf(I_DummySTO.address)); + assert.equal(dummyPOLY.toNumber(), 0); + }); + }); + + describe("Test cases for the CappedSTOFactory", async () => { it("should get the exact details of the factory", async () => { assert.equal((await I_CappedSTOFactory.getSetupCost.call()).toNumber(), cappedSTOSetupCost); @@ -996,7 +1048,7 @@ contract("CappedSTO", accounts => { it("Should successfully invest in second STO", async () => { const polyToInvest = 1000; const stToReceive = (polyToInvest * P_rate)/Math.pow(10, 18); - + await I_PolyToken.getTokens(polyToInvest * Math.pow(10, 18), account_investor3); let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, true, { From 219f24e626bf237535524ecda58aab221c8af9b6 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 18 Mar 2019 17:15:53 -0400 Subject: [PATCH 554/582] Add more test cases --- .../modules/Checkpoint/DividendCheckpoint.sol | 4 +++ test/b_capped_sto.js | 2 ++ test/e_erc20_dividends.js | 34 +++++++++++++++++++ test/f_ether_dividends.js | 23 +++++++++++++ 4 files changed, 63 insertions(+) diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 54e6394cf..626638924 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -294,6 +294,10 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module, P /** * @notice Allows issuer to change maturity / expiry dates for dividends + * @dev NB - setting the maturity of a currently matured dividend to a future date + * @dev will effectively refreeze claims on that dividend until the new maturity date passes + * @ dev NB - setting the expiry date to a past date will mean no more payments can be pulled + * @dev or pushed out of a dividend * @param _dividendIndex Dividend to withdraw from * @param _maturity updated maturity date * @param _expiry updated expiry date diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 6cbbbe51a..ea4317638 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -888,6 +888,8 @@ contract("CappedSTO", accounts => { it("should reclaim ETH and ERC20 from STO", async () => { let initialIssuerETH = BigNumber(await web3.eth.getBalance(token_owner)); let initialIssuerPOLY = BigNumber(await I_PolyToken.balanceOf(token_owner)); + await catchRevert(I_DummySTO.reclaimERC20(I_PolyToken.address, {from: account_polymath, gasPrice: 0})); + await catchRevert(I_DummySTO.reclaimETH( {from: account_polymath, gasPrice: 0})); let tx = await I_DummySTO.reclaimERC20(I_PolyToken.address, {from: token_owner, gasPrice: 0}); let tx2 = await I_DummySTO.reclaimETH({from: token_owner, gasPrice: 0}); let finalIssuerETH = BigNumber(await web3.eth.getBalance(token_owner)); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index af5620832..324c2c3a2 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -805,6 +805,15 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(dividendAmount_temp[1].toNumber(), web3.utils.toWei("0.2", "ether")); }); + it("Pause and unpause the dividend contract", async () => { + await catchRevert(I_ERC20DividendCheckpoint.pause({from: account_polymath})); + let tx = await I_ERC20DividendCheckpoint.pause({from: token_owner}); + await catchRevert(I_ERC20DividendCheckpoint.pullDividendPayment(3, { from: account_investor2, gasPrice: 0 })); + await catchRevert(I_ERC20DividendCheckpoint.unpause({from: account_polymath})); + tx = await I_ERC20DividendCheckpoint.unpause({from: token_owner}); + }); + + it("Investor 2 claims dividend", async () => { let investor1Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); let investor2Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); @@ -834,7 +843,10 @@ contract("ERC20DividendCheckpoint", accounts => { let investor2BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); let investor3BalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); let tempBalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_temp)); + // Issuer can still push payments when contract is paused + let tx = await I_ERC20DividendCheckpoint.pause({from: token_owner}); await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(3, [account_temp, account_investor1], { from: token_owner }); + tx = await I_ERC20DividendCheckpoint.unpause({from: token_owner}); let investor1BalanceAfter2 = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); let investor2BalanceAfter2 = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); let investor3BalanceAfter2 = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); @@ -1227,6 +1239,28 @@ contract("ERC20DividendCheckpoint", accounts => { assert.equal(tx.logs[0].args._checkpointId.toNumber(), 10); }); + it("Update maturity and expiry dates on dividend", async () => { + await catchRevert(I_ERC20DividendCheckpoint.updateDividendDates(7, 0, 1, {from: account_polymath})); + let tx = await I_ERC20DividendCheckpoint.updateDividendDates(7, 0, 1, {from: token_owner}); + let info = await I_ERC20DividendCheckpoint.getDividendData.call(7); + assert.equal(info[1].toNumber(), 0); + assert.equal(info[2].toNumber(), 1); + // Can now reclaim the dividend + await I_ERC20DividendCheckpoint.reclaimDividend(7, {from: token_owner}); + }); + + it("Reclaim ERC20 tokens from the dividend contract", async () => { + let currentDividendBalance = BigNumber(await I_PolyToken.balanceOf.call(I_ERC20DividendCheckpoint.address)); + let currentIssuerBalance = BigNumber(await I_PolyToken.balanceOf.call(token_owner)); + await catchRevert(I_ERC20DividendCheckpoint.reclaimERC20(I_PolyToken.address, {from: account_polymath})); + let tx = await I_ERC20DividendCheckpoint.reclaimERC20(I_PolyToken.address, {from: token_owner}); + assert.equal(await I_PolyToken.balanceOf.call(I_ERC20DividendCheckpoint.address), 0); + let newIssuerBalance = BigNumber(await I_PolyToken.balanceOf.call(token_owner)); + console.log("Reclaimed: " + currentDividendBalance.toNumber()); + assert.equal(newIssuerBalance.sub(currentIssuerBalance).toNumber(), currentDividendBalance.toNumber()); + }); + + it("should allow manager with permission to create checkpoint", async () => { let initCheckpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_ERC20DividendCheckpoint.createCheckpoint({ from: account_manager }); diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index e079649ae..f6e6f2f4a 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -948,8 +948,31 @@ contract("EtherDividendCheckpoint", accounts => { { from: account_manager, value: web3.utils.toWei("12", "ether") } ); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 12); + console.log(tx.logs[0].args._dividendIndex.toNumber()); }); + it("Update maturity and expiry dates on dividend", async () => { + await catchRevert(I_EtherDividendCheckpoint.updateDividendDates(8, 0, 1, {from: account_polymath})); + let tx = await I_EtherDividendCheckpoint.updateDividendDates(8, 0, 1, {from: token_owner}); + let info = await I_EtherDividendCheckpoint.getDividendData.call(8); + assert.equal(info[1].toNumber(), 0); + assert.equal(info[2].toNumber(), 1); + // Can now reclaim the dividend + await I_EtherDividendCheckpoint.reclaimDividend(8, {from: token_owner}); + }); + + it("Reclaim ETH from the dividend contract", async () => { + let currentDividendBalance = BigNumber(await web3.eth.getBalance(I_EtherDividendCheckpoint.address)); + let currentIssuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); + await catchRevert(I_EtherDividendCheckpoint.reclaimETH({from: account_polymath, gasPrice: 0})); + let tx = await I_EtherDividendCheckpoint.reclaimETH({from: token_owner, gasPrice: 0}); + assert.equal(await web3.eth.getBalance(I_EtherDividendCheckpoint.address), 0); + let newIssuerBalance = BigNumber(await web3.eth.getBalance(token_owner)); + console.log("Reclaimed: " + currentDividendBalance.toNumber()); + assert.equal(newIssuerBalance.sub(currentIssuerBalance).toNumber(), currentDividendBalance.toNumber()); + }); + + it("should allow manager with permission to create checkpoint", async () => { let initCheckpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_EtherDividendCheckpoint.createCheckpoint({ from: account_manager }); From 8766fb1ee6d92d4816221b5cc1cb6e0baadd311f Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 20 Mar 2019 07:57:58 -0400 Subject: [PATCH 555/582] Update versions --- contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol | 2 +- contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol | 2 +- contracts/modules/STO/CappedSTOFactory.sol | 2 +- contracts/modules/STO/USDTieredSTOFactory.sol | 2 +- test/b_capped_sto.js | 2 +- test/e_erc20_dividends.js | 2 +- test/f_ether_dividends.js | 2 +- test/p_usd_tiered_sto.js | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 3935154cf..e18e54e96 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -24,7 +24,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); - version = "2.1.0"; + version = "2.1.1"; name = "ERC20DividendCheckpoint"; title = "ERC20 Dividend Checkpoint"; description = "Create ERC20 dividends for token holders at a specific checkpoint"; diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 923af1c64..0d74febf2 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -24,7 +24,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); - version = "2.1.0"; + version = "2.1.1"; name = "EtherDividendCheckpoint"; title = "Ether Dividend Checkpoint"; description = "Create ETH dividends for token holders at a specific checkpoint"; diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 273389737..f649a0f5e 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -16,7 +16,7 @@ contract CappedSTOFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "2.1.0"; + version = "2.1.1"; name = "CappedSTO"; title = "Capped STO"; description = "This smart contract creates a maximum number of tokens (i.e. hard cap) which the total aggregate of tokens acquired by all investors cannot exceed. Security tokens are sent to the investor upon reception of the funds (ETH or POLY), and any security tokens left upon termination of the offering will not be minted."; diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 1e44c7a7e..ba09d77c1 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -21,7 +21,7 @@ contract USDTieredSTOFactory is ModuleFactory { { require(_logicContract != address(0), "0x address is not allowed"); logicContract = _logicContract; - version = "2.1.0"; + version = "2.1.1"; name = "USDTieredSTO"; title = "USD Tiered STO"; /*solium-disable-next-line max-len*/ diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index ea4317638..0779ed142 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -922,7 +922,7 @@ contract("CappedSTO", accounts => { ); let tags = await I_CappedSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "Capped"); - assert.equal(await I_CappedSTOFactory.version.call(), "2.1.0"); + assert.equal(await I_CappedSTOFactory.version.call(), "2.1.1"); }); it("Should fail to change the title -- bad owner", async () => { diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 324c2c3a2..692916f67 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -1272,7 +1272,7 @@ contract("ERC20DividendCheckpoint", accounts => { it("should get the exact details of the factory", async () => { assert.equal((await I_ERC20DividendCheckpointFactory.getSetupCost.call()).toNumber(), 0); assert.equal((await I_ERC20DividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(await I_ERC20DividendCheckpointFactory.version.call(), "2.1.0"); + assert.equal(await I_ERC20DividendCheckpointFactory.version.call(), "2.1.1"); assert.equal( web3.utils.toAscii(await I_ERC20DividendCheckpointFactory.getName.call()).replace(/\u0000/g, ""), "ERC20DividendCheckpoint", diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index f6e6f2f4a..1f7646ce6 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -984,7 +984,7 @@ contract("EtherDividendCheckpoint", accounts => { it("should get the exact details of the factory", async () => { assert.equal((await I_EtherDividendCheckpointFactory.getSetupCost.call()).toNumber(), 0); assert.equal((await I_EtherDividendCheckpointFactory.getTypes.call())[0], 4); - assert.equal(await I_EtherDividendCheckpointFactory.version.call(), "2.1.0"); + assert.equal(await I_EtherDividendCheckpointFactory.version.call(), "2.1.1"); assert.equal( web3.utils.toAscii(await I_EtherDividendCheckpointFactory.getName.call()).replace(/\u0000/g, ""), "EtherDividendCheckpoint", diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index ee5838d0a..117916054 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -4792,7 +4792,7 @@ contract("USDTieredSTO", accounts => { "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.title.call(), "USD Tiered STO", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.getInstructions.call(), "Initialises a USD tiered STO.", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.version.call(), "2.1.0"); + assert.equal(await I_USDTieredSTOFactory.version.call(), "2.1.1"); let tags = await I_USDTieredSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "USD"); assert.equal(web3.utils.hexToString(tags[1]), "Tiered"); From 06bec001bd275f546b1efb52478c5ca249fb2141 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 20 Mar 2019 07:59:40 -0400 Subject: [PATCH 556/582] Only bump dividends --- contracts/modules/STO/CappedSTOFactory.sol | 2 +- contracts/modules/STO/USDTieredSTOFactory.sol | 2 +- test/b_capped_sto.js | 2 +- test/p_usd_tiered_sto.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index f649a0f5e..273389737 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -16,7 +16,7 @@ contract CappedSTOFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "2.1.1"; + version = "2.1.0"; name = "CappedSTO"; title = "Capped STO"; description = "This smart contract creates a maximum number of tokens (i.e. hard cap) which the total aggregate of tokens acquired by all investors cannot exceed. Security tokens are sent to the investor upon reception of the funds (ETH or POLY), and any security tokens left upon termination of the offering will not be minted."; diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index ba09d77c1..1e44c7a7e 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -21,7 +21,7 @@ contract USDTieredSTOFactory is ModuleFactory { { require(_logicContract != address(0), "0x address is not allowed"); logicContract = _logicContract; - version = "2.1.1"; + version = "2.1.0"; name = "USDTieredSTO"; title = "USD Tiered STO"; /*solium-disable-next-line max-len*/ diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 0779ed142..ea4317638 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -922,7 +922,7 @@ contract("CappedSTO", accounts => { ); let tags = await I_CappedSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "Capped"); - assert.equal(await I_CappedSTOFactory.version.call(), "2.1.1"); + assert.equal(await I_CappedSTOFactory.version.call(), "2.1.0"); }); it("Should fail to change the title -- bad owner", async () => { diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 117916054..ee5838d0a 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -4792,7 +4792,7 @@ contract("USDTieredSTO", accounts => { "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.title.call(), "USD Tiered STO", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.getInstructions.call(), "Initialises a USD tiered STO.", "Wrong Module added"); - assert.equal(await I_USDTieredSTOFactory.version.call(), "2.1.1"); + assert.equal(await I_USDTieredSTOFactory.version.call(), "2.1.0"); let tags = await I_USDTieredSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "USD"); assert.equal(web3.utils.hexToString(tags[1]), "Tiered"); From 9872bf9e8ab959503a65af9695f4c64daf047e40 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 Mar 2019 09:32:29 -0300 Subject: [PATCH 557/582] Fix decimals in dividends modules --- CLI/commands/dividends_manager.js | 84 ++++++++++++++++++------------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index f4aca926e..4aa438b38 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -238,9 +238,12 @@ async function manageExistingDividend(dividendIndex) { let dividend = await currentDividendsModule.methods.dividends(dividendIndex).call(); let dividendTokenAddress = gbl.constants.ADDRESS_ZERO; let dividendTokenSymbol = 'ETH'; + let dividendTokenDecimals = 18; if (dividendsType === 'ERC20') { dividendTokenAddress = await currentDividendsModule.methods.dividendTokens(dividendIndex).call(); dividendTokenSymbol = await getERC20TokenSymbol(dividendTokenAddress); + let erc20token = new web3.eth.Contract(abis.erc20(), dividendTokenAddress); + dividendTokenDecimals = await erc20token.methods.decimals().call(); } let progress = await currentDividendsModule.methods.getDividendProgress(dividendIndex).call(); let investorArray = progress[0]; @@ -266,12 +269,12 @@ async function manageExistingDividend(dividendIndex) { console.log(`- Maturity: ${moment.unix(dividend.maturity).format('MMMM Do YYYY, HH:mm:ss')}`); console.log(`- Expiry: ${moment.unix(dividend.expiry).format('MMMM Do YYYY, HH:mm:ss')}`); console.log(`- At checkpoint: ${dividend.checkpointId}`); - console.log(`- Amount: ${web3.utils.fromWei(dividend.amount)} ${dividendTokenSymbol}`); - console.log(`- Claimed amount: ${web3.utils.fromWei(dividend.claimedAmount)} ${dividendTokenSymbol}`); + console.log(`- Amount: ${dividend.amount / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol}`); + console.log(`- Claimed amount: ${dividend.claimedAmount / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol}`); console.log(`- Taxes:`); - console.log(` To withhold: ${web3.utils.fromWei(taxesToWithHeld)} ${dividendTokenSymbol}`); - console.log(` Withheld to-date: ${web3.utils.fromWei(dividend.totalWithheld)} ${dividendTokenSymbol}`); - console.log(` Withdrawn to-date: ${web3.utils.fromWei(dividend.totalWithheldWithdrawn)} ${dividendTokenSymbol}`); + console.log(` To withhold: ${taxesToWithHeld / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol}`); + console.log(` Withheld to-date: ${dividend.totalWithheld / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol}`); + console.log(` Withdrawn to-date: ${dividend.totalWithheldWithdrawn / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol}`); console.log(`- Total investors: ${investorArray.length}`); console.log(` Have already claimed: ${claimedInvestors} (${investorArray.length - excludedInvestors !== 0 ? claimedInvestors / (investorArray.length - excludedInvestors) * 100 : 0}%)`); console.log(` Excluded: ${excludedInvestors} `); @@ -300,6 +303,7 @@ async function manageExistingDividend(dividendIndex) { showReport( web3.utils.hexToUtf8(dividend.name), dividendTokenSymbol, + dividendTokenDecimals, dividend.amount, // Total amount of dividends sent dividend.totalWithheld, // Total amount of taxes withheld dividend.claimedAmount, // Total amount of dividends distributed @@ -314,13 +318,13 @@ async function manageExistingDividend(dividendIndex) { await pushDividends(dividendIndex, dividend.checkpointId); break; case 'Explore account': - await exploreAccount(dividendIndex, dividendTokenAddress, dividendTokenSymbol); + await exploreAccount(dividendIndex, dividendTokenAddress, dividendTokenSymbol, dividendTokenDecimals); break; case 'Withdraw withholding': - await withdrawWithholding(dividendIndex, dividendTokenSymbol); + await withdrawWithholding(dividendIndex, dividendTokenSymbol, dividendTokenDecimals); break; case 'Reclaim expired dividends': - await reclaimedDividend(dividendIndex, dividendTokenSymbol); + await reclaimedDividend(dividendIndex, dividendTokenSymbol, dividendTokenDecimals); return; case 'RETURN': return; @@ -376,6 +380,7 @@ async function createDividends() { let dividendName = readlineSync.question(`Enter a name or title to indetify this dividend: `); let dividendToken = gbl.constants.ADDRESS_ZERO; let dividendSymbol = 'ETH'; + let dividendTokenDecimals = 18; let token; if (dividendsType === 'ERC20') { do { @@ -390,6 +395,7 @@ async function createDividends() { if (erc20Symbol != null) { token = new web3.eth.Contract(abis.erc20(), dividendToken); dividendSymbol = erc20Symbol; + dividendTokenDecimals = await token.methods.decimals().call(); } else { console.log(chalk.red(`${dividendToken} is not a valid ERC20 token address!!`)); } @@ -397,10 +403,13 @@ async function createDividends() { } let dividendAmount = readlineSync.question(`How much ${dividendSymbol} would you like to distribute to token holders? `); - let dividendAmountBN = new web3.utils.BN(dividendAmount); - let issuerBalance = new web3.utils.BN(web3.utils.fromWei(await getBalance(Issuer.address, dividendToken))); - if (issuerBalance.lt(dividendAmountBN)) { - console.log(chalk.red(`You have ${issuerBalance} ${dividendSymbol}.You need ${dividendAmountBN.sub(issuerBalance)} ${dividendSymbol} more!`)); + console.log("Decimals:", dividendTokenDecimals); + let dividendAmountBN = parseFloat(dividendAmount) * Math.pow(10, dividendTokenDecimals); + console.log('Amount to use:', dividendAmountBN); + let issuerBalance = await getBalance(Issuer.address, dividendToken); + console.log('Issuer balance:', issuerBalance); + if (issuerBalance < dividendAmountBN) { + console.log(chalk.red(`You have ${issuerBalance / Math.pow(10, dividendTokenDecimals)} ${dividendSymbol}. You need ${(dividendAmountBN - issuerBalance) / Math.pow(10, dividendTokenDecimals)} ${dividendSymbol} more!`)); } else { let checkpointId = await selectCheckpoint(true); // If there are no checkpoints, it must create a new one let now = Math.floor(Date.now() / 1000); @@ -412,21 +421,21 @@ async function createDividends() { let createDividendAction; if (dividendsType == 'ERC20') { - let approveAction = token.methods.approve(currentDividendsModule._address, web3.utils.toWei(dividendAmountBN)); + let approveAction = token.methods.approve(currentDividendsModule._address, dividendAmountBN); await common.sendTransaction(approveAction); if (checkpointId > 0) { if (useDefaultExcluded) { - createDividendAction = currentDividendsModule.methods.createDividendWithCheckpoint(maturityTime, expiryTime, token.options.address, web3.utils.toWei(dividendAmountBN), checkpointId, web3.utils.toHex(dividendName)); + createDividendAction = currentDividendsModule.methods.createDividendWithCheckpoint(maturityTime, expiryTime, token.options.address, dividendAmountBN, checkpointId, web3.utils.toHex(dividendName)); } else { let excluded = getExcludedFromDataFile(); - createDividendAction = currentDividendsModule.methods.createDividendWithCheckpointAndExclusions(maturityTime, expiryTime, token.options.address, web3.utils.toWei(dividendAmountBN), checkpointId, excluded[0], web3.utils.toHex(dividendName)); + createDividendAction = currentDividendsModule.methods.createDividendWithCheckpointAndExclusions(maturityTime, expiryTime, token.options.address, dividendAmountBN, checkpointId, excluded[0], web3.utils.toHex(dividendName)); } } else { if (useDefaultExcluded) { - createDividendAction = currentDividendsModule.methods.createDividend(maturityTime, expiryTime, token.options.address, web3.utils.toWei(dividendAmountBN), web3.utils.toHex(dividendName)); + createDividendAction = currentDividendsModule.methods.createDividend(maturityTime, expiryTime, token.options.address, dividendAmountBN, web3.utils.toHex(dividendName)); } else { let excluded = getExcludedFromDataFile(); - createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, token.options.address, web3.utils.toWei(dividendAmountBN), excluded[0], web3.utils.toHex(dividendName)); + createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, token.options.address, dividendAmountBN, excluded[0], web3.utils.toHex(dividendName)); } } let receipt = await common.sendTransaction(createDividendAction); @@ -470,7 +479,7 @@ function showInvestors(investorsArray, claimedArray, excludedArray) { console.log(table(dataTable)); } -function showReport(_name, _tokenSymbol, _amount, _witthheld, _claimed, _investorArray, _claimedArray, _excludedArray, _withheldArray, _amountArray) { +function showReport(_name, _tokenSymbol, _tokenDecimals, _amount, _witthheld, _claimed, _investorArray, _claimedArray, _excludedArray, _withheldArray, _amountArray) { let title = `${_name.toUpperCase()} DIVIDEND REPORT`; let dataTable = [[ @@ -485,10 +494,10 @@ function showReport(_name, _tokenSymbol, _amount, _witthheld, _claimed, _investo let investor = _investorArray[i]; let excluded = _excludedArray[i]; let withdrawn = _claimedArray[i] ? 'YES' : 'NO'; - let amount = !excluded ? web3.utils.fromWei(web3.utils.toBN(_amountArray[i]).add(web3.utils.toBN(_withheldArray[i]))) : 0; - let withheld = !excluded ? web3.utils.fromWei(_withheldArray[i]) : 'NA'; + let amount = !excluded ? web3.utils.toBN(_amountArray[i]).add(web3.utils.toBN(_withheldArray[i])).divn(Math.pow(10, _tokenDecimals)) : 0; + let withheld = !excluded ? parseFloat(_withheldArray[i]) / Math.pow(10, _tokenDecimals) : 'NA'; let withheldPercentage = (!excluded) ? (withheld !== '0' ? parseFloat(withheld) / parseFloat(amount) * 100 : 0) : 'NA'; - let received = !excluded ? web3.utils.fromWei(_amountArray[i]) : 0; + let received = !excluded ? parseFloat(_amountArray[i]) / Math.pow(10, _tokenDecimals) : 0; dataTable.push([ investor, amount, @@ -501,9 +510,9 @@ function showReport(_name, _tokenSymbol, _amount, _witthheld, _claimed, _investo console.log(chalk.yellow(`-----------------------------------------------------------------------------------------------------------------------------------------------------------`)); console.log(title.padStart((50 - title.length) / 2, '*').padEnd((50 - title.length) / 2, '*')); console.log(); - console.log(`- Total amount of dividends sent: ${web3.utils.fromWei(_amount)} ${_tokenSymbol} `); - console.log(`- Total amount of taxes withheld: ${web3.utils.fromWei(_witthheld)} ${_tokenSymbol} `); - console.log(`- Total amount of dividends distributed: ${web3.utils.fromWei(_claimed)} ${_tokenSymbol} `); + console.log(`- Total amount of dividends sent: ${parseFloat(_amount) / Math.pow(10, _tokenDecimals)} ${_tokenSymbol} `); + console.log(`- Total amount of taxes withheld: ${parseFloat(_witthheld) / Math.pow(10, _tokenDecimals)} ${_tokenSymbol} `); + console.log(`- Total amount of dividends distributed: ${parseFloat(_claimed) / Math.pow(10, _tokenDecimals)} ${_tokenSymbol} `); console.log(`- Total amount of investors: ${_investorArray.length} `); console.log(); console.log(table(dataTable)); @@ -536,7 +545,7 @@ async function pushDividends(dividendIndex, checkpointId) { } } -async function exploreAccount(dividendIndex, dividendTokenAddress, dividendTokenSymbol) { +async function exploreAccount(dividendIndex, dividendTokenAddress, dividendTokenSymbol, dividendTokenDecimals) { let account = readlineSync.question('Enter address to explore: ', { limit: function (input) { return web3.utils.isAddress(input); @@ -553,33 +562,33 @@ async function exploreAccount(dividendIndex, dividendTokenAddress, dividendToken console.log(); console.log(`Security token balance: ${web3.utils.fromWei(securityTokenBalance)} ${tokenSymbol} `); - console.log(`Dividend token balance: ${web3.utils.fromWei(dividendTokenBalance)} ${dividendTokenSymbol} `); + console.log(`Dividend token balance: ${dividendTokenBalance / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol} `); console.log(`Is excluded: ${isExcluded ? 'YES' : 'NO'} `); if (!isExcluded) { console.log(`Has claimed: ${hasClaimed ? 'YES' : 'NO'} `); if (!hasClaimed) { - console.log(`Dividends available: ${web3.utils.fromWei(dividendBalance)} ${dividendTokenSymbol} `); - console.log(`Tax withheld: ${web3.utils.fromWei(dividendTax)} ${dividendTokenSymbol} `); + console.log(`Dividends available: ${dividendBalance / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol} `); + console.log(`Tax withheld: ${dividendTax / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol} `); } } console.log(); } -async function withdrawWithholding(dividendIndex, dividendTokenSymbol) { +async function withdrawWithholding(dividendIndex, dividendTokenSymbol, dividendTokenDecimals) { let action = currentDividendsModule.methods.withdrawWithholding(dividendIndex); let receipt = await common.sendTransaction(action); let eventName = dividendsType === 'ERC20' ? 'ERC20DividendWithholdingWithdrawn' : 'EtherDividendWithholdingWithdrawn'; let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, eventName); - console.log(chalk.green(`Successfully withdrew ${web3.utils.fromWei(event._withheldAmount)} ${dividendTokenSymbol} from dividend ${event._dividendIndex} tax withholding.`)); + console.log(chalk.green(`Successfully withdrew ${event._withheldAmount / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol} from dividend ${event._dividendIndex} tax withholding.`)); } -async function reclaimedDividend(dividendIndex, dividendTokenSymbol) { +async function reclaimedDividend(dividendIndex, dividendTokenSymbol, dividendTokenDecimals) { let action = currentDividendsModule.methods.reclaimDividend(dividendIndex); let receipt = await common.sendTransaction(action); let eventName = dividendsType === 'ERC20' ? 'ERC20DividendReclaimed' : 'EtherDividendReclaimed'; let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, eventName); console.log(` -Reclaimed amount ${ web3.utils.fromWei(event._claimedAmount)} ${dividendTokenSymbol} +Reclaimed amount ${event._claimedAmount / Math.pow(10, dividendTokenDecimals)} ${dividendTokenSymbol} to account ${ event._claimer} ` ); } @@ -699,7 +708,7 @@ async function selectDividend(dividends) { let result = null; let options = dividends.map(function (d) { return `${d.name} - Amount: ${web3.utils.fromWei(d.amount)} ${d.tokenSymbol} + Amount: ${parseFloat(d.amount) / Math.pow(10, d.tokenDecimals)} ${d.tokenSymbol} Status: ${isExpiredDividend(d) ? 'Expired' : hasRemaining(d) ? 'In progress' : 'Completed'} Token: ${d.tokenSymbol} Created: ${moment.unix(d.created).format('MMMM Do YYYY, HH:mm:ss')} @@ -715,7 +724,7 @@ async function selectDividend(dividends) { } async function getDividends() { - function DividendData(_index, _created, _maturity, _expiry, _amount, _claimedAmount, _name, _tokenSymbol) { + function DividendData(_index, _created, _maturity, _expiry, _amount, _claimedAmount, _name, _tokenSymbol, _tokenDecimals) { this.index = _index; this.created = _created; this.maturity = _maturity; @@ -724,6 +733,7 @@ async function getDividends() { this.claimedAmount = _claimedAmount; this.name = _name; this.tokenSymbol = _tokenSymbol; + this.tokenDecimals = _tokenDecimals; } let dividends = []; @@ -736,9 +746,12 @@ async function getDividends() { let nameArray = dividendsData.names; for (let i = 0; i < nameArray.length; i++) { let tokenSymbol = 'ETH'; + let dividendTokenDecimals = 18; if (dividendsType === 'ERC20') { let tokenAddress = await currentDividendsModule.methods.dividendTokens(i).call(); tokenSymbol = await getERC20TokenSymbol(tokenAddress); + let erc20token = new web3.eth.Contract(abis.erc20(), tokenAddress); + dividendTokenDecimals = await erc20token.methods.decimals().call(); } dividends.push( new DividendData( @@ -749,7 +762,8 @@ async function getDividends() { amountArray[i], claimedAmountArray[i], web3.utils.hexToUtf8(nameArray[i]), - tokenSymbol + tokenSymbol, + dividendTokenDecimals ) ); } From 7095b380f832d41806c26ab4cf4b19d413c689c8 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 Mar 2019 09:32:42 -0300 Subject: [PATCH 558/582] STOs are listed with its version --- CLI/commands/sto_manager.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 4a96b1088..8ab5b62fd 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -122,13 +122,17 @@ async function addSTOModule(stoConfig) { let optionSelected; if (typeof stoConfig === 'undefined') { let availableModules = await moduleRegistry.methods.getModulesByTypeAndToken(gbl.constants.MODULES_TYPES.STO, securityToken.options.address).call(); - let options = await Promise.all(availableModules.map(async function (m) { + let moduleList = await Promise.all(availableModules.map(async function (m) { let moduleFactoryABI = abis.moduleFactory(); let moduleFactory = new web3.eth.Contract(moduleFactoryABI, m); - return web3.utils.hexToUtf8(await moduleFactory.methods.name().call()); + let moduleName = web3.utils.hexToUtf8(await moduleFactory.methods.name().call()); + let moduleVersion = await moduleFactory.methods.version().call(); + return { name: moduleName, version: moduleVersion, factoryAddress: m }; })); + let options = moduleList.map(m => `${m.name} - ${m.version} (${m.factoryAddress})`); + let index = readlineSync.keyInSelect(options, 'What type of STO do you want?', { cancel: 'RETURN' }); - optionSelected = index != -1 ? options[index] : 'RETURN'; + optionSelected = index != -1 ? moduleList[index].name : 'RETURN'; } else { optionSelected = stoConfig.type; } @@ -972,6 +976,8 @@ async function getBalance(from, type) { return await web3.eth.getBalance(from); case gbl.constants.FUND_RAISE_TYPES.POLY: return await polyToken.methods.balanceOf(from).call(); + default: + return '0'; } } From daf208b31385c8a98dd42cd33d62d959b60f1397 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 Mar 2019 10:54:35 -0300 Subject: [PATCH 559/582] Reclaim ETH and ERC20 tokens from STO and Dividends modules --- CLI/commands/dividends_manager.js | 45 ++++++++++++++++++++++++++----- CLI/commands/sto_manager.js | 32 ++++++++++++++++++++++ 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 4aa438b38..97e6985c7 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -146,7 +146,7 @@ async function dividendsManager() { if (currentDividends.length > 0) { options.push('Manage existing dividends'); } - options.push('Create new dividends'); + options.push('Create new dividends', 'Reclaim ETH or ERC20 tokens from contract'); let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); let selected = index != -1 ? options[index] : 'RETURN'; @@ -178,6 +178,9 @@ async function dividendsManager() { case 'Create new dividends': await createDividends(); break; + case 'Reclaim ETH or ERC20 tokens from contract': + await reclaimFromContract(); + break; case 'RETURN': return; } @@ -326,6 +329,9 @@ async function manageExistingDividend(dividendIndex) { case 'Reclaim expired dividends': await reclaimedDividend(dividendIndex, dividendTokenSymbol, dividendTokenDecimals); return; + case 'Reclaim ETH or ERC20 tokens from contract': + await reclaim + break; case 'RETURN': return; } @@ -403,14 +409,12 @@ async function createDividends() { } let dividendAmount = readlineSync.question(`How much ${dividendSymbol} would you like to distribute to token holders? `); - console.log("Decimals:", dividendTokenDecimals); - let dividendAmountBN = parseFloat(dividendAmount) * Math.pow(10, dividendTokenDecimals); - console.log('Amount to use:', dividendAmountBN); + let dividendAmountToSend = parseFloat(dividendAmount) * Math.pow(10, dividendTokenDecimals); let issuerBalance = await getBalance(Issuer.address, dividendToken); - console.log('Issuer balance:', issuerBalance); - if (issuerBalance < dividendAmountBN) { + if (issuerBalance < dividendAmountToSend) { console.log(chalk.red(`You have ${issuerBalance / Math.pow(10, dividendTokenDecimals)} ${dividendSymbol}. You need ${(dividendAmountBN - issuerBalance) / Math.pow(10, dividendTokenDecimals)} ${dividendSymbol} more!`)); } else { + let dividendAmountBN = new web3.utils.BN(dividendAmountToSend.toString()); let checkpointId = await selectCheckpoint(true); // If there are no checkpoints, it must create a new one let now = Math.floor(Date.now() / 1000); let maturityTime = readlineSync.questionInt('Enter the dividend maturity time from which dividend can be paid (Unix Epoch time)\n(Now = ' + now + ' ): ', { defaultInput: now }); @@ -457,7 +461,7 @@ async function createDividends() { createDividendAction = currentDividendsModule.methods.createDividendWithExclusions(maturityTime, expiryTime, excluded, web3.utils.toHex(dividendName)); } } - let receipt = await common.sendTransaction(createDividendAction, { value: web3.utils.toWei(dividendAmountBN) }); + let receipt = await common.sendTransaction(createDividendAction, { value: dividendAmountBN }); let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'EtherDividendDeposited'); console.log(` Dividend ${ event._dividendIndex} deposited` @@ -466,6 +470,33 @@ Dividend ${ event._dividendIndex} deposited` } } +async function reclaimFromContract() { + let options = ['ETH', 'ERC20']; + let index = readlineSync.keyInSelect(options, 'What do you want to reclaim?', { cancel: 'RETURN' }); + let selected = index != -1 ? options[index] : 'RETURN'; + switch (selected) { + case 'ETH': + let ethBalance = await web3.eth.getBalance(currentDividendsModule.options.address); + console.log(chalk.yellow(`Current ETH balance: ${web3.utils.fromWei(ethBalance)} ETH`)); + let reclaimETHAction = currentDividendsModule.methods.reclaimETH(); + await common.sendTransaction(reclaimETHAction); + console.log(chalk.green('ETH has been reclaimed succesfully!')); + break; + case 'ERC20': + let erc20Address = readlineSync.question('Enter the ERC20 token address to reclaim (POLY = ' + polyToken.options.address + '): ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: polyToken.options.address + }); + let reclaimERC20Action = currentDividendsModule.methods.reclaimERC20(erc20Address); + await common.sendTransaction(reclaimERC20Action, { factor: 2 }); + console.log(chalk.green('ERC20 has been reclaimed succesfully!')); + break + } +} + function showInvestors(investorsArray, claimedArray, excludedArray) { let dataTable = [['Investor', 'Has claimed', 'Is excluded']]; for (let i = 0; i < investorsArray.length; i++) { diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 8ab5b62fd..2f09540f6 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -786,6 +786,8 @@ async function usdTieredSTO_configure(currentSTO) { 'Modify limits configuration', 'Modify funding configuration'); } + options.push('Reclaim ETH or ERC20 token from contract'); + let index = readlineSync.keyInSelect(options, 'What do you want to do?', { cancel: 'RETURN' }); let selected = index != -1 ? options[index] : 'Exit'; switch (selected) { @@ -844,6 +846,9 @@ async function usdTieredSTO_configure(currentSTO) { await modfifyFunding(currentSTO); await usdTieredSTO_status(currentSTO); break; + case 'Reclaim ETH or ERC20 token from contract': + await reclaimFromContract(currentSTO); + break; } } } @@ -967,6 +972,33 @@ async function modfifyTiers(currentSTO) { await common.sendTransaction(modifyTiersAction); } +async function reclaimFromContract(currentSTO) { + let options = ['ETH', 'ERC20']; + let index = readlineSync.keyInSelect(options, 'What do you want to reclaim?', { cancel: 'RETURN' }); + let selected = index != -1 ? options[index] : 'RETURN'; + switch (selected) { + case 'ETH': + let ethBalance = await this.getBalance(currentSTO.options.address, gbl.constants.FUND_RAISE_TYPES.ETH); + console.log(chalk.yellow(`Current ETH balance: ${web3.utils.fromWei(ethBalance)} ETH`)); + let reclaimETHAction = currentSTO.methods.reclaimETH(); + await common.sendTransaction(reclaimETHAction); + console.log(chalk.green('ETH has been reclaimed succesfully!')); + break; + case 'ERC20': + let erc20Address = readlineSync.question('Enter the ERC20 token address to reclaim (POLY = ' + polyToken.options.address + '): ', { + limit: function (input) { + return web3.utils.isAddress(input); + }, + limitMessage: "Must be a valid address", + defaultInput: polyToken.options.address + }); + let reclaimERC20Action = currentSTO.methods.reclaimERC20(erc20Address); + await common.sendTransaction(reclaimERC20Action); + console.log(chalk.green('ERC20 has been reclaimed succesfully!')); + break + } +} + ////////////////////// // HELPER FUNCTIONS // ////////////////////// From a6f289b9f11eb58adf508093f265bf5d921375f5 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 Mar 2019 10:59:55 -0300 Subject: [PATCH 560/582] Pause/Unpase dividend modules --- CLI/commands/token_manager.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 8ceb3bb4f..76f5f50fe 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -506,8 +506,10 @@ async function pauseModule(modules) { moduleABI = abis.ISTO(); } else if (modules[index].type == gbl.constants.MODULES_TYPES.TRANSFER) { moduleABI = abis.ITransferManager(); + } else if (modules[index].type == gbl.constants.MODULES_TYPES.DIVIDENDS) { + moduleABI = abis.erc20DividendCheckpoint(); } else { - console.log(chalk.red(`Only STO and TM modules can be paused/unpaused`)); + console.log(chalk.red(`Only STO, TM and DIVIDEND modules can be paused/unpaused`)); process.exit(0); } let pausableModule = new web3.eth.Contract(moduleABI, modules[index].address); @@ -527,8 +529,10 @@ async function unpauseModule(modules) { moduleABI = abis.ISTO(); } else if (modules[index].type == gbl.constants.MODULES_TYPES.TRANSFER) { moduleABI = abis.ITransferManager(); + } else if (modules[index].type == gbl.constants.MODULES_TYPES.DIVIDENDS) { + moduleABI = abis.erc20DividendCheckpoint(); } else { - console.log(chalk.red(`Only STO and TM modules can be paused/unpaused`)); + console.log(chalk.red(`Only STO, TM and DIVIDEND modules can be paused/unpaused`)); process.exit(0); } let pausableModule = new web3.eth.Contract(moduleABI, modules[index].address); @@ -616,7 +620,7 @@ async function getAllModules() { let details = await securityToken.methods.getModule(allModules[i]).call(); let nameTemp = web3.utils.hexToUtf8(details[0]); let pausedTemp = null; - if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER) { + if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER || type == gbl.constants.MODULES_TYPES.DIVIDENDS) { let abiTemp = JSON.parse(require('fs').readFileSync(`${__dirname}/../../build/contracts/${nameTemp}.json`).toString()).abi; let contractTemp = new web3.eth.Contract(abiTemp, details[1]); pausedTemp = await contractTemp.methods.paused().call(); From b0b71d35043d6cffa8723da74c9ddbb34ece233e Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 Mar 2019 11:00:29 -0300 Subject: [PATCH 561/582] Minor fix --- CLI/commands/dividends_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 97e6985c7..8ceaa627e 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -491,7 +491,7 @@ async function reclaimFromContract() { defaultInput: polyToken.options.address }); let reclaimERC20Action = currentDividendsModule.methods.reclaimERC20(erc20Address); - await common.sendTransaction(reclaimERC20Action, { factor: 2 }); + await common.sendTransaction(reclaimERC20Action); console.log(chalk.green('ERC20 has been reclaimed succesfully!')); break } From fc88f2d7ba232dde52c1c93ddd8170002f021d2f Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 Mar 2019 17:00:58 -0300 Subject: [PATCH 562/582] BigNumber library for dividends --- CLI/commands/dividends_manager.js | 10 +++--- CLI/package.json | 3 +- CLI/yarn.lock | 53 ++++++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 8ceaa627e..20880f7c0 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -6,6 +6,7 @@ const gbl = require('./common/global'); const contracts = require('./helpers/contract_addresses'); const abis = require('./helpers/contract_abis'); const csvParse = require('./helpers/csv'); +const BigNumber = require('bignumber.js'); const { table } = require('table') const EXCLUSIONS_DATA_CSV = `${__dirname}/../data/Checkpoint/exclusions_data.csv`; @@ -409,12 +410,11 @@ async function createDividends() { } let dividendAmount = readlineSync.question(`How much ${dividendSymbol} would you like to distribute to token holders? `); - let dividendAmountToSend = parseFloat(dividendAmount) * Math.pow(10, dividendTokenDecimals); - let issuerBalance = await getBalance(Issuer.address, dividendToken); - if (issuerBalance < dividendAmountToSend) { + let dividendAmountBN = new BigNumber(dividendAmount).times(Math.pow(10, dividendTokenDecimals)); + let issuerBalance = new BigNumber(await getBalance(Issuer.address, dividendToken)); + if (issuerBalance.lt(dividendAmountBN)) { console.log(chalk.red(`You have ${issuerBalance / Math.pow(10, dividendTokenDecimals)} ${dividendSymbol}. You need ${(dividendAmountBN - issuerBalance) / Math.pow(10, dividendTokenDecimals)} ${dividendSymbol} more!`)); } else { - let dividendAmountBN = new web3.utils.BN(dividendAmountToSend.toString()); let checkpointId = await selectCheckpoint(true); // If there are no checkpoints, it must create a new one let now = Math.floor(Date.now() / 1000); let maturityTime = readlineSync.questionInt('Enter the dividend maturity time from which dividend can be paid (Unix Epoch time)\n(Now = ' + now + ' ): ', { defaultInput: now }); @@ -525,7 +525,7 @@ function showReport(_name, _tokenSymbol, _tokenDecimals, _amount, _witthheld, _c let investor = _investorArray[i]; let excluded = _excludedArray[i]; let withdrawn = _claimedArray[i] ? 'YES' : 'NO'; - let amount = !excluded ? web3.utils.toBN(_amountArray[i]).add(web3.utils.toBN(_withheldArray[i])).divn(Math.pow(10, _tokenDecimals)) : 0; + let amount = !excluded ? new BigNumber(_amountArray[i]).plus(_withheldArray[i]).div((Math.pow(10, _tokenDecimals))) : 0; let withheld = !excluded ? parseFloat(_withheldArray[i]) / Math.pow(10, _tokenDecimals) : 'NA'; let withheldPercentage = (!excluded) ? (withheld !== '0' ? parseFloat(withheld) / parseFloat(amount) * 100 : 0) : 'NA'; let received = !excluded ? parseFloat(_amountArray[i]) / Math.pow(10, _tokenDecimals) : 0; diff --git a/CLI/package.json b/CLI/package.json index cc2773b74..354ecc878 100644 --- a/CLI/package.json +++ b/CLI/package.json @@ -4,11 +4,12 @@ "description": "CLI for Polymath-core", "main": "polymath-cli.js", "scripts": { - "stable_coin": "scripts/stable_coin.sh" + "stable_coin": "scripts/stable_coin.sh" }, "author": "Polymath Inc", "license": "MIT", "dependencies": { + "bignumber.js": "^8.1.1", "chalk": "^2.4.1", "commander": "^2.16.0", "csv-parse": "^4.0.1", diff --git a/CLI/yarn.lock b/CLI/yarn.lock index 82d60b57f..2cb4b3482 100644 --- a/CLI/yarn.lock +++ b/CLI/yarn.lock @@ -15,6 +15,11 @@ accepts@~1.3.5: mime-types "~2.1.18" negotiator "0.6.1" +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" @@ -125,6 +130,11 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bignumber.js@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.1.1.tgz#4b072ae5aea9c20f6730e4e5d529df1271c4d885" + integrity sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ== + bl@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" @@ -386,6 +396,11 @@ cookie@0.3.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= +cookiejar@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" + integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -586,6 +601,16 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= +elliptic@6.3.3: + version "6.3.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" + integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + inherits "^2.0.1" + elliptic@^6.0.0, elliptic@^6.4.0: version "6.4.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" @@ -963,6 +988,14 @@ hash-base@^3.0.0: inherits "^2.0.1" safe-buffer "^5.0.1" +hash.js@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.0" + hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.5" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" @@ -1717,6 +1750,11 @@ servify@^0.1.12: request "^2.79.0" xhr "^2.3.3" +setimmediate@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -2318,10 +2356,12 @@ xhr-request@^1.0.1: url-set-query "^1.0.0" xhr "^2.0.4" -xhr2@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" - integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8= +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= + dependencies: + cookiejar "^2.1.1" xhr@^2.0.4, xhr@^2.3.3: version "2.5.0" @@ -2333,6 +2373,11 @@ xhr@^2.0.4, xhr@^2.3.3: parse-headers "^2.0.0" xtend "^4.0.0" +xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= + xtend@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From ea1cbc8725330aa8f735f778a5987d1b57488b0a Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 Mar 2019 17:34:40 -0300 Subject: [PATCH 563/582] STO selection fix --- CLI/commands/sto_manager.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 2f09540f6..4b7165373 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -119,10 +119,11 @@ async function modifySTO(selectedSTO, currentSTO) { async function addSTOModule(stoConfig) { console.log(chalk.blue('Launch STO - Configuration')); + let factorySelected; let optionSelected; if (typeof stoConfig === 'undefined') { let availableModules = await moduleRegistry.methods.getModulesByTypeAndToken(gbl.constants.MODULES_TYPES.STO, securityToken.options.address).call(); - let moduleList = await Promise.all(availableModules.map(async function (m) { + moduleList = await Promise.all(availableModules.map(async function (m) { let moduleFactoryABI = abis.moduleFactory(); let moduleFactory = new web3.eth.Contract(moduleFactoryABI, m); let moduleName = web3.utils.hexToUtf8(await moduleFactory.methods.name().call()); @@ -133,17 +134,19 @@ async function addSTOModule(stoConfig) { let index = readlineSync.keyInSelect(options, 'What type of STO do you want?', { cancel: 'RETURN' }); optionSelected = index != -1 ? moduleList[index].name : 'RETURN'; + factorySelected = moduleList[index].factoryAddress; } else { optionSelected = stoConfig.type; + factorySelected = await await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.STO, optionSelected); } console.log('Selected:', optionSelected, '\n'); switch (optionSelected) { case 'CappedSTO': - let cappedSTO = await cappedSTO_launch(stoConfig); + let cappedSTO = await cappedSTO_launch(stoConfig, factorySelected); await cappedSTO_status(cappedSTO); break; case 'USDTieredSTO': - let usdTieredSTO = await usdTieredSTO_launch(stoConfig); + let usdTieredSTO = await usdTieredSTO_launch(stoConfig, factorySelected); await usdTieredSTO_status(usdTieredSTO); break; } @@ -152,12 +155,11 @@ async function addSTOModule(stoConfig) { //////////////// // Capped STO // //////////////// -async function cappedSTO_launch(stoConfig) { +async function cappedSTO_launch(stoConfig, factoryAddress) { console.log(chalk.blue('Launch STO - Capped STO in No. of Tokens')); let cappedSTOFactoryABI = abis.cappedSTOFactory(); - let cappedSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.STO, "CappedSTO"); - let cappedSTOFactory = new web3.eth.Contract(cappedSTOFactoryABI, cappedSTOFactoryAddress); + let cappedSTOFactory = new web3.eth.Contract(cappedSTOFactoryABI, factoryAddress); cappedSTOFactory.setProvider(web3.currentProvider); let stoFee = new web3.utils.BN(await cappedSTOFactory.methods.getSetupCost().call()); @@ -221,7 +223,7 @@ async function cappedSTO_launch(stoConfig) { cappedSTOconfig.wallet] ); - let addModuleAction = securityToken.methods.addModule(cappedSTOFactoryAddress, bytesSTO, stoFee, 0); + let addModuleAction = securityToken.methods.addModule(cappedSTOFactory.options.address, bytesSTO, stoFee, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); @@ -512,12 +514,11 @@ function timesConfigUSDTieredSTO(stoConfig) { return times; } -async function usdTieredSTO_launch(stoConfig) { +async function usdTieredSTO_launch(stoConfig, factoryAddress) { console.log(chalk.blue('Launch STO - USD pegged tiered STO')); let usdTieredSTOFactoryABI = abis.usdTieredSTOFactory(); - let usdTieredSTOFactoryAddress = await contracts.getModuleFactoryAddressByName(securityToken.options.address, gbl.constants.MODULES_TYPES.STO, 'USDTieredSTO'); - let usdTieredSTOFactory = new web3.eth.Contract(usdTieredSTOFactoryABI, usdTieredSTOFactoryAddress); + let usdTieredSTOFactory = new web3.eth.Contract(usdTieredSTOFactoryABI, factoryAddress); usdTieredSTOFactory.setProvider(web3.currentProvider); let stoFee = new web3.utils.BN(await usdTieredSTOFactory.methods.getSetupCost().call()); @@ -562,7 +563,7 @@ async function usdTieredSTO_launch(stoConfig) { addresses.usdToken] ); - let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactoryAddress, bytesSTO, stoFee, 0); + let addModuleAction = securityToken.methods.addModule(usdTieredSTOFactory.options.address, bytesSTO, stoFee, 0); let receipt = await common.sendTransaction(addModuleAction); let event = common.getEventFromLogs(securityToken._jsonInterface, receipt.logs, 'ModuleAdded'); console.log(`STO deployed at address: ${event._module}`); From 2c20b2fbfd92d184bc3076c117d73b4024dcf1c5 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 Mar 2019 21:45:06 -0300 Subject: [PATCH 564/582] Fix for pause/unpause STOs --- CLI/commands/helpers/contract_abis.js | 8 ++++---- CLI/commands/token_manager.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CLI/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index f5d8064a6..2cf7b113d 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -21,7 +21,7 @@ let erc20DividendCheckpointABI; let etherDividendCheckpointABI; let moduleInterfaceABI; let ownableABI; -let iSTOABI; +let stoABI; let iTransferManagerABI; let moduleFactoryABI; let erc20ABI; @@ -50,7 +50,7 @@ try { etherDividendCheckpointABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/EtherDividendCheckpoint.json`).toString()).abi; moduleInterfaceABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/IModule.json`).toString()).abi; ownableABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/Ownable.json`).toString()).abi; - iSTOABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ISTO.json`).toString()).abi + stoABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/STO.json`).toString()).abi iTransferManagerABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ITransferManager.json`).toString()).abi moduleFactoryABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/ModuleFactory.json`).toString()).abi; erc20ABI = JSON.parse(require('fs').readFileSync(`${__dirname}/../../../build/contracts/DetailedERC20.json`).toString()).abi; @@ -129,8 +129,8 @@ module.exports = { ownable: function () { return ownableABI; }, - ISTO: function () { - return iSTOABI; + sto: function () { + return stoABI; }, ITransferManager: function () { return iTransferManagerABI; diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index 76f5f50fe..ccbcf80d8 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -503,7 +503,7 @@ async function pauseModule(modules) { console.log("\nSelected:", options[index]); let moduleABI; if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { - moduleABI = abis.ISTO(); + moduleABI = abis.sto(); } else if (modules[index].type == gbl.constants.MODULES_TYPES.TRANSFER) { moduleABI = abis.ITransferManager(); } else if (modules[index].type == gbl.constants.MODULES_TYPES.DIVIDENDS) { @@ -526,7 +526,7 @@ async function unpauseModule(modules) { console.log("\nSelected: ", options[index]); let moduleABI; if (modules[index].type == gbl.constants.MODULES_TYPES.STO) { - moduleABI = abis.ISTO(); + moduleABI = abis.sto(); } else if (modules[index].type == gbl.constants.MODULES_TYPES.TRANSFER) { moduleABI = abis.ITransferManager(); } else if (modules[index].type == gbl.constants.MODULES_TYPES.DIVIDENDS) { From a19b2a75bd87bf74c29a4dfe7f3a7b18a1326ae7 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 Mar 2019 22:26:04 -0300 Subject: [PATCH 565/582] Show sto version when selecting --- CLI/commands/sto_manager.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CLI/commands/sto_manager.js b/CLI/commands/sto_manager.js index 4b7165373..756787e2d 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -72,7 +72,7 @@ function selectExistingSTO(stoModules, showPaused) { if (!showPaused) { filteredModules = stoModules.filter(m => !m.paused); } - let options = filteredModules.map(m => `${m.name} at ${m.address}`); + let options = filteredModules.map(m => `${m.name} (${m.version}) at ${m.address}`); let index = readlineSync.keyInSelect(options, 'Select a module: ', { cancel: false }); console.log('Selected:', options[index], '\n'); let selectedName = filteredModules[index].name; @@ -1015,13 +1015,14 @@ async function getBalance(from, type) { } async function getAllModulesByType(type) { - function ModuleInfo(_moduleType, _name, _address, _factoryAddress, _archived, _paused) { + function ModuleInfo(_moduleType, _name, _address, _factoryAddress, _archived, _paused, _version) { this.name = _name; this.type = _moduleType; this.address = _address; this.factoryAddress = _factoryAddress; this.archived = _archived; this.paused = _paused; + this.version = _version; } let modules = []; @@ -1037,7 +1038,10 @@ async function getAllModulesByType(type) { let contractTemp = new web3.eth.Contract(abiTemp, details[1]); pausedTemp = await contractTemp.methods.paused().call(); } - modules.push(new ModuleInfo(type, nameTemp, details[1], details[2], details[3], pausedTemp)); + let factoryAbi = abis.moduleFactory(); + let factory = new web3.eth.Contract(factoryAbi, details[2]); + let versionTemp = await factory.methods.version().call(); + modules.push(new ModuleInfo(type, nameTemp, details[1], details[2], details[3], pausedTemp, versionTemp)); } return modules; From c60492507505b3b7cc3c22c83dd5b92a44165a1d Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Wed, 20 Mar 2019 23:47:14 -0300 Subject: [PATCH 566/582] Updated Kovan addresses --- README.md | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 51610e9d4..d310ec4e5 100644 --- a/README.md +++ b/README.md @@ -154,27 +154,21 @@ New Kovan PolyTokenFaucet: 0xb347b9f5b56b431b2cf4e1d90a5995f7519ca792 | Contract | Address | | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -| SecurityTokenRegistry (Proxy): | [0xbefb81114d532bddddc724af20c3516fa75f0afb](https://kovan.etherscan.io/address/0xbefb81114d532bddddc724af20c3516fa75f0afb) | -| ModuleRegistry (Proxy): | [0x0fac8d8cce224eead73c1187df96570aa80a568b](https://kovan.etherscan.io/address/0x0fac8d8cce224eead73c1187df96570aa80a568b) | -| Polymath Registry: | [0x9903e7b5acfe5fa9713771a8d861eb1df8cd7046](https://kovan.etherscan.io/address/0x9903e7b5acfe5fa9713771a8d861eb1df8cd7046) | -| Feature Registry: | [0xa8f85006fdacb3d59ffae564c05433f0c949e911](https://kovan.etherscan.io/address/0xa8f85006fdacb3d59ffae564c05433f0c949e911) | +| SecurityTokenRegistry (Proxy): | [0x91110c2f67e2881a8540417be9eadf5bc9f2f248](https://kovan.etherscan.io/address/0x91110c2f67e2881a8540417be9eadf5bc9f2f248) | +| ModuleRegistry (Proxy): | [0xde6d19d7a68d453244227b6ccc5d8e6c2314627a](https://kovan.etherscan.io/address/0xde6d19d7a68d453244227b6ccc5d8e6c2314627a) | +| Polymath Registry: | [0x5b215a7d39ee305ad28da29bf2f0425c6c2a00b3](https://kovan.etherscan.io/address/0x5b215a7d39ee305ad28da29bf2f0425c6c2a00b3) | +| Feature Registry: | [0x8967a7cfc4b455398be2356cd05cd43b7a39697e](https://kovan.etherscan.io/address/0x8967a7cfc4b455398be2356cd05cd43b7a39697e) | | ETHOracle: | [0xCE5551FC9d43E9D2CC255139169FC889352405C8](https://kovan.etherscan.io/address/0xCE5551FC9d43E9D2CC255139169FC889352405C8) | | POLYOracle: | [0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C](https://kovan.etherscan.io/address/0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C) | -| General Transfer Manager Factory: | [0xfe7e2bb6c200d5222c82d0f8fecca5f8fe4ab8ce](https://kovan.etherscan.io/address/0xfe7e2bb6c200d5222c82d0f8fecca5f8fe4ab8ce) | -| General Permission Manager Factory: | [0xde5eaa8d73f43fc5e7badb203f03ecae2b29bd92](https://kovan.etherscan.io/address/0xde5eaa8d73f43fc5e7badb203f03ecae2b29bd92) | -| CappedSTOFactory: | [0xe14d7dd044cc6cfe37548b6791416c59f19bfc0d](https://kovan.etherscan.io/address/0xe14d7dd044cc6cfe37548b6791416c59f19bfc0d) | -| USDTieredSTO Factory: | [0xf9f0bb9f868d411dd9a9511a79d172449e3c15f5](https://kovan.etherscan.io/address/0xf9f0bb9f868d411dd9a9511a79d172449e3c15f5) | -| EthDividendsCheckpointFactory: | [0x2861425ba5abbf50089c473b28f6c40a8ea5262a](https://kovan.etherscan.io/address/0x2861425ba5abbf50089c473b28f6c40a8ea5262a) | -| ERC20 Dividends Checkpoint Factory: | [0xbf9495550417feaacc43f86d2244581b6d688431](https://kovan.etherscan.io/address/0xbf9495550417feaacc43f86d2244581b6d688431) | -| Count Transfer Manager Factory: | [0x3c3c1f40ae2bdca82b90541b2cfbd41caa941c0e](https://kovan.etherscan.io/address/0x3c3c1f40ae2bdca82b90541b2cfbd41caa941c0e) | -| Percentage Transfer Manager Factory: | [0x8cd00c3914b2967a8b79815037f51c76874236b8](https://kovan.etherscan.io/address/0x8cd00c3914b2967a8b79815037f51c76874236b8) | +| General Transfer Manager Factory: | [0x650e9507e983077d6f822472a7dcc37626d55c7f](https://kovan.etherscan.io/address/0x650e9507e983077d6f822472a7dcc37626d55c7f) | +| General Permission Manager Factory: | [0xbf0bd6305b523ce055baa6dfaa9676d6b9e6090b](https://kovan.etherscan.io/address/0xbf0bd6305b523ce055baa6dfaa9676d6b9e6090b) | +| CappedSTOFactory: | [0x01510b2c03296473f883c12d0723f0a46aa67f13](https://kovan.etherscan.io/address/0x01510b2c03296473f883c12d0723f0a46aa67f13) | +| USDTieredSTO Factory: | [0x8b9743e6129f7b7cca04e3611b5c8cd9b1d11e90](https://kovan.etherscan.io/address/0x8b9743e6129f7b7cca04e3611b5c8cd9b1d11e90) | +| ERC20 Dividends Checkpoint Factory: | [0x4369751df5bcb2f12f1790f525ef212a622b9c60](https://kovan.etherscan.io/address/0x4369751df5bcb2f12f1790f525ef212a622b9c60) | +| Count Transfer Manager Factory: | [0xc7cf0c1ddc85c18672951f9bfeb7163ecc8f0e2f](https://kovan.etherscan.io/address/0xc7cf0c1ddc85c18672951f9bfeb7163ecc8f0e2f) | +| Percentage Transfer Manager Factory: | [0xfea5fcb254bcb4ada0f86903ff822d6372325cb1](https://kovan.etherscan.io/address/0xfea5fcb254bcb4ada0f86903ff822d6372325cb1) | | Manual Approval Transfer Manager Factory: | [0x9faa79e2ccf0eb49aa6ebde1795ad2e951ce78f8](https://kovan.etherscan.io/address/0x9faa79e2ccf0eb49aa6ebde1795ad2e951ce78f8) | - -New ManualApprovalTransferManager 0x9faa79e2ccf0eb49aa6ebde1795ad2e951ce78f8 -(Fixed 0x0 from bug) - - ## Package version requirements for your machine: - node v8.x.x or v9.x.x From a5b6c32ce8b281c6b57749ec1e00a5519d8b6910 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 21 Mar 2019 17:26:46 -0300 Subject: [PATCH 567/582] Version info for all modules --- CLI/commands/token_manager.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/CLI/commands/token_manager.js b/CLI/commands/token_manager.js index ccbcf80d8..a908a4277 100644 --- a/CLI/commands/token_manager.js +++ b/CLI/commands/token_manager.js @@ -107,27 +107,27 @@ async function displayModules() { if (numPM) { console.log(`Permission Manager Modules:`); - pmModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + pmModules.map(m => console.log(`- ${m.name} (${m.version}) is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); } if (numTM) { console.log(`Transfer Manager Modules:`); - tmModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + tmModules.map(m => console.log(`- ${m.name} (${m.version}) is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); } if (numSTO) { console.log(`STO Modules:`); - stoModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + stoModules.map(m => console.log(`- ${m.name} (${m.version}) is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); } if (numCP) { console.log(`Checkpoint Modules:`); - cpModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + cpModules.map(m => console.log(`- ${m.name} (${m.version}) is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); } if (numBURN) { console.log(` Burn Modules:`); - burnModules.map(m => console.log(`- ${m.name} is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); + burnModules.map(m => console.log(`- ${m.name} (${m.version}) is ${(m.archived) ? chalk.yellow('archived') : 'unarchived'} at ${m.address}`)); } } @@ -497,7 +497,7 @@ async function addModule() { } async function pauseModule(modules) { - let options = modules.map(m => `${m.name} (${m.address})`); + let options = modules.map(m => `${m.name} (${m.version}) at ${m.address}`); let index = readlineSync.keyInSelect(options, 'Which module would you like to pause?'); if (index != -1) { console.log("\nSelected:", options[index]); @@ -520,7 +520,7 @@ async function pauseModule(modules) { } async function unpauseModule(modules) { - let options = modules.map(m => `${m.name} (${m.address})`); + let options = modules.map(m => `${m.name} (${m.version}) at ${m.address}`); let index = readlineSync.keyInSelect(options, 'Which module would you like to pause?'); if (index != -1) { console.log("\nSelected: ", options[index]); @@ -543,7 +543,7 @@ async function unpauseModule(modules) { } async function archiveModule(modules) { - let options = modules.map(m => `${m.name} (${m.address})`); + let options = modules.map(m => `${m.name} (${m.version}) at ${m.address}`); let index = readlineSync.keyInSelect(options, 'Which module would you like to archive?'); if (index != -1) { console.log("\nSelected: ", options[index]); @@ -554,7 +554,7 @@ async function archiveModule(modules) { } async function unarchiveModule(modules) { - let options = modules.map(m => `${m.name} (${m.address})`); + let options = modules.map(m => `${m.name} (${m.version}) at ${m.address}`); let index = readlineSync.keyInSelect(options, 'Which module would you like to unarchive?'); if (index != -1) { console.log("\nSelected: ", options[index]); @@ -565,7 +565,7 @@ async function unarchiveModule(modules) { } async function removeModule(modules) { - let options = modules.map(m => `${m.name} (${m.address})`); + let options = modules.map(m => `${m.name} (${m.version}) at ${m.address}`); let index = readlineSync.keyInSelect(options, 'Which module would you like to remove?'); if (index != -1) { console.log("\nSelected: ", options[index]); @@ -576,7 +576,7 @@ async function removeModule(modules) { } async function changeBudget(modules) { - let options = modules.map(m => `${m.name} (${m.address})`); + let options = modules.map(m => `${m.name} (${m.version}) at ${m.address}`); let index = readlineSync.keyInSelect(options, 'Which module would you like to change budget for?'); if (index != -1) { console.log("\nSelected: ", options[index]); @@ -599,13 +599,14 @@ async function showUserInfo(_user) { } async function getAllModules() { - function ModuleInfo(_moduleType, _name, _address, _factoryAddress, _archived, _paused) { + function ModuleInfo(_moduleType, _name, _address, _factoryAddress, _archived, _paused, _version) { this.name = _name; this.type = _moduleType; this.address = _address; this.factoryAddress = _factoryAddress; this.archived = _archived; this.paused = _paused; + this.version = _version; } let modules = []; @@ -620,12 +621,16 @@ async function getAllModules() { let details = await securityToken.methods.getModule(allModules[i]).call(); let nameTemp = web3.utils.hexToUtf8(details[0]); let pausedTemp = null; - if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER || type == gbl.constants.MODULES_TYPES.DIVIDENDS) { + let factoryAbi = abis.moduleFactory(); + let factory = new web3.eth.Contract(factoryAbi, details[2]); + let versionTemp = await factory.methods.version().call(); + if (type == gbl.constants.MODULES_TYPES.STO || type == gbl.constants.MODULES_TYPES.TRANSFER || (type == gbl.constants.MODULES_TYPES.DIVIDENDS && versionTemp === '2.1.1')) { let abiTemp = JSON.parse(require('fs').readFileSync(`${__dirname}/../../build/contracts/${nameTemp}.json`).toString()).abi; let contractTemp = new web3.eth.Contract(abiTemp, details[1]); pausedTemp = await contractTemp.methods.paused().call(); } - modules.push(new ModuleInfo(type, nameTemp, details[1], details[2], details[3], pausedTemp)); + + modules.push(new ModuleInfo(type, nameTemp, details[1], details[2], details[3], pausedTemp, versionTemp)); } catch (error) { console.log(error); console.log(chalk.red(` From c4afe289cc1b8f1f501562f64db03a6236ffda08 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 26 Mar 2019 16:08:47 +0530 Subject: [PATCH 568/582] audit fixes 1..9 --- contracts/libraries/VolumeRestrictionLib.sol | 35 +- .../TransferManager/VolumeRestrictionTM.sol | 356 +++--- .../storage/VolumeRestrictionTMStorage.sol | 4 +- package.json | 2 +- test/y_volume_restriction_tm.js | 30 +- yarn.lock | 1031 +---------------- 6 files changed, 200 insertions(+), 1258 deletions(-) diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol index 9f71d3fed..7129eecca 100644 --- a/contracts/libraries/VolumeRestrictionLib.sol +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -15,7 +15,7 @@ library VolumeRestrictionLib { uint256[] _startTimes, uint256[] _rollingPeriodInDays, uint256[] _endTimes, - uint256[] _restrictionTypes + VolumeRestrictionTMStorage.RestrictionType[] _restrictionTypes ) internal pure @@ -30,14 +30,20 @@ library VolumeRestrictionLib { ); } - function deleteHolderFromList(VolumeRestrictionTMStorage.RestrictedData storage data, address _holder, uint8 _typeOfPeriod) public { + function deleteHolderFromList( + VolumeRestrictionTMStorage.RestrictedData storage data, + address _holder, + VolumeRestrictionTMStorage.TypeOfPeriod _typeOfPeriod + ) + public + { // Deleting the holder if holder's type of Period is `Both` type otherwise // it will assign the given type `_typeOfPeriod` to the _holder typeOfPeriod // `_typeOfPeriod` it always be contrary to the removing restriction // if removing restriction is individual then typeOfPeriod is TypeOfPeriod.OneDay // in uint8 its value is 1. if removing restriction is daily individual then typeOfPeriod // is TypeOfPeriod.MultipleDays in uint8 its value is 0. - if (data.restrictedHolders[_holder].typeOfPeriod != uint8(VolumeRestrictionTMStorage.TypeOfPeriod.Both)) { + if (data.restrictedHolders[_holder].typeOfPeriod != VolumeRestrictionTMStorage.TypeOfPeriod.Both) { uint128 index = data.restrictedHolders[_holder].index; uint256 _len = data.restrictedAddresses.length; if (index != _len) { @@ -51,19 +57,34 @@ library VolumeRestrictionLib { } } - function addRestrictionData(VolumeRestrictionTMStorage.RestrictedData storage data, address _holder, uint8 _callFrom, uint256 _endTime) public { + function addRestrictionData( + VolumeRestrictionTMStorage.RestrictedData storage data, + address _holder, + VolumeRestrictionTMStorage.TypeOfPeriod _callFrom, + uint256 _endTime + ) + public + { uint128 index = data.restrictedHolders[_holder].index; if (data.restrictedHolders[_holder].seen == 0) { data.restrictedAddresses.push(_holder); index = uint128(data.restrictedAddresses.length); } - uint8 _type = _getTypeOfPeriod(data.restrictedHolders[_holder].typeOfPeriod, _callFrom, _endTime); + VolumeRestrictionTMStorage.TypeOfPeriod _type = _getTypeOfPeriod(data.restrictedHolders[_holder].typeOfPeriod, _callFrom, _endTime); data.restrictedHolders[_holder] = VolumeRestrictionTMStorage.RestrictedHolder(uint8(1), _type, index); } - function _getTypeOfPeriod(uint8 _currentTypeOfPeriod, uint8 _callFrom, uint256 _endTime) internal pure returns(uint8) { + function _getTypeOfPeriod( + VolumeRestrictionTMStorage.TypeOfPeriod _currentTypeOfPeriod, + VolumeRestrictionTMStorage.TypeOfPeriod _callFrom, + uint256 _endTime + ) + internal + pure + returns(VolumeRestrictionTMStorage.TypeOfPeriod) + { if (_currentTypeOfPeriod != _callFrom && _endTime != uint256(0)) - return uint8(VolumeRestrictionTMStorage.TypeOfPeriod.Both); + return VolumeRestrictionTMStorage.TypeOfPeriod.Both; else return _callFrom; } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 6547d1b61..fdb691223 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -21,7 +21,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _typeOfRestriction + RestrictionType _typeOfRestriction ); // Emit when the new daily (Individual) restriction is added event AddIndividualDailyRestriction( @@ -30,7 +30,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _typeOfRestriction + RestrictionType _typeOfRestriction ); // Emit when the individual restriction is modified for a given address event ModifyIndividualRestriction( @@ -39,7 +39,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _typeOfRestriction + RestrictionType _typeOfRestriction ); // Emit when individual daily restriction get modified event ModifyIndividualDailyRestriction( @@ -48,7 +48,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _typeOfRestriction + RestrictionType _typeOfRestriction ); // Emit when the new global restriction is added event AddDefaultRestriction( @@ -56,7 +56,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _typeOfRestriction + RestrictionType _typeOfRestriction ); // Emit when the new daily (Default) restriction is added event AddDefaultDailyRestriction( @@ -64,7 +64,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _typeOfRestriction + RestrictionType _typeOfRestriction ); // Emit when default restriction get modified event ModifyDefaultRestriction( @@ -72,7 +72,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _typeOfRestriction + RestrictionType _typeOfRestriction ); // Emit when daily default restriction get modified event ModifyDefaultDailyRestriction( @@ -80,7 +80,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _typeOfRestriction + RestrictionType _typeOfRestriction ); // Emit when the individual restriction gets removed event IndividualRestrictionRemoved(address indexed _holder); @@ -118,13 +118,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Checking the individual restriction if the `_from` comes in the individual category if ((individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) || (individualDailyRestriction[_from].endTime >= now && individualDailyRestriction[_from].startTime <= now)) { - - return _individualRestrictionCheck(_from, _amount, _isTransfer); + + return _restrictionCheck(_isTransfer, _from, _amount, userToBucket[_from], individualRestriction[_from], false); + // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically } else if ((defaultRestriction.endTime >= now && defaultRestriction.startTime <= now) || (defaultDailyRestriction.endTime >= now && defaultDailyRestriction.startTime <= now)) { - - return _defaultRestrictionCheck(_from, _amount, _isTransfer); + + return _restrictionCheck(_isTransfer, _from, _amount, defaultUserToBucket[_from], defaultRestriction, true); } } return Result.NA; @@ -135,7 +136,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _wallet Ethereum wallet/contract address that need to be exempted * @param _change Boolean value used to add (i.e true) or remove (i.e false) from the list */ - function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { + function changeExemptWalletList(address _wallet, bool _change) external withPerm(ADMIN) { require(_wallet != address(0)); require((exemptIndex[_wallet] == 0) == _change); if (_change) { @@ -165,7 +166,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) external withPerm(ADMIN) @@ -187,20 +188,12 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) internal { - - if (_startTime == 0) { - _startTime = now; - } - require( - individualRestriction[_holder].endTime < now, - "Not Allowed" - ); require(_holder != address(0) && exemptIndex[_holder] == 0, "Invalid address"); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); if (individualRestriction[_holder].endTime != 0) { _removeIndividualRestriction(_holder); @@ -210,9 +203,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _startTime, _rollingPeriodInDays, _endTime, - RestrictionType(_restrictionType) + _restrictionType ); - VolumeRestrictionLib.addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.MultipleDays), individualRestriction[_holder].endTime); + VolumeRestrictionLib.addRestrictionData(holderData, _holder, TypeOfPeriod.MultipleDays, individualRestriction[_holder].endTime); emit AddIndividualRestriction( _holder, _allowedTokens, @@ -224,7 +217,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } /** - * @notice Use to add the new individual daily restriction for all token holder + * @notice Use to add the new individual daily restriction for a given token holder * @param _holder Address of the token holder, whom restriction will be implied * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _startTime Unix timestamp at which restriction get into effect @@ -236,7 +229,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) external withPerm(ADMIN) @@ -256,18 +249,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) internal { - if (_startTime == 0) { - _startTime = now; - } - require( - individualDailyRestriction[_holder].endTime < now, - "Not Allowed" - ); - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now, false); if (individualDailyRestriction[_holder].endTime != 0) { _removeIndividualDailyRestriction(_holder); } @@ -276,9 +262,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _startTime, 1, _endTime, - RestrictionType(_restrictionType) + _restrictionType ); - VolumeRestrictionLib.addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.OneDay), individualRestriction[_holder].endTime); + VolumeRestrictionLib.addRestrictionData(holderData, _holder, TypeOfPeriod.OneDay, individualRestriction[_holder].endTime); emit AddIndividualDailyRestriction( _holder, _allowedTokens, @@ -302,9 +288,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _allowedTokens, uint256[] _startTimes, uint256[] _endTimes, - uint256[] _restrictionTypes + RestrictionType[] _restrictionTypes ) - public + external withPerm(ADMIN) { //NB - we duplicate _startTimes below to allow function reuse @@ -335,7 +321,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _startTimes, uint256[] _rollingPeriodInDays, uint256[] _endTimes, - uint256[] _restrictionTypes + RestrictionType[] _restrictionTypes ) public withPerm(ADMIN) @@ -366,30 +352,22 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) external withPerm(ADMIN) { - uint256 startTime = _startTime; - if (_startTime == 0) { - startTime = now; - } - require( - defaultRestriction.endTime < now, - "Not Allowed" - ); - _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); defaultRestriction = VolumeRestriction( _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, - RestrictionType(_restrictionType) + _restrictionType ); emit AddDefaultRestriction( _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -407,30 +385,22 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) external withPerm(ADMIN) { - uint256 startTime = _startTime; - if (_startTime == 0) { - startTime = now; - } - require( - defaultDailyRestriction.endTime < now, - "Not Allowed" - ); - _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, now); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now, false); defaultDailyRestriction = VolumeRestriction( _allowedTokens, - startTime, + _startTime, 1, _endTime, - RestrictionType(_restrictionType) + _restrictionType ); emit AddDefaultDailyRestriction( _allowedTokens, - startTime, + _startTime, 1, _endTime, _restrictionType @@ -450,7 +420,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_holder != address(0)); require(individualRestriction[_holder].endTime != 0); individualRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - VolumeRestrictionLib.deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.OneDay)); + VolumeRestrictionLib.deleteHolderFromList(holderData, _holder, TypeOfPeriod.OneDay); userToBucket[_holder].lastTradedDayTime = 0; userToBucket[_holder].sumOfLastPeriod = 0; userToBucket[_holder].daysCovered = 0; @@ -480,7 +450,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_holder != address(0)); require(individualDailyRestriction[_holder].endTime != 0); individualDailyRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); - VolumeRestrictionLib.deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.MultipleDays)); + VolumeRestrictionLib.deleteHolderFromList(holderData, _holder, TypeOfPeriod.MultipleDays); userToBucket[_holder].dailyLastTradedDayTime = 0; emit IndividualDailyRestrictionRemoved(_holder); } @@ -498,7 +468,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice Use to remove the default restriction */ - function removeDefaultRestriction() public withPerm(ADMIN) { + function removeDefaultRestriction() external withPerm(ADMIN) { require(defaultRestriction.endTime != 0); defaultRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); emit DefaultRestrictionRemoved(); @@ -528,7 +498,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) external withPerm(ADMIN) @@ -550,22 +520,18 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) internal { - /* uint256 startTime = _startTime; */ - if (_startTime == 0) { - _startTime = now; - } - require(individualRestriction[_holder].startTime > now, "Not Allowed"); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); + _isAllowedToModify(individualRestriction[_holder].startTime); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); individualRestriction[_holder] = VolumeRestriction( _allowedTokens, _startTime, _rollingPeriodInDays, _endTime, - RestrictionType(_restrictionType) + _restrictionType ); emit ModifyIndividualRestriction( _holder, @@ -592,7 +558,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) external withPerm(ADMIN) @@ -612,22 +578,20 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) internal { - if (_startTime == 0) { - _startTime = now; - } _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, - (individualDailyRestriction[_holder].startTime <= now ? individualDailyRestriction[_holder].startTime : now) + (individualDailyRestriction[_holder].startTime <= now ? individualDailyRestriction[_holder].startTime : now), + true ); individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, _startTime, 1, _endTime, - RestrictionType(_restrictionType) + _restrictionType ); emit ModifyIndividualDailyRestriction( _holder, @@ -652,9 +616,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _allowedTokens, uint256[] _startTimes, uint256[] _endTimes, - uint256[] _restrictionTypes + RestrictionType[] _restrictionTypes ) - public + external withPerm(ADMIN) { //NB - we duplicate _startTimes below to allow function reuse @@ -685,7 +649,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _startTimes, uint256[] _rollingPeriodInDays, uint256[] _endTimes, - uint256[] _restrictionTypes + RestrictionType[] _restrictionTypes ) public withPerm(ADMIN) @@ -716,27 +680,23 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodInDays, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) external withPerm(ADMIN) { - require(defaultRestriction.startTime > now, "Not Allowed"); - uint256 startTime = _startTime; - if (_startTime == 0) { - startTime = now; - } - _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); + _isAllowedToModify(defaultRestriction.startTime); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); defaultRestriction = VolumeRestriction( _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, - RestrictionType(_restrictionType) + _restrictionType ); emit ModifyDefaultRestriction( _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -756,30 +716,27 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _allowedTokens, uint256 _startTime, uint256 _endTime, - uint256 _restrictionType + RestrictionType _restrictionType ) external withPerm(ADMIN) { - uint256 startTime = _startTime; - if (_startTime == 0) { - startTime = now; - } // If old startTime is already passed then new startTime should be greater than or equal to the // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. - _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, - (defaultDailyRestriction.startTime <= now ? defaultDailyRestriction.startTime : now) + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, + (defaultDailyRestriction.startTime <= now ? defaultDailyRestriction.startTime : now), + true ); defaultDailyRestriction = VolumeRestriction( _allowedTokens, - startTime, + _startTime, 1, _endTime, - RestrictionType(_restrictionType) + _restrictionType ); emit ModifyDefaultDailyRestriction( _allowedTokens, - startTime, + _startTime, 1, _endTime, _restrictionType @@ -790,22 +747,36 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @notice Internal function used to validate the transaction for a given address * If it validates then it also update the storage corressponds to the default restriction */ - function _defaultRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { + function _restrictionCheck( + bool _isTransfer, + address _from, + uint256 _amount, + BucketDetails storage _bucketDetails, + VolumeRestriction memory _restriction, + bool _isDefault + ) + internal + returns (Result) + { // using the variable to avoid stack too deep error - BucketDetails storage bucketDetails = defaultUserToBucket[_from]; - uint256 daysCovered = defaultRestriction.rollingPeriodInDays; + VolumeRestriction memory dailyRestriction = individualDailyRestriction[_from]; + if (_isDefault) + dailyRestriction = defaultDailyRestriction; + + uint256 daysCovered = _restriction.rollingPeriodInDays; uint256 fromTimestamp = 0; uint256 sumOfLastPeriod = 0; uint256 dailyTime = 0; + // This variable works for both allowedDefault or allowedIndividual bool allowedDefault = true; bool allowedDaily; - if (defaultRestriction.endTime >= now && defaultRestriction.startTime <= now) { - if (bucketDetails.lastTradedDayTime < defaultRestriction.startTime) { + if (_restriction.endTime >= now && _restriction.startTime <= now) { + if (_bucketDetails.lastTradedDayTime < _restriction.startTime) { // It will execute when the txn is performed first time after the addition of individual restriction - fromTimestamp = defaultRestriction.startTime; + fromTimestamp = _restriction.startTime; } else { // Picking up the last timestamp - fromTimestamp = bucketDetails.lastTradedDayTime; + fromTimestamp = _bucketDetails.lastTradedDayTime; } // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod @@ -815,14 +786,16 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now), _from, daysCovered, - bucketDetails + _bucketDetails, + _isDefault ); // validation of the transaction amount - if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, defaultRestriction)) { + if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, _restriction)) { allowedDefault = false; } } - (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, bucketDetails.dailyLastTradedDayTime, defaultDailyRestriction); + + (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, _bucketDetails.dailyLastTradedDayTime, dailyRestriction, _isDefault); if (_isTransfer) { _updateStorage( @@ -832,74 +805,18 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { sumOfLastPeriod, daysCovered, dailyTime, - defaultDailyRestriction.endTime, - true + _isDefault ); } return ((allowedDaily && allowedDefault) == true ? Result.NA : Result.INVALID); } - /** - * @notice Internal function used to validate the transaction for a given address - * If it validates then it also update the storage corressponds to the individual restriction - */ - function _individualRestrictionCheck(address _from, uint256 _amount, bool _isTransfer) internal returns (Result) { - // using the variable to avoid stack too deep error - BucketDetails memory bucketDetails = userToBucket[_from]; - VolumeRestriction memory dailyRestriction = individualDailyRestriction[_from]; - VolumeRestriction memory restriction = individualRestriction[_from]; - uint256 daysCovered = individualRestriction[_from].rollingPeriodInDays; - uint256 fromTimestamp = 0; - uint256 sumOfLastPeriod = 0; - uint256 dailyTime = 0; - bool allowedIndividual = true; - bool allowedDaily; - if (restriction.endTime >= now && restriction.startTime <= now) { - if (bucketDetails.lastTradedDayTime < restriction.startTime) { - // It will execute when the txn is performed first time after the addition of individual restriction - fromTimestamp = restriction.startTime; - } else { - // Picking up the last timestamp - fromTimestamp = bucketDetails.lastTradedDayTime; - } - - // Check with the bucket and parse all the new timestamps to calculate the sumOfLastPeriod - // re-using the local variables to avoid the stack too deep error. - (sumOfLastPeriod, fromTimestamp, daysCovered) = _bucketCheck( - fromTimestamp, - BokkyPooBahsDateTimeLibrary.diffDays(fromTimestamp, now), - _from, - daysCovered, - bucketDetails - ); - // validation of the transaction amount - if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, restriction)) { - allowedIndividual = false; - } - } - (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, bucketDetails.dailyLastTradedDayTime, dailyRestriction); - - if (_isTransfer) { - _updateStorage( - _from, - _amount, - fromTimestamp, - sumOfLastPeriod, - daysCovered, - dailyTime, - dailyRestriction.endTime, - false - ); - } - - return ((allowedDaily && allowedIndividual) ? Result.NA : Result.INVALID); - } - function _dailyTxCheck( address from, uint256 amount, uint256 dailyLastTradedDayTime, - VolumeRestriction restriction + VolumeRestriction restriction, + bool isDefault ) internal view @@ -915,7 +832,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { else if (now.sub(dailyLastTradedDayTime) >= 1 days) dailyLastTradedDayTime = dailyLastTradedDayTime.add(BokkyPooBahsDateTimeLibrary.diffDays(dailyLastTradedDayTime, now).mul(1 days)); // Assgining total sum traded on dailyLastTradedDayTime timestamp - txSumOfDay = bucket[from][dailyLastTradedDayTime]; + if (isDefault) + txSumOfDay = defaultBucket[from][dailyLastTradedDayTime]; + else + txSumOfDay = bucket[from][dailyLastTradedDayTime]; return (_checkValidAmountToTransact(txSumOfDay, amount, restriction), dailyLastTradedDayTime); } return (true, dailyLastTradedDayTime); @@ -927,7 +847,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _diffDays, address _from, uint256 _rollingPeriodInDays, - BucketDetails memory _bucketDetails + BucketDetails memory _bucketDetails, + bool isDefault ) internal view @@ -953,7 +874,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Loop starts from the first day covered in sumOfLastPeriod upto the day that is covered by rolling period. uint256 temp = _bucketDetails.daysCovered.sub(counter.sub(_rollingPeriodInDays)); temp = _bucketDetails.lastTradedDayTime.sub(temp.mul(1 days)); - sumOfLastPeriod = sumOfLastPeriod.sub(bucket[_from][temp]); + if (isDefault) + sumOfLastPeriod = sumOfLastPeriod.sub(defaultBucket[_from][temp]); + else + sumOfLastPeriod = sumOfLastPeriod.sub(bucket[_from][temp]); } // Adding the last amount that is transacted on the `_fromTime` not actually doing it but left written to understand // the alogrithm @@ -993,7 +917,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _sumOfLastPeriod, uint256 _daysCovered, uint256 _dailyLastTradedDayTime, - uint256 _endTime, bool isDefault ) internal @@ -1001,11 +924,12 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (isDefault){ BucketDetails storage defaultUserToBucketDetails = defaultUserToBucket[_from]; - _updateStorageActual(_from, _amount, _lastTradedDayTime, _sumOfLastPeriod, _daysCovered, _dailyLastTradedDayTime, _endTime, defaultUserToBucketDetails); + _updateStorageActual(_from, _amount, _lastTradedDayTime, _sumOfLastPeriod, _daysCovered, _dailyLastTradedDayTime, defaultDailyRestriction.endTime, true, defaultUserToBucketDetails); } else { BucketDetails storage userToBucketDetails = userToBucket[_from]; - _updateStorageActual(_from, _amount, _lastTradedDayTime, _sumOfLastPeriod, _daysCovered, _dailyLastTradedDayTime, _endTime, userToBucketDetails); + uint256 _endTime = individualDailyRestriction[_from].endTime; + _updateStorageActual(_from, _amount, _lastTradedDayTime, _sumOfLastPeriod, _daysCovered, _dailyLastTradedDayTime, _endTime, false, userToBucketDetails); } } @@ -1017,6 +941,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _daysCovered, uint256 _dailyLastTradedDayTime, uint256 _endTime, + bool isDefault, BucketDetails storage details ) internal @@ -1037,11 +962,18 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (_lastTradedDayTime !=0) { details.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); // Increasing the total amount of the day by `_amount` - bucket[_from][_lastTradedDayTime] = bucket[_from][_lastTradedDayTime].add(_amount); + if (isDefault) + defaultBucket[_from][_lastTradedDayTime] = defaultBucket[_from][_lastTradedDayTime].add(_amount); + else + bucket[_from][_lastTradedDayTime] = bucket[_from][_lastTradedDayTime].add(_amount); } if ((_dailyLastTradedDayTime != _lastTradedDayTime) && _dailyLastTradedDayTime != 0 && now <= _endTime) { // Increasing the total amount of the day by `_amount` - bucket[_from][_dailyLastTradedDayTime] = bucket[_from][_dailyLastTradedDayTime].add(_amount); + if (isDefault) + defaultBucket[_from][_dailyLastTradedDayTime] = defaultBucket[_from][_dailyLastTradedDayTime].add(_amount); + else + bucket[_from][_dailyLastTradedDayTime] = bucket[_from][_dailyLastTradedDayTime].add(_amount); + } } } @@ -1051,20 +983,26 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _startTime, uint256 _rollingPeriodDays, uint256 _endTime, - uint256 _restrictionType, - uint256 _earliestStartTime + RestrictionType _restrictionType, + uint256 _earliestStartTime, + bool isModifyDaily ) internal pure { - require(_restrictionType == 0 || _restrictionType == 1, "Invalid type"); - require(_startTime >= _earliestStartTime, "Invalid startTime"); - if (_restrictionType == uint256(RestrictionType.Fixed)) { - require(_allowedTokens > 0, "Invalid value"); + require(_restrictionType == RestrictionType.Fixed || _restrictionType == RestrictionType.Percentage, + "Invalid restriction type" + ); + if (isModifyDaily) + require(_startTime >= _earliestStartTime, "Invalid startTime"); + else + require(_startTime > _earliestStartTime, "Invalid startTime"); + if (_restrictionType == RestrictionType.Fixed) { + require(_allowedTokens > 0, "Invalid tokens value"); } else { require( _allowedTokens > 0 && _allowedTokens <= 100 * 10 ** 16, - "Invalid value" + "Invalid tokens value" ); } // Maximum limit for the rollingPeriod is 365 days @@ -1075,6 +1013,10 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ); } + function _isAllowedToModify(uint256 _startTime) internal view { + require(_startTime > now, "Not Allowed to modify after startTime passed"); + } + /** * @notice Use to get the bucket details for a given address * @param _user Address of the token holder for whom the bucket details has queried @@ -1083,7 +1025,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 days covered * @return uint256 24h lastTradedDayTime */ - function getIndividualBucketDetailsToUser(address _user) public view returns(uint256, uint256, uint256, uint256) { + function getIndividualBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { return( userToBucket[_user].lastTradedDayTime, userToBucket[_user].sumOfLastPeriod, @@ -1100,7 +1042,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 days covered * @return uint256 24h lastTradedDayTime */ - function getDefaultBucketDetailsToUser(address _user) public view returns(uint256, uint256, uint256, uint256) { + function getDefaultBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { return( defaultUserToBucket[_user].lastTradedDayTime, defaultUserToBucket[_user].sumOfLastPeriod, @@ -1115,7 +1057,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _at Timestamp */ function getTotalTradedByUser(address _user, uint256 _at) external view returns(uint256) { - return bucket[_user][_at]; + return (bucket[_user][_at].add(defaultBucket[_user][_at])); } /** @@ -1139,7 +1081,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 List of the start time of the restriction corresponds to restricted address * @return uint256 List of the rolling period in days for a restriction corresponds to restricted address. * @return uint256 List of the end time of the restriction corresponds to restricted address. - * @return uint8 List of the type of restriction to validate the value of the `allowedTokens` + * @return RestrictionType List of the type of restriction to validate the value of the `allowedTokens` * of the restriction corresponds to restricted address */ function getRestrictedData() external view returns( @@ -1148,29 +1090,31 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] memory startTime, uint256[] memory rollingPeriodInDays, uint256[] memory endTime, - uint8[] memory typeOfRestriction + RestrictionType[] memory typeOfRestriction ) { uint256 counter = 0; uint256 i = 0; for (i = 0; i < holderData.restrictedAddresses.length; i++) { - counter = counter + (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == uint8(2) ? 2 : 1); + counter = counter + uint256( + holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == TypeOfPeriod.Both ? TypeOfPeriod.Both : TypeOfPeriod.OneDay + ); } allAddresses = new address[](counter); allowedTokens = new uint256[](counter); startTime = new uint256[](counter); rollingPeriodInDays = new uint256[](counter); endTime = new uint256[](counter); - typeOfRestriction = new uint8[](counter); + typeOfRestriction = new RestrictionType[](counter); counter = 0; for (i = 0; i < holderData.restrictedAddresses.length; i++) { allAddresses[counter] = holderData.restrictedAddresses[i]; - if (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.MultipleDays)) { + if (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == TypeOfPeriod.MultipleDays) { _setValues(individualRestriction[holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); } - else if (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.OneDay)) { + else if (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == TypeOfPeriod.OneDay) { _setValues(individualDailyRestriction[holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); } - else if (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == uint8(TypeOfPeriod.Both)) { + else if (holderData.restrictedHolders[holderData.restrictedAddresses[i]].typeOfPeriod == TypeOfPeriod.Both) { _setValues(individualRestriction[holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); counter = counter + 1; allAddresses[counter] = holderData.restrictedAddresses[i]; @@ -1186,7 +1130,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] memory startTime, uint256[] memory rollingPeriodInDays, uint256[] memory endTime, - uint8[] memory typeOfRestriction, + RestrictionType[] memory typeOfRestriction, uint256 index ) internal @@ -1196,7 +1140,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { startTime[index] = restriction.startTime; rollingPeriodInDays[index] = restriction.rollingPeriodInDays; endTime[index] = restriction.endTime; - typeOfRestriction[index] = uint8(restriction.typeOfRestriction); + typeOfRestriction[index] = restriction.typeOfRestriction; } /** diff --git a/contracts/storage/VolumeRestrictionTMStorage.sol b/contracts/storage/VolumeRestrictionTMStorage.sol index 9718c2c09..b8d62c988 100644 --- a/contracts/storage/VolumeRestrictionTMStorage.sol +++ b/contracts/storage/VolumeRestrictionTMStorage.sol @@ -13,7 +13,7 @@ contract VolumeRestrictionTMStorage { // 1 represent true & 0 for false uint8 seen; // Type of period will be enum index of TypeOfPeriod enum - uint8 typeOfPeriod; + TypeOfPeriod typeOfPeriod; // Index of the array where the holder address lives uint128 index; } @@ -51,6 +51,8 @@ contract VolumeRestrictionTMStorage { mapping(address => VolumeRestriction) public individualDailyRestriction; // Storing _from => day's timestamp => total amount transact in a day --individual mapping(address => mapping(uint256 => uint256)) internal bucket; + // Storing _from => day's timestamp => total amount transact in a day --default + mapping(address => mapping(uint256 => uint256)) internal defaultBucket; // Storing the information that used to validate the transaction mapping(address => BucketDetails) internal userToBucket; // Storing the information related to default restriction diff --git a/package.json b/package.json index fbaf43ed0..4d905c166 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "fs": "0.0.2", "openzeppelin-solidity": "1.10.0", "prompt": "^1.0.0", - "truffle-hdwallet-provider-privkey": "0.3.0", + "truffle-hdwallet-provider-privkey": "^0.3.0", "web3": "1.0.0-beta.34" }, "devDependencies": { diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 59b5adaa2..7074d1afa 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -543,7 +543,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [0, 0, 0], + [latestTime() + duration.minutes(1), latestTime() + duration.minutes(1), latestTime() + duration.minutes(1)], [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], [0, 0, 0], @@ -608,7 +608,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ${await I_VolumeRestrictionTM.addIndividualRestriction.estimateGas( account_investor1, web3.utils.toWei("12"), - latestTime() + duration.seconds(2), + latestTime() + duration.seconds(5), 3, latestTime() + duration.days(6), 0, @@ -621,7 +621,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("12"), - latestTime() + duration.seconds(2), + latestTime() + duration.seconds(5), 3, latestTime() + duration.days(6), 0, @@ -739,7 +739,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor3, web3.utils.toWei("6"), - latestTime() + duration.seconds(1), + latestTime() + duration.seconds(10), latestTime() + duration.days(4), 0, { @@ -767,7 +767,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should transfer the tokens within the individual daily restriction limits", async () => { // transfer 2 tokens as per the limit - await increaseTime(5); // increase 5 seconds to layoff the time gap + await increaseTime(15); // increase 5 seconds to layoff the time gap let startTime = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); console.log(` Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, web3.utils.toWei("2"), { from: account_investor3 })} @@ -819,7 +819,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( account_investor1, new BigNumber(5).times(new BigNumber(10).pow(16)), - 0, + latestTime() + duration.seconds(5), latestTime() + duration.days(4), 1, { @@ -847,6 +847,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should transfer tokens on the 2nd day by investor1 (Individual + Individual daily)", async () => { + await increaseTime(6); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor1))[2].toNumber(); @@ -888,7 +889,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor3, new BigNumber(15.36).times(new BigNumber(10).pow(16)), // 15.36 tokens as totalsupply is 1000 - latestTime() + duration.seconds(2), + latestTime() + duration.seconds(10), 6, latestTime() + duration.days(15), 1, @@ -908,7 +909,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should transfer the token by the investor 3 with in the (Individual + Individual daily limit)", async () => { - await increaseTime(4); + await increaseTime(duration.seconds(15)); // Allowed 4 tokens to transfer let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); @@ -1058,7 +1059,7 @@ contract('VolumeRestrictionTransferManager', accounts => { await I_VolumeRestrictionTM.modifyIndividualDailyRestriction( account_investor3, web3.utils.toWei('3'), - 0, + latestTime() + duration.seconds(10), latestTime() + duration.days(5), 0, { @@ -1078,6 +1079,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should allow to sell to transfer more tokens by investor3", async () => { + await increaseTime(duration.seconds(15)); let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); let startTimedaily = (await I_VolumeRestrictionTM.individualDailyRestriction.call(account_investor3))[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[2].toNumber(); @@ -1285,7 +1287,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should add the default daily restriction successfully", async () => { await I_VolumeRestrictionTM.addDefaultDailyRestriction( new BigNumber(2.75).times(new BigNumber(10).pow(16)), - 0, + latestTime() + duration.seconds(10), latestTime() + duration.days(3), 1, { @@ -1305,6 +1307,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should fail to transfer above the daily limit", async () => { + await increaseTime(duration.seconds(15)); await catchRevert( I_SecurityToken.transfer(account_investor3, web3.utils.toWei("5"), { from: account_investor4 }) ) @@ -1342,7 +1345,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should successfully add the default restriction", async () => { await I_VolumeRestrictionTM.addDefaultRestriction( web3.utils.toWei("10"), - 0, + latestTime() + duration.seconds(10), 5, latestTime() + duration.days(10), 0, @@ -1366,7 +1369,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should transfer tokens on by investor 3 (comes under the Default restriction)", async () => { - await increaseTime(10); + await increaseTime(15); tempArray3.length = 0; let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); let startTimedaily = (await I_VolumeRestrictionTM.defaultDailyRestriction.call())[1].toNumber(); @@ -1454,7 +1457,7 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should add the daily default restriction again", async () => { await I_VolumeRestrictionTM.addDefaultDailyRestriction( web3.utils.toWei("2"), - 0, + latestTime() + duration.seconds(10), latestTime() + duration.days(3), 0, { @@ -1474,6 +1477,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should not able to transfer tokens more than the default daily restriction", async () => { + await increaseTime(duration.seconds(15)); await catchRevert( I_SecurityToken.transfer(account_investor2, web3.utils.toWei("3"), { from: account_investor3 }) ); diff --git a/yarn.lock b/yarn.lock index 99f339018..f3d31f1f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,14 +5,12 @@ "@babel/code-frame@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== dependencies: "@babel/highlight" "^7.0.0" "@babel/highlight@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== dependencies: chalk "^2.0.0" esutils "^2.0.2" @@ -21,36 +19,30 @@ "@types/node@^10.3.2": version "10.12.18" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" - integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= abstract-leveldown@~2.6.0: version "2.6.3" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== dependencies: xtend "~4.0.0" abstract-leveldown@~2.7.1: version "2.7.2" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== dependencies: xtend "~4.0.0" accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= dependencies: mime-types "~2.1.18" negotiator "0.6.1" @@ -58,27 +50,22 @@ accepts@~1.3.5: acorn-jsx@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" - integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== acorn@^6.0.2: version "6.0.5" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.5.tgz#81730c0815f3f3b34d8efa95cb7430965f4d887a" - integrity sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg== aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= aes-js@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== ajv@^5.2.2: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" @@ -88,7 +75,6 @@ ajv@^5.2.2: ajv@^6.5.3, ajv@^6.5.5, ajv@^6.6.1: version "6.6.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" - integrity sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -98,7 +84,6 @@ ajv@^6.5.3, ajv@^6.5.5, ajv@^6.6.1: ambi@^2.2.0: version "2.5.0" resolved "https://registry.yarnpkg.com/ambi/-/ambi-2.5.0.tgz#7c8e372be48891157e7cea01cb6f9143d1f74220" - integrity sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA= dependencies: editions "^1.1.1" typechecker "^4.3.0" @@ -106,49 +91,40 @@ ambi@^2.2.0: amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= ansi-escapes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" - integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-regex@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" - integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== dependencies: micromatch "^2.1.5" normalize-path "^2.0.0" @@ -156,12 +132,10 @@ anymatch@^1.3.0: aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -169,51 +143,42 @@ are-we-there-yet@~1.1.2: argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= dependencies: arr-flatten "^1.0.1" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -222,34 +187,28 @@ asn1.js@^4.0.0: asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-eventemitter@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== dependencies: async "^2.4.0" @@ -262,54 +221,44 @@ async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== async@1.x, async@^1.4.2, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.4.1, async@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== dependencies: lodash "^4.17.10" async@~0.9.0: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= async@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" - integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -318,7 +267,6 @@ babel-code-frame@^6.26.0: babel-core@^6.0.14, babel-core@^6.26.0: version "6.26.3" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== dependencies: babel-code-frame "^6.26.0" babel-generator "^6.26.0" @@ -343,7 +291,6 @@ babel-core@^6.0.14, babel-core@^6.26.0: babel-generator@^6.26.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" @@ -357,7 +304,6 @@ babel-generator@^6.26.0: babel-helper-bindify-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" - integrity sha1-FMGeXxQte0fxmlJDHlKxzLxAozA= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -366,7 +312,6 @@ babel-helper-bindify-decorators@^6.24.1: babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= dependencies: babel-helper-explode-assignable-expression "^6.24.1" babel-runtime "^6.22.0" @@ -375,7 +320,6 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -385,7 +329,6 @@ babel-helper-call-delegate@^6.24.1: babel-helper-define-map@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.26.0" @@ -395,7 +338,6 @@ babel-helper-define-map@^6.24.1: babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -404,7 +346,6 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-helper-explode-class@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" - integrity sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes= dependencies: babel-helper-bindify-decorators "^6.24.1" babel-runtime "^6.22.0" @@ -414,7 +355,6 @@ babel-helper-explode-class@^6.24.1: babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= dependencies: babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" @@ -425,7 +365,6 @@ babel-helper-function-name@^6.24.1: babel-helper-get-function-arity@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -433,7 +372,6 @@ babel-helper-get-function-arity@^6.24.1: babel-helper-hoist-variables@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -441,7 +379,6 @@ babel-helper-hoist-variables@^6.24.1: babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -449,7 +386,6 @@ babel-helper-optimise-call-expression@^6.24.1: babel-helper-regex@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= dependencies: babel-runtime "^6.26.0" babel-types "^6.26.0" @@ -458,7 +394,6 @@ babel-helper-regex@^6.24.1: babel-helper-remap-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -469,7 +404,6 @@ babel-helper-remap-async-to-generator@^6.24.1: babel-helper-replace-supers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= dependencies: babel-helper-optimise-call-expression "^6.24.1" babel-messages "^6.23.0" @@ -481,7 +415,6 @@ babel-helper-replace-supers@^6.24.1: babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -489,61 +422,50 @@ babel-helpers@^6.24.1: babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= dependencies: babel-runtime "^6.22.0" babel-plugin-check-es2015-constants@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= dependencies: babel-runtime "^6.22.0" babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= babel-plugin-syntax-async-generators@^6.5.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - integrity sha1-a8lj67FuzLrmuStZbrfzXDQqi5o= babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= babel-plugin-syntax-decorators@^6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" - integrity sha1-MSVjtNvePMgGzuPkFszurd0RrAs= babel-plugin-syntax-dynamic-import@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" - integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= babel-plugin-transform-async-generator-functions@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" - integrity sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-generators "^6.5.0" @@ -552,7 +474,6 @@ babel-plugin-transform-async-generator-functions@^6.24.1: babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-functions "^6.8.0" @@ -561,7 +482,6 @@ babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async- babel-plugin-transform-class-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= dependencies: babel-helper-function-name "^6.24.1" babel-plugin-syntax-class-properties "^6.8.0" @@ -571,7 +491,6 @@ babel-plugin-transform-class-properties@^6.24.1: babel-plugin-transform-decorators@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" - integrity sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0= dependencies: babel-helper-explode-class "^6.24.1" babel-plugin-syntax-decorators "^6.13.0" @@ -582,21 +501,18 @@ babel-plugin-transform-decorators@^6.24.1: babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= dependencies: babel-runtime "^6.26.0" babel-template "^6.26.0" @@ -607,7 +523,6 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= dependencies: babel-helper-define-map "^6.24.1" babel-helper-function-name "^6.24.1" @@ -622,7 +537,6 @@ babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-cla babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -630,14 +544,12 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transfor babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -645,14 +557,12 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2 babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -661,14 +571,12 @@ babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= dependencies: babel-plugin-transform-es2015-modules-commonjs "^6.24.1" babel-runtime "^6.22.0" @@ -677,7 +585,6 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.26.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== dependencies: babel-plugin-transform-strict-mode "^6.24.1" babel-runtime "^6.26.0" @@ -687,7 +594,6 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -696,7 +602,6 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= dependencies: babel-plugin-transform-es2015-modules-amd "^6.24.1" babel-runtime "^6.22.0" @@ -705,7 +610,6 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= dependencies: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" @@ -713,7 +617,6 @@ babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= dependencies: babel-helper-call-delegate "^6.24.1" babel-helper-get-function-arity "^6.24.1" @@ -725,7 +628,6 @@ babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015- babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -733,14 +635,12 @@ babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transfo babel-plugin-transform-es2015-spread@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -749,21 +649,18 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es201 babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -772,7 +669,6 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es20 babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= dependencies: babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" babel-plugin-syntax-exponentiation-operator "^6.8.0" @@ -781,7 +677,6 @@ babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-e babel-plugin-transform-object-rest-spread@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" @@ -789,14 +684,12 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= dependencies: regenerator-transform "^0.10.0" babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -804,7 +697,6 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-polyfill@6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= dependencies: babel-runtime "^6.26.0" core-js "^2.5.0" @@ -813,7 +705,6 @@ babel-polyfill@6.26.0: babel-preset-env@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -849,7 +740,6 @@ babel-preset-env@^1.7.0: babel-preset-es2015@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - integrity sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk= dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-transform-es2015-arrow-functions "^6.22.0" @@ -879,7 +769,6 @@ babel-preset-es2015@6.24.1: babel-preset-stage-2@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" - integrity sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE= dependencies: babel-plugin-syntax-dynamic-import "^6.18.0" babel-plugin-transform-class-properties "^6.24.1" @@ -889,7 +778,6 @@ babel-preset-stage-2@6.24.1: babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" - integrity sha1-g2raCp56f6N8sTj7kyb4eTSkg5U= dependencies: babel-plugin-syntax-trailing-function-commas "^6.22.0" babel-plugin-transform-async-generator-functions "^6.24.1" @@ -900,7 +788,6 @@ babel-preset-stage-3@6.24.1, babel-preset-stage-3@^6.24.1: babel-register@6.26.0, babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= dependencies: babel-core "^6.26.0" babel-runtime "^6.26.0" @@ -913,7 +800,6 @@ babel-register@6.26.0, babel-register@^6.26.0: babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" @@ -921,7 +807,6 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= dependencies: babel-runtime "^6.26.0" babel-traverse "^6.26.0" @@ -932,7 +817,6 @@ babel-template@^6.24.1, babel-template@^6.26.0: babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= dependencies: babel-code-frame "^6.26.0" babel-messages "^6.23.0" @@ -947,7 +831,6 @@ babel-traverse@^6.24.1, babel-traverse@^6.26.0: babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= dependencies: babel-runtime "^6.26.0" esutils "^2.0.2" @@ -957,7 +840,6 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: babelify@^7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= dependencies: babel-core "^6.0.14" object-assign "^4.0.0" @@ -965,34 +847,28 @@ babelify@^7.3.0: babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base-x@^3.0.2: version "3.0.5" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.5.tgz#d3ada59afed05b921ab581ec3112e6444ba0795a" - integrity sha512-C3picSgzPSLE+jW3tcBzJoGwitOtazb5B+5YmAxZm2ybmTi9LNgAtDO/jjVEBZwHoXmDBZ9m/IELj3elJVRBcA== dependencies: safe-buffer "^5.0.1" base64-js@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" - integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg= base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -1005,24 +881,20 @@ base@^0.11.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" bignumber.js@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" - integrity sha512-KWTu6ZMVk9sxlDJQh2YH1UOnfDP8O8TpxUxgQG/vKASoSnEjK9aVuOueFaPcQEYQ5fyNXNTOYwYw3099RYebWg== bignumber.js@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" - integrity sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA== bignumber.js@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.0.1.tgz#5d419191370fb558c64e3e5f70d68e5947138832" - integrity sha512-zAySveTJXkgLYCBi0b14xzfnOs+f3G6x36I8w2a1+PFQpWk/dp0mI0F+ZZK2bu+3ELewDcSyP+Cfq++NcHX7sg== "bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" @@ -1039,31 +911,26 @@ bignumber.js@^8.0.1: binary-extensions@^1.0.0: version "1.12.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" - integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== bindings@^1.2.1: version "1.3.1" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.1.tgz#21fc7c6d67c18516ec5aaa2815b145ff77b26ea5" - integrity sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew== bindings@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.4.0.tgz#909efa49f2ebe07ecd3cb136778f665052040127" - integrity sha512-7znEVX22Djn+nYjxCWKDne0RRloa9XfYa84yk3s+HkE3LpDYZmhArYr9O9huBoHY3/oXispx5LorIX7Sl2CgSQ== dependencies: file-uri-to-path "1.0.0" bip66@^1.1.3: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" - integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= dependencies: safe-buffer "^5.0.1" bitcore-lib@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.15.0.tgz#f924be13869f2aab7e04aeec5642ad3359b6cec2" - integrity sha512-AeXLWhiivF6CDFzrABZHT4jJrflyylDWTi32o30rF92HW9msfuKpjzrHtFKYGa9w0kNVv5HABQjCB3OEav4PhQ== dependencies: bn.js "=4.11.8" bs58 "=4.0.1" @@ -1075,7 +942,6 @@ bitcore-lib@^0.15.0: bitcore-lib@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.16.0.tgz#a2c3ec1108cdb90386f728282ab833e0c77c9533" - integrity sha512-CEtcrPAH2gwgaMN+OPMJc18TBEak1+TtzMyafrqrIbK9PIa3kat195qBJhC0liJSHRiRr6IE2eLcXeIFFs+U8w== dependencies: bn.js "=4.11.8" bs58 "=4.0.1" @@ -1087,7 +953,6 @@ bitcore-lib@^0.16.0: bitcore-mnemonic@^1.5.0: version "1.7.0" resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-1.7.0.tgz#253295a773135e1a0b455871de614996afc8f5e1" - integrity sha512-1JV1okgz9Vv+Y4fG2m3ToR+BGdKA6tSoqjepIxA95BZjW6YaeopVW4iOe/dY9dnkZH4+LA2AJ4YbDE6H3ih3Yw== dependencies: bitcore-lib "^0.16.0" unorm "^1.4.1" @@ -1095,7 +960,6 @@ bitcore-mnemonic@^1.5.0: bl@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== dependencies: readable-stream "^2.3.5" safe-buffer "^5.1.1" @@ -1103,39 +967,32 @@ bl@^1.0.0: block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= dependencies: inherits "~2.0.0" bluebird@^2.9.34: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= bluebird@^3.4.6, bluebird@^3.5.0, bluebird@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" - integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= bn.js@4.11.8, bn.js@=4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== bn.js@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625" - integrity sha1-EhYrwq5x/EClYmwzQ486h1zTdiU= body-parser@1.18.3, body-parser@^1.16.0: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" - integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= dependencies: bytes "3.0.0" content-type "~1.0.4" @@ -1151,7 +1008,6 @@ body-parser@1.18.3, body-parser@^1.16.0: borc@^2.0.2: version "2.1.0" resolved "https://registry.yarnpkg.com/borc/-/borc-2.1.0.tgz#2def2fc69868633b965a9750e7f210d778190303" - integrity sha512-hKTxeYt3AIzIG45epJHv8xJYSF0ktp7nZgFsqi5cPzoL3T8qKMPeUlqydORy6j3NWZvRDANx30PjpTmGho69Gw== dependencies: bignumber.js "^8.0.1" commander "^2.15.0" @@ -1162,7 +1018,6 @@ borc@^2.0.2: brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1170,7 +1025,6 @@ brace-expansion@^1.1.7: braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= dependencies: expand-range "^1.8.1" preserve "^0.2.0" @@ -1179,7 +1033,6 @@ braces@^1.8.2: braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -1195,22 +1048,18 @@ braces@^2.3.1: brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1222,7 +1071,6 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: browserify-cipher@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -1231,7 +1079,6 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -1241,7 +1088,6 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= dependencies: bn.js "^4.1.0" randombytes "^2.0.1" @@ -1249,7 +1095,6 @@ browserify-rsa@^4.0.0: browserify-sha3@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.4.tgz#086c47b8c82316c9d47022c26185954576dd8e26" - integrity sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY= dependencies: js-sha3 "^0.6.1" safe-buffer "^5.1.1" @@ -1257,7 +1102,6 @@ browserify-sha3@^0.0.4: browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= dependencies: bn.js "^4.1.1" browserify-rsa "^4.0.0" @@ -1270,7 +1114,6 @@ browserify-sign@^4.0.0: browserslist@^3.2.6: version "3.2.8" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== dependencies: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" @@ -1278,19 +1121,16 @@ browserslist@^3.2.6: bs58@=4.0.1, bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= dependencies: base-x "^3.0.2" bs58@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" - integrity sha1-VZCNWPGYKrogCPob7Y+RmYopv40= bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== dependencies: bs58 "^4.0.0" create-hash "^1.1.0" @@ -1299,17 +1139,14 @@ bs58check@^2.1.2: bson@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.0.tgz#bee57d1fb6a87713471af4e32bcae36de814b5b0" - integrity sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA== buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== buffer-alloc@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== dependencies: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" @@ -1317,37 +1154,30 @@ buffer-alloc@^1.2.0: buffer-compare@=1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.1.1.tgz#5be7be853af89198d1f4ddc090d1d66a48aef596" - integrity sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY= buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-to-arraybuffer@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^3.0.1: version "3.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" - integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs= dependencies: base64-js "0.0.8" ieee754 "^1.1.4" @@ -1356,7 +1186,6 @@ buffer@^3.0.1: buffer@^4.9.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1365,7 +1194,6 @@ buffer@^4.9.0: buffer@^5.0.5: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" - integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1373,17 +1201,14 @@ buffer@^5.0.5: builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -1398,29 +1223,24 @@ cache-base@^1.0.1: caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= dependencies: callsites "^0.2.0" callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= caminte@0.3.7: version "0.3.7" resolved "https://registry.yarnpkg.com/caminte/-/caminte-0.3.7.tgz#ec1ec0457664a0f092643b7c646c457d5cd6f693" - integrity sha1-7B7ARXZkoPCSZDt8ZGxFfVzW9pM= dependencies: bluebird "^3.4.6" uuid "^3.0.1" @@ -1428,17 +1248,14 @@ caminte@0.3.7: caniuse-lite@^1.0.30000844: version "1.0.30000926" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000926.tgz#4361a99d818ca6e521dbe89a732de62a194a789c" - integrity sha512-diMkEvxfFw09SkbErCLmw/1Fx1ZZe9xfWm4aeA2PUffB48x1tfZeMsK5j4BW7zN7Y4PdqmPVVdG2eYjE5IRTag== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -1449,7 +1266,6 @@ chalk@^1.1.3: chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1458,24 +1274,20 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1: chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= checkpoint-store@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= dependencies: functional-red-black-tree "^1.0.1" chokidar@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= dependencies: anymatch "^1.3.0" async-each "^1.0.0" @@ -1491,12 +1303,10 @@ chokidar@^1.6.0: chownr@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -1504,12 +1314,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" @@ -1519,7 +1327,6 @@ class-utils@^0.3.5: cli-color@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.4.0.tgz#7d10738f48526824f8fe7da51857cb0f572fe01f" - integrity sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w== dependencies: ansi-regex "^2.1.1" d "1" @@ -1531,19 +1338,16 @@ cli-color@^1.4.0: cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -1552,7 +1356,6 @@ cliui@^3.2.0: cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" @@ -1561,22 +1364,18 @@ cliui@^4.0.0: clone@2.x, clone@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= coinstring@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - integrity sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q= dependencies: bs58 "^2.0.1" create-hash "^1.1.1" @@ -1584,7 +1383,6 @@ coinstring@^2.0.0: collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -1592,135 +1390,110 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= colors@^1.1.2: version "1.3.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" - integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" - integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== dependencies: delayed-stream "~1.0.0" commander@2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== commander@2.15.1: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== commander@^2.14.1, commander@^2.15.0, commander@^2.19.0, commander@^2.8.1, commander@^2.9.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== commander@~2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= dependencies: graceful-readlink ">= 1.0.0" compare-versions@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" - integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg== component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== dependencies: safe-buffer "~5.1.1" cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= cookiejar@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0, core-js@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.1.tgz#87416ae817de957a3f249b3b5ca475d4aaed6042" - integrity sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cors@^2.8.1: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== dependencies: object-assign "^4" vary "^1" @@ -1728,7 +1501,6 @@ cors@^2.8.1: coveralls@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" - integrity sha512-Tv0LKe/MkBOilH2v7WBiTBdudg2ChfGbdXafc/s330djpF3zKOmuehTeRwjXWc7pzfj9FrDUTA7tEx6Div8NFw== dependencies: growl "~> 1.10.0" js-yaml "^3.11.0" @@ -1740,7 +1512,6 @@ coveralls@^3.0.2: create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== dependencies: bn.js "^4.1.0" elliptic "^6.0.0" @@ -1748,7 +1519,6 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -1759,7 +1529,6 @@ create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -1771,7 +1540,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: cron-parser@^2.7.3: version "2.7.3" resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.7.3.tgz#12603f89f5375af353a9357be2543d3172eac651" - integrity sha512-t9Kc7HWBWPndBzvbdQ1YG9rpPRB37Tb/tTviziUOh1qs3TARGh3b1p+tnkOHNe1K5iI3oheBPgLqwotMM7+lpg== dependencies: is-nan "^1.2.1" moment-timezone "^0.5.23" @@ -1779,7 +1547,6 @@ cron-parser@^2.7.3: cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" @@ -1788,7 +1555,6 @@ cross-spawn@^5.0.1: cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: nice-try "^1.0.4" path-key "^2.0.1" @@ -1799,12 +1565,10 @@ cross-spawn@^6.0.5: crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= crypto-browserify@3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -1821,96 +1585,80 @@ crypto-browserify@3.12.0: crypto-js@^3.1.4, crypto-js@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" - integrity sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU= crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= csextends@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/csextends/-/csextends-1.2.0.tgz#6374b210984b54d4495f29c99d3dd069b80543e5" - integrity sha512-S/8k1bDTJIwuGgQYmsRoE+8P+ohV32WhQ0l4zqrc0XDdxOhjQQD7/wTZwCzoZX53jSX3V/qwjT+OkPTxWQcmjg== csv-parse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-4.3.0.tgz#e27cc1c4c5426201a896389c9f97273a0d47dad4" - integrity sha512-vrZTSMG/6a5EI30ICFU8IQ1kR3xXXoC3Z7jaUv76E5uCgFahr2sffRoTAffvEd1JZNssAgalI4DaEFUnXqQCGw== cycle@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= dependencies: es5-ext "^0.10.9" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" death@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" - integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= debug@*, debug@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: ms "^2.1.1" debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: mimic-response "^1.0.0" decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== dependencies: file-type "^5.2.0" is-stream "^1.1.0" @@ -1919,7 +1667,6 @@ decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: decompress-tarbz2@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== dependencies: decompress-tar "^4.1.0" file-type "^6.1.0" @@ -1930,7 +1677,6 @@ decompress-tarbz2@^4.0.0: decompress-targz@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== dependencies: decompress-tar "^4.1.1" file-type "^5.2.0" @@ -1939,7 +1685,6 @@ decompress-targz@^4.0.0: decompress-unzip@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= dependencies: file-type "^3.8.0" get-stream "^2.2.0" @@ -1949,7 +1694,6 @@ decompress-unzip@^4.0.1: decompress@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= dependencies: decompress-tar "^4.0.0" decompress-tarbz2 "^4.0.0" @@ -1963,55 +1707,46 @@ decompress@^4.0.0: deep-equal@~0.2.1: version "0.2.2" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" - integrity sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0= deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= deferred-leveldown@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== dependencies: abstract-leveldown "~2.6.0" define-properties@^1.1.1, define-properties@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" @@ -2019,32 +1754,26 @@ define-property@^2.0.2: defined@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= delimit-stream@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" - integrity sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs= depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -2052,34 +1781,28 @@ des.js@^1.0.0: destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= dependencies: repeating "^2.0.0" detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= diff@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== diff@3.5.0, diff@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" @@ -2088,7 +1811,6 @@ diffie-hellman@^5.0.0: doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= dependencies: esutils "^2.0.2" isarray "^1.0.0" @@ -2096,19 +1818,16 @@ doctrine@1.5.0: doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= drbg.js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= dependencies: browserify-aes "^1.0.6" create-hash "^1.1.2" @@ -2117,19 +1836,16 @@ drbg.js@^1.0.1: duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= eachr@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/eachr/-/eachr-2.0.4.tgz#466f7caa10708f610509e32c807aafe57fc122bf" - integrity sha1-Rm98qhBwj2EFCeMsgHqv5X/BIr8= dependencies: typechecker "^2.0.8" ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" @@ -2137,12 +1853,10 @@ ecc-jsbn@~0.1.1: editions@^1.1.1, editions@^1.3.3: version "1.3.4" resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" - integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== editions@^2.1.0, editions@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/editions/-/editions-2.1.3.tgz#727ccf3ec2c7b12dcc652c71000f16c4824d6f7d" - integrity sha512-xDZyVm0A4nLgMNWVVLJvcwMjI80ShiH/27RyLiCnW1L273TcJIA25C4pwJ33AWV01OX6UriP35Xu+lH4S7HWQw== dependencies: errlop "^1.1.1" semver "^5.6.0" @@ -2150,17 +1864,14 @@ editions@^2.1.0, editions@^2.1.2: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.47: version "1.3.96" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.96.tgz#25770ec99b8b07706dedf3a5f43fa50cb54c4f9a" - integrity sha512-ZUXBUyGLeoJxp4Nt6G/GjBRLnyz8IKQGexZ2ndWaoegThgMGFO1tdDYID5gBV32/1S83osjJHyfzvanE/8HY4Q== elliptic@6.3.3: version "6.3.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2170,7 +1881,6 @@ elliptic@6.3.3: elliptic@=6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" - integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2183,7 +1893,6 @@ elliptic@=6.4.0: elliptic@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-3.1.0.tgz#c21682ef762769b56a74201609105da11d5f60cc" - integrity sha1-whaC73YnabVqdCAWCRBdoR1fYMw= dependencies: bn.js "^2.0.3" brorand "^1.0.1" @@ -2193,7 +1902,6 @@ elliptic@^3.1.0: elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: version "6.4.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2206,52 +1914,44 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= dependencies: iconv-lite "~0.4.13" end-of-stream@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: once "^1.4.0" eol@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" - integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== errlop@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/errlop/-/errlop-1.1.1.tgz#d9ae4c76c3e64956c5d79e6e035d6343bfd62250" - integrity sha512-WX7QjiPHhsny7/PQvrhS5VMizXXKoKCS3udaBp8gjlARdbn+XmK300eKBAAN0hGyRaTCtRpOaxK+xFVPUJ3zkw== dependencies: editions "^2.1.2" errno@~0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== dependencies: prr "~1.0.1" error-ex@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" es-abstract@^1.5.0: version "1.13.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== dependencies: es-to-primitive "^1.2.0" function-bind "^1.1.1" @@ -2263,7 +1963,6 @@ es-abstract@^1.5.0: es-to-primitive@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -2272,7 +1971,6 @@ es-to-primitive@^1.2.0: es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: version "0.10.46" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572" - integrity sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw== dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" @@ -2281,7 +1979,6 @@ es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= dependencies: d "1" es5-ext "^0.10.35" @@ -2290,7 +1987,6 @@ es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= dependencies: d "1" es5-ext "~0.10.14" @@ -2298,7 +1994,6 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.1: es6-weak-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8= dependencies: d "1" es5-ext "^0.10.14" @@ -2308,17 +2003,14 @@ es6-weak-map@^2.0.2: escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= dependencies: esprima "^2.7.1" estraverse "^1.9.1" @@ -2330,12 +2022,10 @@ escodegen@1.8.x: eslint-config-standard@^12.0.0: version "12.0.0" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz#638b4c65db0bd5a41319f96bba1f15ddad2107d9" - integrity sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ== eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" - integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== dependencies: debug "^2.6.9" resolve "^1.5.0" @@ -2343,7 +2033,6 @@ eslint-import-resolver-node@^0.3.1: eslint-module-utils@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" - integrity sha1-snA2LNiLGkitMIl2zn+lTphBF0Y= dependencies: debug "^2.6.8" pkg-dir "^1.0.0" @@ -2351,7 +2040,6 @@ eslint-module-utils@^2.2.0: eslint-plugin-es@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz#475f65bb20c993fc10e8c8fe77d1d60068072da6" - integrity sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw== dependencies: eslint-utils "^1.3.0" regexpp "^2.0.1" @@ -2359,7 +2047,6 @@ eslint-plugin-es@^1.3.1: eslint-plugin-import@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" - integrity sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g== dependencies: contains-path "^0.1.0" debug "^2.6.8" @@ -2375,7 +2062,6 @@ eslint-plugin-import@^2.14.0: eslint-plugin-node@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-8.0.0.tgz#fb9e8911f4543514f154bb6a5924b599aa645568" - integrity sha512-Y+ln8iQ52scz9+rSPnSWRaAxeWaoJZ4wIveDR0vLHkuSZGe44Vk1J4HX7WvEP5Cm+iXPE8ixo7OM7gAO3/OKpQ== dependencies: eslint-plugin-es "^1.3.1" eslint-utils "^1.3.1" @@ -2387,17 +2073,14 @@ eslint-plugin-node@^8.0.0: eslint-plugin-promise@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz#2d074b653f35a23d1ba89d8e976a985117d1c6a2" - integrity sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg== eslint-plugin-standard@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c" - integrity sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA== eslint-scope@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" - integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2405,17 +2088,14 @@ eslint-scope@^4.0.0: eslint-utils@^1.3.0, eslint-utils@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" - integrity sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q== eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== eslint@^5.10.0: version "5.11.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.11.1.tgz#8deda83db9f354bf9d3f53f9677af7e0e13eadda" - integrity sha512-gOKhM8JwlFOc2acbOrkYR05NW8M6DCMSvfcJiBB5NDxRE1gv8kbvxKaC9u69e6ZGEMWXcswA/7eKR229cEIpvg== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.5.3" @@ -2458,7 +2138,6 @@ eslint@^5.10.0: espree@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.0.tgz#fc7f984b62b36a0f543b13fb9cd7b9f4a7f5b65c" - integrity sha512-1MpUfwsdS9MMoN7ZXqAr9e9UKdVHDcvrJpyx7mm1WuQlx/ygErEQBzgi5Nh5qBHIoYweprhtMkTCb9GhcAIcsA== dependencies: acorn "^6.0.2" acorn-jsx "^5.0.0" @@ -2467,51 +2146,42 @@ espree@^5.0.0: esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== dependencies: estraverse "^4.1.0" estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eth-block-tracker@^2.2.2: version "2.3.1" resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz#ab6d177e5b50128fa06d7ae9e0489c7484bac95e" - integrity sha512-NamWuMBIl8kmkJFVj8WzGatySTzQPQag4Xr677yFxdVtIxACFbL/dQowk0MzEqIKk93U1TwY3MjVU6mOcwZnKA== dependencies: async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c eth-query "^2.1.0" @@ -2525,7 +2195,6 @@ eth-block-tracker@^2.2.2: eth-lib@0.1.27, eth-lib@^0.1.26: version "0.1.27" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" - integrity sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA== dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2538,7 +2207,6 @@ eth-lib@0.1.27, eth-lib@^0.1.26: eth-lib@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" - integrity sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco= dependencies: bn.js "^4.11.6" elliptic "^6.4.0" @@ -2547,7 +2215,6 @@ eth-lib@0.2.7: eth-lightwallet@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eth-lightwallet/-/eth-lightwallet-3.0.1.tgz#297022932aa568f4e4eb0873bff257f5e5b78709" - integrity sha512-79vVCETy+4l1b6wuOWwjqPW3Bom5ZK46BgkUNwaXhiMG1rrMRHjpjYEWMqH0JHeCzOzB4HBIFz7eK1/4s6w5nA== dependencies: bitcore-lib "^0.15.0" bitcore-mnemonic "^1.5.0" @@ -2564,7 +2231,6 @@ eth-lightwallet@^3.0.1: eth-query@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= dependencies: json-rpc-random-id "^1.0.0" xtend "^4.0.1" @@ -2572,7 +2238,6 @@ eth-query@^2.1.0: eth-sig-util@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= dependencies: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" @@ -2580,7 +2245,6 @@ eth-sig-util@^1.4.2: ethereum-bridge@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/ethereum-bridge/-/ethereum-bridge-0.6.1.tgz#53c93ed7c0e21752a91e5f089a5997e1d6fea228" - integrity sha512-yDTivI85618BoLI71yNRzW6iVcVN2rjnviCIzs0QOCOENj4XpYQhMDGhdqDi8XWDdzTd0Ja/Canuuh3vfE2IcA== dependencies: async "^2.4.1" borc "^2.0.2" @@ -2611,17 +2275,14 @@ ethereum-bridge@^0.6.1: ethereum-common@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= ethereumjs-abi@0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.4.tgz#9ba1bb056492d00c27279f6eccd4d58275912c1a" - integrity sha1-m6G7BWSS0AwnJ59uzNTVgnWRLBo= dependencies: bn.js "^4.10.0" ethereumjs-util "^4.3.0" @@ -2636,7 +2297,6 @@ ethereumjs-abi@^0.6.5, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereu ethereumjs-account@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== dependencies: ethereumjs-util "^5.0.0" rlp "^2.0.0" @@ -2645,7 +2305,6 @@ ethereumjs-account@^2.0.3: ethereumjs-block@^1.2.2: version "1.7.1" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== dependencies: async "^2.0.1" ethereum-common "0.2.0" @@ -2656,7 +2315,6 @@ ethereumjs-block@^1.2.2: ethereumjs-block@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.1.0.tgz#71d1b19e18061f14cf6371bf34ba31a359931360" - integrity sha512-ip+x4/7hUInX+TQfhEKsQh9MJK1Dbjp4AuPjf1UdX3udAV4beYD4EMCNIPzBLCsGS8WQZYXLpo83tVTISYNpow== dependencies: async "^2.0.1" ethereumjs-common "^0.6.0" @@ -2667,19 +2325,16 @@ ethereumjs-block@~2.1.0: ethereumjs-common@^0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-0.6.1.tgz#ec98edf315a7f107afb6acc48e937a8266979fae" - integrity sha512-4jOrfDu9qOBTTGGb3zrfT1tE1Hyc6a8LJpEk0Vk9AYlLkBY7crjVICyJpRvjNI+KLDMpMITMw3eWVZOLMtZdhw== ethereumjs-testrpc-sc@6.1.6: version "6.1.6" resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.6.tgz#290595380b5182814564d4aa38f35b7788aab070" - integrity sha512-iv2qiGBFgk9mn5Nq2enX8dG5WQ7Lk+FCqpnxfPfH4Ns8KLPwttmNOy264nh3SXDJJvcQwz/XnlLteDQVILotbg== dependencies: source-map-support "^0.5.3" ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@^1.3.3, ethereumjs-tx@^1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== dependencies: ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" @@ -2687,7 +2342,6 @@ ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.1, ethereumjs-tx@ ethereumjs-util@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" - integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= dependencies: bn.js "^4.8.0" create-hash "^1.1.2" @@ -2698,7 +2352,6 @@ ethereumjs-util@^4.3.0: ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.3, ethereumjs-util@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" - integrity sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA== dependencies: bn.js "^4.11.0" create-hash "^1.1.2" @@ -2711,7 +2364,6 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum ethereumjs-util@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.0.0.tgz#f14841c182b918615afefd744207c7932c8536c0" - integrity sha512-E3yKUyl0Fs95nvTFQZe/ZSNcofhDzUsDlA5y2uoRmf1+Ec7gpGhNCsgKkZBRh7Br5op8mJcYF/jFbmjj909+nQ== dependencies: bn.js "^4.11.0" create-hash "^1.1.2" @@ -2724,7 +2376,6 @@ ethereumjs-util@^6.0.0: ethereumjs-vm@^2.0.2: version "2.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.5.0.tgz#71dde54a093bd813c9defdc6d45ceb8fcca2f603" - integrity sha512-Cp1do4J2FIJFnbofqLsKb/aoZKG+Q8NBIbTa1qwZPQkQxzeR3DZVpFk/VbE1EUO6Ha0kSClJ1jzfj07z3cScSQ== dependencies: async "^2.1.2" async-eventemitter "^0.2.2" @@ -2741,7 +2392,6 @@ ethereumjs-vm@^2.0.2: ethereumjs-wallet@^0.6.0: version "0.6.3" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz#b0eae6f327637c2aeb9ccb9047b982ac542e6ab1" - integrity sha512-qiXPiZOsStem+Dj/CQHbn5qex+FVkuPmGH7SvSnA9F3tdRDt8dLMyvIj3+U05QzVZNPYh4HXEdnzoYI4dZkr9w== dependencies: aes-js "^3.1.1" bs58check "^2.1.2" @@ -2756,7 +2406,6 @@ ethereumjs-wallet@^0.6.0: ethers@^4.0.20: version "4.0.20" resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.20.tgz#2b072b283bb19f4870daf42cf5593e5375697504" - integrity sha512-1XEejqGYWlcXoVCPFPRfJmf1QQGHW7TNfprtdT1Up66nSuqWE/lYSLgvTNvH/nbSTMRFZqM6ANAbv/1+eUDb7g== dependencies: "@types/node" "^10.3.2" aes-js "3.0.0" @@ -2772,7 +2421,6 @@ ethers@^4.0.20: ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= dependencies: bn.js "4.11.6" number-to-bn "1.7.0" @@ -2780,7 +2428,6 @@ ethjs-unit@0.1.6: ethjs-util@^0.1.3, ethjs-util@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== dependencies: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" @@ -2788,7 +2435,6 @@ ethjs-util@^0.1.3, ethjs-util@^0.1.6: event-emitter@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= dependencies: d "1" es5-ext "~0.10.14" @@ -2796,17 +2442,14 @@ event-emitter@^0.3.5: eventemitter3@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" - integrity sha1-R3hr2qCHyvext15zq8XH1UAVjNA= events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" @@ -2814,7 +2457,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -2827,14 +2469,12 @@ execa@^0.7.0: expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= dependencies: is-posix-bracket "^0.1.0" expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -2847,14 +2487,12 @@ expand-brackets@^2.1.4: expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= dependencies: fill-range "^2.1.0" express@^4.14.0: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" - integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== dependencies: accepts "~1.3.5" array-flatten "1.1.1" @@ -2890,14 +2528,12 @@ express@^4.14.0: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -2905,19 +2541,16 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== extendr@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/extendr/-/extendr-2.1.0.tgz#301aa0bbea565f4d2dc8f570f2a22611a8527b56" - integrity sha1-MBqgu+pWX00tyPVw8qImEahSe1Y= dependencies: typechecker "~2.0.1" external-editor@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" - integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -2926,14 +2559,12 @@ external-editor@^3.0.0: extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= dependencies: is-extglob "^1.0.0" extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -2947,77 +2578,64 @@ extglob@^2.0.4: extract-opts@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d" - integrity sha1-H6KOunNSxttID4hc63GkaBC+bX0= dependencies: typechecker "~2.0.1" extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= eyes@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= fake-merkle-patricia-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= dependencies: checkpoint-store "^1.1.0" fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= dependencies: pend "~1.2.0" fetch-ponyfill@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" - integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= dependencies: node-fetch "~1.7.1" figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" @@ -3025,32 +2643,26 @@ file-entry-cache@^2.0.0: file-type@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= file-type@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha1-LdvqfHP/42No365J3DOMBYwritY= file-type@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= fill-range@^2.1.0: version "2.2.4" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== dependencies: is-number "^2.1.0" isobject "^2.0.0" @@ -3061,7 +2673,6 @@ fill-range@^2.1.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -3071,7 +2682,6 @@ fill-range@^4.0.0: finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" - integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== dependencies: debug "2.6.9" encodeurl "~1.0.2" @@ -3084,7 +2694,6 @@ finalhandler@1.1.1: find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" @@ -3092,14 +2701,12 @@ find-up@^1.0.0: find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" flat-cache@^1.2.1: version "1.3.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" - integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== dependencies: circular-json "^0.3.1" graceful-fs "^4.1.2" @@ -3109,31 +2716,26 @@ flat-cache@^1.2.1: for-each@^0.3.2, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= dependencies: for-in "^1.0.1" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.6" @@ -3142,29 +2744,24 @@ form-data@~2.3.2: forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3175,7 +2772,6 @@ fs-extra@^0.30.0: fs-extra@^2.0.0, fs-extra@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" - integrity sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU= dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3183,7 +2779,6 @@ fs-extra@^2.0.0, fs-extra@^2.1.2: fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3192,14 +2787,12 @@ fs-extra@^7.0.1: fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== dependencies: minipass "^2.2.1" fs-promise@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" - integrity sha1-9k5PhUvPaJqovdy6JokW2z20aFQ= dependencies: any-promise "^1.3.0" fs-extra "^2.0.0" @@ -3209,17 +2802,14 @@ fs-promise@^2.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fs@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.2.tgz#e1f244ef3933c1b2a64bd4799136060d0f5914f8" - integrity sha1-4fJE7zkzwbKmS9R5kTYGDQ9ZFPg= fsevents@^1.0.0: version "1.2.4" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -3227,7 +2817,6 @@ fsevents@^1.0.0: fstream@^1.0.2, fstream@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -3237,17 +2826,14 @@ fstream@^1.0.2, fstream@^1.0.8: function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= ganache-cli@^6.2.5: version "6.2.5" resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.2.5.tgz#efda5115fa3a0c62d7f5729fdd78da70ca55b1ad" - integrity sha512-E4SP8QNeuc2N/ojFoCK+08OYHX8yrtGeFtipZmJPPTQ6U8Hmq3JcbXZDxQfChPQUY5mtbRSwptJa4EtiQyJjAQ== dependencies: bn.js "4.11.8" source-map-support "0.5.9" @@ -3256,7 +2842,6 @@ ganache-cli@^6.2.5: gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -3270,12 +2855,10 @@ gauge@~2.7.3: get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= dependencies: object-assign "^4.0.1" pinkie-promise "^2.0.0" @@ -3283,24 +2866,20 @@ get-stream@^2.2.0: get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= dependencies: glob-parent "^2.0.0" is-glob "^2.0.0" @@ -3308,14 +2887,12 @@ glob-base@^0.3.0: glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= dependencies: is-glob "^2.0.0" glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3327,7 +2904,6 @@ glob@7.1.2: glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= dependencies: inflight "^1.0.4" inherits "2" @@ -3338,7 +2914,6 @@ glob@^5.0.15: glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@~7.1.2: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3350,7 +2925,6 @@ glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@~7.1.2: glob@~6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= dependencies: inflight "^1.0.4" inherits "2" @@ -3361,7 +2935,6 @@ glob@~6.0.4: global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" - integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= dependencies: min-document "^2.19.0" process "~0.5.1" @@ -3369,17 +2942,14 @@ global@~4.3.0: globals@^11.7.0: version "11.9.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249" - integrity sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg== globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== got@7.1.0, got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== dependencies: decompress-response "^3.2.0" duplexer3 "^0.1.4" @@ -3399,27 +2969,22 @@ got@7.1.0, got@^7.1.0: graceful-fs@*, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.15" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= growl@1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== growl@1.10.5, "growl@~> 1.10.0": version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: version "4.0.12" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" - integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA== dependencies: async "^2.5.0" optimist "^0.6.1" @@ -3430,12 +2995,10 @@ handlebars@^4.0.1: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.0: version "5.1.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== dependencies: ajv "^6.5.5" har-schema "^2.0.0" @@ -3443,51 +3006,42 @@ har-validator@~5.1.0: has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= has-to-string-tag-x@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== dependencies: has-symbol-support-x "^1.4.1" has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -3496,7 +3050,6 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -3505,12 +3058,10 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -3518,14 +3069,12 @@ has-values@^1.0.0: has@^1.0.1, has@^1.0.3, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -3533,7 +3082,6 @@ hash-base@^3.0.0: hash.js@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.0" @@ -3541,7 +3089,6 @@ hash.js@1.1.3: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" @@ -3549,7 +3096,6 @@ hash.js@^1.0.0, hash.js@^1.0.3: hdkey@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.0.tgz#e74e7b01d2c47f797fa65d1d839adb7a44639f29" - integrity sha512-E7aU8pNlWUJbXGjTz/+lKf1LkMcA3hUrC5ZleeizrmLSd++kvf8mSOe3q8CmBDA9j4hdfXO5iY6hGiTUCOV2jQ== dependencies: coinstring "^2.0.0" safe-buffer "^5.1.1" @@ -3558,12 +3104,10 @@ hdkey@^1.1.0: he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -3572,7 +3116,6 @@ hmac-drbg@^1.0.0: home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.1" @@ -3580,12 +3123,10 @@ home-or-tmp@^2.0.0: hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" @@ -3595,12 +3136,10 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: http-https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" @@ -3609,7 +3148,6 @@ http-signature@~1.2.0: i18n@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/i18n/-/i18n-0.8.3.tgz#2d8cf1c24722602c2041d01ba6ae5eaa51388f0e" - integrity sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4= dependencies: debug "*" make-plural "^3.0.3" @@ -3621,48 +3159,40 @@ i18n@^0.8.3: i@0.3.x: version "0.3.6" resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d" - integrity sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0= iconv-lite@0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" ieee754@^1.1.4, ieee754@^1.1.8: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== dependencies: minimatch "^3.0.4" ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== ignore@^5.0.2: version "5.0.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.4.tgz#33168af4a21e99b00c5d41cbadb6a6cb49903a45" - integrity sha512-WLsTMEhsQuXpCiG173+f3aymI43SXa+fB1rSfbzyP4GkPP+ZFVuO0/3sFUGNBtifisPeDcl/uD/Y2NxZ7xFq4g== ignorefs@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ignorefs/-/ignorefs-1.2.0.tgz#da59fb858976e4a5e43702ccd1f282fdbc9e5756" - integrity sha1-2ln7hYl25KXkNwLM0fKC/byeV1Y= dependencies: editions "^1.3.3" ignorepatterns "^1.1.0" @@ -3670,22 +3200,18 @@ ignorefs@^1.0.0: ignorepatterns@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ignorepatterns/-/ignorepatterns-1.1.0.tgz#ac8f436f2239b5dfb66d5f0d3a904a87ac67cc5e" - integrity sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4= immediate@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" @@ -3693,22 +3219,18 @@ inflight@^1.0.4: inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= inherits@=2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== inquirer@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.1.tgz#9943fc4882161bdb0b0c9276769c75b32dbfcd52" - integrity sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -3727,91 +3249,76 @@ inquirer@^6.1.0: interpret@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" - integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= dependencies: builtin-modules "^1.0.0" is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -3820,7 +3327,6 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -3829,211 +3335,174 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= dependencies: is-primitive "^2.0.0" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= dependencies: number-is-nan "^1.0.0" is-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= dependencies: is-extglob "^1.0.0" is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= is-nan@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" - integrity sha1-n69ltvttskt/XAYoR16nH5iEAeI= dependencies: define-properties "^1.1.1" is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= dependencies: kind-of "^3.0.2" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= is-promise@^2.1, is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= dependencies: has "^1.0.1" is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== dependencies: has-symbols "^1.0.0" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= iso-url@~0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-0.4.4.tgz#473a45569b6015da0c23f831010aeff69e3841e8" - integrity sha512-mR7/oy5PRtuWaynQ+QRNGbGNg7j3VLIc99DvrSfjmretWTS5zwC3p/D5iX7UvtFU1dBB501wibJIwUuNeo3Rfw== isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= dependencies: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" @@ -4041,12 +3510,10 @@ isomorphic-fetch@^2.2.0: isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= dependencies: abbrev "1.0.x" async "1.x" @@ -4066,7 +3533,6 @@ istanbul@^0.4.5: isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== dependencies: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" @@ -4074,32 +3540,26 @@ isurl@^1.0.0-alpha5: js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= js-sha3@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.6.1.tgz#5b89f77a7477679877f58c4a075240934b1f95c0" - integrity sha1-W4n3enR3Z5h39YxKB1JAk0sflcA= js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4107,22 +3567,18 @@ js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.12.0: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-rpc-engine@^3.6.0: version "3.8.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" - integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== dependencies: async "^2.0.1" babel-preset-env "^1.7.0" @@ -4134,82 +3590,68 @@ json-rpc-engine@^3.6.0: json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= dependencies: inherits "^2.0.1" json-rpc-random-id@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= dependencies: jsonify "~0.0.0" json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json-text-sequence@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" - integrity sha1-py8hfcSvxGKf/1/rME3BvVGi89I= dependencies: delimit-stream "0.1.0" json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= optionalDependencies: graceful-fs "^4.1.6" jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= optionalDependencies: graceful-fs "^4.1.6" jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" extsprintf "1.3.0" @@ -4219,7 +3661,6 @@ jsprim@^1.2.2: keccak@^1.0.2: version "1.4.0" resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" - integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== dependencies: bindings "^1.2.1" inherits "^2.0.3" @@ -4229,7 +3670,6 @@ keccak@^1.0.2: keccakjs@^0.2.0, keccakjs@^0.2.1: version "0.2.3" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72" - integrity sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg== dependencies: browserify-sha3 "^0.0.4" sha3 "^1.2.2" @@ -4237,69 +3677,58 @@ keccakjs@^0.2.0, keccakjs@^0.2.1: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= optionalDependencies: graceful-fs "^4.1.9" lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM= level-codec@~7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== level-errors@^1.0.3: version "1.1.2" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== dependencies: errno "~0.1.1" level-errors@~1.0.3: version "1.0.5" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== dependencies: errno "~0.1.1" level-iterator-stream@~1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= dependencies: inherits "^2.0.1" level-errors "^1.0.3" @@ -4309,7 +3738,6 @@ level-iterator-stream@~1.3.0: level-ws@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= dependencies: readable-stream "~1.0.15" xtend "~2.1.1" @@ -4317,7 +3745,6 @@ level-ws@0.0.0: levelup@^1.2.1: version "1.3.9" resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== dependencies: deferred-leveldown "~1.2.1" level-codec "~7.0.0" @@ -4330,7 +3757,6 @@ levelup@^1.2.1: levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -4338,7 +3764,6 @@ levn@^0.3.0, levn@~0.3.0: load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4349,7 +3774,6 @@ load-json-file@^1.0.0: load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -4359,7 +3783,6 @@ load-json-file@^2.0.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -4367,44 +3790,36 @@ locate-path@^2.0.0: lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= lodash@4.x, lodash@=4.17.11, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== lodash@=4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= log-driver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" - integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== long-timeout@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" - integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ= loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -4412,57 +3827,48 @@ lru-cache@^4.0.1: lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" - integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= dependencies: es5-ext "~0.10.2" ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== dependencies: pify "^3.0.0" make-plural@^3.0.3, make-plural@~3.0.3: version "3.0.6" resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-3.0.6.tgz#2033a03bac290b8f3bb91258f65b9df7e8b01ca7" - integrity sha1-IDOgO6wpC487uRJY9lud9+iwHKc= optionalDependencies: minimist "^1.2.0" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" math-interval-parser@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-interval-parser/-/math-interval-parser-1.1.0.tgz#dbeda5b06b3249973c6df6170fde2386f0afd893" - integrity sha1-2+2lsGsySZc8bfYXD94jhvCv2JM= dependencies: xregexp "^2.0.0" math-random@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" - integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -4471,7 +3877,6 @@ md5.js@^1.3.4: md5@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" - integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk= dependencies: charenc "~0.0.1" crypt "~0.0.1" @@ -4480,19 +3885,16 @@ md5@^2.1.0: media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= dependencies: mimic-fn "^1.0.0" memdown@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= dependencies: abstract-leveldown "~2.7.1" functional-red-black-tree "^1.0.1" @@ -4504,7 +3906,6 @@ memdown@^1.0.0: memoizee@^0.4.14: version "0.4.14" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" - integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== dependencies: d "1" es5-ext "^0.10.45" @@ -4518,17 +3919,14 @@ memoizee@^0.4.14: memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= merkle-patricia-tree@^2.1.2: version "2.3.2" resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== dependencies: async "^1.4.2" ethereumjs-util "^5.0.0" @@ -4542,7 +3940,6 @@ merkle-patricia-tree@^2.1.2: messageformat@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/messageformat/-/messageformat-0.3.1.tgz#e58fff8245e9b3971799e5b43db58b3e9417f5a2" - integrity sha1-5Y//gkXps5cXmeW0PbWLPpQX9aI= dependencies: async "~1.5.2" glob "~6.0.4" @@ -4553,12 +3950,10 @@ messageformat@^0.3.1: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@^2.1.5: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= dependencies: arr-diff "^2.0.0" array-unique "^0.2.1" @@ -4577,7 +3972,6 @@ micromatch@^2.1.5: micromatch@^3.1.10: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4596,7 +3990,6 @@ micromatch@^3.1.10: miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" @@ -4604,73 +3997,60 @@ miller-rabin@^4.0.0: mime-db@~1.37.0: version "1.37.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" - integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.21" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" - integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== dependencies: mime-db "~1.37.0" mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= dependencies: dom-walk "^0.1.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@^1.2.0, minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= minipass@^2.2.1, minipass@^2.3.4: version "2.3.5" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" @@ -4678,14 +4058,12 @@ minipass@^2.2.1, minipass@^2.3.4: minizlib@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== dependencies: minipass "^2.2.1" mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -4693,21 +4071,18 @@ mixin-deep@^1.2.0: mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= dependencies: mkdirp "*" mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" mocha-junit-reporter@^1.18.0: version "1.18.0" resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.18.0.tgz#9209a3fba30025ae3ae5e6bfe7f9c5bc3c2e8ee2" - integrity sha512-y3XuqKa2+HRYtg0wYyhW/XsLm2Ps+pqf9HaTAt7+MVUAKFJaNAHOrNseTZo9KCxjfIbxUWwckP5qCDDPUmjSWA== dependencies: debug "^2.2.0" md5 "^2.1.0" @@ -4718,7 +4093,6 @@ mocha-junit-reporter@^1.18.0: mocha@^4.0.1, mocha@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" - integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== dependencies: browser-stdout "1.3.0" commander "2.11.0" @@ -4734,7 +4108,6 @@ mocha@^4.0.1, mocha@^4.1.0: mocha@^5.0.1: version "5.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== dependencies: browser-stdout "1.3.1" commander "2.15.1" @@ -4751,39 +4124,32 @@ mocha@^5.0.1: mock-fs@^4.1.0: version "4.7.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" - integrity sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA== moment-timezone@^0.5.23: version "0.5.23" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.23.tgz#7cbb00db2c14c71b19303cb47b0fb0a6d8651463" - integrity sha512-WHFH85DkCfiNMDX5D3X7hpNH3/PUhjTGcD0U1SgfBGZxJ3qUmJh5FdvaFjcClxOvB3rzdfj4oRffbI38jEnC1w== dependencies: moment ">= 2.9.0" "moment@>= 2.9.0", moment@^2.22.2: version "2.23.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.23.0.tgz#759ea491ac97d54bac5ad776996e2a58cc1bc225" - integrity sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA== mout@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" - integrity sha1-ujYR318OWx/7/QEWa48C0fX6K5k= ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== multihashes@^0.4.5: version "0.4.14" resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.14.tgz#774db9a161f81a8a27dc60788f91248e020f5244" - integrity sha512-V/g/EIN6nALXfS/xHUAgtfPP3mn3sPIF/i9beuGKf25QXS2QZYCpeVJbDPEannkz32B2fihzCe2D/KMrbcmefg== dependencies: bs58 "^4.0.1" varint "^5.0.0" @@ -4791,27 +4157,22 @@ multihashes@^0.4.5: mustache@*: version "3.0.1" resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.1.tgz#873855f23aa8a95b150fb96d9836edbc5a1d248a" - integrity sha512-jFI/4UVRsRYdUbuDTKT7KzfOp7FiD5WzYmmwNwXyUVypC0xjoTL78Fqc0jHUPIvvGD+6DQSPHIt1NE7D1ArsqA== mustache@^2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" - integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" object-assign "^4.0.1" @@ -4820,22 +4181,18 @@ mz@^2.6.0: nan@2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== nan@^2.0.8, nan@^2.11.0, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: version "2.12.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" - integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -4852,17 +4209,14 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= ncp@1.0.x: version "1.0.1" resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" - integrity sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY= needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== dependencies: debug "^2.1.2" iconv-lite "^0.4.4" @@ -4871,27 +4225,22 @@ needle@^2.2.1: negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== node-async-loop@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/node-async-loop/-/node-async-loop-1.2.2.tgz#c5870299bf6477b780c88b431aa5b37733f55a3d" - integrity sha1-xYcCmb9kd7eAyItDGqWzdzP1Wj0= node-cache@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.0.tgz#48ac796a874e762582692004a376d26dfa875811" - integrity sha512-obRu6/f7S024ysheAjoYFEEBqqDWv4LOMNJEuO8vMeEw2AT4z+NCzO4hlc2lhI4vATzbCQv6kke9FVdx0RbCOw== dependencies: clone "2.x" lodash "4.x" @@ -4899,7 +4248,6 @@ node-cache@^4.1.1: node-fetch@^1.0.1, node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== dependencies: encoding "^0.1.11" is-stream "^1.0.1" @@ -4907,7 +4255,6 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -4923,7 +4270,6 @@ node-pre-gyp@^0.10.0: node-schedule@^1.2.3: version "1.3.1" resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-1.3.1.tgz#6909dd644211bca153b15afc62e1dc0afa7d28be" - integrity sha512-cdNNePwKoisAi4DT00BB11H6IJ/WtA603YZ7+tLJcb/zCmCSxYKcvc+/GTyxC46jN/0ft7741vmMQrvxP8Sd+A== dependencies: cron-parser "^2.7.3" long-timeout "0.1.1" @@ -4932,14 +4278,12 @@ node-schedule@^1.2.3: nopt@3.x, nopt@~3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" osenv "^0.1.4" @@ -4947,7 +4291,6 @@ nopt@^4.0.1: normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" @@ -4957,19 +4300,16 @@ normalize-package-data@^2.3.2: normalize-path@^2.0.0, normalize-path@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" - integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" - integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -4977,14 +4317,12 @@ npm-packlist@^1.1.6: npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" @@ -4994,12 +4332,10 @@ npmlog@^4.0.2: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -5007,17 +4343,14 @@ number-to-bn@1.7.0: oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" @@ -5026,29 +4359,24 @@ object-copy@^0.1.0: object-inspect@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= dependencies: for-own "^0.1.4" is-extendable "^0.1.1" @@ -5056,47 +4384,40 @@ object.omit@^2.0.0: object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" oboe@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" - integrity sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8= dependencies: http-https "^1.0.0" on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" openzeppelin-solidity@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-1.10.0.tgz#d77eee6653f5958d051318a61ba0b436f92216c0" - integrity sha512-igkrumQQ2lrN2zjeQV4Dnb0GpTBj1fzMcd8HPyBUqwI0hhuscX/HzXiqKT6gFQl1j9Wy/ppVVs9fqL/foF7Gmg== optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= dependencies: minimist "~0.0.1" wordwrap "~0.0.2" @@ -5104,7 +4425,6 @@ optimist@^0.6.1: optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" @@ -5116,24 +4436,20 @@ optionator@^0.8.1, optionator@^0.8.2: original-require@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" - integrity sha1-DxMEcVhM0zURxew4yNWSE/msXiA= os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== dependencies: execa "^0.7.0" lcid "^1.0.0" @@ -5142,12 +4458,10 @@ os-locale@^2.0.0: os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -5155,43 +4469,36 @@ osenv@^0.1.4: p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= dependencies: p-limit "^1.1.0" p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= dependencies: p-finally "^1.0.0" p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= parse-asn1@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" - integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -5202,7 +4509,6 @@ parse-asn1@^5.0.0: parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= dependencies: glob-base "^0.3.0" is-dotfile "^1.0.0" @@ -5212,7 +4518,6 @@ parse-glob@^3.0.4: parse-headers@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" - integrity sha1-aug6eqJanZtwCswoaYzR8e1+lTY= dependencies: for-each "^0.3.2" trim "0.0.1" @@ -5220,61 +4525,50 @@ parse-headers@^2.0.0: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-parse@^1.0.5, path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -5283,14 +4577,12 @@ path-type@^1.0.0: path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= dependencies: pify "^2.0.0" pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -5301,116 +4593,94 @@ pbkdf2@^3.0.3: pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" - integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= dependencies: find-up "^1.0.0" pkginfo@0.3.x: version "0.3.1" resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" - integrity sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE= pkginfo@0.x.x: version "0.4.1" resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" - integrity sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8= pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= pragma-singleton@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pragma-singleton/-/pragma-singleton-1.0.3.tgz#6894317bb8d47157e59de2a4a009db7e6f63e30e" - integrity sha1-aJQxe7jUcVflneKkoAnbfm9j4w4= prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= prettier@^1.15.3: version "1.15.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a" - integrity sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg== private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== process@~0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== promise-to-callback@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= dependencies: is-fn "^1.0.0" set-immediate-shim "^1.0.1" @@ -5418,7 +4688,6 @@ promise-to-callback@^1.0.0: prompt@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe" - integrity sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4= dependencies: colors "^1.1.2" pkginfo "0.x.x" @@ -5430,7 +4699,6 @@ prompt@^1.0.0: prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" - integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== dependencies: loose-envify "^1.3.1" object-assign "^4.1.1" @@ -5438,7 +4706,6 @@ prop-types@^15.6.2: proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" - integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== dependencies: forwarded "~0.1.2" ipaddr.js "1.8.0" @@ -5446,22 +4713,18 @@ proxy-addr@~2.0.4: prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24, psl@^1.1.28: version "1.1.31" resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" - integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -5473,22 +4736,18 @@ public-encrypt@^4.0.0: punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== dependencies: decode-uri-component "^0.2.0" object-assign "^4.1.0" @@ -5497,7 +4756,6 @@ query-string@^5.0.1: randomatic@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== dependencies: is-number "^4.0.0" kind-of "^6.0.0" @@ -5506,14 +4764,12 @@ randomatic@^3.0.0: randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -5521,17 +4777,14 @@ randomfill@^1.0.3: randomhex@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" - integrity sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU= range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== dependencies: bytes "3.0.0" http-errors "1.6.3" @@ -5541,7 +4794,6 @@ raw-body@2.3.3: rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" ini "~1.3.0" @@ -5551,7 +4803,6 @@ rc@^1.2.7: react-dom@^16.2.0: version "16.7.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.7.0.tgz#a17b2a7ca89ee7390bc1ed5eb81783c7461748b8" - integrity sha512-D0Ufv1ExCAmF38P2Uh1lwpminZFRXEINJe53zRAbm4KPwSyd6DY/uDoS0Blj9jvPpn1+wivKpZYc8aAAN/nAkg== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5561,7 +4812,6 @@ react-dom@^16.2.0: react@^16.2.0: version "16.7.0" resolved "https://registry.yarnpkg.com/react/-/react-16.7.0.tgz#b674ec396b0a5715873b350446f7ea0802ab6381" - integrity sha512-StCz3QY8lxTb5cl2HJxjwLFOXPIFQp+p+hxQfc8WE0QiLfCtIlKj8/+5tjjKm8uSTlAW+fCPaavGFS06V9Ar3A== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5571,7 +4821,6 @@ react@^16.2.0: read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -5579,7 +4828,6 @@ read-pkg-up@^1.0.1: read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= dependencies: find-up "^2.0.0" read-pkg "^2.0.0" @@ -5587,7 +4835,6 @@ read-pkg-up@^2.0.0: read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" @@ -5596,7 +4843,6 @@ read-pkg@^1.0.0: read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" @@ -5605,14 +4851,12 @@ read-pkg@^2.0.0: read@1.0.x: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= dependencies: mute-stream "~0.0.4" readable-stream@^1.0.33: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5622,7 +4866,6 @@ readable-stream@^1.0.33: readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -5635,7 +4878,6 @@ readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -5645,7 +4887,6 @@ readable-stream@~1.0.15: readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" @@ -5654,29 +4895,24 @@ readdirp@^2.0.0: rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" regenerate@^1.2.1: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" @@ -5685,14 +4921,12 @@ regenerator-transform@^0.10.0: regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== dependencies: is-equal-shallow "^0.1.3" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" @@ -5700,12 +4934,10 @@ regex-not@^1.0.0, regex-not@^1.0.2: regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= dependencies: regenerate "^1.2.1" regjsgen "^0.2.0" @@ -5714,62 +4946,52 @@ regexpu-core@^2.0.0: regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= regjsparser@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= dependencies: is-finite "^1.0.0" req-cwd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-1.0.1.tgz#0d73aeae9266e697a78f7976019677e76acf0fff" - integrity sha1-DXOurpJm5penj3l2AZZ352rPD/8= dependencies: req-from "^1.0.1" req-from@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-from/-/req-from-1.0.1.tgz#bf81da5147947d32d13b947dc12a58ad4587350e" - integrity sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4= dependencies: resolve-from "^2.0.0" request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" - integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= dependencies: lodash "^4.13.1" request-promise@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" - integrity sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ= dependencies: bluebird "^3.5.0" request-promise-core "1.1.1" @@ -5779,7 +5001,6 @@ request-promise@^4.2.2: request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -5805,22 +5026,18 @@ request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.8 require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" - integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" @@ -5828,41 +5045,34 @@ require-uncached@^1.0.3: resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.1.6, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.8.1: version "1.9.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06" - integrity sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ== dependencies: path-parse "^1.0.6" resolve@~1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" - integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw== dependencies: path-parse "^1.0.5" restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" signal-exit "^3.0.2" @@ -5870,31 +5080,26 @@ restore-cursor@^2.0.0: resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= dependencies: through "~2.3.4" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== revalidator@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" - integrity sha1-/s5hv6DBtSoga9axgZgYS91SOjs= rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.6.1, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -5902,74 +5107,62 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: rlp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.1.tgz#9cacf53ad2579163cc56fba64b1f4336f1f2fa46" - integrity sha512-nqB/qy+YjXdp/zj1CjCiDwfLMBPv/XFDol0ir/7O/+Ix90++rvi+QoK1CDJcn8JoqCu2WrPPeRucu4qyIDzALg== dependencies: safe-buffer "^5.1.1" run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= dependencies: is-promise "^2.1.0" rustbn.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" - integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== rxjs@^6.1.0: version "6.3.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" - integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw== dependencies: tslib "^1.9.0" safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-event-emitter@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" - integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== dependencies: events "^3.0.0" safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" safe@^0.4.5: version "0.4.6" resolved "https://registry.yarnpkg.com/safe/-/safe-0.4.6.tgz#1d5580cf2635c5cb940ea48fb5081ae3c25b1be1" - integrity sha1-HVWAzyY1xcuUDqSPtQga48JbG+E= safefs@^3.1.2: version "3.2.2" resolved "https://registry.yarnpkg.com/safefs/-/safefs-3.2.2.tgz#8170c1444d7038e08caea05a374fae2fa349e15c" - integrity sha1-gXDBRE1wOOCMrqBaN0+uL6NJ4Vw= dependencies: graceful-fs "*" "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== scandirectory@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/scandirectory/-/scandirectory-2.5.0.tgz#6ce03f54a090b668e3cbedbf20edf9e310593e72" - integrity sha1-bOA/VKCQtmjjy+2/IO354xBZPnI= dependencies: ignorefs "^1.0.0" safefs "^3.1.2" @@ -5978,7 +5171,6 @@ scandirectory@^2.5.0: scheduler@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.12.0.tgz#8ab17699939c0aedc5a196a657743c496538647b" - integrity sha512-t7MBR28Akcp4Jm+QoR63XgAi9YgCUmgvDHqf5otgAj4QvdoBE4ImCX0ffehefePPG+aitiYHp0g/mW6s4Tp+dw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5986,17 +5178,14 @@ scheduler@^0.12.0: scrypt-async@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-1.3.1.tgz#a11fd6fac981b4b823ee01dee0221169500ddae9" - integrity sha1-oR/W+smBtLgj7gHe4CIRaVAN2uk= scrypt-js@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" - integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== scrypt.js@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" - integrity sha1-r40UZbcemZARC+38WTuUeeA6ito= dependencies: scrypt "^6.0.2" scryptsy "^1.2.1" @@ -6004,7 +5193,6 @@ scrypt.js@0.2.0: scrypt.js@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.3.0.tgz#6c62d61728ad533c8c376a2e5e3e86d41a95c4c0" - integrity sha512-42LTc1nyFsyv/o0gcHtDztrn+aqpkaCNt5Qh7ATBZfhEZU7IC/0oT/qbBH+uRNoAPvs2fwiOId68FDEoSRA8/A== dependencies: scryptsy "^1.2.1" optionalDependencies: @@ -6013,21 +5201,18 @@ scrypt.js@^0.3.0: scrypt@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" - integrity sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0= dependencies: nan "^2.0.8" scryptsy@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= dependencies: pbkdf2 "^3.0.3" secp256k1@^3.0.1: version "3.6.1" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.6.1.tgz#f0475d42096218ff00e45a127242abdff9285335" - integrity sha512-utLpWv4P4agEw7hakR73wlWX0NBmC5t/vkJ0TAfTyvETAUzo0tm6aFKPYetVYRaVubxMeWm5Ekv9ETwOgcDCqw== dependencies: bindings "^1.2.1" bip66 "^1.1.3" @@ -6041,29 +5226,24 @@ secp256k1@^3.0.1: seek-bzip@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= dependencies: commander "~2.8.1" semaphore@>=1.0.1, semaphore@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== semver@~5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== dependencies: debug "2.6.9" depd "~1.1.2" @@ -6082,7 +5262,6 @@ send@0.16.2: serve-static@1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" @@ -6092,7 +5271,6 @@ serve-static@1.13.2: servify@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== dependencies: body-parser "^1.16.0" cors "^2.8.1" @@ -6103,17 +5281,14 @@ servify@^0.1.12: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6123,7 +5298,6 @@ set-value@^0.4.3: set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -6133,22 +5307,18 @@ set-value@^2.0.0: setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -6156,26 +5326,22 @@ sha.js@^2.4.0, sha.js@^2.4.8: sha3@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" - integrity sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k= dependencies: nan "2.10.0" shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shelljs@^0.7.4: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -6184,7 +5350,6 @@ shelljs@^0.7.4: shelljs@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" - integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -6193,17 +5358,14 @@ shelljs@^0.8.1: signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= simple-get@^2.7.0: version "2.8.1" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== dependencies: decompress-response "^3.3.0" once "^1.3.1" @@ -6212,12 +5374,10 @@ simple-get@^2.7.0: slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= slice-ansi@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.0.0.tgz#5373bdb8559b45676e8541c66916cdd6251612e7" - integrity sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ== dependencies: ansi-styles "^3.2.0" astral-regex "^1.0.0" @@ -6226,7 +5386,6 @@ slice-ansi@2.0.0: snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -6235,14 +5394,12 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -6256,22 +5413,18 @@ snapdragon@^0.8.1: sol-digger@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" - integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= sol-explore@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" - integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= sol-explore@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.2.tgz#43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2" - integrity sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI= sol-merger@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-0.1.3.tgz#184284ba4811aebe8950f510df4e8218f568b35f" - integrity sha512-mEirUbl1mZJt2iNBqptsBpxb8n7ZD0trNlnV/+CBAQH8TIFhHIKXdBE8ykD1v+8My18sq7GqHYPmpHE9ckB2Jw== dependencies: bluebird "^3.5.3" cli-color "^1.4.0" @@ -6283,7 +5436,6 @@ sol-merger@^0.1.3: solc@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.24.tgz#354f14b269b38cbaa82a47d1ff151723502b954e" - integrity sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -6294,7 +5446,6 @@ solc@0.4.24: solc@^0.4.2: version "0.4.25" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.25.tgz#06b8321f7112d95b4b903639b1138a4d292f5faa" - integrity sha512-jU1YygRVy6zatgXrLY2rRm7HW1d7a8CkkEgNJwvH2VLpWhMFsMdWcJn6kUqZwcSz/Vm+w89dy7Z/aB5p6AFTrg== dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -6305,7 +5456,6 @@ solc@^0.4.2: solidity-coverage@^0.5.11: version "0.5.11" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" - integrity sha512-qikdsSi6+9XbfvwA0aI7HUVpF9fIFNqRWTw23M89GMDY+b6Gj0wWU9IngJS0fimoZIAdEp3bfChxvpfVcrUesg== dependencies: death "^1.1.0" ethereumjs-testrpc-sc "6.1.6" @@ -6321,7 +5471,6 @@ solidity-coverage@^0.5.11: solidity-docgen@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/solidity-docgen/-/solidity-docgen-0.1.0.tgz#f3a56ff074e8c7d832af3a3d462c3b5abf0f64cb" - integrity sha512-F7ufNWmlP5c5hIi66Ijv9tc+HNosyO7ijWq6pRtyBR1WqyJBH/0DJkD6QZI8HkE8p6LEXiPKxGBWbAeVT9Nu9g== dependencies: commander "^2.14.1" lodash "^4.17.5" @@ -6334,7 +5483,6 @@ solidity-docgen@^0.1.0: solidity-parser-sc@0.4.11: version "0.4.11" resolved "https://registry.yarnpkg.com/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz#86734c9205537007f4d6201b57176e41696ee607" - integrity sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw== dependencies: mocha "^4.1.0" pegjs "^0.10.0" @@ -6343,12 +5491,10 @@ solidity-parser-sc@0.4.11: solium-plugin-security@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" - integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== solium@^1.1.8: version "1.2.1" resolved "https://registry.yarnpkg.com/solium/-/solium-1.2.1.tgz#ead11f2921ba2337461752155cc96149ea08f247" - integrity sha512-PnNOx3BfYvghJE5aV2lWBcbNIa9g9eXQaGPpQPiYixmF7kVR27J2tmSetdsdpwKMVf2Y+H4JEEL7zyfsRjOMFA== dependencies: ajv "^5.2.2" chokidar "^1.6.0" @@ -6367,7 +5513,6 @@ solium@^1.1.8: solparse@2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.7.tgz#5479ff4ba4ca6900df89b902b5af1ee23b816250" - integrity sha512-s2DKdvVxXcWefPgBSb+HgTylomzbNjsKdZDN6PsWi9h+UYdyw7DFozpPCGETNEz523tIjrqBRnSPIoDVL1zv5Q== dependencies: mocha "^4.0.1" pegjs "^0.10.0" @@ -6376,12 +5521,10 @@ solparse@2.2.7: sorted-array-functions@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.2.0.tgz#43265b21d6e985b7df31621b1c11cc68d8efc7c3" - integrity sha512-sWpjPhIZJtqO77GN+LD8dDsDKcWZ9GCOJNqKzi1tvtjGIzwfoyuRH8S0psunmc6Z5P+qfDqztSbwYR5X/e1UTg== source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== dependencies: atob "^2.1.1" decode-uri-component "^0.2.0" @@ -6392,7 +5535,6 @@ source-map-resolve@^0.5.0: source-map-support@0.5.9, source-map-support@^0.5.3: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -6400,36 +5542,30 @@ source-map-support@0.5.9, source-map-support@^0.5.3: source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== dependencies: source-map "^0.5.6" source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= dependencies: amdefine ">=0.0.4" spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -6437,12 +5573,10 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" @@ -6450,29 +5584,24 @@ spdx-expression-parse@^3.0.0: spdx-license-ids@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" - integrity sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@>=1.0.3: version "1.1.2" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" - integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: version "1.16.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.0.tgz#1d4963a2fbffe58050aa9084ca20be81741c07de" - integrity sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -6487,12 +5616,10 @@ sshpk@^1.7.0: stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -6500,32 +5627,26 @@ static-extend@^0.1.1: "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== stdio@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/stdio/-/stdio-0.2.7.tgz#a1c57da10fe1cfaa0c3bf683c9d0743d1b660839" - integrity sha1-ocV9oQ/hz6oMO/aDydB0PRtmCDk= stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -6534,7 +5655,6 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" @@ -6542,7 +5662,6 @@ string-width@^1.0.1: string.prototype.trim@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" - integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= dependencies: define-properties "^1.1.2" es-abstract "^1.5.0" @@ -6551,109 +5670,92 @@ string.prototype.trim@~1.1.2: string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-ansi@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" - integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow== dependencies: ansi-regex "^4.0.0" strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== dependencies: is-natural-number "^4.0.1" strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= dependencies: is-hex-prefixed "1.0.0" strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= supports-color@4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== dependencies: has-flag "^2.0.0" supports-color@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== dependencies: has-flag "^3.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" swarm-js@0.1.37: version "0.1.37" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" - integrity sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ== dependencies: bluebird "^3.5.0" buffer "^5.0.5" @@ -6672,7 +5774,6 @@ swarm-js@0.1.37: table@^5.0.2: version "5.1.1" resolved "https://registry.yarnpkg.com/table/-/table-5.1.1.tgz#92030192f1b7b51b6eeab23ed416862e47b70837" - integrity sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw== dependencies: ajv "^6.6.1" lodash "^4.17.11" @@ -6682,7 +5783,6 @@ table@^5.0.2: tape@^4.4.0, tape@^4.6.3: version "4.9.2" resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.2.tgz#f233e40f09dc7e00fcf9b26755453c3822ad28c0" - integrity sha512-lPXKRKILZ1kZaUy5ynWKs8ATGSUO7HAFHCFnBam6FaGSqPdOwMWbxXHq4EXFLE8WRTleo/YOMXkaUTRmTB1Fiw== dependencies: deep-equal "~1.0.1" defined "~1.0.0" @@ -6701,7 +5801,6 @@ tape@^4.4.0, tape@^4.6.3: tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== dependencies: bl "^1.0.0" buffer-alloc "^1.2.0" @@ -6714,7 +5813,6 @@ tar-stream@^1.5.2: tar.gz@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" - integrity sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg== dependencies: bluebird "^2.9.34" commander "^2.8.1" @@ -6725,7 +5823,6 @@ tar.gz@^1.0.5: tar@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= dependencies: block-stream "*" fstream "^1.0.2" @@ -6734,7 +5831,6 @@ tar@^2.1.1: tar@^4: version "4.4.8" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" - integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" @@ -6747,7 +5843,6 @@ tar@^4: taskgroup@^4.0.5, taskgroup@^4.2.0: version "4.3.1" resolved "https://registry.yarnpkg.com/taskgroup/-/taskgroup-4.3.1.tgz#7de193febd768273c457730497024d512c27915a" - integrity sha1-feGT/r12gnPEV3MElwJNUSwnkVo= dependencies: ambi "^2.2.0" csextends "^1.0.3" @@ -6755,36 +5850,30 @@ taskgroup@^4.0.5, taskgroup@^4.2.0: text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= thenify-all@^1.0.0, thenify-all@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.0" resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" - integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= dependencies: any-promise "^1.0.0" through@^2.3.6, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-ext@^0.1.5: version "0.1.7" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" - integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== dependencies: es5-ext "~0.10.46" next-tick "1" @@ -6792,7 +5881,6 @@ timers-ext@^0.1.5: tingodb@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/tingodb/-/tingodb-0.6.1.tgz#f63336259af7dfa6c90dfe2556a0dfb0d4eede59" - integrity sha1-9jM2JZr336bJDf4lVqDfsNTu3lk= dependencies: lodash "^4.17.5" safe "^0.4.5" @@ -6803,31 +5891,26 @@ tingodb@^0.6.1: tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" to-buffer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -6835,7 +5918,6 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" @@ -6845,7 +5927,6 @@ to-regex@^3.0.1, to-regex@^3.0.2: tough-cookie@>=2.3.3: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: psl "^1.1.28" punycode "^2.1.1" @@ -6853,7 +5934,6 @@ tough-cookie@>=2.3.3: tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: psl "^1.1.24" punycode "^1.4.1" @@ -6861,22 +5941,18 @@ tough-cookie@~2.4.3: tree-kill@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" - integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= -truffle-hdwallet-provider-privkey@0.3.0: +truffle-hdwallet-provider-privkey@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider-privkey/-/truffle-hdwallet-provider-privkey-0.3.0.tgz#6688f5f3db5dce2cb9f502f7b52dab7b5e2522a3" - integrity sha512-rXwYWz9/lgmZQft0lAwj1JTATzG9FErhvI4xy/Vz5gNFjQCGC7yu3aYBc3XI8g2nrIyYUFqaZbrgHmYcAjw/1A== dependencies: ethereumjs-tx "^1.3.4" ethereumjs-wallet "^0.6.0" @@ -6886,7 +5962,6 @@ truffle-hdwallet-provider-privkey@0.3.0: truffle-hdwallet-provider@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-1.0.3.tgz#4ae845f9b2de23f47c4f0fbc6ef2d4b13b494604" - integrity sha512-Lm4MrXHnWg8wHNUoumUBc8AhlCBg05x7wZA81JOFfO0j3QU53A/hhSfV7v8gANbRsvpF5Su0s3SNQGJjewtnYw== dependencies: any-promise "^1.3.0" bindings "^1.3.1" @@ -6895,7 +5970,6 @@ truffle-hdwallet-provider@^1.0.3: truffle-wallet-provider@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/truffle-wallet-provider/-/truffle-wallet-provider-0.0.5.tgz#db59ce6fa1c558766011137509a94dfca8d1408e" - integrity sha1-21nOb6HFWHZgERN1CalN/KjRQI4= dependencies: ethereumjs-wallet "^0.6.0" web3 "^0.18.2" @@ -6904,7 +5978,6 @@ truffle-wallet-provider@0.0.5: truffle@4.1.14: version "4.1.14" resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.14.tgz#8d2c298e29abf9b1e486e44ff9faca6d34bb9030" - integrity sha512-e7tTLvKP3bN9dE7MagfWyFjy4ZgoEGbeujECy1me1ENBzbj/aO/+45gs72qsL3+3IkCNNcWNOJjjrm8BYZZNNg== dependencies: mocha "^4.1.0" original-require "1.0.1" @@ -6913,36 +5986,30 @@ truffle@4.1.14: tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.13.2.tgz#453161770469d45cd266c36404e2bc99a8fa9944" - integrity sha1-RTFhdwRp1FzSZsNkBOK8maj6mUQ= tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" - integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== dependencies: media-typer "0.3.0" mime-types "~2.1.18" @@ -6950,31 +6017,26 @@ type-is@~1.6.16: typechecker@^2.0.8: version "2.1.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.1.0.tgz#d1c2093a54ff8a19f58cff877eeaa54f2242d383" - integrity sha1-0cIJOlT/ihn1jP+HfuqlTyJC04M= typechecker@^4.3.0: version "4.7.0" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.7.0.tgz#5249f427358f45b7250c4924fd4d01ed9ba435e9" - integrity sha512-4LHc1KMNJ6NDGO+dSM/yNfZQRtp8NN7psYrPHUblD62Dvkwsp3VShsbM78kOgpcmMkRTgvwdKOTjctS+uMllgQ== dependencies: editions "^2.1.0" typechecker@~2.0.1: version "2.0.8" resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.0.8.tgz#e83da84bb64c584ccb345838576c40b0337db82e" - integrity sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4= typedarray-to-buffer@^3.1.2, typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" uglify-js@^3.1.4: version "3.4.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" - integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== dependencies: commander "~2.17.1" source-map "~0.6.1" @@ -6982,12 +6044,10 @@ uglify-js@^3.1.4: ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== unbzip2-stream@^1.0.9: version "1.3.1" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" - integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw== dependencies: buffer "^3.0.1" through "^2.3.6" @@ -6995,17 +6055,14 @@ unbzip2-stream@^1.0.9: underscore@1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= underscore@^1.8.3: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -7015,22 +6072,18 @@ union-value@^1.0.0: universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== unorm@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300" - integrity sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA= unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -7038,61 +6091,50 @@ unset-value@^1.0.0: uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= dependencies: prepend-http "^1.0.1" url-set-query@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== utf8@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" - integrity sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g= utf8@^2.1.1, utf8@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" - integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY= utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= utile@0.3.x: version "0.3.0" resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a" - integrity sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo= dependencies: async "~0.9.0" deep-equal "~0.2.1" @@ -7104,22 +6146,18 @@ utile@0.3.x: utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" @@ -7127,17 +6165,14 @@ validate-npm-package-license@^3.0.1: varint@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf" - integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8= vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -7146,7 +6181,6 @@ verror@1.10.0: watchr@~2.4.13: version "2.4.13" resolved "https://registry.yarnpkg.com/watchr/-/watchr-2.4.13.tgz#d74847bb4d6f90f61fe2c74f9f68662aa0e07601" - integrity sha1-10hHu01vkPYf4sdPn2hmKqDgdgE= dependencies: eachr "^2.0.2" extendr "^2.1.0" @@ -7160,7 +6194,6 @@ watchr@~2.4.13: web3-bzz@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.34.tgz#068d37777ab65e5c60f8ec8b9a50cfe45277929c" - integrity sha1-Bo03d3q2Xlxg+OyLmlDP5FJ3kpw= dependencies: got "7.1.0" swarm-js "0.1.37" @@ -7169,7 +6202,6 @@ web3-bzz@1.0.0-beta.34: web3-core-helpers@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.34.tgz#b168da00d3e19e156bc15ae203203dd4dfee2d03" - integrity sha1-sWjaANPhnhVrwVriAyA91N/uLQM= dependencies: underscore "1.8.3" web3-eth-iban "1.0.0-beta.34" @@ -7178,7 +6210,6 @@ web3-core-helpers@1.0.0-beta.34: web3-core-method@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.34.tgz#ec163c8a2c490fa02a7ec15559fa7307fc7cc6dd" - integrity sha1-7BY8iixJD6AqfsFVWfpzB/x8xt0= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7189,7 +6220,6 @@ web3-core-method@1.0.0-beta.34: web3-core-promievent@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.34.tgz#a4f4fa6784bb293e82c60960ae5b56a94cd03edc" - integrity sha1-pPT6Z4S7KT6CxglgrltWqUzQPtw= dependencies: any-promise "1.3.0" eventemitter3 "1.1.1" @@ -7197,7 +6227,6 @@ web3-core-promievent@1.0.0-beta.34: web3-core-requestmanager@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.34.tgz#01f8f6cf2ae6b6f0b70c38bae1ef741b5bab215c" - integrity sha1-Afj2zyrmtvC3DDi64e90G1urIVw= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7208,7 +6237,6 @@ web3-core-requestmanager@1.0.0-beta.34: web3-core-subscriptions@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.34.tgz#9fed144033f221c3cf21060302ffdaf5ef2de2de" - integrity sha1-n+0UQDPyIcPPIQYDAv/a9e8t4t4= dependencies: eventemitter3 "1.1.1" underscore "1.8.3" @@ -7217,7 +6245,6 @@ web3-core-subscriptions@1.0.0-beta.34: web3-core@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.34.tgz#121be8555e9fb00d2c5d05ddd3381d0c9e46987e" - integrity sha1-EhvoVV6fsA0sXQXd0zgdDJ5GmH4= dependencies: web3-core-helpers "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7227,7 +6254,6 @@ web3-core@1.0.0-beta.34: web3-eth-abi@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.34.tgz#034533e3aa2f7e59ff31793eaea685c0ed5af67a" - integrity sha1-A0Uz46ovfln/MXk+rqaFwO1a9no= dependencies: bn.js "4.11.6" underscore "1.8.3" @@ -7237,7 +6263,6 @@ web3-eth-abi@1.0.0-beta.34: web3-eth-accounts@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.34.tgz#e09142eeecc797ac3459b75e9b23946d3695f333" - integrity sha1-4JFC7uzHl6w0WbdemyOUbTaV8zM= dependencies: any-promise "1.3.0" crypto-browserify "3.12.0" @@ -7253,7 +6278,6 @@ web3-eth-accounts@1.0.0-beta.34: web3-eth-contract@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.34.tgz#9dbb38fae7643a808427a20180470ec7415c91e6" - integrity sha1-nbs4+udkOoCEJ6IBgEcOx0FckeY= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -7267,7 +6291,6 @@ web3-eth-contract@1.0.0-beta.34: web3-eth-iban@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.34.tgz#9af458605867ccf74ea979aaf326b38ba6a5ba0c" - integrity sha1-mvRYYFhnzPdOqXmq8yazi6alugw= dependencies: bn.js "4.11.6" web3-utils "1.0.0-beta.34" @@ -7275,7 +6298,6 @@ web3-eth-iban@1.0.0-beta.34: web3-eth-personal@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.34.tgz#9afba167342ebde5420bcd5895c3f6c34388f205" - integrity sha1-mvuhZzQuveVCC81YlcP2w0OI8gU= dependencies: web3-core "1.0.0-beta.34" web3-core-helpers "1.0.0-beta.34" @@ -7286,7 +6308,6 @@ web3-eth-personal@1.0.0-beta.34: web3-eth@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.34.tgz#74086000850c6fe6f535ef49837d6d4bb6113268" - integrity sha1-dAhgAIUMb+b1Ne9Jg31tS7YRMmg= dependencies: underscore "1.8.3" web3-core "1.0.0-beta.34" @@ -7304,7 +6325,6 @@ web3-eth@1.0.0-beta.34: web3-net@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.34.tgz#427cea2f431881449c8e38d523290f173f9ff63d" - integrity sha1-QnzqL0MYgUScjjjVIykPFz+f9j0= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7313,7 +6333,6 @@ web3-net@1.0.0-beta.34: web3-provider-engine@^13.8.0: version "13.8.0" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz#4c7c1ad2af5f1fe10343b8a65495879a2f9c00df" - integrity sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ== dependencies: async "^2.5.0" clone "^2.0.0" @@ -7338,7 +6357,6 @@ web3-provider-engine@^13.8.0: web3-provider-engine@^8.4.0: version "8.6.1" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz#4d86e19e30caaf97df351511ec0f60136e5b30eb" - integrity sha1-TYbhnjDKr5ffNRUR7A9gE25bMOs= dependencies: async "^2.1.2" clone "^2.0.0" @@ -7358,7 +6376,6 @@ web3-provider-engine@^8.4.0: web3-providers-http@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.34.tgz#e561b52bbb43766282007d40285bfe3550c27e7a" - integrity sha1-5WG1K7tDdmKCAH1AKFv+NVDCfno= dependencies: web3-core-helpers "1.0.0-beta.34" xhr2 "0.1.4" @@ -7366,7 +6383,6 @@ web3-providers-http@1.0.0-beta.34: web3-providers-ipc@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.34.tgz#a1b77f1a306d73649a9c039052e40cb71328d00a" - integrity sha1-obd/GjBtc2SanAOQUuQMtxMo0Ao= dependencies: oboe "2.1.3" underscore "1.8.3" @@ -7375,7 +6391,6 @@ web3-providers-ipc@1.0.0-beta.34: web3-providers-ws@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.34.tgz#7de70f1b83f2de36476772156becfef6e3516eb3" - integrity sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM= dependencies: underscore "1.8.3" web3-core-helpers "1.0.0-beta.34" @@ -7384,7 +6399,6 @@ web3-providers-ws@1.0.0-beta.34: web3-shh@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.34.tgz#975061d71eaec42ccee576f7bd8f70f03844afe0" - integrity sha1-l1Bh1x6uxCzO5Xb3vY9w8DhEr+A= dependencies: web3-core "1.0.0-beta.34" web3-core-method "1.0.0-beta.34" @@ -7394,7 +6408,6 @@ web3-shh@1.0.0-beta.34: web3-utils@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.34.tgz#9411fc39aaef39ca4e06169f762297d9ff020970" - integrity sha1-lBH8OarvOcpOBhafdiKX2f8CCXA= dependencies: bn.js "4.11.6" eth-lib "0.1.27" @@ -7407,7 +6420,6 @@ web3-utils@1.0.0-beta.34: web3@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/web3/-/web3-0.19.1.tgz#e763d5b1107c4bc24abd4f8cbee1ba3659e6eb31" - integrity sha1-52PVsRB8S8JKvU+MvuG6Nlnm6zE= dependencies: bignumber.js "^4.0.2" crypto-js "^3.1.4" @@ -7418,7 +6430,6 @@ web3@0.19.1: web3@0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.2.tgz#c54dac5fc0e377399c04c1a6ecbb12e4513278d6" - integrity sha1-xU2sX8DjdzmcBMGm7LsS5FEyeNY= dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7429,7 +6440,6 @@ web3@0.20.2: web3@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.34.tgz#347e561b784098cb5563315f490479a1d91f2ab1" - integrity sha1-NH5WG3hAmMtVYzFfSQR5odkfKrE= dependencies: web3-bzz "1.0.0-beta.34" web3-core "1.0.0-beta.34" @@ -7442,7 +6452,6 @@ web3@1.0.0-beta.34: web3@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" - integrity sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js#master" crypto-js "^3.1.4" @@ -7452,7 +6461,6 @@ web3@^0.16.0: web3@^0.18.2, web3@^0.18.4: version "0.18.4" resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" - integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0= dependencies: bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" crypto-js "^3.1.4" @@ -7463,7 +6471,6 @@ web3@^0.18.2, web3@^0.18.4: web3@^0.20.6: version "0.20.7" resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.7.tgz#1605e6d81399ed6f85a471a4f3da0c8be57df2f7" - integrity sha512-VU6/DSUX93d1fCzBz7WP/SGCQizO1rKZi4Px9j/3yRyfssHyFcZamMw2/sj4E8TlfMXONvZLoforR8B4bRoyTQ== dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -7474,7 +6481,6 @@ web3@^0.20.6: websocket@^1.0.28: version "1.0.28" resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.28.tgz#9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3" - integrity sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA== dependencies: debug "^2.2.0" nan "^2.11.0" @@ -7493,41 +6499,34 @@ websocket@^1.0.28: whatwg-fetch@>=0.10.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@^1.1.1, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= winston@2.1.x: version "2.1.1" resolved "https://registry.yarnpkg.com/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" - integrity sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4= dependencies: async "~1.0.0" colors "1.0.x" @@ -7540,7 +6539,6 @@ winston@2.1.x: winston@^2.3.1: version "2.4.4" resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.4.tgz#a01e4d1d0a103cf4eada6fc1f886b3110d71c34b" - integrity sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q== dependencies: async "~1.0.0" colors "1.0.x" @@ -7552,17 +6550,14 @@ winston@^2.3.1: wordwrap@^1.0.0, wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -7570,19 +6565,16 @@ wrap-ansi@^2.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= dependencies: mkdirp "^0.5.1" ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" @@ -7591,14 +6583,12 @@ ws@^3.0.0: xhr-request-promise@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" - integrity sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0= dependencies: xhr-request "^1.0.1" xhr-request@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== dependencies: buffer-to-arraybuffer "^0.0.5" object-assign "^4.1.1" @@ -7611,19 +6601,16 @@ xhr-request@^1.0.1: xhr2-cookies@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= dependencies: cookiejar "^2.1.1" xhr2@*, xhr2@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" - integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8= xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: version "2.5.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" - integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== dependencies: global "~4.3.0" is-function "^1.0.1" @@ -7633,54 +6620,44 @@ xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: xml@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" - integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= xmlhttprequest@*, xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= xregexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" - integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= dependencies: object-keys "~0.4.0" y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= dependencies: camelcase "^3.0.0" lodash.assign "^4.0.6" @@ -7688,21 +6665,18 @@ yargs-parser@^2.4.1: yargs-parser@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== dependencies: camelcase "^4.1.0" yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= dependencies: camelcase "^4.1.0" yargs@11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -7720,7 +6694,6 @@ yargs@11.1.0: yargs@^10.0.3: version "10.1.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" - integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -7738,7 +6711,6 @@ yargs@^10.0.3: yargs@^4.6.0, yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= dependencies: cliui "^3.2.0" decamelize "^1.1.1" @@ -7758,7 +6730,6 @@ yargs@^4.6.0, yargs@^4.7.1: yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" From 95e7b2cf2686ef6d420ed1c663cb16dde8a48fec Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 26 Mar 2019 19:34:44 +0530 Subject: [PATCH 569/582] add test cases for the major issue --- test/y_volume_restriction_tm.js | 148 +++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 1 deletion(-) diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 7074d1afa..f536ac8da 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -72,6 +72,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tempArray = new Array(); let tempArray3 = new Array(); let tempArrayGlobal = new Array(); + let delegateArray = new Array(); // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -1359,7 +1360,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(data[2].toNumber(), 5); let dataRestriction = await I_VolumeRestrictionTM.defaultRestriction.call(); console.log(` - *** Add Individual restriction data *** + *** Add Default restriction data *** Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(18)).toNumber()} StartTime : ${dataRestriction[1].toNumber()} Rolling Period in days : ${dataRestriction[2].toNumber()} @@ -1633,6 +1634,151 @@ contract('VolumeRestrictionTransferManager', accounts => { }); + describe("Test the major issue from the audit", async() => { + + it("Should add the individual restriction for the delegate 2 address", async() => { + await I_GeneralTransferManager.modifyWhitelist( + account_delegate2, + latestTime(), + latestTime(), + latestTime() + duration.days(30), + true, + { + from: token_owner + } + ); + + await I_SecurityToken.mint(account_delegate2, web3.utils.toWei("20"), { from: token_owner }); + + await I_VolumeRestrictionTM.addIndividualRestriction( + account_delegate2, + web3.utils.toWei("12"), + latestTime() + duration.minutes(1), + 2, + latestTime() + duration.days(5.5), + 0, + { + from: token_owner + } + ); + assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_delegate2))[2].toNumber(), 2); + + let data = await I_VolumeRestrictionTM.getRestrictedData.call(); + console.log(data[0].length); + await printRestrictedData(data); + + // Add default restriction as well + + await I_VolumeRestrictionTM.removeDefaultRestriction({from: token_owner}); + await I_VolumeRestrictionTM.addDefaultRestriction( + web3.utils.toWei("5"), + latestTime() + duration.minutes(1), + 5, + latestTime() + duration.days(10), + 0, + { + from: token_owner + } + ); + + data = await I_VolumeRestrictionTM.defaultRestriction.call(); + assert.equal(data[0].toNumber(), web3.utils.toWei("5")); + assert.equal(data[2].toNumber(), 5); + let dataRestriction = await I_VolumeRestrictionTM.defaultRestriction.call(); + console.log(` + *** Add Default restriction data *** + Allowed Tokens: ${dataRestriction[0].dividedBy(new BigNumber(10).pow(18)).toNumber()} + StartTime : ${dataRestriction[1].toNumber()} + Rolling Period in days : ${dataRestriction[2].toNumber()} + EndTime : ${dataRestriction[3].toNumber()} + Type of Restriction: ${dataRestriction[4].toNumber()} + `); + }); + + it("Should transact with delegate address 2", async() => { + await increaseTime(duration.minutes(2)); + + let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_delegate2))[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.individualRestriction.call(account_delegate2))[2].toNumber(); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("6"), {from: account_delegate2}); + delegateArray.push(6); + + console.log(`Print the default bucket details`); + let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_delegate2); + await print(data, account_delegate2); + assert.equal(data[0].toNumber(), 0); + assert.equal(data[1].toNumber(), 0); + + console.log(`Print the individual bucket details`); + data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_delegate2); + await print(data, account_delegate2); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_delegate2, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[1].dividedBy(new BigNumber(10).pow(18)).toNumber(), await calculateSum(rollingPeriod, delegateArray)); + assert.equal(data[2].toNumber(), 0); + assert.equal(amt, 6); + + // Sell more tokens + await increaseTime(duration.days(5.1)); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("9"), {from: account_delegate2}); + + delegateArray.push(9); + + console.log(`Print the default bucket details`); + let dataDefault = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_delegate2); + await print(dataDefault, account_delegate2); + assert.equal(dataDefault[0].toNumber(), 0); + assert.equal(dataDefault[1].toNumber(), 0); + console.log(`Print the individual bucket details`); + let dataIndividual = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_delegate2); + await print(dataIndividual, account_delegate2); + + // get the trade amount using the timestamp + let amtTraded = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_delegate2, dataIndividual[0])) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + // Verify the storage changes + assert.equal(dataIndividual[0].toNumber(), startTime + duration.days(dataIndividual[2].toNumber())); + assert.equal(dataIndividual[2].toNumber(), 5); + assert.equal(amtTraded, 9); + }); + + it("Should transact under the default restriction and check whether the bucket data affected or not", async() => { + await increaseTime(duration.days(0.6)); + let individualStartTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_delegate2))[1].toNumber(); + let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); + + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), {from: account_delegate2}); + + console.log(`Print the individual bucket details`); + let dataIndividual = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_delegate2); + await print(dataIndividual, account_delegate2); + + // Verify the storage changes + assert.equal(dataIndividual[0].toNumber(), individualStartTime + duration.days(dataIndividual[2].toNumber())); + assert.equal(dataIndividual[2].toNumber(), 5); + + console.log(`Print the default bucket details`); + let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_delegate2); + await print(data, account_delegate2); + + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_delegate2, data[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + // Verify the storage changes + assert.equal(data[0].toNumber(), dataIndividual[0].toNumber()); + assert.equal(data[2].toNumber(), 0); + assert.equal(amt, 14); + }) + }) + describe("VolumeRestriction Transfer Manager Factory test cases", async () => { it("Should get the exact details of the factory", async () => { From de6decc7ef5e1ecc8277a7be9d7b27218e73a759 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 26 Mar 2019 23:32:53 +0530 Subject: [PATCH 570/582] test fix --- test/y_volume_restriction_tm.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index f536ac8da..e0ee12fd9 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -1773,9 +1773,9 @@ contract('VolumeRestrictionTransferManager', accounts => { let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_delegate2, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes - assert.equal(data[0].toNumber(), dataIndividual[0].toNumber()); - assert.equal(data[2].toNumber(), 0); - assert.equal(amt, 14); + assert.equal(data[0].toNumber(), dataIndividual[0].toNumber() + 1); + assert.equal(data[2].toNumber(), 5); + assert.equal(amt, 5); }) }) From 1191f3839e2e627c7b448bcc78832c46b06ed92d Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 27 Mar 2019 10:19:24 +0530 Subject: [PATCH 571/582] improve the test run --- test/y_volume_restriction_tm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index e0ee12fd9..0b73b68ff 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -1773,7 +1773,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_delegate2, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes - assert.equal(data[0].toNumber(), dataIndividual[0].toNumber() + 1); + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); assert.equal(data[2].toNumber(), 5); assert.equal(amt, 5); }) From 60b2aa057c8d93623caf3937f2b8370553ed0ae7 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 28 Mar 2019 16:58:57 +0530 Subject: [PATCH 572/582] add the startTime == 0 check --- .../TransferManager/VolumeRestrictionTM.sol | 74 +++++++++++-------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index fdb691223..7a2e9ef58 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -193,14 +193,15 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { internal { require(_holder != address(0) && exemptIndex[_holder] == 0, "Invalid address"); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); + uint256 startTime = _getValidStartTime(_startTime); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); if (individualRestriction[_holder].endTime != 0) { _removeIndividualRestriction(_holder); } individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -209,7 +210,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddIndividualRestriction( _holder, _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -252,14 +253,15 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { RestrictionType _restrictionType ) internal - { - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now, false); + { + uint256 startTime = _getValidStartTime(_startTime); + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, now, false); if (individualDailyRestriction[_holder].endTime != 0) { _removeIndividualDailyRestriction(_holder); } individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -268,7 +270,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddIndividualDailyRestriction( _holder, _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -356,18 +358,19 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); + { + uint256 startTime = _getValidStartTime(_startTime); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); defaultRestriction = VolumeRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType ); emit AddDefaultRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -389,18 +392,19 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now, false); + { + uint256 startTime = _getValidStartTime(_startTime); + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, now, false); defaultDailyRestriction = VolumeRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType ); emit AddDefaultDailyRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -525,10 +529,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { internal { _isAllowedToModify(individualRestriction[_holder].startTime); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); + uint256 startTime = _getValidStartTime(_startTime); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -536,7 +541,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit ModifyIndividualRestriction( _holder, _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -581,14 +586,15 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { RestrictionType _restrictionType ) internal - { - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, + { + uint256 startTime = _getValidStartTime(_startTime); + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, (individualDailyRestriction[_holder].startTime <= now ? individualDailyRestriction[_holder].startTime : now), true ); individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -596,7 +602,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit ModifyIndividualDailyRestriction( _holder, _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -684,19 +690,20 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { + { _isAllowedToModify(defaultRestriction.startTime); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); + uint256 startTime = _getValidStartTime(_startTime); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); defaultRestriction = VolumeRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType ); emit ModifyDefaultRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -720,23 +727,24 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { + { + uint256 startTime = _getValidStartTime(_startTime); // If old startTime is already passed then new startTime should be greater than or equal to the // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, (defaultDailyRestriction.startTime <= now ? defaultDailyRestriction.startTime : now), true ); defaultDailyRestriction = VolumeRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType ); emit ModifyDefaultDailyRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -1017,6 +1025,12 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_startTime > now, "Not Allowed to modify after startTime passed"); } + function _getValidStartTime(uint256 _startTime) internal view returns(uint256) { + if (_startTime == 0) + _startTime = now + 1; + return _startTime; + } + /** * @notice Use to get the bucket details for a given address * @param _user Address of the token holder for whom the bucket details has queried From 031f5dd9e3b403b2604f805e8f38893a9ffdadde Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 29 Mar 2019 15:37:59 +0530 Subject: [PATCH 573/582] resolve the edge case when the investors restriction changes --- contracts/libraries/VolumeRestrictionLib.sol | 56 ++++++++ .../TransferManager/VolumeRestrictionTM.sol | 122 +++++++++++------- .../storage/VolumeRestrictionTMStorage.sol | 2 + test/y_volume_restriction_tm.js | 90 +++++++++++-- 4 files changed, 212 insertions(+), 58 deletions(-) diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol index 7129eecca..2bc38ef51 100644 --- a/contracts/libraries/VolumeRestrictionLib.sol +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -89,5 +89,61 @@ library VolumeRestrictionLib { return _callFrom; } + function _isValidAmountAfterRestrictionChanges( + uint256 _amountTradedLastDay, + uint256 _amount, + uint256 _sumOfLastPeriod, + uint256 _allowedAmount, + uint256 _lastTradedTimestamp + ) + internal + view + returns(bool) + { + if (BokkyPooBahsDateTimeLibrary.diffSeconds(_lastTradedTimestamp, now) < 86400) { + (uint256 lastTxYear, uint256 lastTxMonth, uint256 lastTxDay) = BokkyPooBahsDateTimeLibrary.timestampToDate(_lastTradedTimestamp); + (uint256 currentTxYear, uint256 currentTxMonth, uint256 currentTxDay) = BokkyPooBahsDateTimeLibrary.timestampToDate(now); + // This if statement is to check whether the last transaction timestamp (of `individualRestriction[_from]` + // when `_isDefault` is true or defaultRestriction when `_isDefault` is false) is comes within the same day of the current + // transaction timestamp or not. + if (lastTxYear == currentTxYear && lastTxMonth == currentTxMonth && lastTxDay == currentTxDay) { + if ((_sumOfLastPeriod.add(_amount)).add(_amountTradedLastDay) > _allowedAmount) + return false; + } + } + return true; + } + + function getAllowedAmount( + VolumeRestrictionTMStorage.RestrictionType _typeOfRestriction, + uint256 _allowedTokens, + address _securityToken + ) + public + view + returns(uint256 allowedAmount) + { + if (_typeOfRestriction == VolumeRestrictionTMStorage.RestrictionType.Percentage) { + allowedAmount = (_allowedTokens.mul(ISecurityToken(_securityToken).totalSupply())) / uint256(10) ** 18; + } else { + allowedAmount = _allowedTokens; + } + } + + function _getBucketDetails(VolumeRestrictionTMStorage.BucketDetails storage _bucket) internal view returns( + uint256, + uint256, + uint256, + uint256, + uint256 + ) { + return( + _bucket.lastTradedDayTime, + _bucket.sumOfLastPeriod, + _bucket.daysCovered, + _bucket.dailyLastTradedDayTime, + _bucket.lastTradedTimestamp + ); + } } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 7a2e9ef58..ea009b94c 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -191,7 +191,12 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { RestrictionType _restrictionType ) internal - { + { + // It will help to reduce the chances of transaction failure (Specially when the issuer + // wants to set the startTime near to the current block.timestamp) and minting delayed because + // of the gas fee or network congestion that lead to the process block timestamp may grater + // than the given startTime. + _startTime = _getValidStartTime(_startTime); require(_holder != address(0) && exemptIndex[_holder] == 0, "Invalid address"); uint256 startTime = _getValidStartTime(_startTime); _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); @@ -759,7 +764,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { bool _isTransfer, address _from, uint256 _amount, - BucketDetails storage _bucketDetails, + BucketDetails memory _bucketDetails, VolumeRestriction memory _restriction, bool _isDefault ) @@ -767,10 +772,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { returns (Result) { // using the variable to avoid stack too deep error - VolumeRestriction memory dailyRestriction = individualDailyRestriction[_from]; - if (_isDefault) - dailyRestriction = defaultDailyRestriction; - + VolumeRestriction memory dailyRestriction = _isDefault ? defaultDailyRestriction :individualDailyRestriction[_from]; uint256 daysCovered = _restriction.rollingPeriodInDays; uint256 fromTimestamp = 0; uint256 sumOfLastPeriod = 0; @@ -798,7 +800,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { _isDefault ); // validation of the transaction amount - if (!_checkValidAmountToTransact(sumOfLastPeriod, _amount, _restriction)) { + if ( + !_checkValidAmountToTransact( + _isDefault, _from, sumOfLastPeriod, _amount, _restriction.typeOfRestriction, _restriction.allowedTokens + ) + ) { allowedDefault = false; } } @@ -819,11 +825,60 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { return ((allowedDaily && allowedDefault) == true ? Result.NA : Result.INVALID); } + /** + * @notice The function is used to check specific edge case where the user restriction type change from + * default to individual or vice versa. It will return true when last transaction traded by the user + * and the current txn timestamp lies in the same day. + */ + function _isValidAmountAfterRestrictionChanges( + bool _isDefault, + address _from, + uint256 _amount, + uint256 _sumOfLastPeriod, + uint256 _allowedAmount + ) + internal + view + returns(bool) + { + BucketDetails storage bucketDetails = _isDefault ? userToBucket[_from] : defaultUserToBucket[_from]; + uint256 amountTradedLastDay = _isDefault ? bucket[_from][bucketDetails.lastTradedDayTime]: defaultBucket[_from][bucketDetails.lastTradedDayTime]; + return VolumeRestrictionLib._isValidAmountAfterRestrictionChanges( + amountTradedLastDay, + _amount, + _sumOfLastPeriod, + _allowedAmount, + bucketDetails.lastTradedTimestamp + ); + } + + function _checkValidAmountToTransact( + bool _isDefault, + address _from, + uint256 _sumOfLastPeriod, + uint256 _amountToTransact, + RestrictionType _typeOfRestriction, + uint256 _allowedTokens + ) + internal + view + returns (bool) + { + uint256 allowedAmount = VolumeRestrictionLib.getAllowedAmount( + _typeOfRestriction, + _allowedTokens, + securityToken + ); + // Validation on the amount to transact + bool allowed = allowedAmount >= _sumOfLastPeriod.add(_amountToTransact); + return (allowed && _isValidAmountAfterRestrictionChanges(_isDefault, _from, _amountToTransact, _sumOfLastPeriod, allowedAmount)); + } + function _dailyTxCheck( address from, uint256 amount, uint256 dailyLastTradedDayTime, - VolumeRestriction restriction, + VolumeRestriction memory restriction, bool isDefault ) internal @@ -834,8 +889,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // the total amount get traded on a particular day (~ _fromTime) if ( now <= restriction.endTime && now >= restriction.startTime) { uint256 txSumOfDay = 0; + // This if condition will be executed when the individual daily restriction executed first time if (dailyLastTradedDayTime == 0 || dailyLastTradedDayTime < restriction.startTime) - // This if condition will be executed when the individual daily restriction executed first time dailyLastTradedDayTime = restriction.startTime.add(BokkyPooBahsDateTimeLibrary.diffDays(restriction.startTime, now).mul(1 days)); else if (now.sub(dailyLastTradedDayTime) >= 1 days) dailyLastTradedDayTime = dailyLastTradedDayTime.add(BokkyPooBahsDateTimeLibrary.diffDays(dailyLastTradedDayTime, now).mul(1 days)); @@ -844,7 +899,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { txSumOfDay = defaultBucket[from][dailyLastTradedDayTime]; else txSumOfDay = bucket[from][dailyLastTradedDayTime]; - return (_checkValidAmountToTransact(txSumOfDay, amount, restriction), dailyLastTradedDayTime); + return (_checkValidAmountToTransact(isDefault, from, txSumOfDay, amount, restriction.typeOfRestriction, restriction.allowedTokens), dailyLastTradedDayTime); } return (true, dailyLastTradedDayTime); } @@ -899,25 +954,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { return (sumOfLastPeriod, _fromTime, counter); } - function _checkValidAmountToTransact( - uint256 _sumOfLastPeriod, - uint256 _amountToTransact, - VolumeRestriction _restriction - ) - internal - view - returns (bool) - { - uint256 _allowedAmount = 0; - if (_restriction.typeOfRestriction == RestrictionType.Percentage) { - _allowedAmount = (_restriction.allowedTokens.mul(ISecurityToken(securityToken).totalSupply())) / uint256(10) ** 18; - } else { - _allowedAmount = _restriction.allowedTokens; - } - // Validation on the amount to transact - return (_allowedAmount >= _sumOfLastPeriod.add(_amountToTransact)); - } - function _updateStorage( address _from, uint256 _amount, @@ -966,6 +1002,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { if (details.daysCovered != _daysCovered) { details.daysCovered = _daysCovered; } + // Assigning the latest transaction timestamp + details.lastTradedTimestamp = now; if (_amount != 0) { if (_lastTradedDayTime !=0) { details.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); @@ -999,18 +1037,18 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { pure { require(_restrictionType == RestrictionType.Fixed || _restrictionType == RestrictionType.Percentage, - "Invalid restriction type" + "Invalid type" ); if (isModifyDaily) require(_startTime >= _earliestStartTime, "Invalid startTime"); else require(_startTime > _earliestStartTime, "Invalid startTime"); if (_restrictionType == RestrictionType.Fixed) { - require(_allowedTokens > 0, "Invalid tokens value"); + require(_allowedTokens > 0, "Invalid value"); } else { require( _allowedTokens > 0 && _allowedTokens <= 100 * 10 ** 16, - "Invalid tokens value" + "Invalid value" ); } // Maximum limit for the rollingPeriod is 365 days @@ -1022,7 +1060,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } function _isAllowedToModify(uint256 _startTime) internal view { - require(_startTime > now, "Not Allowed to modify after startTime passed"); + require(_startTime > now, "Start time already passed"); } function _getValidStartTime(uint256 _startTime) internal view returns(uint256) { @@ -1039,13 +1077,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 days covered * @return uint256 24h lastTradedDayTime */ - function getIndividualBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { - return( - userToBucket[_user].lastTradedDayTime, - userToBucket[_user].sumOfLastPeriod, - userToBucket[_user].daysCovered, - userToBucket[_user].dailyLastTradedDayTime - ); + function getIndividualBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256, uint256) { + return VolumeRestrictionLib._getBucketDetails(userToBucket[_user]); } /** @@ -1056,13 +1089,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 days covered * @return uint256 24h lastTradedDayTime */ - function getDefaultBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256) { - return( - defaultUserToBucket[_user].lastTradedDayTime, - defaultUserToBucket[_user].sumOfLastPeriod, - defaultUserToBucket[_user].daysCovered, - defaultUserToBucket[_user].dailyLastTradedDayTime - ); + function getDefaultBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256, uint256) { + return VolumeRestrictionLib._getBucketDetails(defaultUserToBucket[_user]); } /** diff --git a/contracts/storage/VolumeRestrictionTMStorage.sol b/contracts/storage/VolumeRestrictionTMStorage.sol index b8d62c988..bf6555ac9 100644 --- a/contracts/storage/VolumeRestrictionTMStorage.sol +++ b/contracts/storage/VolumeRestrictionTMStorage.sol @@ -39,6 +39,8 @@ contract VolumeRestrictionTMStorage { uint256 sumOfLastPeriod; // It is the sum of transacted amount within the last rollingPeriodDays uint256 daysCovered; // No of days covered till (from the startTime of VolumeRestriction) uint256 dailyLastTradedDayTime; + uint256 lastTradedTimestamp; // It is the timestamp at which last transaction get executed + uint256 lastTradedAmount; // It is the timestamp at which last transaction get executed } // Global restriction that applies to all token holders diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 0b73b68ff..97e8feda0 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -87,6 +87,7 @@ contract('VolumeRestrictionTransferManager', accounts => { .dividedBy(new BigNumber(10).pow(18)).toNumber()} Individual Total Trade on daily latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[3])) .dividedBy(new BigNumber(10).pow(18)).toNumber()} + Last Transaction time in UTC: ${(new Date((data[4].toNumber()) * 1000 )).toUTCString()} `) } @@ -115,6 +116,14 @@ contract('VolumeRestrictionTransferManager', accounts => { return sum; } + async function setTime() { + let currentTime = latestTime(); + let currentHour = (new Date(currentTime * 1000)).getUTCHours(); + console.log(`Earlier time ${new Date(latestTime() * 1000).toUTCString()}`); + await increaseTime(duration.hours(24 - currentHour)); + console.log(`Current time ${new Date(latestTime() * 1000).toUTCString()}`); + } + before(async () => { // Accounts setup account_polymath = accounts[0]; @@ -1634,8 +1643,8 @@ contract('VolumeRestrictionTransferManager', accounts => { }); - describe("Test the major issue from the audit", async() => { - + describe("Test the major issue from the audit ( Possible accounting corruption between individualRestriction​ and ​defaultRestriction)", async() => { + it("Should add the individual restriction for the delegate 2 address", async() => { await I_GeneralTransferManager.modifyWhitelist( account_delegate2, @@ -1648,7 +1657,9 @@ contract('VolumeRestrictionTransferManager', accounts => { } ); - await I_SecurityToken.mint(account_delegate2, web3.utils.toWei("20"), { from: token_owner }); + await I_SecurityToken.mint(account_delegate2, web3.utils.toWei("50"), { from: token_owner }); + // Use to set the time to start of the day 0:00 to test the edge case properly + await setTime(); await I_VolumeRestrictionTM.addIndividualRestriction( account_delegate2, @@ -1664,7 +1675,6 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_delegate2))[2].toNumber(), 2); let data = await I_VolumeRestrictionTM.getRestrictedData.call(); - console.log(data[0].length); await printRestrictedData(data); // Add default restriction as well @@ -1674,7 +1684,7 @@ contract('VolumeRestrictionTransferManager', accounts => { web3.utils.toWei("5"), latestTime() + duration.minutes(1), 5, - latestTime() + duration.days(10), + latestTime() + duration.days(20), 0, { from: token_owner @@ -1748,18 +1758,27 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(amtTraded, 9); }); - it("Should transact under the default restriction and check whether the bucket data affected or not", async() => { + it("Should fail to transact -- edge case when user restriction changes and do the transfer on the same day", async() => { await increaseTime(duration.days(0.6)); + //sell tokens upto the limit + await catchRevert( + I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), {from: account_delegate2}) + ); + }); + + it("Should transact under the default restriction unaffected from the edge case", async() => { + await increaseTime(duration.days(0.5)); let individualStartTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_delegate2))[1].toNumber(); let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); //sell tokens upto the limit - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("5"), {from: account_delegate2}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("4"), {from: account_delegate2}); console.log(`Print the individual bucket details`); let dataIndividual = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_delegate2); await print(dataIndividual, account_delegate2); + console.log(dataIndividual[4].toString()); // Verify the storage changes assert.equal(dataIndividual[0].toNumber(), individualStartTime + duration.days(dataIndividual[2].toNumber())); @@ -1768,16 +1787,65 @@ contract('VolumeRestrictionTransferManager', accounts => { console.log(`Print the default bucket details`); let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_delegate2); await print(data, account_delegate2); + console.log(data[4].toString()); // get the trade amount using the timestamp let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_delegate2, data[0].toNumber())) .dividedBy(new BigNumber(10).pow(18)).toNumber(); // Verify the storage changes assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); - assert.equal(data[2].toNumber(), 5); - assert.equal(amt, 5); - }) - }) + assert.equal(data[2].toNumber(), 6); + assert.equal(amt, 4); + }); + + it("Should check whether user is able to transfer when amount is less than the restriction limit (when restriction change)", async() => { + + await I_VolumeRestrictionTM.addIndividualRestriction( + account_delegate2, + web3.utils.toWei("7"), + latestTime() + duration.minutes(1), + 1, + latestTime() + duration.days(2), + 0, + { + from: token_owner + } + ); + assert.equal((await I_VolumeRestrictionTM.individualRestriction.call(account_delegate2))[2].toNumber(), 1); + let individualStartTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_delegate2))[1].toNumber(); + let startTime = (await I_VolumeRestrictionTM.defaultRestriction.call())[1].toNumber(); + let rollingPeriod = (await I_VolumeRestrictionTM.defaultRestriction.call())[2].toNumber(); + + await increaseTime(duration.minutes(2)); + + // sell tokens when user restriction changes from the default restriction to individual restriction + await catchRevert (I_SecurityToken.transfer(account_investor1, web3.utils.toWei("5")), {from: account_delegate2}); + + // allow to transact when the day limit is with in the restriction. default allow to transact maximum 5 tokens within + // a given rolling period. 4 tokens are already sold here user trying to sell 1 more token on the same day + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1"), {from: account_delegate2}); + + console.log(`Print the individual bucket details`); + let dataIndividual = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_delegate2); + await print(dataIndividual, account_delegate2); + + // Verify the storage changes + assert.equal(dataIndividual[0].toNumber(), individualStartTime + duration.days(dataIndividual[2].toNumber())); + assert.equal(dataIndividual[2].toNumber(), 0); + // get the trade amount using the timestamp + let amt = (await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_delegate2, dataIndividual[0].toNumber())) + .dividedBy(new BigNumber(10).pow(18)).toNumber(); + assert.equal(amt, 1); + + console.log(`Print the default bucket details`); + let data = await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_delegate2); + await print(data, account_delegate2); + + // Verify the storage changes + assert.equal(data[0].toNumber(), startTime + duration.days(data[2].toNumber())); + assert.equal(data[2].toNumber(), 6); + }); + }); describe("VolumeRestriction Transfer Manager Factory test cases", async () => { From 36723052ac4b79c097f418e18cd834b9a4135dca Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 29 Mar 2019 16:03:42 +0530 Subject: [PATCH 574/582] Minor change --- .../TransferManager/VolumeRestrictionTM.sol | 59 +++++++++---------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index ea009b94c..1c0cb6792 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -118,13 +118,13 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Checking the individual restriction if the `_from` comes in the individual category if ((individualRestriction[_from].endTime >= now && individualRestriction[_from].startTime <= now) || (individualDailyRestriction[_from].endTime >= now && individualDailyRestriction[_from].startTime <= now)) { - + return _restrictionCheck(_isTransfer, _from, _amount, userToBucket[_from], individualRestriction[_from], false); - + // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically } else if ((defaultRestriction.endTime >= now && defaultRestriction.startTime <= now) || (defaultDailyRestriction.endTime >= now && defaultDailyRestriction.startTime <= now)) { - + return _restrictionCheck(_isTransfer, _from, _amount, defaultUserToBucket[_from], defaultRestriction, true); } } @@ -191,22 +191,21 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { RestrictionType _restrictionType ) internal - { + { // It will help to reduce the chances of transaction failure (Specially when the issuer // wants to set the startTime near to the current block.timestamp) and minting delayed because // of the gas fee or network congestion that lead to the process block timestamp may grater - // than the given startTime. + // than the given startTime. _startTime = _getValidStartTime(_startTime); require(_holder != address(0) && exemptIndex[_holder] == 0, "Invalid address"); - uint256 startTime = _getValidStartTime(_startTime); - _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); if (individualRestriction[_holder].endTime != 0) { _removeIndividualRestriction(_holder); } individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -215,7 +214,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddIndividualRestriction( _holder, _allowedTokens, - startTime, + _startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -258,15 +257,15 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { RestrictionType _restrictionType ) internal - { - uint256 startTime = _getValidStartTime(_startTime); - _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, now, false); + { + _startTime = _getValidStartTime(_startTime); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now, false); if (individualDailyRestriction[_holder].endTime != 0) { _removeIndividualDailyRestriction(_holder); } individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, - startTime, + _startTime, 1, _endTime, _restrictionType @@ -275,7 +274,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddIndividualDailyRestriction( _holder, _allowedTokens, - startTime, + _startTime, 1, _endTime, _restrictionType @@ -363,7 +362,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { + { uint256 startTime = _getValidStartTime(_startTime); _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); defaultRestriction = VolumeRestriction( @@ -397,7 +396,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { + { uint256 startTime = _getValidStartTime(_startTime); _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, now, false); defaultDailyRestriction = VolumeRestriction( @@ -591,7 +590,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { RestrictionType _restrictionType ) internal - { + { uint256 startTime = _getValidStartTime(_startTime); _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, (individualDailyRestriction[_holder].startTime <= now ? individualDailyRestriction[_holder].startTime : now), @@ -695,7 +694,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { + { _isAllowedToModify(defaultRestriction.startTime); uint256 startTime = _getValidStartTime(_startTime); _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); @@ -732,7 +731,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) external withPerm(ADMIN) - { + { uint256 startTime = _getValidStartTime(_startTime); // If old startTime is already passed then new startTime should be greater than or equal to the // old startTime otherwise any past startTime can be allowed in compare to earlier startTime. @@ -767,9 +766,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { BucketDetails memory _bucketDetails, VolumeRestriction memory _restriction, bool _isDefault - ) + ) internal - returns (Result) + returns (Result) { // using the variable to avoid stack too deep error VolumeRestriction memory dailyRestriction = _isDefault ? defaultDailyRestriction :individualDailyRestriction[_from]; @@ -808,7 +807,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { allowedDefault = false; } } - + (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, _bucketDetails.dailyLastTradedDayTime, dailyRestriction, _isDefault); if (_isTransfer) { @@ -827,7 +826,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice The function is used to check specific edge case where the user restriction type change from - * default to individual or vice versa. It will return true when last transaction traded by the user + * default to individual or vice versa. It will return true when last transaction traded by the user * and the current txn timestamp lies in the same day. */ function _isValidAmountAfterRestrictionChanges( @@ -836,9 +835,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _amount, uint256 _sumOfLastPeriod, uint256 _allowedAmount - ) + ) internal - view + view returns(bool) { BucketDetails storage bucketDetails = _isDefault ? userToBucket[_from] : defaultUserToBucket[_from]; @@ -895,7 +894,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { else if (now.sub(dailyLastTradedDayTime) >= 1 days) dailyLastTradedDayTime = dailyLastTradedDayTime.add(BokkyPooBahsDateTimeLibrary.diffDays(dailyLastTradedDayTime, now).mul(1 days)); // Assgining total sum traded on dailyLastTradedDayTime timestamp - if (isDefault) + if (isDefault) txSumOfDay = defaultBucket[from][dailyLastTradedDayTime]; else txSumOfDay = bucket[from][dailyLastTradedDayTime]; @@ -1010,16 +1009,16 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // Increasing the total amount of the day by `_amount` if (isDefault) defaultBucket[_from][_lastTradedDayTime] = defaultBucket[_from][_lastTradedDayTime].add(_amount); - else + else bucket[_from][_lastTradedDayTime] = bucket[_from][_lastTradedDayTime].add(_amount); } if ((_dailyLastTradedDayTime != _lastTradedDayTime) && _dailyLastTradedDayTime != 0 && now <= _endTime) { // Increasing the total amount of the day by `_amount` if (isDefault) defaultBucket[_from][_dailyLastTradedDayTime] = defaultBucket[_from][_dailyLastTradedDayTime].add(_amount); - else + else bucket[_from][_dailyLastTradedDayTime] = bucket[_from][_dailyLastTradedDayTime].add(_amount); - + } } } @@ -1036,7 +1035,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { internal pure { - require(_restrictionType == RestrictionType.Fixed || _restrictionType == RestrictionType.Percentage, + require(_restrictionType == RestrictionType.Fixed || _restrictionType == RestrictionType.Percentage, "Invalid type" ); if (isModifyDaily) From 6aba6b94aab414ba797574069e1c9556f2ee24b5 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 29 Mar 2019 16:44:06 +0530 Subject: [PATCH 575/582] VRTM size reduction to 24.21KB --- contracts/libraries/VolumeRestrictionLib.sol | 26 ++++---- .../TransferManager/VolumeRestrictionTM.sol | 60 +++++++++---------- 2 files changed, 41 insertions(+), 45 deletions(-) diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol index 2bc38ef51..98c9d4205 100644 --- a/contracts/libraries/VolumeRestrictionLib.sol +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -34,8 +34,8 @@ library VolumeRestrictionLib { VolumeRestrictionTMStorage.RestrictedData storage data, address _holder, VolumeRestrictionTMStorage.TypeOfPeriod _typeOfPeriod - ) - public + ) + public { // Deleting the holder if holder's type of Period is `Both` type otherwise // it will assign the given type `_typeOfPeriod` to the _holder typeOfPeriod @@ -60,10 +60,10 @@ library VolumeRestrictionLib { function addRestrictionData( VolumeRestrictionTMStorage.RestrictedData storage data, address _holder, - VolumeRestrictionTMStorage.TypeOfPeriod _callFrom, + VolumeRestrictionTMStorage.TypeOfPeriod _callFrom, uint256 _endTime - ) - public + ) + public { uint128 index = data.restrictedHolders[_holder].index; if (data.restrictedHolders[_holder].seen == 0) { @@ -78,7 +78,7 @@ library VolumeRestrictionLib { VolumeRestrictionTMStorage.TypeOfPeriod _currentTypeOfPeriod, VolumeRestrictionTMStorage.TypeOfPeriod _callFrom, uint256 _endTime - ) + ) internal pure returns(VolumeRestrictionTMStorage.TypeOfPeriod) @@ -89,14 +89,14 @@ library VolumeRestrictionLib { return _callFrom; } - function _isValidAmountAfterRestrictionChanges( + function isValidAmountAfterRestrictionChanges( uint256 _amountTradedLastDay, uint256 _amount, uint256 _sumOfLastPeriod, uint256 _allowedAmount, uint256 _lastTradedTimestamp ) - internal + public view returns(bool) { @@ -111,16 +111,16 @@ library VolumeRestrictionLib { return false; } } - return true; + return true; } function getAllowedAmount( - VolumeRestrictionTMStorage.RestrictionType _typeOfRestriction, + VolumeRestrictionTMStorage.RestrictionType _typeOfRestriction, uint256 _allowedTokens, address _securityToken - ) - public - view + ) + internal + view returns(uint256 allowedAmount) { if (_typeOfRestriction == VolumeRestrictionTMStorage.RestrictionType.Percentage) { diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 1c0cb6792..5a06b4b2b 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -10,7 +10,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { using SafeMath for uint256; // permission definition - bytes32 public constant ADMIN = "ADMIN"; + bytes32 internal constant ADMIN = "ADMIN"; // Emit when the token holder is added/removed from the exemption list event ChangedExemptWalletList(address indexed _wallet, bool _change); @@ -138,13 +138,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { */ function changeExemptWalletList(address _wallet, bool _change) external withPerm(ADMIN) { require(_wallet != address(0)); - require((exemptIndex[_wallet] == 0) == _change); + uint256 exemptIndexWallet = exemptIndex[_wallet]; + require((exemptIndexWallet == 0) == _change); if (_change) { exemptAddresses.push(_wallet); exemptIndex[_wallet] = exemptAddresses.length; } else { - exemptAddresses[exemptIndex[_wallet] - 1] = exemptAddresses[exemptAddresses.length - 1]; - exemptIndex[exemptAddresses[exemptIndex[_wallet] - 1]] = exemptIndex[_wallet]; + exemptAddresses[exemptIndexWallet - 1] = exemptAddresses[exemptAddresses.length - 1]; + exemptIndex[exemptAddresses[exemptIndexWallet - 1]] = exemptIndexWallet; delete exemptIndex[_wallet]; exemptAddresses.length --; } @@ -196,16 +197,16 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { // wants to set the startTime near to the current block.timestamp) and minting delayed because // of the gas fee or network congestion that lead to the process block timestamp may grater // than the given startTime. - _startTime = _getValidStartTime(_startTime); + uint256 startTime = _getValidStartTime(_startTime); require(_holder != address(0) && exemptIndex[_holder] == 0, "Invalid address"); - _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now, false); if (individualRestriction[_holder].endTime != 0) { _removeIndividualRestriction(_holder); } individualRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -214,7 +215,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddIndividualRestriction( _holder, _allowedTokens, - _startTime, + startTime, _rollingPeriodInDays, _endTime, _restrictionType @@ -258,14 +259,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { ) internal { - _startTime = _getValidStartTime(_startTime); - _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now, false); + uint256 startTime = _getValidStartTime(_startTime); + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, now, false); if (individualDailyRestriction[_holder].endTime != 0) { _removeIndividualDailyRestriction(_holder); } individualDailyRestriction[_holder] = VolumeRestriction( _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -274,7 +275,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { emit AddIndividualDailyRestriction( _holder, _allowedTokens, - _startTime, + startTime, 1, _endTime, _restrictionType @@ -296,7 +297,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _endTimes, RestrictionType[] _restrictionTypes ) - external + public //Marked public to save code size withPerm(ADMIN) { //NB - we duplicate _startTimes below to allow function reuse @@ -329,7 +330,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _endTimes, RestrictionType[] _restrictionTypes ) - public + public //Marked public to save code size withPerm(ADMIN) { VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); @@ -360,7 +361,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _endTime, RestrictionType _restrictionType ) - external + public //Marked public to save code size withPerm(ADMIN) { uint256 startTime = _getValidStartTime(_startTime); @@ -394,7 +395,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _endTime, RestrictionType _restrictionType ) - external + public //Marked public to save code size withPerm(ADMIN) { uint256 startTime = _getValidStartTime(_startTime); @@ -628,7 +629,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _endTimes, RestrictionType[] _restrictionTypes ) - external + public //Marked public to save code size withPerm(ADMIN) { //NB - we duplicate _startTimes below to allow function reuse @@ -661,7 +662,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256[] _endTimes, RestrictionType[] _restrictionTypes ) - public + public //Marked public to save code size withPerm(ADMIN) { VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); @@ -692,7 +693,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _endTime, RestrictionType _restrictionType ) - external + public //Marked public to save code size withPerm(ADMIN) { _isAllowedToModify(defaultRestriction.startTime); @@ -729,7 +730,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { uint256 _endTime, RestrictionType _restrictionType ) - external + public //Marked public to save code size withPerm(ADMIN) { uint256 startTime = _getValidStartTime(_startTime); @@ -842,7 +843,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { { BucketDetails storage bucketDetails = _isDefault ? userToBucket[_from] : defaultUserToBucket[_from]; uint256 amountTradedLastDay = _isDefault ? bucket[_from][bucketDetails.lastTradedDayTime]: defaultBucket[_from][bucketDetails.lastTradedDayTime]; - return VolumeRestrictionLib._isValidAmountAfterRestrictionChanges( + return VolumeRestrictionLib.isValidAmountAfterRestrictionChanges( amountTradedLastDay, _amount, _sumOfLastPeriod, @@ -1042,13 +1043,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { require(_startTime >= _earliestStartTime, "Invalid startTime"); else require(_startTime > _earliestStartTime, "Invalid startTime"); - if (_restrictionType == RestrictionType.Fixed) { - require(_allowedTokens > 0, "Invalid value"); - } else { - require( - _allowedTokens > 0 && _allowedTokens <= 100 * 10 ** 16, - "Invalid value" - ); + require(_allowedTokens > 0, "Invalid value"); + if (_restrictionType != RestrictionType.Fixed) { + require(_allowedTokens <= 100 * 10 ** 16, "Invalid value"); } // Maximum limit for the rollingPeriod is 365 days require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365, "Invalid rollingperiod"); @@ -1059,7 +1056,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } function _isAllowedToModify(uint256 _startTime) internal view { - require(_startTime > now, "Start time already passed"); + require(_startTime > now, "Invalid startTime"); } function _getValidStartTime(uint256 _startTime) internal view returns(uint256) { @@ -1187,10 +1184,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { /** * @notice Returns the permissions flag that are associated with Percentage transfer Manager */ - function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](1); + function getPermissions() public view returns(bytes32[] memory allPermissions) { + allPermissions = new bytes32[](1); allPermissions[0] = ADMIN; - return allPermissions; } } From 5a2231a548d7763b7b7a8145f100469ecde18daa Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 29 Mar 2019 17:19:24 +0530 Subject: [PATCH 576/582] Reduced VRTM size to be under the limit --- contracts/libraries/VolumeRestrictionLib.sol | 53 ------------- .../TransferManager/VolumeRestrictionTM.sol | 76 ++++++++++++++----- 2 files changed, 55 insertions(+), 74 deletions(-) diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol index 98c9d4205..d0d9de06d 100644 --- a/contracts/libraries/VolumeRestrictionLib.sol +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -9,27 +9,6 @@ library VolumeRestrictionLib { using SafeMath for uint256; - function _checkLengthOfArray( - address[] _holders, - uint256[] _allowedTokens, - uint256[] _startTimes, - uint256[] _rollingPeriodInDays, - uint256[] _endTimes, - VolumeRestrictionTMStorage.RestrictionType[] _restrictionTypes - ) - internal - pure - { - require( - _holders.length == _allowedTokens.length && - _allowedTokens.length == _startTimes.length && - _startTimes.length == _rollingPeriodInDays.length && - _rollingPeriodInDays.length == _endTimes.length && - _endTimes.length == _restrictionTypes.length, - "Length mismatch" - ); - } - function deleteHolderFromList( VolumeRestrictionTMStorage.RestrictedData storage data, address _holder, @@ -114,36 +93,4 @@ library VolumeRestrictionLib { return true; } - function getAllowedAmount( - VolumeRestrictionTMStorage.RestrictionType _typeOfRestriction, - uint256 _allowedTokens, - address _securityToken - ) - internal - view - returns(uint256 allowedAmount) - { - if (_typeOfRestriction == VolumeRestrictionTMStorage.RestrictionType.Percentage) { - allowedAmount = (_allowedTokens.mul(ISecurityToken(_securityToken).totalSupply())) / uint256(10) ** 18; - } else { - allowedAmount = _allowedTokens; - } - } - - function _getBucketDetails(VolumeRestrictionTMStorage.BucketDetails storage _bucket) internal view returns( - uint256, - uint256, - uint256, - uint256, - uint256 - ) { - return( - _bucket.lastTradedDayTime, - _bucket.sumOfLastPeriod, - _bucket.daysCovered, - _bucket.dailyLastTradedDayTime, - _bucket.lastTradedTimestamp - ); - } - } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 5a06b4b2b..6ff35e166 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -301,7 +301,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { withPerm(ADMIN) { //NB - we duplicate _startTimes below to allow function reuse - VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); + _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); for (uint256 i = 0; i < _holders.length; i++) { _addIndividualDailyRestriction( _holders[i], @@ -333,7 +333,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { public //Marked public to save code size withPerm(ADMIN) { - VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); for (uint256 i = 0; i < _holders.length; i++) { _addIndividualRestriction( _holders[i], @@ -633,7 +633,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { withPerm(ADMIN) { //NB - we duplicate _startTimes below to allow function reuse - VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); + _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); for (uint256 i = 0; i < _holders.length; i++) { _modifyIndividualDailyRestriction( _holders[i], @@ -665,7 +665,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { public //Marked public to save code size withPerm(ADMIN) { - VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + _checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); for (uint256 i = 0; i < _holders.length; i++) { _modifyIndividualRestriction( _holders[i], @@ -864,11 +864,12 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { view returns (bool) { - uint256 allowedAmount = VolumeRestrictionLib.getAllowedAmount( - _typeOfRestriction, - _allowedTokens, - securityToken - ); + uint256 allowedAmount; + if (_typeOfRestriction == RestrictionType.Percentage) { + allowedAmount = (_allowedTokens.mul(ISecurityToken(securityToken).totalSupply())) / uint256(10) ** 18; + } else { + allowedAmount = _allowedTokens; + } // Validation on the amount to transact bool allowed = allowedAmount >= _sumOfLastPeriod.add(_amountToTransact); return (allowed && _isValidAmountAfterRestrictionChanges(_isDefault, _from, _amountToTransact, _sumOfLastPeriod, allowedAmount)); @@ -919,14 +920,12 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { { uint256 counter = _bucketDetails.daysCovered; uint256 sumOfLastPeriod = _bucketDetails.sumOfLastPeriod; - uint256 i = 0; if (_diffDays >= _rollingPeriodInDays) { // If the difference of days is greater than the rollingPeriod then sumOfLastPeriod will always be zero sumOfLastPeriod = 0; counter = counter.add(_diffDays); } else { - for (i = 0; i < _diffDays; i++) { - counter++; + for (uint256 diffDaysPlusDaysCovered = _diffDays + counter; counter < diffDaysPlusDaysCovered; counter++) { // This condition is to check whether the first rolling period is covered or not // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting // the earlier value at that index @@ -1000,7 +999,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { details.dailyLastTradedDayTime = _dailyLastTradedDayTime; } if (details.daysCovered != _daysCovered) { - details.daysCovered = _daysCovered; + details.daysCovered = _daysCovered; } // Assigning the latest transaction timestamp details.lastTradedTimestamp = now; @@ -1036,27 +1035,25 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { internal pure { - require(_restrictionType == RestrictionType.Fixed || _restrictionType == RestrictionType.Percentage, - "Invalid type" - ); + require(uint256(_restrictionType) < 2); if (isModifyDaily) require(_startTime >= _earliestStartTime, "Invalid startTime"); else require(_startTime > _earliestStartTime, "Invalid startTime"); - require(_allowedTokens > 0, "Invalid value"); + require(_allowedTokens > 0); if (_restrictionType != RestrictionType.Fixed) { require(_allowedTokens <= 100 * 10 ** 16, "Invalid value"); } // Maximum limit for the rollingPeriod is 365 days require(_rollingPeriodDays >= 1 && _rollingPeriodDays <= 365, "Invalid rollingperiod"); require( - BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays && _endTime > _startTime, + BokkyPooBahsDateTimeLibrary.diffDays(_startTime, _endTime) >= _rollingPeriodDays, "Invalid times" ); } function _isAllowedToModify(uint256 _startTime) internal view { - require(_startTime > now, "Invalid startTime"); + require(_startTime > now); } function _getValidStartTime(uint256 _startTime) internal view returns(uint256) { @@ -1074,7 +1071,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 24h lastTradedDayTime */ function getIndividualBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256, uint256) { - return VolumeRestrictionLib._getBucketDetails(userToBucket[_user]); + return _getBucketDetails(userToBucket[_user]); } /** @@ -1086,7 +1083,23 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @return uint256 24h lastTradedDayTime */ function getDefaultBucketDetailsToUser(address _user) external view returns(uint256, uint256, uint256, uint256, uint256) { - return VolumeRestrictionLib._getBucketDetails(defaultUserToBucket[_user]); + return _getBucketDetails(defaultUserToBucket[_user]); + } + + function _getBucketDetails(BucketDetails storage _bucket) internal view returns( + uint256, + uint256, + uint256, + uint256, + uint256 + ) { + return( + _bucket.lastTradedDayTime, + _bucket.sumOfLastPeriod, + _bucket.daysCovered, + _bucket.dailyLastTradedDayTime, + _bucket.lastTradedTimestamp + ); } /** @@ -1181,6 +1194,27 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { typeOfRestriction[index] = restriction.typeOfRestriction; } + function _checkLengthOfArray( + address[] _holders, + uint256[] _allowedTokens, + uint256[] _startTimes, + uint256[] _rollingPeriodInDays, + uint256[] _endTimes, + VolumeRestrictionTMStorage.RestrictionType[] _restrictionTypes + ) + internal + pure + { + require( + _holders.length == _allowedTokens.length && + _allowedTokens.length == _startTimes.length && + _startTimes.length == _rollingPeriodInDays.length && + _rollingPeriodInDays.length == _endTimes.length && + _endTimes.length == _restrictionTypes.length, + "Length mismatch" + ); + } + /** * @notice Returns the permissions flag that are associated with Percentage transfer Manager */ From 7309dcb2c638234897ac07086bb8aea90da881dd Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 29 Mar 2019 18:12:00 +0530 Subject: [PATCH 577/582] add the code comments --- contracts/libraries/VolumeRestrictionLib.sol | 5 ++++- contracts/modules/TransferManager/VolumeRestrictionTM.sol | 8 +++++++- test/y_volume_restriction_tm.js | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol index d0d9de06d..46e1ddb7e 100644 --- a/contracts/libraries/VolumeRestrictionLib.sol +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -78,7 +78,9 @@ library VolumeRestrictionLib { public view returns(bool) - { + { + // if restriction is to check whether the current transaction is performed within the 24 hours + // span after the last transaction performed by the user if (BokkyPooBahsDateTimeLibrary.diffSeconds(_lastTradedTimestamp, now) < 86400) { (uint256 lastTxYear, uint256 lastTxMonth, uint256 lastTxDay) = BokkyPooBahsDateTimeLibrary.timestampToDate(_lastTradedTimestamp); (uint256 currentTxYear, uint256 currentTxMonth, uint256 currentTxDay) = BokkyPooBahsDateTimeLibrary.timestampToDate(now); @@ -86,6 +88,7 @@ library VolumeRestrictionLib { // when `_isDefault` is true or defaultRestriction when `_isDefault` is false) is comes within the same day of the current // transaction timestamp or not. if (lastTxYear == currentTxYear && lastTxMonth == currentTxMonth && lastTxDay == currentTxDay) { + // Not allow to transact more than the current transaction restriction allowed amount if ((_sumOfLastPeriod.add(_amount)).add(_amountTradedLastDay) > _allowedAmount) return false; } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 6ff35e166..b651a4a7a 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -829,6 +829,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @notice The function is used to check specific edge case where the user restriction type change from * default to individual or vice versa. It will return true when last transaction traded by the user * and the current txn timestamp lies in the same day. + * NB - Instead of comparing the current day transaction amount, we are comparing the total amount traded + * on the lastTradedDayTime that makes the restriction strict. The reason is not availability of amount + * that transacted on the current day (because of bucket desgin). */ function _isValidAmountAfterRestrictionChanges( bool _isDefault, @@ -841,6 +844,7 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { view returns(bool) { + // Always use the alternate bucket details as per the current transaction restriction BucketDetails storage bucketDetails = _isDefault ? userToBucket[_from] : defaultUserToBucket[_from]; uint256 amountTradedLastDay = _isDefault ? bucket[_from][bucketDetails.lastTradedDayTime]: defaultBucket[_from][bucketDetails.lastTradedDayTime]; return VolumeRestrictionLib.isValidAmountAfterRestrictionChanges( @@ -920,12 +924,14 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { { uint256 counter = _bucketDetails.daysCovered; uint256 sumOfLastPeriod = _bucketDetails.sumOfLastPeriod; + uint256 i = 0; if (_diffDays >= _rollingPeriodInDays) { // If the difference of days is greater than the rollingPeriod then sumOfLastPeriod will always be zero sumOfLastPeriod = 0; counter = counter.add(_diffDays); } else { - for (uint256 diffDaysPlusDaysCovered = _diffDays + counter; counter < diffDaysPlusDaysCovered; counter++) { + for (i = 0; i < _diffDays; i++) { + counter++; // This condition is to check whether the first rolling period is covered or not // if not then it continues and adding 0 value into sumOfLastPeriod without subtracting // the earlier value at that index diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 97e8feda0..2d8bc05f6 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -1182,7 +1182,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }) - it("Should successfully to transact tokens in the second rolling period", async () => { + it("Should successfully transact tokens in the second rolling period", async () => { // Should transact freely tokens daily limit is also ended let startTime = (await I_VolumeRestrictionTM.individualRestriction.call(account_investor3))[1].toNumber(); From 4c43cf54c05c13fdd00142b04c910a3a26431025 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 29 Mar 2019 19:20:45 +0530 Subject: [PATCH 578/582] increase the time to fix the coverage --- test/y_volume_restriction_tm.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 2d8bc05f6..e456d0c4a 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -422,7 +422,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("12"), - latestTime() + duration.seconds(2), + latestTime() + duration.seconds(10), 3, latestTime() + duration.days(5), 0, @@ -442,7 +442,7 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [latestTime() + duration.seconds(5), latestTime() + duration.seconds(5), latestTime() + duration.seconds(5)], [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], [0, 0, 0], @@ -458,7 +458,7 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [latestTime() + duration.seconds(5), latestTime() + duration.seconds(5), latestTime() + duration.seconds(5)], [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], [0, 0, 0], @@ -474,7 +474,7 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10")], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [latestTime() + duration.seconds(5), latestTime() + duration.seconds(5), latestTime() + duration.seconds(5)], [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], [0, 0, 0], @@ -490,7 +490,7 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [latestTime() + duration.seconds(5), latestTime() + duration.seconds(5)], [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], [0, 0, 0], @@ -506,7 +506,7 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [latestTime() + duration.seconds(5), latestTime() + duration.seconds(5), latestTime() + duration.seconds(5)], [3], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], [0, 0, 0], @@ -522,7 +522,7 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [latestTime() + duration.seconds(5), latestTime() + duration.seconds(5), latestTime() + duration.seconds(5)], [3, 4, 5], [latestTime() + duration.days(5)], [0, 0, 0], @@ -538,7 +538,7 @@ contract('VolumeRestrictionTransferManager', accounts => { I_VolumeRestrictionTM.addIndividualRestrictionMulti( [account_investor2, account_delegate3, account_investor4], [web3.utils.toWei("12"), web3.utils.toWei("10"), web3.utils.toWei("15")], - [latestTime() + duration.seconds(2), latestTime() + duration.seconds(2), latestTime() + duration.seconds(2)], + [latestTime() + duration.seconds(5), latestTime() + duration.seconds(5), latestTime() + duration.seconds(5)], [3, 4, 5], [latestTime() + duration.days(5), latestTime() + duration.days(6), latestTime() + duration.days(7)], [], @@ -618,7 +618,7 @@ contract('VolumeRestrictionTransferManager', accounts => { ${await I_VolumeRestrictionTM.addIndividualRestriction.estimateGas( account_investor1, web3.utils.toWei("12"), - latestTime() + duration.seconds(5), + 0, 3, latestTime() + duration.days(6), 0, @@ -631,7 +631,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tx = await I_VolumeRestrictionTM.addIndividualRestriction( account_investor1, web3.utils.toWei("12"), - latestTime() + duration.seconds(5), + 0, 3, latestTime() + duration.days(6), 0, From 8d8760559404b2701a1e901b46b179ddcca4b7c5 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 29 Mar 2019 21:42:16 +0530 Subject: [PATCH 579/582] optimize the code --- contracts/libraries/VolumeRestrictionLib.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol index 46e1ddb7e..b0962f231 100644 --- a/contracts/libraries/VolumeRestrictionLib.sol +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -82,12 +82,12 @@ library VolumeRestrictionLib { // if restriction is to check whether the current transaction is performed within the 24 hours // span after the last transaction performed by the user if (BokkyPooBahsDateTimeLibrary.diffSeconds(_lastTradedTimestamp, now) < 86400) { - (uint256 lastTxYear, uint256 lastTxMonth, uint256 lastTxDay) = BokkyPooBahsDateTimeLibrary.timestampToDate(_lastTradedTimestamp); - (uint256 currentTxYear, uint256 currentTxMonth, uint256 currentTxDay) = BokkyPooBahsDateTimeLibrary.timestampToDate(now); + (,, uint256 lastTxDay) = BokkyPooBahsDateTimeLibrary.timestampToDate(_lastTradedTimestamp); + (,, uint256 currentTxDay) = BokkyPooBahsDateTimeLibrary.timestampToDate(now); // This if statement is to check whether the last transaction timestamp (of `individualRestriction[_from]` // when `_isDefault` is true or defaultRestriction when `_isDefault` is false) is comes within the same day of the current // transaction timestamp or not. - if (lastTxYear == currentTxYear && lastTxMonth == currentTxMonth && lastTxDay == currentTxDay) { + if (lastTxDay == currentTxDay) { // Not allow to transact more than the current transaction restriction allowed amount if ((_sumOfLastPeriod.add(_amount)).add(_amountTradedLastDay) > _allowedAmount) return false; From c4b537daa6600a418e8344b80039eea2eb6fbb82 Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Tue, 2 Apr 2019 08:42:34 -0300 Subject: [PATCH 580/582] updated readme with 2.1.0 mainnet addresses --- README.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d310ec4e5..5e7d97328 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ You can easily navigate through it with the sidebar directory in order to run th ## Mainnet -### v2.0.0 +### v2.1.0 | Contract | Address | | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | @@ -127,15 +127,15 @@ You can easily navigate through it with the sidebar directory in order to run th | Feature Registry: | [0xa3eacb03622bf1513880892b7270d965f693ffb5](https://etherscan.io/address/0xa3eacb03622bf1513880892b7270d965f693ffb5) | | ETHOracle: | [0x60055e9a93aae267da5a052e95846fa9469c0e7a](https://etherscan.io/address/0x60055e9a93aae267da5a052e95846fa9469c0e7a) | | POLYOracle: | [0x52cb4616E191Ff664B0bff247469ce7b74579D1B](https://etherscan.io/address/0x52cb4616E191Ff664B0bff247469ce7b74579D1B) | -| General Transfer Manager Factory: | [0xdc95598ef2bbfdb66d02d5f3eea98ea39fbc8b26](https://etherscan.io/address/0xdc95598ef2bbfdb66d02d5f3eea98ea39fbc8b26) | +| General Transfer Manager Factory (2.0.0): | [0xdc95598ef2bbfdb66d02d5f3eea98ea39fbc8b26](https://etherscan.io/address/0xdc95598ef2bbfdb66d02d5f3eea98ea39fbc8b26) | +| General Transfer Manager Factory (2.1.0): | [0xa8b60c9b7054782f46931e35e7012037a574ecee](https://etherscan.io/address/0xa8b60c9b7054782f46931e35e7012037a574ecee) | | General Permission Manager Factory: | [0xf0aa1856360277c60052d6095c5b787b01388cdd](https://etherscan.io/address/0xf0aa1856360277c60052d6095c5b787b01388cdd) | -| CappedSTOFactory: | [0x77d89663e8819023a87bfe2bc9baaa6922c0e57c](https://etherscan.io/address/0x77d89663e8819023a87bfe2bc9baaa6922c0e57c) | -| USDTieredSTO Factory: | [0x5a3a30bddae1f857a19b1aed93b5cdb3c3da809a](https://etherscan.io/address/0x5a3a30bddae1f857a19b1aed93b5cdb3c3da809a) | -| EthDividendsCheckpointFactory: | [0x968c74c52f15b2de323eca8c677f6c9266bfefd6](https://etherscan.io/address/0x968c74c52f15b2de323eca8c677f6c9266bfefd6) | -| ERC20 Dividends Checkpoint Factory: | [0x82f9f1ab41bacb1433c79492e54bf13bccd7f9ae](https://etherscan.io/address/0x82f9f1ab41bacb1433c79492e54bf13bccd7f9ae) | -| Count Transfer Manager Factory: | [0xd9fd7e34d6e2c47a69e02131cf8554d52c3445d5](https://etherscan.io/address/0xd9fd7e34d6e2c47a69e02131cf8554d52c3445d5) | +| CappedSTOFactory (2.1.0): | [0x26bcd18a748ade7fafb250bb014c7121a412870c](https://etherscan.io/address/0x26bcd18a748ade7fafb250bb014c7121a412870c) | +| USDTieredSTO Factory (2.1.0): | [0x0148ed61ffa8e0da7908a62aa2d1f266688656c4](https://etherscan.io/address/0x0148ed61ffa8e0da7908a62aa2d1f266688656c4) | +| ERC20 Dividends Checkpoint Factory (2.1.0): | [0x855152c9b98babadc996a0dd71c8b3682b8f4786](https://etherscan.io/address/0x855152c9b98babadc996a0dd71c8b3682b8f4786) | +| Count Transfer Manager Factory (2.1.0): | [0x575ed30ec5700f369115b079be8059001e79eb7b](https://etherscan.io/address/0x575ed30ec5700f369115b079be8059001e79eb7b) | | Percentage Transfer Manager Factory: | [0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b](https://etherscan.io/address/0xe6267a9c0a227d21c95b782b1bd32bb41fc3b43b) | -| Manual Approval Transfer Manager Factory (2.0.1): | [0x6af2afad53cb334e62b90ddbdcf3a086f654c298](https://etherscan.io/address/0x6af2afad53cb334e62b90ddbdcf3a086f654c298) | +| Manual Approval Transfer Manager Factory (2.1.0): | [0xe5b21cf83f5e49aba4601e8d8cf182f889208cfd](https://etherscan.io/address/0xe5b21cf83f5e49aba4601e8d8cf182f889208cfd) | New SecurityTokenRegistry (2.0.1): 0x538136ed73011a766bf0a126a27300c3a7a2e6a6 @@ -144,12 +144,9 @@ New SecurityTokenRegistry (2.0.1): 0x538136ed73011a766bf0a126a27300c3a7a2e6a6 New ModuleRegistry (2.0.1): 0xbc18f144ccf87f2d98e6fa0661799fcdc3170119 (fixed bug with missing transferOwnership function) -New ManualApprovalTransferManager 0x6af2afad53cb334e62b90ddbdcf3a086f654c298 -(Fixed 0x0 from bug) - ## KOVAN -### v2.0.0 +### v2.1.0 New Kovan PolyTokenFaucet: 0xb347b9f5b56b431b2cf4e1d90a5995f7519ca792 | Contract | Address | From 5b4f4293ccfe5be407ace75f42fbf46c91741701 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 2 Apr 2019 12:15:39 -0300 Subject: [PATCH 581/582] Fix to keep transfer_manager compatible with GTM v1.0.0 --- CLI/commands/transfer_manager.js | 43 +++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 5a5b148ca..13f59b128 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -304,6 +304,11 @@ async function addTransferManagerModule() { async function generalTransferManager() { console.log('\n', chalk.blue(`General Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + let moduleFactoryABI = abis.moduleFactory(); + let factoryAddress = await currentTransferManager.methods.factory().call(); + let moduleFactory = new web3.eth.Contract(moduleFactoryABI, factoryAddress); + let moduleVersion = await moduleFactory.methods.version().call(); + // Show current data let displayIssuanceAddress = await currentTransferManager.methods.issuanceAddress().call(); let displaySigningAddress = await currentTransferManager.methods.signingAddress().call(); @@ -311,27 +316,37 @@ async function generalTransferManager() { let displayAllowAllWhitelistTransfers = await currentTransferManager.methods.allowAllWhitelistTransfers().call(); let displayAllowAllWhitelistIssuances = await currentTransferManager.methods.allowAllWhitelistIssuances().call(); let displayAllowAllBurnTransfers = await currentTransferManager.methods.allowAllBurnTransfers().call(); - let displayDefaults = await currentTransferManager.methods.defaults().call(); - let displayInvestors = await currentTransferManager.methods.getInvestors().call(); - + let displayDefaults; + let displayInvestors; + if (moduleVersion != '1.0.0') { + displayDefaults = await currentTransferManager.methods.defaults().call(); + displayInvestors = await currentTransferManager.methods.getInvestors().call(); + } console.log(`- Issuance address: ${displayIssuanceAddress}`); console.log(`- Signing address: ${displaySigningAddress}`); console.log(`- Allow all transfers: ${displayAllowAllTransfers ? `YES` : `NO`}`); console.log(`- Allow all whitelist transfers: ${displayAllowAllWhitelistTransfers ? `YES` : `NO`}`); console.log(`- Allow all whitelist issuances: ${displayAllowAllWhitelistIssuances ? `YES` : `NO`}`); console.log(`- Allow all burn transfers: ${displayAllowAllBurnTransfers ? `YES` : `NO`}`); - console.log(`- Default times:`); - console.log(` - From time: ${displayDefaults.fromTime} (${moment.unix(displayDefaults.fromTime).format('MMMM Do YYYY, HH:mm:ss')})`); - console.log(` - To time: ${displayDefaults.toTime} (${moment.unix(displayDefaults.toTime).format('MMMM Do YYYY, HH:mm:ss')})`); - console.log(`- Investors: ${displayInvestors.length}`); + if (displayDefaults) { + console.log(`- Default times:`); + console.log(` - From time: ${displayDefaults.fromTime} (${moment.unix(displayDefaults.fromTime).format('MMMM Do YYYY, HH:mm:ss')})`); + console.log(` - To time: ${displayDefaults.toTime} (${moment.unix(displayDefaults.toTime).format('MMMM Do YYYY, HH:mm:ss')})`); + } + if (displayInvestors) { + console.log(`- Investors: ${displayInvestors.length}`); + } // ------------------ let options = []; - if (displayInvestors.length > 0) { + if (displayInvestors && displayInvestors.length > 0) { options.push(`Show investors`, `Show whitelist data`); } - options.push('Modify whitelist', 'Modify whitelist from CSV', /*'Modify Whitelist Signed',*/ - 'Change the default times used when they are zero', `Change issuance address`, 'Change signing address'); + options.push('Modify whitelist', 'Modify whitelist from CSV') /*'Modify Whitelist Signed',*/ + if (displayDefaults) { + options.push('Change the default times used when they are zero'); + } + options.push(`Change issuance address`, 'Change signing address'); if (displayAllowAllTransfers) { options.push('Disallow all transfers'); @@ -401,8 +416,12 @@ async function generalTransferManager() { let canBuyFromSTO = readlineSync.keyInYNStrict('Can the investor buy from security token offerings?'); let modifyWhitelistAction = currentTransferManager.methods.modifyWhitelist(investor, fromTime, toTime, expiryTime, canBuyFromSTO); let modifyWhitelistReceipt = await common.sendTransaction(modifyWhitelistAction); - let modifyWhitelistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); - console.log(chalk.green(`${modifyWhitelistEvent._investor} has been whitelisted sucessfully!`)); + if (moduleVersion != '1.0.0') { + let modifyWhitelistEvent = common.getEventFromLogs(currentTransferManager._jsonInterface, modifyWhitelistReceipt.logs, 'ModifyWhitelist'); + console.log(chalk.green(`${modifyWhitelistEvent._investor} has been whitelisted sucessfully!`)); + } else { + console.log(chalk.green(`${investor} has been whitelisted sucessfully!`)); + } break; case 'Modify whitelist from CSV': await modifyWhitelistInBatch(); From 2e481ac1d904a3b86e67d878dc2010eaa11aaa68 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 5 Apr 2019 13:37:09 +0530 Subject: [PATCH 582/582] docs update & minor improvements --- .../TransferManager/VolumeRestrictionTM.sol | 101 +++++++++++------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index b651a4a7a..0c6818c03 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -159,7 +159,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _startTime Unix timestamp at which restriction get into effect * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionType Whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function addIndividualRestriction( address _holder, @@ -228,7 +229,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionType Whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function addIndividualDailyRestriction( address _holder, @@ -288,7 +290,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. * @param _startTimes Array of unix timestamps at which restrictions get into effect * @param _endTimes Array of unix timestamps at which restriction effects will gets end. - * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionTypes Array of restriction types value whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function addIndividualDailyRestrictionMulti( address[] _holders, @@ -320,7 +323,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _startTimes Array of unix timestamps at which restrictions get into effect * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) * @param _endTimes Array of unix timestamps at which restriction effects will gets end. - * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionTypes Array of restriction types value whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function addIndividualRestrictionMulti( address[] _holders, @@ -352,7 +356,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _startTime Unix timestamp at which restriction get into effect * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionType Whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function addDefaultRestriction( uint256 _allowedTokens, @@ -387,7 +392,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionType Whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function addDefaultDailyRestriction( uint256 _allowedTokens, @@ -499,7 +505,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _startTime Unix timestamp at which restriction get into effect * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionType Whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function modifyIndividualRestriction( address _holder, @@ -561,7 +568,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _allowedTokens Amount of tokens allowed to be trade for a given address. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionType Whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function modifyIndividualDailyRestriction( address _holder, @@ -620,7 +628,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _allowedTokens Array of amount of tokens allowed to be trade for a given address. * @param _startTimes Array of unix timestamps at which restrictions get into effect * @param _endTimes Array of unix timestamps at which restriction effects will gets end. - * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionTypes Array of restriction types value whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function modifyIndividualDailyRestrictionMulti( address[] _holders, @@ -652,7 +661,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _startTimes Array of unix timestamps at which restrictions get into effect * @param _rollingPeriodInDays Array of rolling period in days (Minimum value should be 1 day) * @param _endTimes Array of unix timestamps at which restriction effects will gets end. - * @param _restrictionTypes Array of restriction types value will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionTypes Array of restriction types value whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function modifyIndividualRestrictionMulti( address[] _holders, @@ -684,7 +694,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _startTime Unix timestamp at which restriction get into effect * @param _rollingPeriodInDays Rolling period in days (Minimum value should be 1 day) * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionType Whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function modifyDefaultRestriction( uint256 _allowedTokens, @@ -722,7 +733,8 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { * @param _allowedTokens Amount of tokens allowed to be traded for all token holder. * @param _startTime Unix timestamp at which restriction get into effect * @param _endTime Unix timestamp at which restriction effects will gets end. - * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + * @param _restrictionType Whether it will be `Fixed` (fixed no. of tokens allowed to transact) + * or `Percentage` (tokens are calculated as per the totalSupply in the fly). */ function modifyDefaultDailyRestriction( uint256 _allowedTokens, @@ -880,11 +892,11 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } function _dailyTxCheck( - address from, - uint256 amount, - uint256 dailyLastTradedDayTime, - VolumeRestriction memory restriction, - bool isDefault + address _from, + uint256 _amount, + uint256 _dailyLastTradedDayTime, + VolumeRestriction memory _restriction, + bool _isDefault ) internal view @@ -892,21 +904,31 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { { // Checking whether the daily restriction is added or not if yes then calculate // the total amount get traded on a particular day (~ _fromTime) - if ( now <= restriction.endTime && now >= restriction.startTime) { + if ( now <= _restriction.endTime && now >= _restriction.startTime) { uint256 txSumOfDay = 0; // This if condition will be executed when the individual daily restriction executed first time - if (dailyLastTradedDayTime == 0 || dailyLastTradedDayTime < restriction.startTime) - dailyLastTradedDayTime = restriction.startTime.add(BokkyPooBahsDateTimeLibrary.diffDays(restriction.startTime, now).mul(1 days)); - else if (now.sub(dailyLastTradedDayTime) >= 1 days) - dailyLastTradedDayTime = dailyLastTradedDayTime.add(BokkyPooBahsDateTimeLibrary.diffDays(dailyLastTradedDayTime, now).mul(1 days)); + if (_dailyLastTradedDayTime == 0 || _dailyLastTradedDayTime < _restriction.startTime) + _dailyLastTradedDayTime = _restriction.startTime.add(BokkyPooBahsDateTimeLibrary.diffDays(_restriction.startTime, now).mul(1 days)); + else if (now.sub(_dailyLastTradedDayTime) >= 1 days) + _dailyLastTradedDayTime = _dailyLastTradedDayTime.add(BokkyPooBahsDateTimeLibrary.diffDays(_dailyLastTradedDayTime, now).mul(1 days)); // Assgining total sum traded on dailyLastTradedDayTime timestamp - if (isDefault) - txSumOfDay = defaultBucket[from][dailyLastTradedDayTime]; + if (_isDefault) + txSumOfDay = defaultBucket[_from][_dailyLastTradedDayTime]; else - txSumOfDay = bucket[from][dailyLastTradedDayTime]; - return (_checkValidAmountToTransact(isDefault, from, txSumOfDay, amount, restriction.typeOfRestriction, restriction.allowedTokens), dailyLastTradedDayTime); + txSumOfDay = bucket[_from][_dailyLastTradedDayTime]; + return ( + _checkValidAmountToTransact( + _isDefault, + _from, + txSumOfDay, + _amount, + _restriction.typeOfRestriction, + _restriction.allowedTokens + ), + _dailyLastTradedDayTime + ); } - return (true, dailyLastTradedDayTime); + return (true, _dailyLastTradedDayTime); } /// Internal function for the bucket check @@ -1041,7 +1063,6 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { internal pure { - require(uint256(_restrictionType) < 2); if (isModifyDaily) require(_startTime >= _earliestStartTime, "Invalid startTime"); else @@ -1182,22 +1203,22 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, ITransferManager { } function _setValues( - VolumeRestriction memory restriction, - uint256[] memory allowedTokens, - uint256[] memory startTime, - uint256[] memory rollingPeriodInDays, - uint256[] memory endTime, - RestrictionType[] memory typeOfRestriction, - uint256 index + VolumeRestriction memory _restriction, + uint256[] memory _allowedTokens, + uint256[] memory _startTime, + uint256[] memory _rollingPeriodInDays, + uint256[] memory _endTime, + RestrictionType[] memory _typeOfRestriction, + uint256 _index ) internal pure { - allowedTokens[index] = restriction.allowedTokens; - startTime[index] = restriction.startTime; - rollingPeriodInDays[index] = restriction.rollingPeriodInDays; - endTime[index] = restriction.endTime; - typeOfRestriction[index] = restriction.typeOfRestriction; + _allowedTokens[_index] = _restriction.allowedTokens; + _startTime[_index] = _restriction.startTime; + _rollingPeriodInDays[_index] = _restriction.rollingPeriodInDays; + _endTime[_index] = _restriction.endTime; + _typeOfRestriction[_index] = _restriction.typeOfRestriction; } function _checkLengthOfArray(